r21889: * Pull from SAMBA-3_0_25 svn r21888
authorGerald Carter <jerry@samba.org>
Tue, 20 Mar 2007 16:56:16 +0000 (16:56 +0000)
committerGerald Carter <jerry@samba.org>
Tue, 20 Mar 2007 16:56:16 +0000 (16:56 +0000)
* Set version to 3.0.25pre2

127 files changed:
MAINTAINERS
WHATSNEW.txt
examples/VFS/Makefile.in
examples/VFS/configure.in
examples/VFS/skel_opaque.c
examples/VFS/skel_transparent.c
source/Makefile.in
source/VERSION
source/auth/auth_domain.c
source/auth/auth_winbind.c
source/client/client.c
source/client/clitar.c
source/client/mount.cifs.c
source/client/smbctool.c
source/configure.in
source/include/client.h
source/include/doserr.h
source/include/includes.h
source/include/msdfs.h
source/include/nt_printing.h
source/include/rpc_secdes.h
source/include/rpc_srvsvc.h
source/include/smb.h
source/include/smbprofile.h
source/include/trans2.h
source/include/vfs.h
source/include/vfs_macros.h
source/lib/debug.c
source/lib/interface.c
source/lib/ldap_escape.c
source/lib/messages.c
source/lib/smbldap_util.c
source/lib/system.c
source/lib/time.c
source/lib/util.c
source/libaddns/dnsgss.c
source/libads/cldap.c
source/libads/kerberos_keytab.c
source/libads/kerberos_verify.c
source/libads/krb5_errs.c
source/libads/ldap.c
source/libads/ldap_user.c
source/libads/sasl.c
source/libads/smb_krb5_locator.c [new file with mode: 0644]
source/librpc/ndr/libndr.h
source/librpc/ndr/ndr.c
source/libsmb/cliconnect.c
source/libsmb/clidfs.c
source/libsmb/clifile.c
source/libsmb/clikrb5.c
source/libsmb/clilist.c
source/libsmb/cliquota.c
source/libsmb/clirap.c
source/libsmb/doserr.c
source/libsmb/errormap.c
source/libsmb/libsmbclient.c
source/locking/brlock.c
source/locking/locking.c
source/modules/nfs4_acls.c
source/modules/vfs_cap.c
source/modules/vfs_catia.c
source/modules/vfs_default.c
source/modules/vfs_full_audit.c
source/modules/vfs_netatalk.c
source/modules/vfs_recycle.c
source/nsswitch/idmap.c
source/nsswitch/idmap_ldap.c
source/nsswitch/pam_winbind.c
source/nsswitch/wb_common.c
source/nsswitch/winbind_client.h
source/nsswitch/winbind_nss_irix.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd.h
source/nsswitch/winbindd_ads.c
source/nsswitch/winbindd_cred_cache.c
source/nsswitch/winbindd_dual.c
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_pam.c
source/nsswitch/winbindd_rpc.c
source/nsswitch/winbindd_user.c
source/param/loadparm.c
source/passdb/lookup_sid.c
source/passdb/pdb_ldap.c
source/printing/nt_printing.c
source/printing/print_cups.c
source/profile/profile.c
source/rpc_client/cli_srvsvc.c
source/rpc_parse/parse_srv.c
source/rpc_server/srv_dfs_nt.c
source/rpc_server/srv_pipe_hnd.c
source/rpc_server/srv_samr_nt.c
source/rpc_server/srv_srvsvc.c
source/rpc_server/srv_srvsvc_nt.c
source/rpcclient/cmd_samr.c
source/smbd/close.c
source/smbd/dir.c
source/smbd/dosmode.c
source/smbd/fileio.c
source/smbd/files.c
source/smbd/msdfs.c
source/smbd/negprot.c
source/smbd/notify_inotify.c
source/smbd/nttrans.c
source/smbd/open.c
source/smbd/pipes.c
source/smbd/process.c
source/smbd/reply.c
source/smbd/sesssetup.c
source/smbd/trans2.c
source/tdb/common/open.c
source/tdb/common/tdb.c
source/tdb/common/tdb_private.h
source/tdb/include/tdb.h
source/torture/cmd_vfs.c
source/torture/nsstest.c
source/torture/torture.c
source/utils/net_ads.c
source/utils/net_ads_gpo.c
source/utils/net_rpc.c
source/utils/net_sam.c
source/utils/net_status.c
source/utils/ntlm_auth.c
source/utils/pdbedit.c
source/utils/smbcontrol.c
source/utils/status.c
source/utils/status_profile.c
source/web/statuspage.c

index 9f67bf945de639de6e55ecce5aec79696d460b1b..2b09221efc0d980986c542cd52ef388e2cde5105 100644 (file)
@@ -7,7 +7,7 @@ portions of the Samba 3.0 code.  It also lists developers
 responsible for 3rd party projects that work with Samba
 (e.g. vfs modules).
 
-Note that this list is for you benefit, but please do not
+Note that this list is for your benefit, but please do not
 abuse it by constantly emailing a stream of help questions
 to the maintainers.  Some are more open to direct 
 communication than others and some struggle with enormous
@@ -26,11 +26,10 @@ libmsrpc            Chris Nichols <skel@samba.org>
 
 libsmbclient           Derrell Lipman <derrell@samba.org>
 
-pdb_*sql               <samba-pdbsql@samba.org>
-                       Peter Rindfuss: pdb_mysql
-                       Darrell McGuire: pdb_mysql
-                       Ulrich Meis: pdb_pgsql 
-                       Filip Jirsák: pdb_pgsql
+pdb_*sql               Wilco Baan Hofman <synnack@users.sf.net>
+                       Florian Effenberger <floeff@users.sf.net>
+
+                       http://pdbsql.sourceforge.net/
 
 printing               Gerald (Jerry) Carter <jerry@samba.org>
 
index f28d1d8290ed3974b9fd01bf81ce1eed03df5359..1566a4c599f10a36a0e06d1a403295719fb22136 100644 (file)
@@ -89,7 +89,7 @@ smb.conf changes
     idmap expire time                  New             900
     idmap negative time                        New             120
     kernel change notify               Per share       Yes
-    max stat cache size                Modified        1024MB
+    max stat cache size                Modified        1024KB
     printjob username                  New             %U
     winbind normalize names            New             no
 
@@ -304,11 +304,11 @@ o   J Raynor <raynorj@mn.rr.com>
 
 
 o   Jiri Sasek <Jiri.Sasek@Sun.COM>
-    I Fix possible NULL dereference in adt_tree.c
+    * Fix possible NULL dereference in adt_tree.c
 
 
 o   Karolin Seeger <ks@sernet.de>
-    * Improvements to 'net sam policy'
+    * Add 'net sam policy' commands.
     * Fixes for "net usershare" and "guest_ok=y"
 
 
index caf8f030aa48163bc132df0fe84d6f01b2fc54a4..53914994b1ce218499ed2a9e336dc89676062448 100644 (file)
@@ -39,5 +39,5 @@ clean:
        rm -f core *~ *% *.bak *.o *.$(SHLIBEXT)
 
 distclean: clean
-       rm config.* Makefile
+       rm -f config.status config.cache Makefile
 
index 515d43f0096af5d0de3635b6bb6b48566fad5a9f..1a0ff6bb4ca1b0a77228e6fe422835eb0b9bb307 100644 (file)
@@ -182,6 +182,10 @@ PICFLAGS=""
 PICSUFFIX="po"
 SHLIBEXT="so"
 
+# Since we are not embedded in the Samba tree, building shared modules is
+# really the only option.
+enable_shared=yes
+
 if test "$enable_shared" = "yes"; then
   # this bit needs to be modified for each OS that is suported by
   # smbwrapper. You need to specify how to created a shared library and
index 096068da147bf6b3c60564906d7d9dff1b0c1119..7103d0c27b7b3a1697d417ad820804e3d35ea817 100644 (file)
  * --metze
  */
 
+/* NOTE: As of approximately Samba 3.0.24, the vfswrap_* functions are not
+ * global symbols. They are included here only as an pointer that opaque
+ * operations should not call further into the VFS.
+ */
+
 static int skel_connect(vfs_handle_struct *handle,  const char *service, const char *user)    
 {
        return 0;
@@ -211,9 +216,9 @@ static char *skel_getwd(vfs_handle_struct *handle,  char *buf)
        return vfswrap_getwd(NULL,  buf);
 }
 
-static int skel_utime(vfs_handle_struct *handle,  const char *path, struct utimbuf *times)
+static int skel_ntimes(vfs_handle_struct *handle,  const char *path, const struct timespec ts[2])
 {
-       return vfswrap_utime(NULL,  path, times);
+       return vfswrap_ntimes(NULL,  path, ts);
 }
 
 static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset)
@@ -236,6 +241,7 @@ static int skel_symlink(vfs_handle_struct *handle,  const char *oldpath, const c
        return vfswrap_symlink(NULL,  oldpath, newpath);
 }
 
+
 static int skel_readlink(vfs_handle_struct *handle,  const char *path, char *buf, size_t bufsiz)
 {
        return vfswrap_readlink(NULL,  path, buf, bufsiz);
@@ -256,25 +262,43 @@ static char *skel_realpath(vfs_handle_struct *handle,  const char *path, char *r
        return vfswrap_realpath(NULL,  path, resolved_path);
 }
 
-static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
+static NTSTATUS skel_notify_watch(struct vfs_handle_struct *handle,
+           struct sys_notify_context *ctx, struct notify_entry *e,
+           void (*callback)(struct sys_notify_context *ctx, void *private_data, struct notify_event *ev),
+           void *private_data, void *handle_p)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+static int skel_chflags(vfs_handle_struct *handle,  const char *path, uint flags)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
+static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+       int fd, uint32 security_info, SEC_DESC **ppdesc)
 {
        errno = ENOSYS;
        return 0;
 }
 
-static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc)
+static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+       const char *name, uint32 security_info, SEC_DESC **ppdesc)
 {
        errno = ENOSYS;
        return 0;
 }
 
-static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int
+       fd, uint32 security_info_sent, SEC_DESC *psd)
 {
        errno = ENOSYS;
        return False;
 }
 
-static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const
+       char *name, uint32 security_info_sent, SEC_DESC *psd)
 {
        errno = ENOSYS;
        return False;
@@ -578,7 +602,7 @@ static vfs_op_tuple skel_op_tuples[] = {
        {SMB_VFS_OP(skel_fchown),                       SMB_VFS_OP_FCHOWN,              SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_chdir),                        SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_getwd),                        SMB_VFS_OP_GETWD,               SMB_VFS_LAYER_OPAQUE},
-       {SMB_VFS_OP(skel_utime),                        SMB_VFS_OP_UTIME,               SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(skel_ntimes),                       SMB_VFS_OP_NTIMES,              SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_ftruncate),                    SMB_VFS_OP_FTRUNCATE,           SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_lock),                         SMB_VFS_OP_LOCK,                SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_getlock),                      SMB_VFS_OP_GETLOCK,             SMB_VFS_LAYER_OPAQUE},
@@ -587,6 +611,10 @@ static vfs_op_tuple skel_op_tuples[] = {
        {SMB_VFS_OP(skel_link),                         SMB_VFS_OP_LINK,                SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_mknod),                        SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(skel_realpath),                     SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(skel_notify_watch),                 SMB_VFS_OP_NOTIFY_WATCH,        SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(skel_chflags),                      SMB_VFS_OP_CHFLAGS,             SMB_VFS_LAYER_OPAQUE},
+
+
 
        /* NT File ACL operations */
 
index 2a379cd6d894896e1d75f87d99c5802fffaf0aae..2efb3d54a78f49b3742db0feb8dd7009da4214f3 100644 (file)
@@ -210,9 +210,9 @@ static char *skel_getwd(vfs_handle_struct *handle,  char *buf)
        return SMB_VFS_NEXT_GETWD(handle, buf);
 }
 
-static int skel_utime(vfs_handle_struct *handle,  const char *path, struct utimbuf *times)
+static int skel_ntimes(vfs_handle_struct *handle,  const char *path, const struct timespec ts[2])
 {
-       return SMB_VFS_NEXT_UTIME(handle, path, times);
+       return SMB_VFS_NEXT_NTIMES(handle, path, ts);
 }
 
 static int skel_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T offset)
@@ -255,22 +255,40 @@ static char *skel_realpath(vfs_handle_struct *handle,  const char *path, char *r
        return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
 }
 
-static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc)
+static NTSTATUS skel_notify_watch(struct vfs_handle_struct *handle,
+           struct sys_notify_context *ctx, struct notify_entry *e,
+           void (*callback)(struct sys_notify_context *ctx, void *private_data, struct notify_event *ev),
+           void *private_data, void *handle_p)
+{
+       return SMB_VFS_NEXT_NOTIFY_WATCH(handle, ctx, e, callback,
+               private_data, handle_p);
+}
+
+static int skel_chflags(vfs_handle_struct *handle,  const char *path, uint flags)
+{
+       return SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
+}
+
+static size_t skel_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+       int fd, uint32 security_info, SEC_DESC **ppdesc)
 {
        return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc);
 }
 
-static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc)
+static size_t skel_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+       const char *name, uint32 security_info, SEC_DESC **ppdesc)
 {
        return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp, name, security_info, ppdesc);
 }
 
-static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+       int fd, uint32 security_info_sent, SEC_DESC *psd)
 {
        return SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, fd, security_info_sent, psd);
 }
 
-static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd)
+static BOOL skel_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
+       const char *name, uint32 security_info_sent, SEC_DESC *psd)
 {
        return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd);
 }
@@ -545,7 +563,7 @@ static vfs_op_tuple skel_op_tuples[] = {
        {SMB_VFS_OP(skel_fchown),                       SMB_VFS_OP_FCHOWN,              SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_chdir),                        SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_getwd),                        SMB_VFS_OP_GETWD,               SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(skel_utime),                        SMB_VFS_OP_UTIME,               SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(skel_ntimes),                       SMB_VFS_OP_NTIMES,              SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_ftruncate),                    SMB_VFS_OP_FTRUNCATE,           SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_lock),                         SMB_VFS_OP_LOCK,                SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_getlock),                      SMB_VFS_OP_GETLOCK,             SMB_VFS_LAYER_TRANSPARENT},
@@ -554,6 +572,8 @@ static vfs_op_tuple skel_op_tuples[] = {
        {SMB_VFS_OP(skel_link),                         SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_mknod),                        SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(skel_realpath),                     SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(skel_notify_watch),                 SMB_VFS_OP_NOTIFY_WATCH,        SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(skel_chflags),                      SMB_VFS_OP_CHFLAGS,             SMB_VFS_LAYER_TRANSPARENT},
 
        /* NT File ACL operations */
 
index 3f3aa5ea57a21c63555f14dda2b7b536b7451b65..f27fed1f391b77ac889682d689e19b759857c47a 100644 (file)
@@ -159,7 +159,8 @@ TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
        bin/locktest2@EXEEXT@ bin/nsstest@EXEEXT@ bin/vfstest@EXEEXT@ \
        bin/pdbtest@EXEEXT@ bin/talloctort@EXEEXT@ bin/replacetort@EXEEXT@
 
-BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@
+BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@ \
+       @SMBMOUNT_PROGS@
 
 EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ \
        bin/talloctort@EXEEXT@ bin/replacetort@EXEEXT@ \
@@ -788,6 +789,10 @@ WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
 
 WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) @WINBIND_NSS_EXTRA_OBJS@
 
+SMB_KRB5_LOCATOR_OBJ1 = libads/smb_krb5_locator.o
+SMB_KRB5_LOCATOR_OBJ = $(SMB_KRB5_LOCATOR_OBJ1) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
+                      $(LIBNMB_OBJ) $(RPC_PARSE_OBJ1) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(DOSERR_OBJ)
+
 POPT_OBJ=popt/findme.o popt/popt.o popt/poptconfig.o \
           popt/popthelp.o popt/poptparse.o
 
@@ -1275,6 +1280,12 @@ bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
                $(LDAP_LIBS) $(KRB5LIBS) $(LIBS) \
                @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
 
+@SMB_KRB5_LOCATOR@: $(SMB_KRB5_LOCATOR_OBJ) 
+       @echo "Linking $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(SMB_KRB5_LOCATOR_OBJ) \
+               $(LDAP_LIBS) $(LIBS) -lcom_err \
+               @SONAMEFLAG@`basename $@`
+
 bin/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy
        @echo "Linking shared library $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ) -lpam @INIPARSERLIBS@ $(GPLIBS) \
@@ -1655,7 +1666,8 @@ revert:
        @$(SHELL) $(srcdir)/script/revert.sh $(BINDIR) $(BIN_PROGS) $(SCRIPTS)
 
 installman: installdirs
-       @$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
+       @SMBMOUNT_PROGS="@SMBMOUNT_PROGS@" $(SHELL) \
+               $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@"
 
 .PHONY: showlayout
 
index fc1f872b07abce80182a7eb9137159a29ffb1c11..4d4416c8ee3a9e2e38aa1ddf85a1ab039c4e72d3 100644 (file)
@@ -47,7 +47,7 @@ SAMBA_VERSION_REVISION=
 # e.g. SAMBA_VERSION_PRE_RELEASE=1                     #
 #  ->  "2.2.9pre1"                                     #
 ########################################################
-SAMBA_VERSION_PRE_RELEASE=1
+SAMBA_VERSION_PRE_RELEASE=2
 
 ########################################################
 # For 'rc' releases the version will be                #
index 6468c18cb0ea592c7c2a06aaec288cc6f343c6c1..a32677d037074f190f56365e776f2c5a47ca5dac 100644 (file)
@@ -237,7 +237,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
                                                      user_info->logon_parameters,/* flags such as 'allow workstation logon' */ 
                                                      dc_name,                    /* server name */
                                                      user_info->smb_name,        /* user name logging on. */
-                                                     user_info->domain,          /* domain name */
+                                                     user_info->client_domain,   /* domain name */
                                                      user_info->wksta_name,      /* workstation name */
                                                      chal,                       /* 8 byte challenge. */
                                                      user_info->lm_resp,         /* lanman 24 byte response */
index fa56757950d7a427ebf6d4695c38e067de8dc5d3..f06f83f4065027be74bec2e3afc7b90d055b4d1e 100644 (file)
@@ -108,7 +108,8 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
 
        /* we are contacting the privileged pipe */
        become_root();
-       result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
+       result = winbindd_priv_request_response(WINBINDD_PAM_AUTH_CRAP,
+                                               &request, &response);
        unbecome_root();
 
        if ( result == NSS_STATUS_UNAVAIL )  {
index 8ed3f1dc21ec8c8edda0090fce31f59166be7117..e95b9ed9ce3446615f48abdfacddae2decb3d6e0 100644 (file)
@@ -271,19 +271,17 @@ static int do_cd(char *newdir)
 
        pstrcpy(saved_dir, cur_dir);
 
-       if (*p == CLI_DIRSEP_CHAR)
+       if (*p == CLI_DIRSEP_CHAR) {
                pstrcpy(cur_dir,p);
-       else
+       } else {
                pstrcat(cur_dir,p);
-
-       if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
-               pstrcat(cur_dir, CLI_DIRSEP_STR);
+               if ((cur_dir[0] != '\0') && (*(cur_dir+strlen(cur_dir)-1) != CLI_DIRSEP_CHAR)) {
+                       pstrcat(cur_dir, CLI_DIRSEP_STR);
+               }
        }
        
-       dos_clean_name(cur_dir);
+       clean_name(cur_dir);
        pstrcpy( dname, cur_dir );
-       pstrcat(cur_dir,CLI_DIRSEP_STR);
-       dos_clean_name(cur_dir);
        
        if ( !cli_resolve_path( "", cli, dname, &targetcli, targetpath ) ) {
                d_printf("cd %s: %s\n", dname, cli_errstr(cli));
@@ -291,9 +289,9 @@ static int do_cd(char *newdir)
                goto out;
        }
 
-       
-       if ( strequal(targetpath,CLI_DIRSEP_STR ) )
-               return 0;   
+       if (strequal(targetpath,CLI_DIRSEP_STR )) {
+               return 0;
+       }
                
        /* Use a trans2_qpathinfo to test directories for modern servers.
           Except Win9x doesn't support the qpathinfo_basic() call..... */ 
@@ -312,7 +310,7 @@ static int do_cd(char *newdir)
                }               
        } else {
                pstrcat( targetpath, CLI_DIRSEP_STR );
-               dos_clean_name( targetpath );
+               clean_name( targetpath );
                
                if ( !cli_chkpath(targetcli, targetpath) ) {
                        d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
@@ -387,7 +385,7 @@ static void display_finfo(file_info *finfo)
                                 finfo->name,
                                 attrib_string(finfo->mode),
                                (double)finfo->size,
-                               time_to_asc(&t));
+                               time_to_asc(t));
                        dir_total += finfo->size;
                } else {
                        pstring afname;
@@ -398,25 +396,25 @@ static void display_finfo(file_info *finfo)
                                return;
                        /* create absolute filename for cli_nt_create() FIXME */
                        pstrcpy( afname, cwd);
-                       pstrcat( afname, "\\");
+                       pstrcat( afname, CLI_DIRSEP_STR);
                        pstrcat( afname, finfo->name);
                        /* print file meta date header */
                        d_printf( "FILENAME:%s\n", afname);
                        d_printf( "MODE:%s\n", attrib_string(finfo->mode));
                        d_printf( "SIZE:%.0f\n", (double)finfo->size);
-                       d_printf( "MTIME:%s", time_to_asc(&t));
-                       fnum = cli_nt_create(cli, afname, CREATE_ACCESS_READ);
+                       d_printf( "MTIME:%s", time_to_asc(t));
+                       fnum = cli_nt_create(finfo->cli, afname, CREATE_ACCESS_READ);
                        if (fnum == -1) {
                                DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
                                        afname,
-                                       cli_errstr( cli)));
+                                       cli_errstr( finfo->cli)));
                        } else {
                                SEC_DESC *sd = NULL;
-                               sd = cli_query_secdesc(cli, fnum, ctx);
+                               sd = cli_query_secdesc(finfo->cli, fnum, ctx);
                                if (!sd) {
                                        DEBUG( 0, ("display_finfo() failed to "
                                                "get security descriptor: %s",
-                                               cli_errstr( cli)));
+                                               cli_errstr( finfo->cli)));
                                } else {
                                        display_sec_desc(sd);
                                }
@@ -591,7 +589,8 @@ static void do_list_helper(const char *mntpoint, file_info *f, const char *mask,
                                return;
                        p[1] = 0;
                        pstrcat(mask2, f->name);
-                       pstrcat(mask2,"\\*");
+                       pstrcat(mask2,CLI_DIRSEP_STR);
+                       pstrcat(mask2,"*");
                        add_to_do_list_queue(mask2);
                }
                return;
@@ -714,6 +713,11 @@ static int cmd_dir(void)
                pstrcat(mask,"*");
        }
 
+       if (showacls) {
+               /* cwd is only used if showacls is on */
+               pstrcpy(cwd, cur_dir);
+       }
+
        do_list(mask, attribute, display_finfo, recurse, True);
 
        rc = do_dskattr();
@@ -790,17 +794,6 @@ static int do_get(char *rname, char *lname, BOOL reget)
 
        GetTimeOfDay(&tp_start);
        
-       if ( targetcli->dfsroot ) {
-               pstring path;
-
-               /* we need to refer to the full \server\share\path format 
-                  for dfs shares */
-
-               pstrcpy( path, targetname );
-               cli_dfs_make_full_path( targetname, targetcli->desthost, 
-                       targetcli->share, path);
-       }
-
        fnum = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE);
 
        if (fnum == -1) {
@@ -924,7 +917,7 @@ static int cmd_get(void)
                return 1;
        }
        pstrcpy(lname,p);
-       dos_clean_name(rname);
+       clean_name(rname);
        
        next_token_nr(NULL,lname,NULL,sizeof(lname));
        
@@ -1025,7 +1018,7 @@ static int cmd_more(void)
                unlink(lname);
                return 1;
        }
-       dos_clean_name(rname);
+       clean_name(rname);
 
        rc = do_get(rname, lname, False);
 
@@ -1155,14 +1148,20 @@ static int cmd_mkdir(void)
        if (recurse) {
                pstring ddir;
                pstring ddir2;
+               struct cli_state *targetcli;
+               pstring targetname;
                *ddir2 = 0;
                
-               pstrcpy(ddir,mask);
+               if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
+                       return 1;
+               }
+
+               pstrcpy(ddir,targetname);
                trim_char(ddir,'.','\0');
                p = strtok(ddir,"/\\");
                while (p) {
                        pstrcat(ddir2,p);
-                       if (!cli_chkpath(cli, ddir2)) { 
+                       if (!cli_chkpath(targetcli, ddir2)) { 
                                do_mkdir(ddir2);
                        }
                        pstrcat(ddir2,CLI_DIRSEP_STR);
@@ -1358,7 +1357,7 @@ static int cmd_put(void)
        else
                pstrcat(rname,lname);
        
-       dos_clean_name(rname);
+       clean_name(rname);
 
        {
                SMB_STRUCT_STAT st;
@@ -1672,13 +1671,13 @@ static void do_del(file_info *finfo)
 {
        pstring mask;
 
-       pstr_sprintf( mask, "%s\\%s", finfo->dir, finfo->name );
+       pstr_sprintf( mask, "%s%c%s", finfo->dir, CLI_DIRSEP_CHAR, finfo->name );
 
        if (finfo->mode & aDIR) 
                return;
 
-       if (!cli_unlink(cli, mask)) {
-               d_printf("%s deleting remote file %s\n",cli_errstr(cli),mask);
+       if (!cli_unlink(finfo->cli, mask)) {
+               d_printf("%s deleting remote file %s\n",cli_errstr(finfo->cli),mask);
        }
 }
 
@@ -1717,6 +1716,8 @@ static int cmd_wdel(void)
        pstring mask;
        pstring buf;
        uint16 attribute;
+       struct cli_state *targetcli;
+       pstring targetname;
 
        if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
                d_printf("wdel 0x<attrib> <wcard>\n");
@@ -1733,13 +1734,17 @@ static int cmd_wdel(void)
        pstrcpy(mask,cur_dir);
        pstrcat(mask,buf);
 
-       if (!cli_unlink_full(cli, mask, attribute)) {
-               d_printf("%s deleting remote files %s\n",cli_errstr(cli),mask);
+       if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
+               d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       if (!cli_unlink_full(targetcli, targetname, attribute)) {
+               d_printf("%s deleting remote files %s\n",cli_errstr(targetcli),targetname);
        }
        return 0;
 }
 
-
 /****************************************************************************
 ****************************************************************************/
 
@@ -1779,6 +1784,146 @@ static int cmd_open(void)
        return 0;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static int cmd_posix_open(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+       mode_t mode;
+       int fnum;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_open <filename> 0<mode>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_open <filename> 0<mode>\n");
+               return 1;
+       }
+       mode = (mode_t)strtol(buf, (char **)NULL, 8);
+
+       if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
+               d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode);
+       if (fnum == -1) {
+               fnum = cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode);
+               if (fnum != -1) {
+                       d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
+               } else {
+                       d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+               }
+       } else {
+               d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
+       }
+
+       return 0;
+}
+
+static int cmd_posix_mkdir(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+       mode_t mode;
+       int fnum;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_mkdir <filename> 0<mode>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_mkdir <filename> 0<mode>\n");
+               return 1;
+       }
+       mode = (mode_t)strtol(buf, (char **)NULL, 8);
+
+       if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
+               d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+
+       fnum = cli_posix_mkdir(targetcli, targetname, mode);
+       if (fnum == -1) {
+               d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
+       } else {
+               d_printf("posix_mkdir created directory %s\n", targetname);
+       }
+
+       return 0;
+}
+
+static int cmd_posix_unlink(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_unlink <filename>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+
+       if (!cli_resolve_path( "", cli, mask, &targetcli, targetname )) {
+               d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       if (!cli_posix_unlink(targetcli, targetname)) {
+               d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
+       } else {
+               d_printf("posix_unlink deleted file %s\n", targetname);
+       }
+
+       return 0;
+}
+
+static int cmd_posix_rmdir(void)
+{
+       pstring mask;
+       pstring buf;
+       struct cli_state *targetcli;
+       pstring targetname;
+
+       pstrcpy(mask,cur_dir);
+       
+       if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
+               d_printf("posix_rmdir <filename>\n");
+               return 1;
+       }
+       pstrcat(mask,buf);
+
+       if (!cli_resolve_path( "", cli, mask, &targetcli, targetname)) {
+               d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
+               return 1;
+       }
+       
+       if (!cli_posix_rmdir(targetcli, targetname)) {
+               d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
+       } else {
+               d_printf("posix_rmdir deleted directory %s\n", targetname);
+       }
+
+       return 0;
+}
+
 static int cmd_close(void)
 {
        fstring buf;
@@ -1829,6 +1974,9 @@ static int cmd_posix(void)
         if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
                pstrcat(caps, "pathnames ");
        }
+        if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
+               pstrcat(caps, "posix_path_operations ");
+       }
 
        if (strlen(caps) > 0 && caps[strlen(caps)-1] == ' ') {
                caps[strlen(caps)-1] = '\0';
@@ -2013,6 +2161,8 @@ static int cmd_symlink(void)
 {
        pstring oldname,newname;
        pstring buf,buf2;
+       struct cli_state *targetcli;
+       pstring targetname;
   
        if (!SERVER_HAS_UNIX_CIFS(cli)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
@@ -2030,9 +2180,14 @@ static int cmd_symlink(void)
        pstrcpy(oldname,buf);
        pstrcat(newname,buf2);
 
-       if (!cli_unix_symlink(cli, oldname, newname)) {
+       if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
+               d_printf("link %s: %s\n", oldname, cli_errstr(cli));
+               return 1;
+       }
+
+       if (!cli_unix_symlink(targetcli, targetname, newname)) {
                d_printf("%s symlinking files (%s -> %s)\n",
-                       cli_errstr(cli), newname, oldname);
+                       cli_errstr(targetcli), newname, targetname);
                return 1;
        } 
 
@@ -2230,7 +2385,6 @@ static int cmd_getfacl(void)
                return 1;
        }
 
-
        if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
                d_printf("%s getfacl doing a stat on file %s\n",
                        cli_errstr(targetcli), src);
@@ -2415,7 +2569,7 @@ static int cmd_stat(void)
 
        lt = localtime(&sbuf.st_atime);
        if (lt) {
-               strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
+               strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
        } else {
                fstrcpy(mode_str, "unknown");
        }
@@ -2423,7 +2577,7 @@ static int cmd_stat(void)
 
        lt = localtime(&sbuf.st_mtime);
        if (lt) {
-               strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
+               strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
        } else {
                fstrcpy(mode_str, "unknown");
        }
@@ -2431,7 +2585,7 @@ static int cmd_stat(void)
 
        lt = localtime(&sbuf.st_ctime);
        if (lt) {
-               strftime(mode_str, sizeof(mode_str), "%F %T %z", lt);
+               strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
        } else {
                fstrcpy(mode_str, "unknown");
        }
@@ -2472,7 +2626,6 @@ static int cmd_chown(void)
                return 1;
        }
 
-
        if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
                d_printf("Server doesn't support UNIX CIFS calls.\n");
                return 1;
@@ -2495,6 +2648,8 @@ static int cmd_rename(void)
 {
        pstring src,dest;
        pstring buf,buf2;
+       struct cli_state *targetcli;
+       pstring targetname;
   
        pstrcpy(src,cur_dir);
        pstrcpy(dest,cur_dir);
@@ -2508,8 +2663,13 @@ static int cmd_rename(void)
        pstrcat(src,buf);
        pstrcat(dest,buf2);
 
-       if (!cli_rename(cli, src, dest)) {
-               d_printf("%s renaming files\n",cli_errstr(cli));
+       if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
+               d_printf("chown %s: %s\n", src, cli_errstr(cli));
+               return 1;
+       }
+
+       if (!cli_rename(targetcli, targetname, dest)) {
+               d_printf("%s renaming files\n",cli_errstr(targetcli));
                return 1;
        }
        
@@ -2602,7 +2762,7 @@ static int cmd_newer(void)
        if (ok && (sys_stat(buf,&sbuf) == 0)) {
                newer_than = sbuf.st_mtime;
                DEBUG(1,("Getting files newer than %s",
-                        time_to_asc(&newer_than)));
+                        time_to_asc(newer_than)));
        } else {
                newer_than = 0;
        }
@@ -2738,7 +2898,7 @@ static int cmd_reget(void)
                return 1;
        }
        pstrcpy(local_name, p);
-       dos_clean_name(remote_name);
+       clean_name(remote_name);
        
        next_token_nr(NULL, local_name, NULL, sizeof(local_name));
        
@@ -2776,7 +2936,7 @@ static int cmd_reput(void)
        else
                pstrcat(remote_name, local_name);
        
-       dos_clean_name(remote_name);
+       clean_name(remote_name);
 
        return do_put(remote_name, local_name, True);
 }
@@ -3067,6 +3227,10 @@ static struct
   {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
   {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
   {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
+  {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
+  {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},  
   {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
index f228db119981f62b7cb981b39759d8f47a8a9130..7bbb9fc58bf68554bf7ec637f57ed38b164da6f0 100644 (file)
@@ -652,7 +652,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
 
        fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE);
 
-       dos_clean_name(rname);
+       clean_name(rname);
 
        if (fnum == -1) {
                DEBUG(0,("%s opening remote file %s (%s)\n",
@@ -1650,7 +1650,7 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
                                        if (sys_stat(argv[Optind], &stbuf) == 0) {
                                                newer_than = stbuf.st_mtime;
                                                DEBUG(1,("Getting files newer than %s",
-                                                       time_to_asc(&newer_than)));
+                                                       time_to_asc(newer_than)));
                                                newOptind++;
                                                Optind++;
                                        } else {
index 076001ccc076ff22e9cb7e7b0b93a69b2f48ef72..7e4c27c820b8368d12b03988dfc81fc0240d6cd0 100755 (executable)
 #define MS_MOVE 8192 
 #endif 
 
+#ifndef MS_BIND
+#define MS_BIND 4096
+#endif
+
 #define CONST_DISCARD(type, ptr)      ((type) ((void *) (ptr)))
 
 const char *thisprogram;
index b7042f99cb2a5a8dc6389addeb133548a06397fc..2063418a91657be8d46a8b8b4547decb5b1ca5c5 100644 (file)
@@ -368,7 +368,7 @@ static int do_cd(char *newdir)
        all_string_sub(cur_dir, "/./", "/", 0);
        
        /* Format the directory in a libmsmbclient friendly way */
-       unix_clean_name(cur_dir);
+       clean_name(cur_dir);
        all_string_sub(cur_dir, "/./", "/", 0);
        pstrcpy(targetpath, "smb:");
        pstrcat(targetpath, service);
@@ -445,7 +445,7 @@ static void display_finfo(file_info *finfo)
                         finfo->name,
                         attrib_string(finfo->mode),
                         (double)finfo->size,
-                        time_to_asc(&t));
+                        time_to_asc(t));
                dir_total += finfo->size;
        }
 }
@@ -458,7 +458,7 @@ static void display_stat(char *name, struct stat *st)
 {
        time_t t = st->st_mtime;
        pstring time_str;
-       pstrcpy(time_str, time_to_asc(&t));
+       pstrcpy(time_str, time_to_asc(t));
        time_str[strlen(time_str)-1] = 0;
        d_printf("> %-30s", name);
        d_printf("%10.10s %8.0f  %s\n", *mode_t_string(st->st_mode), (double)st->st_size, time_str);
@@ -1130,7 +1130,7 @@ static int cmd_more(void)
                unlink(lname);
                return 1;
        }
-       dos_clean_name(rname);
+       clean_name(rname);
 
        rc = do_get(rname, lname, False);
 
@@ -2561,7 +2561,7 @@ static int cmd_newer(void)
        if (ok && (sys_stat(buf,&sbuf) == 0)) {
                newer_than = sbuf.st_mtime;
                DEBUG(1,("Getting files newer than %s",
-                        time_to_asc(&newer_than)));
+                        time_to_asc(newer_than)));
        } else {
                newer_than = 0;
        }
@@ -2678,7 +2678,7 @@ static int cmd_reget(void)
                return 1;
        }
        pstrcpy(local_name, p);
-       dos_clean_name(remote_name);
+       clean_name(remote_name);
        
        next_token_nr(NULL, local_name, NULL, sizeof(local_name));
        
@@ -2716,7 +2716,7 @@ static int cmd_reput(void)
        else
                pstrcat(remote_name, local_name);
        
-       dos_clean_name(remote_name);
+       clean_name(remote_name);
 
        return do_put(remote_name, local_name, True);
 }
index f54c9bd29828ae1822252009c2d336cb4eb3e701..13152f39b249128eca93c76137ffc145dc9ae18a 100644 (file)
@@ -299,6 +299,7 @@ AC_SUBST(PAM_MODULES)
 AC_SUBST(INSTALL_PAM_MODULES)
 AC_SUBST(UNINSTALL_PAM_MODULES)
 AC_SUBST(EXTRA_BIN_PROGS)
+AC_SUBST(SMBMOUNT_PROGS)
 AC_SUBST(CIFSMOUNT_PROGS)
 AC_SUBST(INSTALL_CIFSMOUNT)
 AC_SUBST(UNINSTALL_CIFSMOUNT)
@@ -2966,6 +2967,23 @@ if test x"$samba_cv_HAVE_STAT_ST_BLKSIZE" = x"yes"; then
     AC_DEFINE(HAVE_STAT_ST_BLKSIZE,1,[Whether the stat struct has a st_blksize property])
 fi
 
+AC_CACHE_CHECK([for st_flags in struct stat],
+       samba_cv_HAVE_STAT_ST_FLAGS,
+       [
+           AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>],
+           [struct stat st;  st.st_flags = 0;],
+           samba_cv_HAVE_STAT_ST_FLAGS=yes,
+           samba_cv_HAVE_STAT_ST_FLAGS=no,
+           samba_cv_HAVE_STAT_ST_FLAGS=cross)
+       ])
+
+if test x"$samba_cv_HAVE_STAT_ST_FLAGS" = x"yes"; then
+    AC_DEFINE(HAVE_STAT_ST_FLAGS, 1,
+               [Whether the stat struct has a st_flags member])
+fi
+
 case "$host_os" in
 *linux*)
 AC_CACHE_CHECK([for broken RedHat 7.2 system header files],samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS,[
@@ -3413,6 +3431,7 @@ if test x"$with_ads_support" != x"no"; then
     CPPFLAGS=$ac_save_CPPFLAGS
     LDFLAGS=$ac_save_LDFLAGS
   fi
+  AC_CHECK_HEADERS(krb5/locate_plugin.h)
 fi
 
 # Now we have determined whether we really want ADS support
@@ -3832,6 +3851,20 @@ if test x"$with_ads_support" != x"no"; then
                [Whether the type krb5_addresses type exists])
   fi
 
+  AC_CACHE_CHECK([whether krb5_mk_error takes 3 arguments MIT or 9 Heimdal],
+               samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE, [
+    AC_TRY_COMPILE([#include <krb5.h>],
+    [
+    krb5_mk_error(0,0,0);],
+    samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE=yes,
+    samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE=no)])
+
+  if test x"$samba_cv_HAVE_SHORT_KRB5_MK_ERROR_INTERFACE" = x"yes"; then
+    AC_DEFINE(HAVE_SHORT_KRB5_MK_ERROR_INTERFACE,1,
+              [whether krb5_mk_error takes 3 arguments MIT or 9 Heimdal])
+  fi
+
+
   #
   #
   # Now the decisions whether we can support krb5
@@ -4017,7 +4050,7 @@ AC_ARG_WITH(smbmount,
        *linux*)
                AC_MSG_RESULT(yes)
                AC_DEFINE(WITH_SMBMOUNT,1,[Whether to build smbmount])
-               EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/smbmount bin/smbmnt bin/smbumount"
+               SMBMOUNT_PROGS="bin/smbmount bin/smbmnt bin/smbumount"
                ;;
        *)
                AC_MSG_ERROR(not on a linux system!)
@@ -5571,6 +5604,8 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
 WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
 NSSSONAMEVERSIONSUFFIX=""
 
+SMB_KRB5_LOCATOR="bin/smb_krb5_locator.$SHLIBEXT"
+
 case "$host_os" in
        *linux*)
                NSSSONAMEVERSIONSUFFIX=".2"
@@ -5640,6 +5675,8 @@ AC_SUBST(WINBIND_NSS_EXTRA_OBJS)
 AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
 AC_SUBST(NSSSONAMEVERSIONSUFFIX)
 
+AC_SUBST(SMB_KRB5_LOCATOR)
+
 # Check the setting of --with-winbind
 
 AC_ARG_WITH(winbind,
index dc266995c6283be3ccb343cf8f8df06154e2629e..aa8a647947023f12b490c2c094ca68898fa1bcc7 100644 (file)
  * These definitions depend on smb.h
  */
 
-typedef struct file_info
-{
-       SMB_BIG_UINT size;
-       uint16 mode;
-       uid_t uid;
-       gid_t gid;
-       /* these times are normally kept in GMT */
-       struct timespec mtime_ts;
-       struct timespec atime_ts;
-       struct timespec ctime_ts;
-       pstring name;
-       pstring dir;
-       char short_name[13*3]; /* the *3 is to cope with multi-byte */
-} file_info;
-
 struct print_job_info
 {
        uint16 id;
@@ -173,6 +158,21 @@ struct cli_state {
        BOOL case_sensitive; /* False by default. */
 };
 
+typedef struct file_info {
+       struct cli_state *cli;
+       SMB_BIG_UINT size;
+       uint16 mode;
+       uid_t uid;
+       gid_t gid;
+       /* these times are normally kept in GMT */
+       struct timespec mtime_ts;
+       struct timespec atime_ts;
+       struct timespec ctime_ts;
+       pstring name;
+       pstring dir;
+       char short_name[13*3]; /* the *3 is to cope with multi-byte */
+} file_info;
+
 #define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001
 #define CLI_FULL_CONNECTION_USE_KERBEROS 0x0002
 #define CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK 0x0004
index 4e3a85ff73f8adb10e9f67905ed7f330983d66ff..3c3978a5b9fa2797e7baf5b73eeb1dbffbe64937 100644 (file)
 #define WERR_SERVICE_NEVER_STARTED W_ERROR(1077)
 #define WERR_MACHINE_LOCKED W_ERROR(1271)
 #define WERR_NO_LOGON_SERVERS W_ERROR(1311)
+#define WERR_LOGON_FAILURE W_ERROR(1326)
 #define WERR_NO_SUCH_DOMAIN W_ERROR(1355)
 #define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338)
 #define WERR_TIME_SKEW W_ERROR(1398)
index 34b9c36c8ac1855a96d2ddd7016cfb367b54f329..bdd92f219eec5cf170ea8b487b80e06e68e0e0ae 100644 (file)
@@ -1181,6 +1181,10 @@ krb5_error_code handle_krberror_packet(krb5_context context,
                                          krb5_data *packet);
 void krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt);
 krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt);
+krb5_error_code smb_krb5_mk_error(krb5_context context,
+                                       krb5_error_code error_code,
+                                       const krb5_principal server,
+                                       krb5_data *reply);
 #endif /* HAVE_KRB5 */
 
 
index 4e3487de0f45ef0bec6c84c3d53cefa690f5a89b..05cfe4e102f52732a942e7b99ce418ad19c82ac3 100644 (file)
@@ -51,7 +51,7 @@ struct referral {
 };
 
 struct junction_map {
-       pstring service_name;
+       fstring service_name;
        pstring volume_name;
        pstring comment;
        int referral_count;
@@ -59,31 +59,12 @@ struct junction_map {
 };
 
 struct dfs_path {
-       pstring hostname;
-       pstring servicename;
+       fstring hostname;
+       fstring servicename;
        pstring reqpath;
+       BOOL posix_path;
 };
 
-#define RESOLVE_DFSPATH(name, conn, inbuf, outbuf)             \
-{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) &&         \
-      lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&          \
-      dfs_redirect(name, conn, False))                         \
-             return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED,     \
-                              ERRSRV, ERRbadpath);; }          
-
-#define RESOLVE_DFSPATH_STATUS(name, conn, inbuf, outbuf)              \
-{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) &&         \
-      lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&          \
-      dfs_redirect(name, conn, False))                         \
-             return NT_STATUS_PATH_NOT_COVERED;; }             
-
-#define RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf)        \
-{ if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) &&         \
-      lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) &&          \
-      dfs_redirect(name,conn, True))                           \
-             return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED,     \
-                              ERRSRV, ERRbadpath);; }          
-
 #define init_dfsroot(conn, inbuf, outbuf)                      \
 { if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {          \
         DEBUG(2,("Serving %s as a Dfs root\n",                         \
index 5bd64ae7be39cc83f8558fd1a4b754db4743a7bd..c2dde7d4785f82458f5ce20e03702f93b3ebc51b 100644 (file)
@@ -386,18 +386,13 @@ typedef struct {
 #define NE_HEADER_MAJOR_VER_OFFSET      63
 
 /* Portable Executable format */
-#define PE_HEADER_SIZE                  248
+#define PE_HEADER_SIZE                  24
 #define PE_HEADER_SIGNATURE_OFFSET      0
 #define PE_HEADER_SIGNATURE             0x00004550
 #define PE_HEADER_MACHINE_OFFSET        4
 #define PE_HEADER_MACHINE_I386          0x14c
 #define PE_HEADER_NUMBER_OF_SECTIONS    6
-#define PE_HEADER_MAJOR_OS_VER_OFFSET   64
-#define PE_HEADER_MINOR_OS_VER_OFFSET   66
-#define PE_HEADER_MAJOR_IMG_VER_OFFSET  68
-#define PE_HEADER_MINOR_IMG_VER_OFFSET  70
-#define PE_HEADER_MAJOR_SS_VER_OFFSET   72
-#define PE_HEADER_MINOR_SS_VER_OFFSET   74
+#define PE_HEADER_OPTIONAL_HEADER_SIZE  20
 #define PE_HEADER_SECT_HEADER_SIZE      40
 #define PE_HEADER_SECT_NAME_OFFSET      0
 #define PE_HEADER_SECT_SIZE_DATA_OFFSET 16
index 9e65052f84987b59adbf77acafd1a76b55c05c6c..6bfddcef01f713f9146d17ab4329920f09b751f7 100644 (file)
@@ -195,6 +195,7 @@ typedef struct standard_mapping {
 
 /* Combinations of standard masks. */
 #define STANDARD_RIGHTS_ALL_ACCESS     STD_RIGHT_ALL_ACCESS /* 0x001f0000 */
+#define STANDARD_RIGHTS_MODIFY_ACCESS  STD_RIGHT_READ_CONTROL_ACCESS /* 0x00020000 */
 #define STANDARD_RIGHTS_EXECUTE_ACCESS STD_RIGHT_READ_CONTROL_ACCESS /* 0x00020000 */
 #define STANDARD_RIGHTS_READ_ACCESS    STD_RIGHT_READ_CONTROL_ACCESS /* 0x00020000 */
 #define STANDARD_RIGHTS_WRITE_ACCESS \
@@ -243,10 +244,23 @@ typedef struct standard_mapping {
 
 #define GENERIC_RIGHTS_FILE_EXECUTE \
                (STANDARD_RIGHTS_EXECUTE_ACCESS | \
+               STD_RIGHT_SYNCHRONIZE_ACCESS    | \
                SA_RIGHT_FILE_READ_ATTRIBUTES   | \
                SA_RIGHT_FILE_EXECUTE)            
 
-               
+#define GENERIC_RIGHTS_FILE_MODIFY \
+               (STANDARD_RIGHTS_MODIFY_ACCESS  | \
+               STD_RIGHT_SYNCHRONIZE_ACCESS    | \
+               STD_RIGHT_DELETE_ACCESS         | \
+               SA_RIGHT_FILE_WRITE_ATTRIBUTES  | \
+               SA_RIGHT_FILE_READ_ATTRIBUTES   | \
+               SA_RIGHT_FILE_EXECUTE           | \
+               SA_RIGHT_FILE_WRITE_EA          | \
+               SA_RIGHT_FILE_READ_EA           | \
+               SA_RIGHT_FILE_APPEND_DATA       | \
+               SA_RIGHT_FILE_WRITE_DATA        | \
+               SA_RIGHT_FILE_READ_DATA)
+
 /* SAM server specific access rights */
 
 #define SA_RIGHT_SAM_CONNECT_SERVER    0x00000001
index 5d32d65c3df895a6301d1380471ca4b6b724991f..62acce580506c9a5bb628d00c9920570dc5bd9f3 100644 (file)
@@ -5,6 +5,8 @@
    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
    Copyright (C) Paul Ashton 1997
    Copyright (C) Nigel Williams 2001
+   Copyright (C) Gerald (Jerry) Carter 2006.
+
    
    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
@@ -72,128 +74,84 @@ typedef struct net_srv_disk_enum {
        WERROR status;               /* return status */
 } SRV_Q_NET_DISK_ENUM, SRV_R_NET_DISK_ENUM;
 
-typedef struct net_name_validate {
-       uint32 ptr_srv_name;
-       UNISTR2 uni_srv_name;
-       UNISTR2 uni_name; /*name to validate*/
+/***************************/
+
+typedef struct  {
+       UNISTR2 *servername;
+       UNISTR2 sharename;
        uint32 type;
        uint32 flags;
        WERROR status;
-} SRV_Q_NET_NAME_VALIDATE, SRV_R_NET_NAME_VALIDATE;
-
-/* SESS_INFO_0 (pointers to level 0 session info strings) */
-typedef struct ptr_sess_info0
-{
-       uint32 ptr_name; /* pointer to name. */
-
-} SESS_INFO_0;
+} SRV_Q_NET_NAME_VALIDATE;
 
-/* SESS_INFO_0_STR (level 0 session info strings) */
-typedef struct str_sess_info0
-{
-       UNISTR2 uni_name; /* unicode string of name */
+typedef struct  {
+       WERROR status;
+} SRV_R_NET_NAME_VALIDATE;
 
-} SESS_INFO_0_STR;
+/***************************/
 
 /* oops - this is going to take up a *massive* amount of stack. */
 /* the UNISTR2s already have 1024 uint16 chars in them... */
-#define MAX_SESS_ENTRIES 32
 
-/* SRV_SESS_INFO_0 */
-typedef struct srv_sess_info_0_info
-{
-       uint32 num_entries_read;                     /* EntriesRead */
-       uint32 ptr_sess_info;                       /* Buffer */
-       uint32 num_entries_read2;                    /* EntriesRead */
+#define MAX_SESS_ENTRIES 32
 
-       SESS_INFO_0     info_0    [MAX_SESS_ENTRIES]; /* session entry pointers */
-       SESS_INFO_0_STR info_0_str[MAX_SESS_ENTRIES]; /* session entry strings */
+typedef struct {
+       UNISTR2 *sharename;
+} SESS_INFO_0;
 
+typedef struct {
+       uint32 num_entries_read;
+       uint32 ptr_sess_info;
+       uint32 num_entries_read2;
+       SESS_INFO_0 info_0[MAX_SESS_ENTRIES];
 } SRV_SESS_INFO_0;
 
-/* SESS_INFO_1 (pointers to level 1 session info strings) */
-typedef struct ptr_sess_info1
-{
-       uint32 ptr_name; /* pointer to name. */
-       uint32 ptr_user; /* pointer to user name. */
-
+typedef struct {
+       UNISTR2 *sharename;
+       UNISTR2 *username;
        uint32 num_opens;
        uint32 open_time;
        uint32 idle_time;
        uint32 user_flags;
-
 } SESS_INFO_1;
 
-/* SESS_INFO_1_STR (level 1 session info strings) */
-typedef struct str_sess_info1
-{
-       UNISTR2 uni_name; /* unicode string of name */
-       UNISTR2 uni_user; /* unicode string of user */
-
-} SESS_INFO_1_STR;
-
-/* SRV_SESS_INFO_1 */
-typedef struct srv_sess_info_1_info
-{
-       uint32 num_entries_read;                     /* EntriesRead */
-       uint32 ptr_sess_info;                       /* Buffer */
-       uint32 num_entries_read2;                    /* EntriesRead */
-
-       SESS_INFO_1     info_1    [MAX_SESS_ENTRIES]; /* session entry pointers */
-       SESS_INFO_1_STR info_1_str[MAX_SESS_ENTRIES]; /* session entry strings */
-
+typedef struct {
+       uint32 num_entries_read;
+       uint32 ptr_sess_info;
+       uint32 num_entries_read2;
+       SESS_INFO_1 info_1[MAX_SESS_ENTRIES];
 } SRV_SESS_INFO_1;
 
-/* SRV_SESS_INFO_CTR */
-typedef struct srv_sess_info_ctr_info
-{
-       uint32 switch_value;         /* switch value */
-       uint32 ptr_sess_ctr;       /* pointer to sess info union */
-       union
-    {
-               SRV_SESS_INFO_0 info0; /* session info level 0 */
-               SRV_SESS_INFO_1 info1; /* session info level 1 */
-
-    } sess;
+typedef struct {
+       uint32 switch_value;
+       uint32 ptr_sess_ctr;
+       union {
+               SRV_SESS_INFO_0 info0; 
+               SRV_SESS_INFO_1 info1; 
+       } sess;
 
 } SRV_SESS_INFO_CTR;
 
-
-/* SRV_Q_NET_SESS_ENUM */
-typedef struct q_net_sess_enum_info
-{
-       uint32 ptr_srv_name;         /* pointer (to server name?) */
-       UNISTR2 uni_srv_name;        /* server name */
-
-       uint32 ptr_qual_name;         /* pointer (to qualifier name) */
-       UNISTR2 uni_qual_name;        /* qualifier name "\\qualifier" */
-
-       uint32 ptr_user_name;         /* pointer (to user name */
-       UNISTR2 uni_user_name;        /* user name */
-
-       uint32 sess_level;          /* session level */
-
+typedef struct {
+       UNISTR2 *servername;
+       UNISTR2 *qualifier;
+       UNISTR2 *username;
+       uint32 sess_level;
        SRV_SESS_INFO_CTR *ctr;
-
-       uint32 preferred_len;        /* preferred maximum length (0xffff ffff) */
+       uint32 preferred_len;
        ENUM_HND enum_hnd;
-
 } SRV_Q_NET_SESS_ENUM;
 
-/* SRV_R_NET_SESS_ENUM */
-typedef struct r_net_sess_enum_info
-{
-       uint32 sess_level;          /* share level */
-
+typedef struct {
+       uint32 sess_level; 
        SRV_SESS_INFO_CTR *ctr;
-
-       uint32 total_entries;                    /* total number of entries */
+       uint32 total_entries;
        ENUM_HND enum_hnd;
-
-       WERROR status;               /* return status */
-
+       WERROR status;
 } SRV_R_NET_SESS_ENUM;
 
+/***************************/
+
 /* SRV_Q_NET_SESS_DEL */
 typedef struct q_net_sess_del
 {
@@ -685,104 +643,47 @@ typedef struct r_net_share_del
 
 } SRV_R_NET_SHARE_DEL;
 
-/* FILE_INFO_3 (level 3 file info strings) */
-typedef struct file_info3_info
-{
+/***************************/
+
+typedef struct {
        uint32 id;            /* file index */
        uint32 perms;         /* file permissions. don't know what format */
        uint32 num_locks;     /* file locks */
-       uint32 ptr_path_name; /* file name */
-       uint32 ptr_user_name; /* file owner */
-
+       UNISTR2 *path;        /* file name */
+       UNISTR2 *user;        /* file owner */
 } FILE_INFO_3;
 
-/* FILE_INFO_3_STR (level 3 file info strings) */
-typedef struct str_file_info3_info
-{
-       UNISTR2 uni_path_name; /* unicode string of file name */
-       UNISTR2 uni_user_name; /* unicode string of file owner. */
-
-} FILE_INFO_3_STR;
-
-/* SRV_FILE_INFO_3 */
-typedef struct srv_file_info_3
-{
-       uint32 num_entries_read;                     /* EntriesRead */
-       uint32 ptr_file_info;                        /* Buffer */
-
-       uint32 num_entries_read2;                    /* EntriesRead */
-       FILE_INFO_3     info_3;     /* file entry details */
-       FILE_INFO_3_STR info_3_str; /* file entry strings */
-} SRV_FILE_INFO_3;
-
-/* SRV_FILE_INFO_CTR */
-typedef struct srv_file_info_3_info
-{
-       uint32 switch_value;         /* switch value */
+typedef struct {
+       uint32 level;                /* switch value */
        uint32 ptr_file_info;        /* pointer to file info union */
 
        uint32 num_entries;
        uint32 ptr_entries;
        uint32 num_entries2;
-       union
-       {
-               SRV_FILE_INFO_3 *info3;
+       union {
+               FILE_INFO_3 *info3;
        } file;
 
 } SRV_FILE_INFO_CTR;
 
-
-/* SRV_Q_NET_FILE_ENUM */
-typedef struct q_net_file_enum_info
-{
-       uint32 ptr_srv_name;         /* pointer (to server name?) */
-       UNISTR2 uni_srv_name;        /* server name */
-
-       uint32 ptr_qual_name;         /* pointer (to qualifier name) */
-       UNISTR2 uni_qual_name;        /* qualifier name "\\qualifier" */
-
-       uint32 ptr_user_name;         /* pointer (to user name) */
-       UNISTR2 uni_user_name;        /* user name */
-
-       uint32 file_level;          /* file level */
-
+typedef struct {
+       UNISTR2 *servername;
+       UNISTR2 *qualifier;
+       UNISTR2 *username;
+       uint32 level;
        SRV_FILE_INFO_CTR ctr;
-
-       uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
+       uint32 preferred_len;     /* preferred maximum length (0xffff ffff) */
        ENUM_HND enum_hnd;
-
 } SRV_Q_NET_FILE_ENUM;
 
-
-/* SRV_R_NET_FILE_ENUM */
-typedef struct r_net_file_enum_info
-{
-       uint32 file_level;          /* file level */
-
+typedef struct {
+       uint32 level;   
        SRV_FILE_INFO_CTR ctr;
-
-       uint32 total_entries;                    /* total number of files */
+       uint32 total_entries;
        ENUM_HND enum_hnd;
-
-       WERROR status;        /* return status */
-
+       WERROR status;      
 } SRV_R_NET_FILE_ENUM;
 
-/* SRV_Q_NET_FILE_CLOSE */
-typedef struct q_net_file_close
-{
-       uint32 ptr_srv_name;         /* pointer to server name */
-       UNISTR2 uni_srv_name;        /* server name */
-       
-       uint32 file_id;
-} SRV_Q_NET_FILE_CLOSE;
-
-/* SRV_R_NET_FILE_CLOSE */
-typedef struct r_net_file_close
-{
-       WERROR status;               /* return status */
-} SRV_R_NET_FILE_CLOSE;
-
 /* SRV_INFO_100 */
 typedef struct srv_info_100_info
 {
@@ -967,4 +868,17 @@ typedef struct r_net_file_set_secdesc
        WERROR status;
 } SRV_R_NET_FILE_SET_SECDESC;
 
+/***************************/
+
+typedef struct {
+       UNISTR2 *servername;
+       uint32 file_id;
+} SRV_Q_NET_FILE_CLOSE;
+
+typedef struct {
+       WERROR status;
+} SRV_R_NET_FILE_CLOSE;
+
+/***************************/
+
 #endif /* _RPC_SRVSVC_H */
index 3f0356f2248361f6466c03a9e8d86c024edaa2e8..a8fb39797b2aaf9057ca7b49e388d190b0ba4671 100644 (file)
@@ -500,12 +500,13 @@ typedef struct files_struct {
        uint32 access_mask;             /* NTCreateX access bits (FILE_READ_DATA etc.) */
        uint32 share_access;            /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */
        BOOL pending_modtime_owner;
-       time_t pending_modtime;
-       time_t last_write_time;
+       struct timespec pending_modtime;
+       struct timespec last_write_time;
        int oplock_type;
        int sent_oplock_break;
        struct timed_event *oplock_timeout;
        struct lock_struct last_lock_failure;
+       int current_lock_count; /* Count the number of outstanding locks and pending locks. */
 
        struct share_mode_entry *pending_break_messages;
        int num_pending_break_messages;
index fa7c6e4a5aec18a1d9bc5c7e1f4c3e83fa1683be..cc501739c163ea54ee99f39bbb93063f26a7f657 100644 (file)
@@ -152,9 +152,9 @@ enum profile_stats_values
 #define syscall_getwd_count __profile_stats_value(PR_VALUE_SYSCALL_GETWD, count)
 #define syscall_getwd_time __profile_stats_value(PR_VALUE_SYSCALL_GETWD, time)
 
-       PR_VALUE_SYSCALL_UTIME,
-#define syscall_utime_count __profile_stats_value(PR_VALUE_SYSCALL_UTIME, count)
-#define syscall_utime_time __profile_stats_value(PR_VALUE_SYSCALL_UTIME, time)
+       PR_VALUE_SYSCALL_NTIMES,
+#define syscall_ntimes_count __profile_stats_value(PR_VALUE_SYSCALL_NTIMES, count)
+#define syscall_ntimes_time __profile_stats_value(PR_VALUE_SYSCALL_NTIMES, time)
 
        PR_VALUE_SYSCALL_FTRUNCATE,
 #define syscall_ftruncate_count __profile_stats_value(PR_VALUE_SYSCALL_FTRUNCATE, count)
index 5b9623e3d40525e966551c9bb70f21090ee45062..c7faf4f63f6dbbf3d30a57ad305b07311134019a 100644 (file)
@@ -1,6 +1,8 @@
 /* 
    Unix SMB/CIFS implementation.
    SMB transaction2 handling
+
+   Copyright (C) James Peach 2007
    Copyright (C) Jeremy Allison 1994-2002.
 
    Extensively modified by Andrew Tridgell, 1995
@@ -352,6 +354,7 @@ Byte offset   Type     name                description
 
 #define SMB_QUERY_FILE_UNIX_BASIC      0x200   /* UNIX File Info*/
 #define SMB_SET_FILE_UNIX_BASIC        0x200
+#define SMB_SET_FILE_UNIX_INFO2        0x20B   /* UNIX File Info2 */
 
 #define SMB_MODE_NO_CHANGE                 0xFFFFFFFF     /* file mode value which */
                                               /* means "don't change it" */
@@ -435,6 +438,18 @@ Offset Size         Name
 #define UNIX_EXTRA_MASK                 0007000
 #define UNIX_ALL_MASK                   0007777
 
+/* Flags for chflags (CIFS_UNIX_EXTATTR_CAP capability) and
+ * SMB_QUERY_FILE_UNIX_INFO2.
+ */
+#define EXT_SECURE_DELETE               0x00000001
+#define EXT_ENABLE_UNDELETE             0x00000002
+#define EXT_SYNCHRONOUS                 0x00000004
+#define EXT_IMMUTABLE                  0x00000008
+#define EXT_OPEN_APPEND_ONLY            0x00000010
+#define EXT_DO_NOT_BACKUP               0x00000020
+#define EXT_NO_UPDATE_ATIME             0x00000040
+#define EXT_HIDDEN                     0x00000080
+
 #define SMB_QUERY_FILE_UNIX_LINK       0x201
 #define SMB_SET_FILE_UNIX_LINK         0x201
 #define SMB_SET_FILE_UNIX_HLINK        0x203
@@ -455,8 +470,35 @@ Offset Size         Name
 #define SMB_QUERY_FILE_UNIX_INFO2      0x20B   /* UNIX File Info2 */
 #define SMB_SET_FILE_UNIX_INFO2        0x20B
 
+/*
+SMB_QUERY_FILE_UNIX_INFO2 is SMB_QUERY_FILE_UNIX_BASIC with create
+time and file flags appended. The corresponding info level for
+findfirst/findnext is SMB_FIND_FILE_UNIX_INFO2.
+    Size    Offset  Value
+    ---------------------
+    0      LARGE_INTEGER EndOfFile  File size
+    8      LARGE_INTEGER Blocks     Number of blocks used on disk
+    16     LARGE_INTEGER ChangeTime Attribute change time
+    24     LARGE_INTEGER LastAccessTime           Last access time
+    32     LARGE_INTEGER LastModificationTime     Last modification time
+    40     LARGE_INTEGER Uid        Numeric user id for the owner
+    48     LARGE_INTEGER Gid        Numeric group id of owner
+    56     ULONG Type               Enumeration specifying the file type
+    60     LARGE_INTEGER devmajor   Major device number if type is device
+    68     LARGE_INTEGER devminor   Minor device number if type is device
+    76     LARGE_INTEGER uniqueid   This is a server-assigned unique id
+    84     LARGE_INTEGER permissions           Standard UNIX permissions
+    92     LARGE_INTEGER nlinks                        Number of hard links
+    100    LARGE_INTEGER CreationTime          Create/birth time
+    108    ULONG FileFlags          File flags enumeration
+    112    ULONG FileFlagsMask      Mask of valid flags
+*/
+
 /* Transact 2 Find First levels */
 #define SMB_FIND_FILE_UNIX             0x202
+#define SMB_FIND_FILE_UNIX_INFO2       0x20B /* UNIX File Info2 */
+
+#define SMB_FILE_UNIX_INFO2_SIZE 116
 
 /*
  Info level for TRANS2_QFSINFO - returns version of CIFS UNIX extensions, plus
@@ -564,6 +606,37 @@ number of entries sent will be zero.
 
 */
 
+#define SMB_QUERY_POSIX_WHOAMI     0x202
+
+enum smb_whoami_flags {
+    SMB_WHOAMI_GUEST = 0x1 /* Logged in as (or squashed to) guest */
+};
+
+/* Mask of which WHOAMI bits are valid. This should make it easier for clients
+ * to cope with servers that have different sets of WHOAMI flags (as more get
+ * added).
+ */
+#define SMB_WHOAMI_MASK 0x00000001
+
+/*
+   SMBWhoami - Query the user mapping performed by the server for the
+   connected tree. This is a subcommand of the TRANS2_QFSINFO.
+
+   Returns:
+       4 bytes unsigned -      mapping flags (smb_whoami_flags)
+       4 bytes unsigned -      flags mask
+
+       8 bytes unsigned -      primary UID
+       8 bytes unsigned -      primary GID
+       4 bytes unsigned -      number of supplementary GIDs
+       4 bytes unsigned -      number of SIDs
+       4 bytes unsigned -      SID list byte count
+       4 bytes -               pad / reserved (must be zero)
+
+       8 bytes unsigned[] -    list of GIDs (may be empty)
+       DOM_SID[] -             list of SIDs (may be empty)
+*/
+
 /* The query/set info levels for POSIX ACLs. */
 #define SMB_QUERY_POSIX_ACL  0x204
 #define SMB_SET_POSIX_ACL  0x204
@@ -589,7 +662,7 @@ number of entries sent will be zero.
 
 #define SMB_POSIX_IGNORE_ACE_ENTRIES   0xFFFF
 
-/* Definition of parameter block of SMB_SET_POSIX_LOCK */
+/* Definition of data block of SMB_SET_POSIX_LOCK */
 /*
   [2 bytes] lock_type - 0 = Read, 1 = Write, 2 = Unlock
   [2 bytes] lock_flags - 1 = Wait (only valid for setlock)
@@ -628,11 +701,11 @@ number of entries sent will be zero.
 #define SMB_O_NOFOLLOW                 0x400
 #define SMB_O_DIRECT                   0x800
 
-/* Definition of request parameter block for SMB_POSIX_PATH_OPEN */
+/* Definition of request data block for SMB_POSIX_PATH_OPEN */
 /*
   [4 bytes] flags (as smb_ntcreate_Flags).
-  [4 bytes] open_mode
-  [4 bytes] mode_t             - same encoding as "Standard UNIX permissions" above.
+  [4 bytes] open_mode                  - SMB_O_xxx flags above.
+  [8 bytes] mode_t (permissions)       - same encoding as "Standard UNIX permissions" above in SMB_SET_FILE_UNIX_BASIC.
   [2 bytes] ret_info_level     - optimization. Info level to be returned.
 */
 
@@ -641,8 +714,20 @@ number of entries sent will be zero.
 #define SMB_NO_INFO_LEVEL_RETURNED 0xFFFF
 
 /*
-  [2 bytes] reply info level    - as requested or 0xFFFF if not available.
+  [2 bytes] - flags field. Identical to flags reply for oplock response field in SMBNTCreateX)
+  [2 bytes] - FID returned.
+  [4 bytes] - CreateAction (same as in NTCreateX response).
+  [2 bytes] - reply info level    - as requested or 0xFFFF if not available.
+  [2 bytes] - padding (must be zero)
   [n bytes] - info level reply  - if available.
 */
 
+/* Definition of request data block for SMB_POSIX_UNLINK */
+/*
+  [2 bytes] flags (defined below).
+*/
+
+#define SMB_POSIX_UNLINK_FILE_TARGET 0
+#define SMB_POSIX_UNLINK_DIRECTORY_TARGET 1
+
 #endif
index 2d04a374c4cae96b3fc66c76ea8a6933f496b9db..29e96f6b506b9c20f3194b761b4ad2e88126e54d 100644 (file)
    Also include kernel_flock call - jmcd */
 /* Changed to version 19, kernel change notify has been merged 
    Also included linux setlease call - jmcd */
-#define SMB_VFS_INTERFACE_VERSION 19
+/* Changed to version 20, use ntimes call instead of utime (greater
+ * timestamp resolition. JRA. */
+/* Changed to version21 to add chflags operation -- jpeach */
+#define SMB_VFS_INTERFACE_VERSION 21
 
 
 /* to bug old modules which are trying to compile with the old functions */
@@ -144,7 +147,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_FCHOWN,
        SMB_VFS_OP_CHDIR,
        SMB_VFS_OP_GETWD,
-       SMB_VFS_OP_UTIME,
+       SMB_VFS_OP_NTIMES,
        SMB_VFS_OP_FTRUNCATE,
        SMB_VFS_OP_LOCK,
        SMB_VFS_OP_KERNEL_FLOCK,
@@ -156,6 +159,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_MKNOD,
        SMB_VFS_OP_REALPATH,
        SMB_VFS_OP_NOTIFY_WATCH,
+       SMB_VFS_OP_CHFLAGS,
 
        /* NT ACL operations. */
 
@@ -269,7 +273,7 @@ struct vfs_ops {
                int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid);
                int (*chdir)(struct vfs_handle_struct *handle, const char *path);
                char *(*getwd)(struct vfs_handle_struct *handle, char *buf);
-               int (*utime)(struct vfs_handle_struct *handle, const char *path, struct utimbuf *times);
+               int (*ntimes)(struct vfs_handle_struct *handle, const char *path, const struct timespec ts[2]);
                int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset);
                BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type);
                int (*kernel_flock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 share_mode);
@@ -287,6 +291,7 @@ struct vfs_ops {
                                                          void *private_data,
                                                          struct notify_event *ev),
                                         void *private_data, void *handle_p);
+               int (*chflags)(struct vfs_handle_struct *handle, const char *path, uint flags);
                
                /* NT ACL operations. */
                
@@ -392,7 +397,7 @@ struct vfs_ops {
                struct vfs_handle_struct *fchown;
                struct vfs_handle_struct *chdir;
                struct vfs_handle_struct *getwd;
-               struct vfs_handle_struct *utime;
+               struct vfs_handle_struct *ntimes;
                struct vfs_handle_struct *ftruncate;
                struct vfs_handle_struct *lock;
                struct vfs_handle_struct *kernel_flock;
@@ -404,6 +409,7 @@ struct vfs_ops {
                struct vfs_handle_struct *mknod;
                struct vfs_handle_struct *realpath;
                struct vfs_handle_struct *notify_watch;
+               struct vfs_handle_struct *chflags;
 
                /* NT ACL operations. */
 
index f50da3a02b566a1d1e3adecfff1b1e8c47c731f7..2ff313b42ce664c970c266700d6d3ac1f393dd55 100644 (file)
@@ -67,7 +67,7 @@
 #define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid)))
 #define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (path)))
 #define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (buf)))
-#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (path), (times)))
+#define SMB_VFS_NTIMES(conn, path, ts) ((conn)->vfs.ops.ntimes((conn)->vfs.handles.ntimes, (path), (ts)))
 #define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset)))
 #define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
 #define SMB_VFS_KERNEL_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs.ops.kernel_flock((fsp)->conn->vfs.handles.kernel_flock, (fsp), (fd), (share_mode)))
@@ -79,6 +79,7 @@
 #define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (path), (mode), (dev)))
 #define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (path), (resolved_path)))
 #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)))
 
 /* NT ACL operations. */
 #define SMB_VFS_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
 #define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid)))
 #define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (path)))
 #define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (buf)))
-#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (path), (times)))
+#define SMB_VFS_OPAQUE_NTIMES(conn, path, ts) ((conn)->vfs_opaque.ops.ntimes((conn)->vfs_opaque.handles.ntimes, (path), (ts)))
 #define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset)))
 #define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
 #define SMB_VFS_OPAQUE_FLOCK(fsp, fd, share_mode) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.kernel_flock, (fsp), (fd), (share_mode)))
 #define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (path), (mode), (dev)))
 #define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (path), (resolved_path)))
 #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)))
 
 /* NT ACL operations. */
 #define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
 #define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid)))
 #define SMB_VFS_NEXT_CHDIR(handle, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (path)))
 #define SMB_VFS_NEXT_GETWD(handle, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (buf)))
-#define SMB_VFS_NEXT_UTIME(handle, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (path), (times)))
+#define SMB_VFS_NEXT_NTIMES(handle, path, ts) ((handle)->vfs_next.ops.ntimes((handle)->vfs_next.handles.ntimes, (path), (ts)))
 #define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset)))
 #define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type)))
 #define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, fd, share_mode)((handle)->vfs_next.ops.kernel_flock((handle)->vfs_next.handles.kernel_flock, (fsp), (fd), (share_mode)))
 #define SMB_VFS_NEXT_MKNOD(handle, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (path), (mode), (dev)))
 #define SMB_VFS_NEXT_REALPATH(handle, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (path), (resolved_path)))
 #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)))
 
 /* NT ACL operations. */
 #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc)))
index 5f1416611067c96f1f50187895a63e74b8c9e533..62fda5741c9f9681111dbd696bb443c1707f9b10 100644 (file)
@@ -962,7 +962,7 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
        /* Print the header if timestamps are turned on.  If parameters are
         * not yet loaded, then default to timestamps on.
         */
-       if( lp_timestamp_logs() || !(lp_loaded()) ) {
+       if( lp_timestamp_logs() || lp_debug_prefix_timestamp() || !(lp_loaded()) ) {
                char header_str[200];
 
                header_str[0] = '\0';
@@ -980,9 +980,15 @@ BOOL dbghdr( int level, const char *file, const char *func, int line )
                }
   
                /* Print it all out at once to prevent split syslog output. */
-               (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
+               if( lp_debug_prefix_timestamp() ) {
+                   (void)Debug1( "[%s, %d%s] ",
+                       current_timestring(lp_debug_hires_timestamp()), level,
+                       header_str);
+               } else {
+                   (void)Debug1( "[%s, %d%s] %s:%s(%d)\n",
                        current_timestring(lp_debug_hires_timestamp()), level,
                        header_str, file, func, line );
+               }
        }
 
        errno = old_errno;
index 9d0b966390f57347912e554699e6e91d806f1247..e2c9294b281362bb65ea700844f3938ec7fffa61 100644 (file)
@@ -231,6 +231,18 @@ void load_interfaces(void)
 }
 
 
+void gfree_interfaces(void)
+{
+       while (local_interfaces) {
+               struct interface *iface = local_interfaces;
+               DLIST_REMOVE(local_interfaces, local_interfaces);
+               ZERO_STRUCTPN(iface);
+               SAFE_FREE(iface);
+       }
+
+       SAFE_FREE(probed_ifaces);
+}
+
 /****************************************************************************
 return True if the list of probed interfaces has changed
 ****************************************************************************/
index 26230884341deb1952064b16c7d36dcc9cb7f98c..8907399be4a71ef8908ee80097e792f4dc380f76 100644 (file)
@@ -89,3 +89,47 @@ char *escape_ldap_string_alloc(const char *s)
        *p = '\0';
        return output;
 }
+
+char *escape_rdn_val_string_alloc(const char *s)
+{
+       char *output, *p;
+
+       /* The maximum size of the escaped string can be twice the actual size */
+       output = (char *)SMB_MALLOC(2*strlen(s) + 1);
+
+       if (output == NULL) {
+               return NULL;
+       }
+
+       p = output;
+       
+       while (*s)
+       {
+               switch (*s)
+               {
+               case ',':
+               case '=':
+               case '+':
+               case '<':
+               case '>':
+               case '#':
+               case ';':
+               case '\\':
+               case '\"':
+                       *p++ = '\\';
+                       *p++ = *s;
+                       break;
+               default:
+                       *p = *s;
+                       p++;
+               }
+               
+               s++;
+       }
+       
+       *p = '\0';
+
+       /* resize the string to the actual final size */
+       output = (char *)SMB_REALLOC(output, strlen(output) + 1);
+       return output;
+}
index e0bf86a46cee38fd564638bd5d519ce910e8a8c2..e2c8a6b52fac42f092ee19d6e23d96265228d18b 100644 (file)
@@ -133,6 +133,9 @@ BOOL message_init(void)
                return False;
        }
 
+       /* Activate the per-hashchain freelist */
+       tdb_set_max_dead(tdb, 5);
+
        CatchSignal(SIGUSR1, SIGNAL_CAST sig_usr1);
 
        message_register(MSG_PING, ping_message, NULL);
index aff4eff6f6d0fa6f8c40287112a7c12eb80d7af5..11b27bf98fb44c4fd1d8dbdeeef4977020f31afb 100644 (file)
@@ -39,12 +39,21 @@ static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state
        const char *policy_attr = NULL;
        pstring dn;
        LDAPMod **mods = NULL;
+       char *escape_domain_name;
 
        DEBUG(3,("add_new_domain_account_policies: Adding new account policies for domain\n"));
-       
+
+       escape_domain_name = escape_rdn_val_string_alloc(domain_name);
+       if (!escape_domain_name) {
+               DEBUG(0, ("Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
        pstr_sprintf(dn, "%s=%s,%s", 
                get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
-               domain_name, lp_ldap_suffix());
+               escape_domain_name, lp_ldap_suffix());
+
+       SAFE_FREE(escape_domain_name);
 
        for (i=1; decode_account_policy_name(i) != NULL; i++) {
 
@@ -104,10 +113,20 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
        LDAPMessage *result = NULL;
        int num_result;
        const char **attr_list;
+       char *escape_domain_name;
+
+       /* escape for filter */
+       escape_domain_name = escape_ldap_string_alloc(domain_name);
+       if (!escape_domain_name) {
+               DEBUG(0, ("Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
        slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", 
                  get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
-                 domain_name, LDAP_OBJ_DOMINFO);
+                 escape_domain_name, LDAP_OBJ_DOMINFO);
+
+       SAFE_FREE(escape_domain_name);
 
        attr_list = get_attr_list( NULL, dominfo_attr_list );
        rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
@@ -129,9 +148,18 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
        /* Check if we need to add an entry */
        DEBUG(3,("add_new_domain_info: Adding new domain\n"));
 
+       /* this time escape for DN */
+       escape_domain_name = escape_rdn_val_string_alloc(domain_name);
+       if (!escape_domain_name) {
+               DEBUG(0, ("Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
        pstr_sprintf(dn, "%s=%s,%s",
                     get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
-                    domain_name, lp_ldap_suffix());
+                    escape_domain_name, lp_ldap_suffix());
+
+       SAFE_FREE(escape_domain_name);
 
        /* Free original search */
        ldap_msgfree(result);
@@ -210,11 +238,20 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
        int rc;
        const char **attr_list;
        int count;
+       char *escape_domain_name;
+       
+       escape_domain_name = escape_ldap_string_alloc(domain_name);
+       if (!escape_domain_name) {
+               DEBUG(0, ("Out of memory!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
        pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
                LDAP_OBJ_DOMINFO,
                get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
-               domain_name);
+               escape_domain_name);
+
+       SAFE_FREE(escape_domain_name);
 
        DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter));
 
index 20b31113ecd71a17cd49e6d6d54af11d404eb014..eaebc7190f05492423e38475041b19f75cd7cf01 100644 (file)
  A wrapper for memalign
 ********************************************************************/
 
-voidsys_memalign( size_t align, size_t size )
+void *sys_memalign( size_t align, size_t size )
 {
-#if defined(HAVE_MEMALIGN)
-       return memalign( align, size );
-#elif defined(HAVE_POSIX_MEMALIGN)
-       char *p = NULL;
+#if defined(HAVE_POSIX_MEMALIGN)
+       void *p = NULL;
        int ret = posix_memalign( &p, align, size );
        if ( ret == 0 )
                return p;
                
        return NULL;
+#elif defined(HAVE_MEMALIGN)
+       return memalign( align, size );
 #else
-       DEBUG(0,("memalign functionalaity not available on this platform!\n"));
-       return NULL;
+       /* On *BSD systems memaligns doesn't exist, but memory will
+        * be aligned on allocations of > pagesize. */
+#if defined(SYSCONF_SC_PAGESIZE)
+       size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+#elif defined(HAVE_GETPAGESIZE)
+       size_t pagesize = (size_t)getpagesize();
+#else
+       size_t pagesize = (size_t)-1;
+#endif
+       if (pagesize == (size_t)-1) {
+               DEBUG(0,("memalign functionalaity not available on this platform!\n"));
+               return NULL;
+       }
+       if (size < pagesize) {
+               size = pagesize;
+       }
+       return SMB_MALLOC(size);
 #endif
 }
 
index 403fb0594d42d413cfc72e7860382601dbb982bd..e98f8232abc58fa2beb3c552f40ccf21843cb7cb 100644 (file)
@@ -4,6 +4,7 @@
 
    Copyright (C) Andrew Tridgell               1992-2004
    Copyright (C) Stefan (metze) Metzmacher     2002   
+   Copyright (C) Jeremy Allison                        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
 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
 #endif
 
-/**
+#define NTTIME_INFINITY (NTTIME)0x8000000000000000LL
+
+/***************************************************************************
  External access to time_t_min and time_t_max.
-**/
+****************************************************************************/
+
 time_t get_time_t_max(void)
 {
        return TIME_T_MAX;
 }
 
-/**
-a gettimeofday wrapper
-**/
+/***************************************************************************
+ A gettimeofday wrapper.
+****************************************************************************/
+
 void GetTimeOfDay(struct timeval *tval)
 {
 #ifdef HAVE_GETTIMEOFDAY_TZ
@@ -56,14 +61,6 @@ void GetTimeOfDay(struct timeval *tval)
 #endif
 }
 
-struct timespec convert_time_t_to_timespec(time_t t)
-{
-       struct timespec ts;
-       ts.tv_sec = t;
-       ts.tv_nsec = 0;
-       return ts;
-}
-
 #if (SIZEOF_LONG == 8)
 #define TIME_FIXUP_CONSTANT_INT 11644473600L
 #elif (SIZEOF_LONG_LONG == 8)
@@ -111,10 +108,10 @@ void unix_to_nt_time(NTTIME *nt, time_t t)
        *nt = t2;
 }
 
+/****************************************************************************
+ Check if it's a null unix time.
+****************************************************************************/
 
-/**
-check if it's a null unix time
-**/
 BOOL null_time(time_t t)
 {
        return t == 0 || 
@@ -122,15 +119,26 @@ BOOL null_time(time_t t)
                t == (time_t)-1;
 }
 
+/****************************************************************************
+ Check if it's a null NTTIME.
+****************************************************************************/
 
-/**
-check if it's a null NTTIME
-**/
 BOOL null_nttime(NTTIME t)
 {
        return t == 0 || t == (NTTIME)-1;
 }
 
+/****************************************************************************
+ Check if it's a null timespec.
+****************************************************************************/
+
+BOOL null_timespec(struct timespec ts)
+{
+       return ts.tv_sec == 0 || 
+               ts.tv_sec == (time_t)0xFFFFFFFF || 
+               ts.tv_sec == (time_t)-1;
+}
+
 /*******************************************************************
   create a 16 bit dos packed date
 ********************************************************************/
@@ -547,8 +555,9 @@ NTTIME timeval_to_nttime(const struct timeval *tv)
 }
 
 /*******************************************************************
-yield the difference between *A and *B, in seconds, ignoring leap seconds
+ Yield the difference between *A and *B, in seconds, ignoring leap seconds.
 ********************************************************************/
+
 static int tm_diff(struct tm *a, struct tm *b)
 {
        int ay = a->tm_year + (1900 - 1);
@@ -566,9 +575,10 @@ static int tm_diff(struct tm *a, struct tm *b)
 
 int extra_time_offset=0;
 
-/**
-  return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
- */
+/*******************************************************************
+ Return the UTC offset in seconds west of UTC, or 0 if it cannot be determined.
+********************************************************************/
+
 int get_time_zone(time_t t)
 {
        struct tm *tm = gmtime(&t);
@@ -778,7 +788,7 @@ void put_long_date(char *p, time_t t)
  structure.
 ****************************************************************************/
 
-time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+time_t get_create_time(const SMB_STRUCT_STAT *st,BOOL fake_dirs)
 {
        time_t ret, ret1;
 
@@ -800,7 +810,7 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
        return ret;
 }
 
-struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+struct timespec get_create_timespec(const SMB_STRUCT_STAT *st,BOOL fake_dirs)
 {
        struct timespec ts;
        ts.tv_sec = get_create_time(st, fake_dirs);
@@ -812,7 +822,7 @@ struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
  Get/Set all the possible time fields from a stat struct as a timespec.
 ****************************************************************************/
 
-struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
+struct timespec get_atimespec(const SMB_STRUCT_STAT *pst)
 {
 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
        struct timespec ret;
@@ -852,7 +862,7 @@ void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
 #endif
 }
 
-struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
+struct timespec get_mtimespec(const SMB_STRUCT_STAT *pst)
 {
 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
        struct timespec ret;
@@ -892,7 +902,7 @@ void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
 #endif
 }
 
-struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
+struct timespec get_ctimespec(const SMB_STRUCT_STAT *pst)
 {
 #if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
        struct timespec ret;
@@ -1020,6 +1030,81 @@ time_t convert_timespec_to_time_t(struct timespec ts)
        return ts.tv_sec;
 }
 
+struct timespec convert_time_t_to_timespec(time_t t)
+{
+       struct timespec ts;
+       ts.tv_sec = t;
+       ts.tv_nsec = 0;
+       return ts;
+}
+
+/****************************************************************************
+ Convert a normalized timeval to a timespec.
+****************************************************************************/
+
+struct timespec convert_timeval_to_timespec(const struct timeval tv)
+{
+       struct timespec ts;
+       ts.tv_sec = tv.tv_sec;
+       ts.tv_nsec = tv.tv_usec * 1000;
+       return ts;
+}
+
+/****************************************************************************
+ Convert a normalized timespec to a timeval.
+****************************************************************************/
+
+struct timeval convert_timespec_to_timeval(const struct timespec ts)
+{
+       struct timeval tv;
+       tv.tv_sec = ts.tv_sec;
+       tv.tv_usec = ts.tv_nsec / 1000;
+       return tv;
+}
+
+/****************************************************************************
+ Return a timespec for the current time
+****************************************************************************/
+
+struct timespec timespec_current(void)
+{
+       struct timeval tv;
+       struct timespec ts;
+       GetTimeOfDay(&tv);
+       ts.tv_sec = tv.tv_sec;
+       ts.tv_nsec = tv.tv_sec * 1000;
+       return ts;
+}
+
+/****************************************************************************
+ Return the lesser of two timespecs.
+****************************************************************************/
+
+struct timespec timespec_min(const struct timespec *ts1,
+                          const struct timespec *ts2)
+{
+       if (ts1->tv_sec < ts2->tv_sec) return *ts1;
+       if (ts1->tv_sec > ts2->tv_sec) return *ts2;
+       if (ts1->tv_nsec < ts2->tv_nsec) return *ts1;
+       return *ts2;
+}
+
+/****************************************************************************
+  compare two timespec structures. 
+  Return -1 if ts1 < ts2
+  Return 0 if ts1 == ts2
+  Return 1 if ts1 > ts2
+****************************************************************************/
+
+int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
+{
+       if (ts1->tv_sec  > ts2->tv_sec)  return 1;
+       if (ts1->tv_sec  < ts2->tv_sec)  return -1;
+       if (ts1->tv_nsec > ts2->tv_nsec) return 1;
+       if (ts1->tv_nsec < ts2->tv_nsec) return -1;
+       return 0;
+}
+
 /****************************************************************************
  Interprets an nt time into a unix struct timespec.
  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
@@ -1180,6 +1265,10 @@ time_t nt_time_to_unix_abs(const NTTIME *nt)
                return (time_t)-1;
        }
 
+       if (*nt == NTTIME_INFINITY) {
+               return (time_t)-1;
+       }
+
        /* reverse the time */
        /* it's a negative value, turn it to positive */
        d=~*nt;
@@ -1248,7 +1337,7 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
                
        if (t == (time_t)-1) {
                /* that's what NT uses for infinite */
-               *nt = 0x8000000000000000LL;
+               *nt = NTTIME_INFINITY;
                return;
        }               
 
@@ -1278,10 +1367,10 @@ BOOL null_mtime(time_t mtime)
  and asctime fail.
 ****************************************************************************/
 
-const char *time_to_asc(const time_t *t)
+const char *time_to_asc(const time_t t)
 {
        const char *asct;
-       struct tm *lt = localtime(t);
+       struct tm *lt = localtime(&t);
 
        if (!lt) {
                return "unknown time";
@@ -1306,7 +1395,7 @@ const char *display_time(NTTIME nttime)
        if (nttime==0)
                return "Now";
 
-       if (nttime==0x8000000000000000LL)
+       if (nttime==NTTIME_INFINITY)
                return "Never";
 
        high = 65536;   
@@ -1335,10 +1424,9 @@ BOOL nt_time_is_set(const NTTIME *nt)
                return False;
        }
 
-       if (*nt == 0x8000000000000000LL) {
+       if (*nt == NTTIME_INFINITY) {
                return False;
        }
 
        return True;
 }
-
index 67c9c8d37a71cf56c10fc2c9997c989cfedd2bfb..45d3916ebe684489f92e4825479ce481a159cdb7 100644 (file)
@@ -200,6 +200,7 @@ void gfree_all( void )
        gfree_debugsyms();
        gfree_charcnv();
        gfree_messages();
+       gfree_interfaces();
 
        /* release the talloc null_context memory last */
        talloc_disable_null_tracking();
@@ -579,6 +580,13 @@ void dos_clean_name(char *s)
        /* remove any double slashes */
        all_string_sub(s, "\\\\", "\\", 0);
 
+       /* Remove leading .\\ characters */
+       if(strncmp(s, ".\\", 2) == 0) {
+               trim_string(s, ".\\", NULL);
+               if(*s == 0)
+                       pstrcpy(s,".\\");
+       }
+
        while ((p = strstr_m(s,"\\..\\")) != NULL) {
                pstring s1;
 
@@ -593,7 +601,6 @@ void dos_clean_name(char *s)
        }  
 
        trim_string(s,NULL,"\\..");
-
        all_string_sub(s, "\\.\\", "\\", 0);
 }
 
@@ -631,6 +638,13 @@ void unix_clean_name(char *s)
        }  
 
        trim_string(s,NULL,"/..");
+       all_string_sub(s, "/./", "/", 0);
+}
+
+void clean_name(char *s)
+{
+       dos_clean_name(s);
+       unix_clean_name(s);
 }
 
 /*******************************************************************
@@ -912,17 +926,6 @@ void *malloc_(size_t size)
 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
 }
 
-/****************************************************************************
- Internal malloc wrapper. Externally visible.
-****************************************************************************/
-
-void *memalign_(size_t align, size_t size)
-{
-#undef memalign
-       return memalign(align, size);
-#define memalign(align, s) __ERROR_DONT_USE_MEMALIGN_DIRECTLY
-}
-
 /****************************************************************************
  Internal calloc wrapper. Not externally visible.
 ****************************************************************************/
@@ -974,11 +977,7 @@ void *memalign_array(size_t el_size, size_t align, unsigned int count)
                return NULL;
        }
 
-#if defined(PARANOID_MALLOC_CHECKER)
-       return memalign_(align, el_size*count);
-#else
        return sys_memalign(align, el_size*count);
-#endif
 }
 
 /****************************************************************************
@@ -2093,6 +2092,9 @@ BOOL is_myname_or_ipaddr(const char *s)
 
        /* check for loopback */
 
+       if (strequal(servername, "127.0.0.1")) 
+               return True;
+
        if (strequal(servername, "localhost")) 
                return True;
 
index 798fd4404ee34fc35f595f2ae3be04ca1f24d8af..8324e6761f319e4c97c3aa542765db685826aa30 100644 (file)
@@ -252,6 +252,11 @@ DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
        krb5_init_context( &krb_ctx );
        krb5_parse_name( krb_ctx, targetname, &host_principal );
 
+       /* don't free the principal until after you call
+          gss_release_name() or else you'll get a segv
+          as the krb5_copy_principal() does a structure 
+          copy and not a deep copy.    --jerry*/
+
        input_name.value = &host_principal;
        input_name.length = sizeof( host_principal );
 
@@ -267,8 +272,11 @@ DNS_ERROR dns_negotiate_sec_ctx( const char *target_realm,
 
        err = dns_negotiate_gss_ctx_int(mem_ctx, conn, keyname, 
                                        targ_name, gss_ctx, srv_type );
-
+       
        gss_release_name( &minor, &targ_name );
+
+       /* now we can free the principal */
+
        krb5_free_principal( krb_ctx, host_principal );
        krb5_free_context( krb_ctx );
 
index 72018c620d8ac43dd74be52983fba91cbfdc32e9..3cb98c59c58ff801e737610fc511567fde8c04dc 100644 (file)
@@ -187,8 +187,10 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
 {
        int ret;
        ASN1_DATA data;
-       DATA_BLOB blob;
-       DATA_BLOB os1, os2, os3;
+       DATA_BLOB blob = data_blob(NULL, 0);
+       DATA_BLOB os1 = data_blob(NULL, 0);
+       DATA_BLOB os2 = data_blob(NULL, 0);
+       DATA_BLOB os3 = data_blob(NULL, 0);
        int i1;
        /* half the time of a regular ldap timeout, not less than 3 seconds. */
        unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
@@ -238,6 +240,9 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
 
        if (data.has_error) {
                data_blob_free(&blob);
+               data_blob_free(&os1);
+               data_blob_free(&os2);
+               data_blob_free(&os3);
                asn1_free(&data);
                DEBUG(1,("Failed to parse cldap reply\n"));
                return -1;
index ba1a91656742c67766a813b2583f346d6c9dce5e..0ad225fbebb841e1224f886d63428ed765d059d5 100644 (file)
@@ -55,20 +55,20 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
        
        ret = smb_krb5_parse_name(context, princ_s, &princ);
        if (ret) {
-               DEBUG(1,("ads_keytab_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
+               DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_parse_name(%s) failed (%s)\n", princ_s, error_message(ret)));
                goto out;
        }
 
        /* Seek and delete old keytab entries */
        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
        if (ret != KRB5_KT_END && ret != ENOENT ) {
-               DEBUG(3,("ads_keytab_add_entry: Will try to delete old keytab entries\n"));
+               DEBUG(3,("smb_krb5_kt_add_entry: Will try to delete old keytab entries\n"));
                while(!krb5_kt_next_entry(context, keytab, &kt_entry, &cursor)) {
                        BOOL compare_name_ok = False;
 
                        ret = smb_krb5_unparse_name(context, kt_entry.principal, &ktprinc);
                        if (ret) {
-                               DEBUG(1,("ads_keytab_add_entry: smb_krb5_unparse_name failed (%s)\n",
+                               DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_unparse_name failed (%s)\n",
                                        error_message(ret)));
                                goto out;
                        }
@@ -89,7 +89,7 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
 #endif
 
                        if (!compare_name_ok) {
-                               DEBUG(10,("ads_keytab_add_entry: ignoring keytab entry principal %s, kvno = %d\n",
+                               DEBUG(10,("smb_krb5_kt_add_entry: ignoring keytab entry principal %s, kvno = %d\n",
                                        ktprinc, kt_entry.vno));
                        }
 
@@ -97,39 +97,39 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
 
                        if (compare_name_ok) {
                                if (kt_entry.vno == kvno - 1) {
-                                       DEBUG(5,("ads_keytab_add_entry: Saving previous (kvno %d) entry for principal: %s.\n",
+                                       DEBUG(5,("smb_krb5_kt_add_entry: Saving previous (kvno %d) entry for principal: %s.\n",
                                                kvno - 1, princ_s));
                                } else {
 
-                                       DEBUG(5,("ads_keytab_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
+                                       DEBUG(5,("smb_krb5_kt_add_entry: Found old entry for principal: %s (kvno %d) - trying to remove it.\n",
                                                princ_s, kt_entry.vno));
                                        ret = krb5_kt_end_seq_get(context, keytab, &cursor);
                                        ZERO_STRUCT(cursor);
                                        if (ret) {
-                                               DEBUG(1,("ads_keytab_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
+                                               DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get() failed (%s)\n",
                                                        error_message(ret)));
                                                goto out;
                                        }
                                        ret = krb5_kt_remove_entry(context, keytab, &kt_entry);
                                        if (ret) {
-                                               DEBUG(1,("ads_keytab_add_entry: krb5_kt_remove_entry failed (%s)\n",
+                                               DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
                                                        error_message(ret)));
                                                goto out;
                                        }
 
-                                       DEBUG(5,("ads_keytab_add_entry: removed old entry for principal: %s (kvno %d).\n",
+                                       DEBUG(5,("smb_krb5_kt_add_entry: removed old entry for principal: %s (kvno %d).\n",
                                                princ_s, kt_entry.vno));
 
                                        ret = krb5_kt_start_seq_get(context, keytab, &cursor);
                                        if (ret) {
-                                               DEBUG(1,("ads_keytab_add_entry: krb5_kt_start_seq failed (%s)\n",
+                                               DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_start_seq failed (%s)\n",
                                                        error_message(ret)));
                                                goto out;
                                        }
                                        ret = smb_krb5_kt_free_entry(context, &kt_entry);
                                        ZERO_STRUCT(kt_entry);
                                        if (ret) {
-                                               DEBUG(1,("ads_keytab_add_entry: krb5_kt_remove_entry failed (%s)\n",
+                                               DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_remove_entry failed (%s)\n",
                                                        error_message(ret)));
                                                goto out;
                                        }
@@ -141,7 +141,7 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
                        ret = smb_krb5_kt_free_entry(context, &kt_entry);
                        ZERO_STRUCT(kt_entry);
                        if (ret) {
-                               DEBUG(1,("ads_keytab_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
+                               DEBUG(1,("smb_krb5_kt_add_entry: smb_krb5_kt_free_entry failed (%s)\n", error_message(ret)));
                                goto out;
                        }
                }
@@ -149,7 +149,7 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
                ret = krb5_kt_end_seq_get(context, keytab, &cursor);
                ZERO_STRUCT(cursor);
                if (ret) {
-                       DEBUG(1,("ads_keytab_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
+                       DEBUG(1,("smb_krb5_kt_add_entry: krb5_kt_end_seq_get failed (%s)\n",error_message(ret)));
                        goto out;
                }
        }
@@ -180,13 +180,13 @@ static int smb_krb5_kt_add_entry( krb5_context context, krb5_keytab keytab,
                kt_entry.principal = princ;
                kt_entry.vno       = kvno;
 
-               DEBUG(3,("ads_keytab_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
+               DEBUG(3,("smb_krb5_kt_add_entry: adding keytab entry for (%s) with encryption type (%d) and version (%d)\n",
                        princ_s, enctypes[i], kt_entry.vno));
                ret = krb5_kt_add_entry(context, keytab, &kt_entry);
                krb5_free_keyblock_contents(context, keyp);
                ZERO_STRUCT(kt_entry);
                if (ret) {
-                       DEBUG(1,("ads_keytab_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
+                       DEBUG(1,("smb_krb5_kt_add_entry: adding entry to keytab failed (%s)\n", error_message(ret)));
                        goto out;
                }
        }
index 2c114b1240e6c61d269bf7826c85f9b52249121d..0ec03ef4bf2c54a2d0ac38f895d8bbfbee0ad4b8 100644 (file)
@@ -7,6 +7,7 @@
    Copyright (C) Guenther Deschner 2003, 2005
    Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Jeremy Allison 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
@@ -37,9 +38,12 @@ const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int );
  ads_keytab_add_entry function for details.
 ***********************************************************************************/
 
-static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context,
-                       const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, 
-                       krb5_keyblock **keyblock)
+static BOOL ads_keytab_verify_ticket(krb5_context context,
+                                       krb5_auth_context auth_context,
+                                       const DATA_BLOB *ticket,
+                                       krb5_ticket **pp_tkt,
+                                       krb5_keyblock **keyblock,
+                                       krb5_error_code *perr)
 {
        krb5_error_code ret = 0;
        BOOL auth_ok = False;
@@ -51,6 +55,11 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
        fstring my_name, my_fqdn;
        int i;
        int number_matched_principals = 0;
+       krb5_data packet;
+
+       *pp_tkt = NULL;
+       *keyblock = NULL;
+       *perr = 0;
 
        /* Generate the list of principal names which we expect
         * clients might want to use for authenticating to the file
@@ -103,11 +112,11 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
                        }
 
                        number_matched_principals++;
-                       p_packet->length = ticket->length;
-                       p_packet->data = (char *)ticket->data;
+                       packet.length = ticket->length;
+                       packet.data = (char *)ticket->data;
                        *pp_tkt = NULL;
 
-                       ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet,
+                       ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, &packet,
                                                                      kt_entry.principal, keytab,
                                                                      NULL, pp_tkt, keyblock);
 
@@ -125,7 +134,8 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
                                * entries - Guenther */
                                        
                                if (ret == KRB5KRB_AP_ERR_TKT_NYV || 
-                                   ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+                                   ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
+                                   ret == KRB5KRB_AP_ERR_SKEW) {
                                        break;
                                }
                        } else {
@@ -184,6 +194,7 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
        if (keytab) {
                krb5_kt_close(context, keytab);
        }
+       *perr = ret;
        return auth_ok;
 }
 
@@ -191,32 +202,40 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
  Try to verify a ticket using the secrets.tdb.
 ***********************************************************************************/
 
-static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context,
-                                     krb5_principal host_princ,
-                                     const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt,
-                                     krb5_keyblock **keyblock)
+static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
+                                               krb5_auth_context auth_context,
+                                               krb5_principal host_princ,
+                                               const DATA_BLOB *ticket,
+                                               krb5_ticket **pp_tkt,
+                                               krb5_keyblock **keyblock,
+                                               krb5_error_code *perr)
 {
        krb5_error_code ret = 0;
        BOOL auth_ok = False;
        char *password_s = NULL;
        krb5_data password;
        krb5_enctype enctypes[4] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, 0, 0 };
+       krb5_data packet;
        int i;
 
+       *pp_tkt = NULL;
+       *keyblock = NULL;
+       *perr = 0;
+
 #if defined(ENCTYPE_ARCFOUR_HMAC)
        enctypes[2] = ENCTYPE_ARCFOUR_HMAC;
 #endif
 
-       ZERO_STRUCTP(keyblock);
-
        if (!secrets_init()) {
                DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
+               *perr = KRB5_CONFIG_CANTOPEN;
                return False;
        }
 
        password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
        if (!password_s) {
                DEBUG(1,("ads_secrets_verify_ticket: failed to fetch machine password\n"));
+               *perr = KRB5_LIBOS_CANTREADPWD;
                return False;
        }
 
@@ -225,14 +244,15 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
 
        /* CIFS doesn't use addresses in tickets. This would break NAT. JRA */
 
-       p_packet->length = ticket->length;
-       p_packet->data = (char *)ticket->data;
+       packet.length = ticket->length;
+       packet.data = (char *)ticket->data;
 
        /* We need to setup a auth context with each possible encoding type in turn. */
        for (i=0;enctypes[i];i++) {
                krb5_keyblock *key = NULL;
 
                if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
+                       ret = ENOMEM;
                        goto out;
                }
        
@@ -243,7 +263,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
 
                krb5_auth_con_setuseruserkey(context, auth_context, key);
 
-               if (!(ret = krb5_rd_req(context, &auth_context, p_packet, 
+               if (!(ret = krb5_rd_req(context, &auth_context, &packet, 
                                        NULL,
                                        NULL, NULL, pp_tkt))) {
                        DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
@@ -260,7 +280,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
 
                /* successfully decrypted but ticket is just not valid at the moment */
                if (ret == KRB5KRB_AP_ERR_TKT_NYV || 
-                   ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+                   ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
+                   ret == KRB5KRB_AP_ERR_SKEW) {
                        break;
                }
 
@@ -270,7 +291,7 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
 
  out:
        SAFE_FREE(password_s);
-
+       *perr = ret;
        return auth_ok;
 }
 
@@ -280,9 +301,11 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
 ***********************************************************************************/
 
 NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
-                          const char *realm, time_t time_offset,
-                          const DATA_BLOB *ticket, 
-                          char **principal, PAC_DATA **pac_data,
+                          const char *realm,
+                          time_t time_offset,
+                          const DATA_BLOB *ticket,
+                          char **principal,
+                          PAC_DATA **pac_data,
                           DATA_BLOB *ap_rep,
                           DATA_BLOB *session_key)
 {
@@ -296,20 +319,22 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
        krb5_rcache rcache = NULL;
        krb5_keyblock *keyblock = NULL;
        time_t authtime;
-       int ret;
-
+       krb5_error_code ret = 0;
+       
        krb5_principal host_princ = NULL;
        krb5_const_principal client_principal = NULL;
        char *host_princ_s = NULL;
-       BOOL got_replay_mutex = False;
-
        BOOL auth_ok = False;
+       BOOL got_replay_mutex = False;
        BOOL got_auth_data = False;
 
        ZERO_STRUCT(packet);
        ZERO_STRUCT(auth_data);
-       ZERO_STRUCTP(ap_rep);
-       ZERO_STRUCTP(session_key);
+
+       *principal = NULL;
+       *pac_data = NULL;
+       *ap_rep = data_blob(NULL,0);
+       *session_key = data_blob(NULL,0);
 
        initialize_krb5_error_table();
        ret = krb5_init_context(&context);
@@ -339,6 +364,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
        }
 
        asprintf(&host_princ_s, "%s$", global_myname());
+       if (!host_princ_s) {
+               goto out;
+       }
+
        strlower_m(host_princ_s);
        ret = smb_krb5_parse_name(context, host_princ_s, &host_princ);
        if (ret) {
@@ -353,6 +382,7 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
 
        if (!grab_server_mutex("replay cache mutex")) {
                DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n"));
+               ret = KRB5_CC_IO;
                goto out;
        }
 
@@ -375,11 +405,11 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
        }
 
        if (lp_use_kerberos_keytab()) {
-               auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt, &keyblock);
+               auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &tkt, &keyblock, &ret);
        }
        if (!auth_ok) {
                auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
-                                                   ticket, &packet, &tkt, &keyblock);
+                                                   ticket, &tkt, &keyblock, &ret);
        }
 
        release_server_mutex();
@@ -395,6 +425,15 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
        if (!auth_ok) {
                DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", 
                         error_message(ret)));
+               /* Try map the error return in case it's something like
+                * a clock skew error.
+                */
+               sret = krb5_to_nt_status(ret);
+               if (NT_STATUS_IS_OK(sret) || NT_STATUS_EQUAL(sret,NT_STATUS_UNSUCCESSFUL)) {
+                       sret = NT_STATUS_LOGON_FAILURE;
+               }
+               DEBUG(10,("ads_verify_ticket: returning error %s\n",
+                       nt_errstr(sret) ));
                goto out;
        } 
        
@@ -409,8 +448,10 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
        }
 
        *ap_rep = data_blob(packet.data, packet.length);
-       SAFE_FREE(packet.data);
-       packet.length = 0;
+       if (packet.data) {
+               kerberos_free_data_contents(context, &packet);
+               ZERO_STRUCT(packet);
+       }
 
        get_krb5_smb_session_key(context, auth_context, session_key, True);
        dump_data_pw("SMB session key (from ticket)\n", session_key->data, session_key->length);
index 89cfc2d14397622538982e4b15f392d61cac6498..c153bee96e6ddebfe9e5ce146324bbf8507fa516 100644 (file)
@@ -59,6 +59,8 @@ static const struct {
        {KRB5_CC_NOTFOUND, NT_STATUS_NO_SUCH_FILE},
        {KRB5_FCC_NOFILE, NT_STATUS_NO_SUCH_FILE},
        {KRB5KDC_ERR_NONE, NT_STATUS_OK},
+       {KRB5_RC_MALLOC, NT_STATUS_NO_MEMORY},
+       {ENOMEM, NT_STATUS_NO_MEMORY},
        {0, NT_STATUS_OK}
 };
 
index dfc68fdc2b14eda2bd8f79e3bacf96a4587dac7a..1d08a01a26389c7fb1ce1af44de0413b4bb1c15f 100644 (file)
@@ -1635,6 +1635,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
        char *samAccountName, *controlstr;
        TALLOC_CTX *ctx;
        ADS_MODLIST mods;
+       char *machine_escaped = NULL;
        char *new_dn;
        const char *objectClass[] = {"top", "person", "organizationalPerson",
                                     "user", "computer", NULL};
@@ -1647,8 +1648,13 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
                return ADS_ERROR(LDAP_NO_MEMORY);
 
        ret = ADS_ERROR(LDAP_NO_MEMORY);
-               
-       new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_name, org_unit);
+
+       machine_escaped = escape_rdn_val_string_alloc(machine_name);
+       if (!machine_escaped) {
+               goto done;
+       }
+
+       new_dn = talloc_asprintf(ctx, "cn=%s,%s", machine_escaped, org_unit);
        samAccountName = talloc_asprintf(ctx, "%s$", machine_name);
 
        if ( !new_dn || !samAccountName ) {
@@ -1675,6 +1681,7 @@ ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name,
        ret = ads_gen_add(ads, new_dn, mods);
 
 done:
+       SAFE_FREE(machine_escaped);
        ads_msgfree(ads, res);
        talloc_destroy(ctx);
        
index 66d94d29d3acdea94b3d3778f4f9673c9a2e3aa5..afbbc0b421a7d2e09eed72de0ee02ef22ae38a09 100644 (file)
@@ -50,6 +50,7 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
        ADS_MODLIST mods;
        ADS_STATUS status;
        const char *upn, *new_dn, *name, *controlstr;
+       char *name_escaped = NULL;
        const char *objectClass[] = {"top", "person", "organizationalPerson",
                                     "user", NULL};
 
@@ -63,7 +64,9 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
 
        if (!(upn = talloc_asprintf(ctx, "%s@%s", user, ads->config.realm)))
                goto done;
-       if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name, container,
+       if (!(name_escaped = escape_rdn_val_string_alloc(name)))
+               goto done;
+       if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name_escaped, container,
                                       ads->config.bind_path)))
                goto done;
        if (!(controlstr = talloc_asprintf(ctx, "%u", (UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE))))
@@ -81,6 +84,7 @@ ADS_STATUS ads_add_user_acct(ADS_STRUCT *ads, const char *user,
        status = ads_gen_add(ads, new_dn, mods);
 
  done:
+       SAFE_FREE(name_escaped);
        talloc_destroy(ctx);
        return status;
 }
@@ -92,6 +96,7 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
        ADS_MODLIST mods;
        ADS_STATUS status;
        char *new_dn;
+       char *name_escaped = NULL;
        const char *objectClass[] = {"top", "group", NULL};
 
        if (!(ctx = talloc_init("ads_add_group_acct")))
@@ -99,7 +104,9 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
 
        status = ADS_ERROR(LDAP_NO_MEMORY);
 
-       if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", group, container,
+       if (!(name_escaped = escape_rdn_val_string_alloc(group)))
+               goto done;
+       if (!(new_dn = talloc_asprintf(ctx, "cn=%s,%s,%s", name_escaped, container,
                                       ads->config.bind_path)))
                goto done;
        if (!(mods = ads_init_mods(ctx)))
@@ -114,6 +121,7 @@ ADS_STATUS ads_add_group_acct(ADS_STRUCT *ads, const char *group,
        status = ads_gen_add(ads, new_dn, mods);
 
  done:
+       SAFE_FREE(name_escaped);
        talloc_destroy(ctx);
        return status;
 }
index 812f3961f195bb900a4afe4fffa9cf7fe654381b..013985a121500ffb3c9de9b65fc1c04dafef138c 100644 (file)
@@ -311,9 +311,9 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        int gss_rc, rc;
        uint8 *p;
        uint32 max_msg_size = 0;
-       char *sname;
+       char *sname = NULL;
        ADS_STATUS status;
-       krb5_principal principal;
+       krb5_principal principal = NULL;
        krb5_context ctx = NULL;
        krb5_enctype enc_types[] = {
 #ifdef ENCTYPE_ARCFOUR_HMAC
@@ -331,25 +331,40 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        initialize_krb5_error_table();
        status = ADS_ERROR_KRB5(krb5_init_context(&ctx));
        if (!ADS_ERR_OK(status)) {
+               SAFE_FREE(sname);
                return status;
        }
        status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types));
        if (!ADS_ERR_OK(status)) {
+               SAFE_FREE(sname);
+               krb5_free_context(ctx); 
                return status;
        }
        status = ADS_ERROR_KRB5(smb_krb5_parse_name(ctx, sname, &principal));
        if (!ADS_ERR_OK(status)) {
+               SAFE_FREE(sname);
+               krb5_free_context(ctx); 
                return status;
        }
 
-       free(sname);
-       krb5_free_context(ctx); 
-
        input_name.value = &principal;
        input_name.length = sizeof(principal);
 
        gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name);
+
+       /*
+        * The MIT libraries have a *HORRIBLE* bug - input_value.value needs
+        * to point to the *address* of the krb5_principal, and the gss libraries
+        * to a shallow copy of the krb5_principal pointer - so we need to keep
+        * the krb5_principal around until we do the gss_release_name. MIT *SUCKS* !
+        * Just one more way in which MIT engineers screwed me over.... JRA.
+        */
+
+       SAFE_FREE(sname);
+
        if (gss_rc) {
+               krb5_free_principal(ctx, principal);
+               krb5_free_context(ctx); 
                return ADS_ERROR_GSS(gss_rc, minor_status);
        }
 
@@ -407,8 +422,6 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
                if (gss_rc == 0) break;
        }
 
-       gss_release_name(&minor_status, &serv_name);
-
        gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token,
                            (int *)&conf_state,NULL);
        if (gss_rc) {
@@ -463,6 +476,11 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        gss_release_buffer(&minor_status, &input_token);
 
 failed:
+
+       gss_release_name(&minor_status, &serv_name);
+       krb5_free_principal(ctx, principal);
+       krb5_free_context(ctx); 
+
        if(scred)
                ber_bvfree(scred);
        return status;
diff --git a/source/libads/smb_krb5_locator.c b/source/libads/smb_krb5_locator.c
new file mode 100644 (file)
index 0000000..be14a12
--- /dev/null
@@ -0,0 +1,386 @@
+/* 
+   Unix SMB/CIFS implementation.
+   kerberos locator plugin
+   Copyright (C) Guenther Deschner 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 2 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, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
+
+#include <krb5/locate_plugin.h>
+
+static const char *get_service_from_locate_service_type(enum locate_service_type svc)
+{
+       switch (svc) {
+               case locate_service_kdc:
+               case locate_service_master_kdc:
+                       return "88";
+               case locate_service_kadmin:
+               case locate_service_krb524:
+                       /* not supported */
+                       return NULL;
+               case locate_service_kpasswd:
+                       return "464";
+               default:
+                       break;
+       }
+       return NULL;
+
+}
+
+static const char *locate_service_type_name(enum locate_service_type svc)
+{
+       switch (svc) {
+               case locate_service_kdc:
+                       return "locate_service_kdc";
+               case locate_service_master_kdc:
+                       return "locate_service_master_kdc";
+               case locate_service_kadmin:
+                       return "locate_service_kadmin";
+               case locate_service_krb524:
+                       return "locate_service_krb524";
+               case locate_service_kpasswd:
+                       return "locate_service_kpasswd";
+               default:
+                       break;
+       }
+       return NULL;
+}
+
+static const char *socktype_name(int socktype)
+{
+       switch (socktype) {
+               case SOCK_STREAM:
+                       return "SOCK_STREAM";
+               case SOCK_DGRAM:
+                       return "SOCK_DGRAM";
+               default:
+                       break;
+       }
+       return "unknown";
+}
+
+static const char *family_name(int family)
+{
+       switch (family) {
+               case AF_UNSPEC:
+                       return "AF_UNSPEC";
+               case AF_INET:
+                       return "AF_INET";
+               case AF_INET6:
+                       return "AF_INET6";
+               default:
+                       break;
+       }
+       return "unknown";
+}
+
+/**
+ * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
+ *
+ * @param svc 
+ * @param realm string
+ * @param socktype integer
+ * @param family integer
+ *
+ * @return integer.
+ */
+
+static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc,
+                                               const char *realm,
+                                               int socktype,
+                                               int family)
+{
+       if (!realm || strlen(realm) == 0) {
+               return EINVAL;
+       }
+
+       switch (svc) {
+               case locate_service_kdc:
+               case locate_service_master_kdc:
+               case locate_service_kpasswd:
+                       break;
+               case locate_service_kadmin:
+               case locate_service_krb524:
+#ifdef KRB5_PLUGIN_NO_HANDLE
+                       return KRB5_PLUGIN_NO_HANDLE;
+#else
+                       return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+               default:
+                       return EINVAL;
+       }
+
+       switch (family) {
+               case AF_UNSPEC:
+               case AF_INET:
+                       break;
+               case AF_INET6: /* not yet */
+#ifdef KRB5_PLUGIN_NO_HANDLE
+                       return KRB5_PLUGIN_NO_HANDLE;
+#else
+                       return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+               default:
+                       return EINVAL;
+       }
+
+       switch (socktype) {
+               case SOCK_STREAM:
+               case SOCK_DGRAM:
+               case 0: /* Heimdal uses that */
+                       break;
+               default:
+                       return EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * Try to get addrinfo for a given host and call the krb5 callback
+ *
+ * @param name string
+ * @param service string
+ * @param in struct addrinfo hint
+ * @param cbfunc krb5 callback function
+ * @param cbdata void pointer cbdata
+ *
+ * @return krb5_error_code.
+ */
+
+static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name, 
+                                                   const char *service,
+                                                   struct addrinfo *in,
+                                                   int (*cbfunc)(void *, int, struct sockaddr *),
+                                                   void *cbdata)
+{
+       struct addrinfo *out;
+       int ret;
+       int count = 3;
+
+       while (count) {
+
+               ret = getaddrinfo(name, service, in, &out);
+               if (ret == 0) {
+                       break;
+               }
+
+               if (ret == EAI_AGAIN) {
+                       count--;
+                       continue;
+               }
+
+               DEBUG(10,("smb_krb5_locator_lookup: got ret: %s (%d)\n", 
+                       gai_strerror(ret), ret));
+#ifdef KRB5_PLUGIN_NO_HANDLE
+               return KRB5_PLUGIN_NO_HANDLE;
+#else
+               return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+       }
+
+       ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr);
+       if (ret) {
+               DEBUG(10,("smb_krb5_locator_lookup: failed to call callback: %s (%d)\n", 
+                       error_message(ret), ret));
+       }
+
+       freeaddrinfo(out);
+
+       return ret;
+}
+
+/**
+ * PUBLIC INTERFACE: locate init
+ *
+ * @param context krb5_context
+ * @param privata_data pointer to private data pointer
+ *
+ * @return krb5_error_code.
+ */
+
+krb5_error_code smb_krb5_locator_init(krb5_context context, 
+                                     void **private_data)
+{
+       setup_logging("smb_krb5_locator", True);
+       load_case_tables();
+       lp_load(dyn_CONFIGFILE,True,False,False,True);
+
+       DEBUG(10,("smb_krb5_locator_init: called\n"));
+
+       return 0;
+}
+
+/**
+ * PUBLIC INTERFACE: close locate
+ *
+ * @param private_data pointer to private data
+ *
+ * @return void.
+ */
+
+void smb_krb5_locator_close(void *private_data)
+{
+       DEBUG(10,("smb_krb5_locator_close: called\n"));
+
+       /* gfree_all(); */
+}
+
+/**
+ * PUBLIC INTERFACE: locate lookup
+ *
+ * @param private_data pointer to private data
+ * @param svc enum locate_service_type.
+ * @param realm string
+ * @param socktype integer
+ * @param family integer
+ * @param cbfunc callback function to send back entries
+ * @param cbdata void pointer to cbdata
+ *
+ * @return krb5_error_code.
+ */
+
+krb5_error_code smb_krb5_locator_lookup(void *private_data,
+                                       enum locate_service_type svc,
+                                       const char *realm,
+                                       int socktype,
+                                       int family,
+                                       int (*cbfunc)(void *, int, struct sockaddr *),
+                                       void *cbdata)
+{
+       NTSTATUS status;
+       krb5_error_code ret;
+       char *sitename = NULL;
+       struct ip_service *ip_list;
+       int count = 0;
+       struct addrinfo aihints;
+       char *saf_name = NULL;
+       int i;
+
+       DEBUG(10,("smb_krb5_locator_lookup: called for\n"));
+       DEBUGADD(10,("\tsvc: %s (%d), realm: %s\n", 
+               locate_service_type_name(svc), svc, realm));
+       DEBUGADD(10,("\tsocktype: %s (%d), family: %s (%d)\n", 
+               socktype_name(socktype), socktype,
+               family_name(family), family));
+
+       ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, family);
+       if (ret) {
+               DEBUG(10,("smb_krb5_locator_lookup: returning ret: %s (%d)\n", 
+                       error_message(ret), ret));
+               return ret;
+       }
+
+       /* first try to fetch from SAF cache */
+
+       saf_name = saf_fetch(realm);
+       if (!saf_name || strlen(saf_name) == 0) {
+               DEBUG(10,("smb_krb5_locator_lookup: no SAF name stored for %s\n", 
+                       realm));
+               goto find_kdc;
+       }
+
+       DEBUG(10,("smb_krb5_locator_lookup: got %s for %s from SAF cache\n", 
+               saf_name, realm));
+
+       ZERO_STRUCT(aihints);
+       
+       aihints.ai_family = family;
+       aihints.ai_socktype = socktype;
+
+       ret = smb_krb5_locator_call_cbfunc(saf_name, 
+                                         get_service_from_locate_service_type(svc), 
+                                         &aihints, 
+                                         cbfunc, cbdata);
+       if (ret) {
+               return ret;
+       }
+
+       return 0;
+
+ find_kdc:
+
+       /* now try to find via site-aware DNS SRV query */
+
+       sitename = sitename_fetch(realm);
+       status = get_kdc_list(realm, sitename, &ip_list, &count);
+
+       /* if we didn't found any KDCs on our site go to the main list */
+
+       if (NT_STATUS_IS_OK(status) && sitename && (count == 0)) {
+               SAFE_FREE(ip_list);
+               SAFE_FREE(sitename);
+               status = get_kdc_list(realm, NULL, &ip_list, &count);
+       }
+
+       SAFE_FREE(sitename);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10,("smb_krb5_locator_lookup: got %s (%s)\n",
+                       nt_errstr(status), 
+                       error_message(nt_status_to_krb5(status))));
+#ifdef KRB5_PLUGIN_NO_HANDLE
+               return KRB5_PLUGIN_NO_HANDLE;
+#else
+               return KRB5_KDC_UNREACH; /* Heimdal */
+#endif
+       }
+
+       for (i=0; i<count; i++) {
+
+               const char *host = NULL;
+               const char *port = NULL;
+
+               ZERO_STRUCT(aihints);
+
+               aihints.ai_family = family;
+               aihints.ai_socktype = socktype;
+
+               host = inet_ntoa(ip_list[i].ip);
+               port = get_service_from_locate_service_type(svc);
+
+               ret = smb_krb5_locator_call_cbfunc(host,
+                                                 port,
+                                                 &aihints, 
+                                                 cbfunc, cbdata);
+               if (ret) {
+                       /* got error */
+                       break;
+               }
+       }
+
+       SAFE_FREE(ip_list);
+
+       return ret;
+}
+
+#ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
+#define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
+#else
+#define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
+#endif
+
+const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = {
+       0, /* version */
+       smb_krb5_locator_init,
+       smb_krb5_locator_close,
+       smb_krb5_locator_lookup,
+};
+
+#endif
index 32dd0ef6c59f3399938c4a23c66901325801927b..faa7c56455dc2308f2a3497c901a9d4ff6a0f459 100644 (file)
@@ -223,7 +223,7 @@ enum ndr_compression_alg {
        } \
 } while(0)
 
-#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n)))
+#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, n))
 
 #define NDR_PUSH_ALIGN(ndr, n) do { \
        if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \
index f6a132c18616249fab3bdb16d3852d46ad9c21ea..4f0599e5c03deb4f1dfe0251b2cc7c677fcab258 100644 (file)
@@ -160,10 +160,18 @@ DATA_BLOB ndr_push_blob(struct ndr_push *ndr)
 
 
 /*
-  expand the available space in the buffer to 'size'
+  expand the available space in the buffer to ndr->offset + extra_size
 */
-NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t size)
+NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size)
 {
+       uint32_t size = extra_size + ndr->offset;
+
+       if (size < ndr->offset) {
+               /* extra_size overflowed the offset */
+               return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",
+                                       size);
+       }
+
        if (ndr->alloc_size > size) {
                return NT_STATUS_OK;
        }
index e2213c1fcde11aa4d3142846a77ff054522120eb..0f09747dbf1115d1a2ba82e94132a20f32b8b037 100644 (file)
@@ -693,8 +693,6 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
                                DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
                                nt_status = NT_STATUS_UNSUCCESSFUL;
                        } else {
-                               data_blob_free(&msg1);
-                               
                                blob = cli_session_setup_blob_receive(cli);
                                
                                nt_status = cli_nt_error(cli);
@@ -706,6 +704,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
                                        }
                                }
                        }
+                       data_blob_free(&msg1);
                }
                
                if (!blob.length) {
@@ -736,6 +735,8 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
                turn++;
        } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
 
+       data_blob_free(&blob_in);
+
        if (NT_STATUS_IS_OK(nt_status)) {
 
                DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
index 916e4cefc6ec1aa1403a74b305de0e90c1352ba2..4009b98b418404bc8920f7b348b658cd02323fb7 100644 (file)
@@ -3,6 +3,7 @@
    client connect/disconnect routines
    Copyright (C) Andrew Tridgell                  1994-1998
    Copyright (C) Gerald (Jerry) Carter            2004
+   Copyright (C) Jeremy Allison                   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
 
 #include "includes.h"
 
+/********************************************************************
+ Important point.
+
+ DFS paths are *always* of the form \server\share\<pathname> (the \ characters
+ are not C escaped here).
+
+ - but if we're using POSIX paths then <pathname> may contain
+   '/' separators, not '\\' separators. So cope with '\\' or '/'
+   as a separator when looking at the pathname part.... JRA.
+********************************************************************/
 
 struct client_connection {
        struct client_connection *prev, *next;
@@ -194,14 +205,14 @@ static void cli_cm_set_mntpoint( struct cli_state *c, const char *mnt )
        
        if ( p ) {
                pstrcpy( p->mount, mnt );
-               dos_clean_name( p->mount );
+               clean_name(p->mount);
        }
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-const char * cli_cm_get_mntpoint( struct cli_state *c )
+const char *cli_cm_get_mntpoint( struct cli_state *c )
 {
        struct client_connection *p;
        int i;
@@ -221,8 +232,9 @@ const char * cli_cm_get_mntpoint( struct cli_state *c )
  Add a new connection to the list
 ********************************************************************/
 
-static struct cli_state* cli_cm_connect( const char *server, const char *share,
-                                         BOOL show_hdr )
+static struct cli_state *cli_cm_connect( const char *server,
+                                       const char *share,
+                                       BOOL show_hdr)
 {
        struct client_connection *node;
        
@@ -247,7 +259,7 @@ static struct cli_state* cli_cm_connect( const char *server, const char *share,
  Return a connection to a server.
 ********************************************************************/
 
-static struct cli_statecli_cm_find( const char *server, const char *share )
+static struct cli_state *cli_cm_find( const char *server, const char *share )
 {
        struct client_connection *p;
 
@@ -264,7 +276,9 @@ static struct cli_state* cli_cm_find( const char *server, const char *share )
  global variable as a side-effect (but only if the connection is successful).
 ****************************************************************************/
 
-struct cli_state* cli_cm_open( const char *server, const char *share, BOOL show_hdr )
+struct cli_state *cli_cm_open(const char *server,
+                               const char *share,
+                               BOOL show_hdr)
 {
        struct cli_state *c;
        
@@ -272,8 +286,9 @@ struct cli_state* cli_cm_open( const char *server, const char *share, BOOL show_
 
        c = cli_cm_find( server, share );
        
-       if ( !c )
-               c = cli_cm_connect( server, share, show_hdr );
+       if ( !c ) {
+               c = cli_cm_connect(server, share, show_hdr);
+       }
 
        return c;
 }
@@ -295,7 +310,6 @@ void cli_cm_shutdown( void )
        }
 
        connections = NULL;
-
        return;
 }
 
@@ -354,110 +368,104 @@ void cli_cm_set_dest_ip(struct in_addr ip )
        have_ip = True;
 }
 
-/********************************************************************
- split a dfs path into the server and share name components
-********************************************************************/
+/**********************************************************************
+ split a dfs path into the server, share name, and extrapath components
+**********************************************************************/
 
-static void split_dfs_path( const char *nodepath, fstring server, fstring share )
+static void split_dfs_path( const char *nodepath, fstring server, fstring share, pstring extrapath )
 {
-       char *p;
+       char *p, *q;
        pstring path;
 
        pstrcpy( path, nodepath );
 
-       if ( path[0] != '\\' )
+       if ( path[0] != '\\' ) {
                return;
+       }
 
-       p = strrchr_m( path, '\\' );
-
-       if ( !p )
+       p = strchr_m( path + 1, '\\' );
+       if ( !p ) {
                return;
+       }
 
        *p = '\0';
        p++;
 
+       /* Look for any extra/deep path */
+       q = strchr_m(p, '\\');
+       if (q != NULL) {
+               *q = '\0';
+               q++;
+               pstrcpy( extrapath, q );
+       } else {
+               pstrcpy( extrapath, '\0' );
+       }
+       
        fstrcpy( share, p );
        fstrcpy( server, &path[1] );
 }
 
 /****************************************************************************
- return the original path truncated at the first wildcard character
(also strips trailing \'s).  Trust the caller to provide a NULL 
+ Return the original path truncated at the directory component before
the first wildcard character. Trust the caller to provide a NULL 
  terminated string
 ****************************************************************************/
 
-static void clean_path( pstring clean, const char *path )
+static void clean_path(const char *path, pstring path_out)
 {
-       int len;
-       char *p;
-       pstring newpath;
-               
-       pstrcpy( newpath, path );
-       p = newpath;
-       
-       while ( p ) {
-               /* first check for '*' */
+       size_t len;
+       char *p1, *p2, *p;
                
-               p = strrchr_m( newpath, '*' );
-               if ( p ) {
-                       *p = '\0';
-                       p = newpath;
-                       continue;
+       /* No absolute paths. */
+       while (IS_DIRECTORY_SEP(*path)) {
+               path++;
+       }
+
+       pstrcpy(path_out, path);
+
+       p1 = strchr_m(path_out, '*');
+       p2 = strchr_m(path_out, '?');
+
+       if (p1 || p2) {
+               if (p1 && p2) {
+                       p = MIN(p1,p2);
+               } else if (!p1) {
+                       p = p2;
+               } else {
+                       p = p1;
                }
-       
-               /* first check for '?' */
-               
-               p = strrchr_m( newpath, '?' );
-               if ( p ) {
+               *p = '\0';
+
+               /* Now go back to the start of this component. */
+               p1 = strrchr_m(path_out, '/');
+               p2 = strrchr_m(path_out, '\\');
+               p = MAX(p1,p2);
+               if (p) {
                        *p = '\0';
-                       p = newpath;
                }
        }
-       
-       /* strip a trailing backslash */
-       
-       len = strlen( newpath );
-       if ( (len > 0) && (newpath[len-1] == '\\') )
-               newpath[len-1] = '\0';
-               
-       pstrcpy( clean, newpath );
+
+       /* Strip any trailing separator */
+
+       len = strlen(path_out);
+       if ( (len > 0) && IS_DIRECTORY_SEP(path_out[len-1])) {
+               path_out[len-1] = '\0';
+       }
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-BOOL cli_dfs_make_full_path( pstring path, const char *server, const char *share,
-                            const char *dir )
+static void cli_dfs_make_full_path( struct cli_state *cli,
+                                       const char *dir,
+                                       pstring path_out)
 {
-       pstring servicename;
-       char *sharename;
-       const char *directory;
-
-       
-       /* make a copy so we don't modify the global string 'service' */
-       
-       pstrcpy(servicename, share);
-       sharename = servicename;
-       
-       if (*sharename == '\\') {
-       
-               server = sharename+2;
-               sharename = strchr_m(server,'\\');
-               
-               if (!sharename) 
-                       return False;
-                       
-               *sharename = 0;
-               sharename++;
+       /* Ensure the extrapath doesn't start with a separator. */
+       while (IS_DIRECTORY_SEP(*dir)) {
+               dir++;
        }
 
-       directory = dir;
-       if ( *directory == '\\' )
-               directory++;
-       
-       pstr_sprintf( path, "\\%s\\%s\\%s", server, sharename, directory );
-
-       return True;
+       pstr_sprintf( path_out, "\\%s\\%s\\%s", cli->desthost, cli->share, dir);
 }
 
 /********************************************************************
@@ -483,9 +491,11 @@ static BOOL cli_dfs_check_error( struct cli_state *cli, NTSTATUS status )
  get the dfs referral link
 ********************************************************************/
 
-BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path, 
-                           CLIENT_DFS_REFERRAL**refs, size_t *num_refs,
-                          uint16 *consumed)
+BOOL cli_dfs_get_referral( struct cli_state *cli,
+                       const char *path, 
+                       CLIENT_DFS_REFERRAL**refs,
+                       size_t *num_refs,
+                       uint16 *consumed)
 {
        unsigned int data_len = 0;
        unsigned int param_len = 0;
@@ -529,10 +539,9 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
                uint16 ref_size;
                int i;
                uint16 node_offset;
-               
-               
+
                referrals = SMB_XMALLOC_ARRAY( CLIENT_DFS_REFERRAL, num_referrals );
-       
+
                /* start at the referrals array */
        
                p = rdata+8;
@@ -554,7 +563,6 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
 
                        p += ref_size;
                }
-       
        }
        
        *num_refs = num_referrals;
@@ -566,115 +574,167 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
        return True;
 }
 
+
 /********************************************************************
 ********************************************************************/
 
-BOOL cli_resolve_path( const char *mountpt, struct cli_state *rootcli, const char *path,
-                       struct cli_state **targetcli, pstring targetpath )
+BOOL cli_resolve_path( const char *mountpt,
+                       struct cli_state *rootcli,
+                       const char *path,
+                       struct cli_state **targetcli,
+                       pstring targetpath)
 {
        CLIENT_DFS_REFERRAL *refs = NULL;
        size_t num_refs;
        uint16 consumed;
        struct cli_state *cli_ipc;
-       pstring fullpath, cleanpath;
+       pstring dfs_path, cleanpath, extrapath;
        int pathlen;
        fstring server, share;
        struct cli_state *newcli;
        pstring newpath;
        pstring newmount;
-       char *ppath;
+       char *ppath, *temppath = NULL;
        
        SMB_STRUCT_STAT sbuf;
        uint32 attributes;
        
-       if ( !rootcli || !path || !targetcli )
+       if ( !rootcli || !path || !targetcli ) {
                return False;
+       }
                
-       *targetcli = NULL;
-       
-       /* send a trans2_query_path_info to check for a referral */
-       
-       clean_path( cleanpath,  path );
-       cli_dfs_make_full_path( fullpath, rootcli->desthost, rootcli->share, cleanpath );
+       /* Don't do anything if this is not a DFS root. */
 
-       /* don't bother continuing if this is not a dfs root */
-       
-       if ( !rootcli->dfsroot || cli_qpathinfo_basic( rootcli, cleanpath, &sbuf, &attributes ) ) {
+       if ( !rootcli->dfsroot) {
                *targetcli = rootcli;
                pstrcpy( targetpath, path );
                return True;
        }
 
-       /* special case where client asked for a path that does not exist */
+       *targetcli = NULL;
+
+       /* Send a trans2_query_path_info to check for a referral. */
+
+       clean_path(path, cleanpath);
+       cli_dfs_make_full_path(rootcli, cleanpath, dfs_path );
+
+       if (cli_qpathinfo_basic( rootcli, dfs_path, &sbuf, &attributes ) ) {
+               /* This is an ordinary path, just return it. */
+               *targetcli = rootcli;
+               pstrcpy( targetpath, path );
+               goto done;
+       }
+
+       /* Special case where client asked for a path that does not exist */
 
        if ( cli_dfs_check_error(rootcli, NT_STATUS_OBJECT_NAME_NOT_FOUND) ) {
                *targetcli = rootcli;
                pstrcpy( targetpath, path );
-               return True;
+               goto done;
        }
 
-       /* we got an error, check for DFS referral */
-                       
-       if ( !cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED) ) 
+       /* We got an error, check for DFS referral. */
+
+       if ( !cli_dfs_check_error(rootcli, NT_STATUS_PATH_NOT_COVERED))  {
                return False;
+       }
 
-       /* check for the referral */
+       /* Check for the referral. */
 
-       if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) )
+       if ( !(cli_ipc = cli_cm_open( rootcli->desthost, "IPC$", False )) ) {
                return False;
+       }
        
-       if ( !cli_dfs_get_referral(cli_ipc, fullpath, &refs, &num_refs, &consumed) 
-               || !num_refs )
-       {
+       if ( !cli_dfs_get_referral(cli_ipc, dfs_path, &refs, &num_refs, &consumed) 
+                       || !num_refs ) {
                return False;
        }
        
-       /* just store the first referral for now
-          Make sure to recreate the original string including any wildcards */
+       /* Just store the first referral for now. */
+
+       split_dfs_path( refs[0].dfspath, server, share, extrapath );
+       SAFE_FREE(refs);
+
+       /* Make sure to recreate the original string including any wildcards. */
        
-       cli_dfs_make_full_path( fullpath, rootcli->desthost, rootcli->share, path );
-       pathlen = strlen( fullpath )*2;
+       cli_dfs_make_full_path( rootcli, path, dfs_path);
+       pathlen = strlen( dfs_path )*2;
        consumed = MIN(pathlen, consumed );
-       pstrcpy( targetpath, &fullpath[consumed/2] );
+       pstrcpy( targetpath, &dfs_path[consumed/2] );
+       dfs_path[consumed/2] = '\0';
 
-       split_dfs_path( refs[0].dfspath, server, share );
-       SAFE_FREE( refs );
-       
-       /* open the connection to the target path */
+       /*
+        * targetpath is now the unconsumed part of the path.
+        * dfs_path is now the consumed part of the path (in \server\share\path format).
+        */
+
+       /* Open the connection to the target server & share */
        
        if ( (*targetcli = cli_cm_open(server, share, False)) == NULL ) {
-               d_printf("Unable to follow dfs referral [//%s/%s]\n",
+               d_printf("Unable to follow dfs referral [\\%s\\%s]\n",
                        server, share );
-                       
                return False;
        }
        
+       if (strlen(extrapath) > 0) {
+               string_append(&temppath, extrapath);
+               string_append(&temppath, targetpath);
+               pstrcpy( targetpath, temppath );
+       }
+       
        /* parse out the consumed mount path */
        /* trim off the \server\share\ */
 
-       fullpath[consumed/2] = '\0';
-       dos_clean_name( fullpath );
-       if ((ppath = strchr_m( fullpath, '\\' )) == NULL)
+       ppath = dfs_path;
+
+       if (*ppath != '\\') {
+               d_printf("cli_resolve_path: dfs_path (%s) not in correct format.\n",
+                       dfs_path );
                return False;
-       if ((ppath = strchr_m( ppath+1, '\\' )) == NULL)
+       }
+
+       ppath++; /* Now pointing at start of server name. */
+       
+       if ((ppath = strchr_m( dfs_path, '\\' )) == NULL) {
                return False;
-       if ((ppath = strchr_m( ppath+1, '\\' )) == NULL)
+       }
+
+       ppath++; /* Now pointing at start of share name. */
+
+       if ((ppath = strchr_m( ppath+1, '\\' )) == NULL) {
                return False;
-       ppath++;
-       
+       }
+
+       ppath++; /* Now pointing at path component. */
+
        pstr_sprintf( newmount, "%s\\%s", mountpt, ppath );
+
        cli_cm_set_mntpoint( *targetcli, newmount );
 
-       /* check for another dfs referral, note that we are not 
-          checking for loops here */
+       /* Check for another dfs referral, note that we are not 
+          checking for loops here. */
 
-       if ( !strequal( targetpath, "\\" ) ) {
+       if ( !strequal( targetpath, "\\" ) &&  !strequal( targetpath, "/")) {
                if ( cli_resolve_path( newmount, *targetcli, targetpath, &newcli, newpath ) ) {
+                       /*
+                        * When cli_resolve_path returns true here it's always
+                        * returning the complete path in newpath, so we're done
+                        * here.
+                        */
                        *targetcli = newcli;
                        pstrcpy( targetpath, newpath );
+                       return True;
                }
        }
 
+  done:
+
+       /* If returning True ensure we return a dfs root full path. */
+       if ( (*targetcli)->dfsroot ) {
+               pstrcpy(dfs_path, targetpath );
+               cli_dfs_make_full_path( *targetcli, dfs_path, targetpath); 
+       }
+
        return True;
 }
 
@@ -690,6 +750,7 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
        pstring fullpath;
        BOOL res;
        uint16 cnum;
+       pstring newextrapath;
        
        if ( !cli || !sharename )
                return False;
@@ -698,8 +759,9 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
 
        /* special case.  never check for a referral on the IPC$ share */
 
-       if ( strequal( sharename, "IPC$" ) )
+       if ( strequal( sharename, "IPC$" ) ) {
                return False;
+       }
                
        /* send a trans2_query_path_info to check for a referral */
        
@@ -719,13 +781,13 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
        }
 
        cli->cnum = cnum;
-               
+
        if (!res || !num_refs ) {
                SAFE_FREE( refs );
                return False;
        }
        
-       split_dfs_path( refs[0].dfspath, newserver, newshare );
+       split_dfs_path( refs[0].dfspath, newserver, newshare, newextrapath );
 
        /* check that this is not a self-referral */
 
index 2fe9eb17259c746358d43312c7edea556785acf4..ce2081a81e1f3559b1d3db928bb9669721819946 100644 (file)
@@ -1775,3 +1775,200 @@ BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
 
        return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
 }
+
+/****************************************************************************
+ Convert open "flags" arg to uint32 on wire.
+****************************************************************************/
+
+static uint32 open_flags_to_wire(int flags)
+{
+       int open_mode = flags & O_ACCMODE;
+       uint32 ret = 0;
+
+       switch (open_mode) {
+               case O_WRONLY:
+                       ret |= SMB_O_WRONLY;
+                       break;
+               case O_RDWR:
+                       ret |= SMB_O_RDWR;
+                       break;
+               default:
+               case O_RDONLY:
+                       ret |= SMB_O_RDONLY;
+                       break;
+       }
+
+       if (flags & O_CREAT) {
+               ret |= SMB_O_CREAT;
+       }
+       if (flags & O_EXCL) {
+               ret |= SMB_O_EXCL;
+       }
+       if (flags & O_TRUNC) {
+               ret |= SMB_O_TRUNC;
+       }
+#if defined(O_SYNC)
+       if (flags & O_SYNC) {
+               ret |= SMB_O_SYNC;
+       }
+#endif /* O_SYNC */
+       if (flags & O_APPEND) {
+               ret |= SMB_O_APPEND;
+       }
+#if defined(O_DIRECT)
+       if (flags & O_DIRECT) {
+               ret |= SMB_O_DIRECT;
+       }
+#endif
+#if defined(O_DIRECTORY)
+       if (flags & O_DIRECTORY) {
+               ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+               ret |= SMB_O_DIRECTORY;
+       }
+#endif
+       return ret;
+}
+
+/****************************************************************************
+ Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
+****************************************************************************/
+
+static int cli_posix_open_internal(struct cli_state *cli, const char *fname, int flags, mode_t mode, BOOL is_dir)
+{
+       unsigned int data_len = 0;
+       unsigned int param_len = 0;
+       uint16 setup = TRANSACT2_SETPATHINFO;
+       char param[sizeof(pstring)+6];
+       char data[18];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+       int fnum = -1;
+       uint32 wire_flags = open_flags_to_wire(flags);
+
+       memset(param, 0, sizeof(param));
+       SSVAL(param,0, SMB_POSIX_PATH_OPEN);
+       p = &param[6];
+
+       p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       if (is_dir) {
+               wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
+               wire_flags |= SMB_O_DIRECTORY;
+       }
+
+       p = data;
+       SIVAL(p,0,0); /* No oplock. */
+       SIVAL(p,4,wire_flags);
+       SIVAL(p,8,unix_perms_to_wire(mode));
+       SIVAL(p,12,0); /* Top bits of perms currently undefined. */
+       SSVAL(p,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
+
+       data_len = 18;
+
+       if (!cli_send_trans(cli, SMBtrans2,
+               NULL,                        /* name */
+               -1, 0,                          /* fid, flags */
+               &setup, 1, 0,                   /* setup, length, max */
+               param, param_len, 2,            /* param, length, max */
+               (char *)&data,  data_len, cli->max_xmit /* data, length, max */
+               )) {
+                       return -1;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+               &rparam, &param_len,
+               &rdata, &data_len)) {
+                       return -1;
+       }
+
+       fnum = SVAL(rdata,2);
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       return fnum;
+}
+
+/****************************************************************************
+ open - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_open(struct cli_state *cli, const char *fname, int flags, mode_t mode)
+{
+       return cli_posix_open_internal(cli, fname, flags, mode, False);
+}
+
+/****************************************************************************
+ mkdir - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
+{
+       return (cli_posix_open_internal(cli, fname, O_CREAT, mode, True) == -1) ? -1 : 0;
+}
+
+/****************************************************************************
+ unlink or rmdir - POSIX semantics.
+****************************************************************************/
+
+static BOOL cli_posix_unlink_internal(struct cli_state *cli, const char *fname, BOOL is_dir)
+{
+       unsigned int data_len = 0;
+       unsigned int param_len = 0;
+       uint16 setup = TRANSACT2_SETPATHINFO;
+       char param[sizeof(pstring)+6];
+       char data[2];
+       char *rparam=NULL, *rdata=NULL;
+       char *p;
+
+       memset(param, 0, sizeof(param));
+       SSVAL(param,0, SMB_POSIX_PATH_UNLINK);
+       p = &param[6];
+
+       p += clistr_push(cli, p, fname, sizeof(param)-6, STR_TERMINATE);
+       param_len = PTR_DIFF(p, param);
+
+       SSVAL(data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
+                       SMB_POSIX_UNLINK_FILE_TARGET);
+       data_len = 2;
+
+       if (!cli_send_trans(cli, SMBtrans2,
+               NULL,                        /* name */
+               -1, 0,                          /* fid, flags */
+               &setup, 1, 0,                   /* setup, length, max */
+               param, param_len, 2,            /* param, length, max */
+               (char *)&data,  data_len, cli->max_xmit /* data, length, max */
+               )) {
+                       return False;
+       }
+
+       if (!cli_receive_trans(cli, SMBtrans2,
+               &rparam, &param_len,
+               &rdata, &data_len)) {
+                       return False;
+       }
+
+       SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+
+       return True;
+}
+
+/****************************************************************************
+ unlink - POSIX semantics.
+****************************************************************************/
+
+BOOL cli_posix_unlink(struct cli_state *cli, const char *fname)
+{
+       return cli_posix_unlink_internal(cli, fname, False);
+}
+
+/****************************************************************************
+ rmdir - POSIX semantics.
+****************************************************************************/
+
+int cli_posix_rmdir(struct cli_state *cli, const char *fname)
+{
+       return cli_posix_unlink_internal(cli, fname, True);
+}
index f06a19b345c2b9b58cc5924fba24be97a80b2676..5018e146cad9cde37f2ecf61d0de4eb760857f64 100644 (file)
@@ -75,6 +75,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
        krb5_error_code ret;
        char *utf8_name;
 
+       *principal = NULL;
        if (push_utf8_allocate(&utf8_name, name) == (size_t)-1) {
                return ENOMEM;
        }
@@ -97,6 +98,7 @@ static krb5_error_code smb_krb5_parse_name_norealm_conv(krb5_context context,
        krb5_error_code ret;
        char *utf8_name;
 
+       *unix_name = NULL;
        ret = krb5_unparse_name(context, principal, &utf8_name);
        if (ret) {
                return ret;
@@ -1415,6 +1417,43 @@ done:
 }
 #endif
 
+ krb5_error_code smb_krb5_mk_error(krb5_context context,
+                               krb5_error_code error_code,
+                               const krb5_principal server,
+                               krb5_data *reply)
+{
+#ifdef HAVE_SHORT_KRB5_MK_ERROR_INTERFACE /* MIT */
+       /*
+        * The MIT interface is *terrible*.
+        * We have to construct this ourselves...
+        */
+       krb5_error e;
+
+       memset(&e, 0, sizeof(e));
+       krb5_us_timeofday(context, &e.stime, &e.susec);
+       e.server = server;
+#if defined(krb5_err_base)
+       e.error = error_code - krb5_err_base;
+#elif defined(ERROR_TABLE_BASE_krb5)
+       e.error = error_code - ERROR_TABLE_BASE_krb5;
+#else
+       e.error = error_code; /* Almost certainly wrong, but what can we do... ? */
+#endif
+
+       return krb5_mk_error(context, &e, reply);
+#else /* Heimdal. */
+       return krb5_mk_error(context,
+                               error_code,
+                               NULL,
+                               NULL, /* e_data */
+                               NULL,
+                               server,
+                               NULL,
+                               NULL,
+                               reply);
+#endif
+}
+
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
  int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
index 22cb5930c26734b8705926d1777175dce728dbc3..3e76cd47754db9815bff5ac4320131dcfed19ebc 100644 (file)
@@ -44,6 +44,7 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
                *p_resume_key = 0;
        }
        memcpy(finfo,&def_finfo,sizeof(*finfo));
+       finfo->cli = cli;
 
        switch (level) {
                case 1: /* OS/2 understands this */
@@ -185,13 +186,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
        /* NT uses 260, OS/2 uses 2. Both accept 1. */
        info_level = (cli->capabilities&CAP_NT_SMBS)?260:1;
        
-       /* when getting a directory listing from a 2k dfs root share, 
-          we have to include the full path (\server\share\mask) here */
-          
-       if ( cli->dfsroot )
-               pstr_sprintf( mask, "\\%s\\%s\\%s", cli->desthost, cli->share, Mask );
-       else
-               pstrcpy(mask,Mask);
+       pstrcpy(mask,Mask);
        
        while (ff_eos == 0) {
                loop_count++;
@@ -377,6 +372,7 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
 
        *finfo = def_finfo;
 
+       finfo->cli = cli;
        finfo->mode = CVAL(p,21);
        
        /* this date is converted to GMT by make_unix_date */
index 25c36c214fc006ca29f4a0da92011491230f9fd8..5627d28bb5d455a7024915f0e44356217c00b946 100644 (file)
@@ -323,11 +323,13 @@ BOOL cli_list_user_quota(struct cli_state *cli, int quota_fnum, SMB_NTQUOTA_LIST
 
                if ((tmp_list_ent=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_LIST))==NULL) {
                        DEBUG(0,("talloc_zero() failed\n"));
+                       talloc_destroy(mem_ctx);
                        return (-1);
                }
 
                if ((tmp_list_ent->quotas=TALLOC_ZERO_P(mem_ctx,SMB_NTQUOTA_STRUCT))==NULL) {
                        DEBUG(0,("talloc_zero() failed\n"));
+                       talloc_destroy(mem_ctx);
                        return (-1);
                }
 
index 61cdd79f36b02f11996c21d19cca5515eea35a8d..05dc36e91c3614219b6c399f2a58cd8cf294797d 100644 (file)
 
 #include "includes.h"
 
-
 /****************************************************************************
-Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
+ Call a remote api on an arbitrary pipe.  takes param, data and setup buffers.
 ****************************************************************************/
+
 BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name, 
                   uint16 *setup, uint32 setup_count, uint32 max_setup_count,
                   char *params, uint32 param_count, uint32 max_param_count,
@@ -32,28 +32,29 @@ BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
                   char **rparam, uint32 *rparam_count,
                   char **rdata, uint32 *rdata_count)
 {
-  cli_send_trans(cli, SMBtrans, 
+       cli_send_trans(cli, SMBtrans, 
                  pipe_name, 
                  0,0,                         /* fid, flags */
                  setup, setup_count, max_setup_count,
                  params, param_count, max_param_count,
                  data, data_count, max_data_count);
 
-  return (cli_receive_trans(cli, SMBtrans, 
+       return (cli_receive_trans(cli, SMBtrans, 
                             rparam, (unsigned int *)rparam_count,
                             rdata, (unsigned int *)rdata_count));
 }
 
 /****************************************************************************
-call a remote api
+ Call a remote api
 ****************************************************************************/
+
 BOOL cli_api(struct cli_state *cli,
             char *param, int prcnt, int mprcnt,
             char *data, int drcnt, int mdrcnt,
             char **rparam, unsigned int *rprcnt,
             char **rdata, unsigned int *rdrcnt)
 {
-  cli_send_trans(cli,SMBtrans,
+       cli_send_trans(cli,SMBtrans,
                  PIPE_LANMAN,             /* Name */
                  0,0,                     /* fid, flags */
                  NULL,0,0,                /* Setup, length, max */
@@ -61,15 +62,15 @@ BOOL cli_api(struct cli_state *cli,
                  data, drcnt, mdrcnt      /* Data, length, max */ 
                 );
 
-  return (cli_receive_trans(cli,SMBtrans,
+       return (cli_receive_trans(cli,SMBtrans,
                             rparam, rprcnt,
                             rdata, rdrcnt));
 }
 
-
 /****************************************************************************
-perform a NetWkstaUserLogon
+ Perform a NetWkstaUserLogon.
 ****************************************************************************/
+
 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
 {
        char *rparam = NULL;
@@ -129,8 +130,9 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
 }
 
 /****************************************************************************
-call a NetShareEnum - try and browse available connections on a host
+ Call a NetShareEnum - try and browse available connections on a host.
 ****************************************************************************/
+
 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
 {
        char *rparam = NULL;
@@ -196,14 +198,14 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co
        return count;
 }
 
-
 /****************************************************************************
-call a NetServerEnum for the specified workgroup and servertype mask.  This
-function then calls the specified callback function for each name returned.
+ Call a NetServerEnum for the specified workgroup and servertype mask.  This
+ function then calls the specified callback function for each name returned.
 
-The callback function takes 4 arguments: the machine name, the server type,
-the comment and a state pointer.
+ The callback function takes 4 arguments: the machine name, the server type,
+ the comment and a state pointer.
 ****************************************************************************/
+
 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
                       void (*fn)(const char *, uint32, const char *, void *),
                       void *state)
@@ -286,99 +288,99 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
        return(count > 0);
 }
 
-
-
 /****************************************************************************
-Send a SamOEMChangePassword command
+ Send a SamOEMChangePassword command.
 ****************************************************************************/
+
 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
                              const char *old_password)
 {
-  pstring param;
-  unsigned char data[532];
-  char *p = param;
-  unsigned char old_pw_hash[16];
-  unsigned char new_pw_hash[16];
-  unsigned int data_len;
-  unsigned int param_len = 0;
-  char *rparam = NULL;
-  char *rdata = NULL;
-  unsigned int rprcnt, rdrcnt;
-
-  if (strlen(user) >= sizeof(fstring)-1) {
-    DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
-    return False;
-  }
-
-  SSVAL(p,0,214); /* SamOEMChangePassword command. */
-  p += 2;
-  pstrcpy_base(p, "zsT", param);
-  p = skip_string(p,1);
-  pstrcpy_base(p, "B516B16", param);
-  p = skip_string(p,1);
-  pstrcpy_base(p,user, param);
-  p = skip_string(p,1);
-  SSVAL(p,0,532);
-  p += 2;
-
-  param_len = PTR_DIFF(p,param);
-
-  /*
-   * Get the Lanman hash of the old password, we
-   * use this as the key to make_oem_passwd_hash().
-   */
-  E_deshash(old_password, old_pw_hash);
-
-  encode_pw_buffer(data, new_password, STR_ASCII);
+       pstring param;
+       unsigned char data[532];
+       char *p = param;
+       unsigned char old_pw_hash[16];
+       unsigned char new_pw_hash[16];
+       unsigned int data_len;
+       unsigned int param_len = 0;
+       char *rparam = NULL;
+       char *rdata = NULL;
+       unsigned int rprcnt, rdrcnt;
+
+       if (strlen(user) >= sizeof(fstring)-1) {
+               DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
+               return False;
+       }
+
+       SSVAL(p,0,214); /* SamOEMChangePassword command. */
+       p += 2;
+       pstrcpy_base(p, "zsT", param);
+       p = skip_string(p,1);
+       pstrcpy_base(p, "B516B16", param);
+       p = skip_string(p,1);
+       pstrcpy_base(p,user, param);
+       p = skip_string(p,1);
+       SSVAL(p,0,532);
+       p += 2;
+
+       param_len = PTR_DIFF(p,param);
+
+       /*
+        * Get the Lanman hash of the old password, we
+        * use this as the key to make_oem_passwd_hash().
+        */
+       E_deshash(old_password, old_pw_hash);
+
+       encode_pw_buffer(data, new_password, STR_ASCII);
   
 #ifdef DEBUG_PASSWORD
-  DEBUG(100,("make_oem_passwd_hash\n"));
-  dump_data(100, (char *)data, 516);
+       DEBUG(100,("make_oem_passwd_hash\n"));
+       dump_data(100, (char *)data, 516);
 #endif
-  SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
+       SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
 
-  /* 
-   * Now place the old password hash in the data.
-   */
-  E_deshash(new_password, new_pw_hash);
+       /* 
+        * Now place the old password hash in the data.
+        */
+       E_deshash(new_password, new_pw_hash);
 
-  E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
+       E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
 
-  data_len = 532;
+       data_len = 532;
     
-  if (cli_send_trans(cli,SMBtrans,
+       if (cli_send_trans(cli,SMBtrans,
                     PIPE_LANMAN,                          /* name */
                     0,0,                                  /* fid, flags */
                     NULL,0,0,                             /* setup, length, max */
                     param,param_len,2,                    /* param, length, max */
                     (char *)data,data_len,0                       /* data, length, max */
                    ) == False) {
-    DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
-              user ));
-    return False;
-  }
+               DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
+                       user ));
+               return False;
+       }
 
-  if (!cli_receive_trans(cli,SMBtrans,
+       if (!cli_receive_trans(cli,SMBtrans,
                        &rparam, &rprcnt,
                        &rdata, &rdrcnt)) {
-         DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
-                  user ));
-         return False;
-  }
+               DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
+                       user ));
+               return False;
+       }
   
-  if (rparam)
-         cli->rap_error = SVAL(rparam,0);
+       if (rparam) {
+               cli->rap_error = SVAL(rparam,0);
+       }
   
-  SAFE_FREE(rparam);
-  SAFE_FREE(rdata);
+       SAFE_FREE(rparam);
+       SAFE_FREE(rdata);
 
-  return (cli->rap_error == 0);
+       return (cli->rap_error == 0);
 }
 
-
 /****************************************************************************
-send a qpathinfo call
+ Send a qpathinfo call.
 ****************************************************************************/
+
 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, 
                   time_t *change_time,
                    time_t *access_time,
@@ -458,10 +460,10 @@ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
        return True;
 }
 
-
 /****************************************************************************
-send a setpathinfo call
+ Send a setpathinfo call.
 ****************************************************************************/
+
 BOOL cli_setpathinfo(struct cli_state *cli, const char *fname, 
                      time_t create_time,
                      time_t access_time,
@@ -556,9 +558,8 @@ BOOL cli_setpathinfo(struct cli_state *cli, const char *fname,
        return True;
 }
 
-
 /****************************************************************************
-send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
+ Send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level.
 ****************************************************************************/
 
 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, 
@@ -631,10 +632,10 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
        return True;
 }
 
-
 /****************************************************************************
-send a qfileinfo QUERY_FILE_NAME_INFO call
+ Send a qfileinfo QUERY_FILE_NAME_INFO call.
 ****************************************************************************/
+
 BOOL cli_qfilename(struct cli_state *cli, int fnum, 
                   pstring name)
 {
@@ -674,10 +675,10 @@ BOOL cli_qfilename(struct cli_state *cli, int fnum,
        return True;
 }
 
-
 /****************************************************************************
-send a qfileinfo call
+ Send a qfileinfo call.
 ****************************************************************************/
+
 BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
                   uint16 *mode, SMB_OFF_T *size,
                   struct timespec *create_time,
@@ -749,10 +750,10 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
        return True;
 }
 
-
 /****************************************************************************
-send a qpathinfo BASIC_INFO call
+ Send a qpathinfo BASIC_INFO call.
 ****************************************************************************/
+
 BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name, 
                           SMB_STRUCT_STAT *sbuf, uint32 *attributes )
 {
@@ -765,18 +766,12 @@ BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
        pstring path;
        int len;
        
-       /* send full paths to dfs root shares */
-       
-       if ( cli->dfsroot )
-               pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name );
-       else
-               pstrcpy( path, name );
-       
+       pstrcpy( path, name );
        /* cleanup */
        
        len = strlen( path );
-       if ( path[len] == '\\' )
-               path[len] = '\0';
+       if ( path[len-1] == '\\' || path[len-1] == '/')
+               path[len-1] = '\0';
 
        p = param;
        memset(p, 0, 6);
@@ -820,7 +815,7 @@ BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
 }
 
 /****************************************************************************
-send a qfileinfo call
+ Send a qfileinfo call.
 ****************************************************************************/
 
 BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
@@ -875,11 +870,10 @@ BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutd
        return True;
 }
 
-
-
 /****************************************************************************
-send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
+ Send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call.
 ****************************************************************************/
+
 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
 {
        unsigned int data_len = 0;
index 8628db3abc9d60cc1a945c5bb28939f6928d55da..414c2d491681952d8af3f3f184e54d62c749b571 100644 (file)
@@ -68,6 +68,7 @@ werror_code_struct dos_errs[] =
        { "WERR_DFS_CANT_CREATE_JUNCT", WERR_DFS_CANT_CREATE_JUNCT },
        { "WERR_MACHINE_LOCKED", WERR_MACHINE_LOCKED },
        { "WERR_NO_LOGON_SERVERS", WERR_NO_LOGON_SERVERS },
+       { "WERR_LOGON_FAILURE", WERR_LOGON_FAILURE },
        { "WERR_NO_SUCH_DOMAIN", WERR_NO_SUCH_DOMAIN },
        { "WERR_INVALID_SECURITY_DESCRIPTOR", WERR_INVALID_SECURITY_DESCRIPTOR },
        { "WERR_INVALID_OWNER", WERR_INVALID_OWNER },
@@ -83,8 +84,9 @@ werror_code_struct dos_errs[] =
 };
 
 /*****************************************************************************
returns a DOS error message.  not amazingly helpful, but better than a number.
Returns a DOS error message.  not amazingly helpful, but better than a number.
  *****************************************************************************/
+
 const char *dos_errstr(WERROR werror)
 {
         static pstring msg;
index 6745c0e23a3f157c8dde30daa90e8a8d493ff34b..cb5e8311cad022319315b8ba792edbf905c7da53 100644 (file)
@@ -1511,7 +1511,6 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
        { EACCES, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
        { ENOENT, ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND },
        { ENOTDIR, ERRDOS, ERRbadpath,  NT_STATUS_NOT_A_DIRECTORY },
-       { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
        { EIO, ERRHRD, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
        { EBADF, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
        { EINVAL, ERRSRV, ERRsrverror, NT_STATUS_INVALID_HANDLE },
@@ -1534,6 +1533,9 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
 #ifdef EROFS
        { EROFS, ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
 #endif
+#ifdef ENAMETOOLONG
+       { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
+#endif
 #ifdef EFBIG
        { EFBIG, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL },
 #endif
index 6a154aa68e2b687091c471904f2cdc3490a8b9d7..7fbf5a10c54e686da4683946342c2ce9d48e65fa 100644 (file)
@@ -1116,13 +1116,6 @@ smbc_open_ctx(SMBCCTX *context,
                }
                /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/
                
-               if ( targetcli->dfsroot )
-               {
-                       pstring temppath;
-                       pstrcpy(temppath, targetpath);
-                       cli_dfs_make_full_path( targetpath, targetcli->desthost, targetcli->share, temppath);
-               }
-               
                if ((fd = cli_open(targetcli, targetpath, flags,
                                    context->internal->_share_mode)) < 0) {
 
@@ -1519,14 +1512,6 @@ smbc_getatr(SMBCCTX * context,
                return False;
        }
        
-       if ( targetcli->dfsroot )
-       {
-               pstring temppath;
-               pstrcpy(temppath, targetpath);
-               cli_dfs_make_full_path(targetpath, targetcli->desthost,
-                                       targetcli->share, temppath);
-       }
-  
        if (!srv->no_pathinfo2 &&
             cli_qpathinfo2(targetcli, targetpath,
                            create_time_ts,
index 872ed2bbeaf8c1c04d278eb380a79b38c28994b8..76a4039d823bc2293d579210638df15bda935ef1 100644 (file)
@@ -273,6 +273,9 @@ void brl_init(int read_only)
                        lock_path("brlock.tdb")));
                return;
        }
+
+       /* Activate the per-hashchain freelist */
+       tdb_set_max_dead(tdb, 5);
 }
 
 /****************************************************************************
index ffac43aff5933b18c13aeba05ea9a6758c65e39f..37e6dbc4e54cfd49c1b92b46198632c1e96ae97e 100644 (file)
@@ -222,6 +222,12 @@ struct byte_range_lock *do_lock(files_struct *fsp,
                        lock_flav,
                        blocking_lock);
 
+       /* blocking ie. pending, locks also count here,
+        * as this is an efficiency counter to avoid checking
+        * the lock db. on close. JRA. */
+
+       fsp->current_lock_count++;
+
        return br_lck;
 }
 
@@ -268,6 +274,9 @@ NTSTATUS do_unlock(files_struct *fsp,
                return NT_STATUS_RANGE_NOT_LOCKED;
        }
 
+       SMB_ASSERT(fsp->current_lock_count > 0);
+       fsp->current_lock_count--;
+
        return NT_STATUS_OK;
 }
 
@@ -315,6 +324,9 @@ NTSTATUS do_lock_cancel(files_struct *fsp,
                return NT_STATUS_DOS(ERRDOS, ERRcancelviolation);
        }
 
+       SMB_ASSERT(fsp->current_lock_count > 0);
+       fsp->current_lock_count--;
+
        return NT_STATUS_OK;
 }
 
@@ -330,6 +342,14 @@ void locking_close_file(files_struct *fsp)
                return;
        }
 
+       /* If we have not outstanding locks or pending
+        * locks then we don't need to look in the lock db.
+        */
+
+       if (fsp->current_lock_count == 0) {
+               return;
+       }
+
        br_lck = brl_get_locks(NULL,fsp);
 
        if (br_lck) {
@@ -363,6 +383,9 @@ BOOL locking_init(int read_only)
                return False;
        }
 
+       /* Activate the per-hashchain freelist */
+       tdb_set_max_dead(tdb, 5);
+
        if (!posix_locking_init(read_only))
                return False;
 
@@ -858,15 +881,29 @@ BOOL rename_share_filename(struct share_mode_lock *lck,
        return True;
 }
 
-BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+static int pull_delete_on_close_flag(TDB_DATA key, TDB_DATA dbuf,
+                                    void *private_data)
 {
-       BOOL result;
-       struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, NULL, NULL);
-       if (!lck) {
-               return False;
+       BOOL *result = (BOOL *)private_data;
+       struct locking_data *data;
+
+       if (dbuf.dsize < sizeof(struct locking_data)) {
+               smb_panic("PANIC: parse_share_modes: buffer too short.\n");
        }
-       result = lck->delete_on_close;
-       TALLOC_FREE(lck);
+
+       data = (struct locking_data *)dbuf.dptr;
+
+       *result = data->u.s.delete_on_close;
+       return 0;
+}
+
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
+{
+       TDB_DATA key = locking_key(dev, inode);
+       BOOL result = False;
+
+       tdb_parse_record(tdb, key, pull_delete_on_close_flag,
+                        (void *)&result);
        return result;
 }
 
index 91ebba1f5889bd2e2e4c361c74bbbbc998df67ed..dd4524085792413dc9c02642c02657216d585ebf 100644 (file)
@@ -604,31 +604,33 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp,
        if (smbacl4_GetFileOwner(fsp, &sbuf))
                return False;
 
-       /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
-       if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd))
-       {
-               DEBUG(8, ("unpack_nt_owners failed"));
-               return False;
-       }
-       if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) ||
-               ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
-               need_chown = True;
-       }
-       if (need_chown) {
-               if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) {
-                       if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
-                               DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
-                                       fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) ));
-                               return False;
+       if (params.do_chown) {
+               /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
+               if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd))
+               {
+                       DEBUG(8, ("unpack_nt_owners failed"));
+                       return False;
+               }
+               if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) ||
+                       ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) {
+                       need_chown = True;
+               }
+               if (need_chown) {
+                       if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) {
+                               if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) {
+                                       DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n",
+                                               fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) ));
+                                       return False;
+                               }
+                               DEBUG(10,("chown %s, %u, %u succeeded.\n",
+                                       fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
+                               if (smbacl4_GetFileOwner(fsp, &sbuf))
+                                       return False;
+                               need_chown = False;
+                       } else { /* chown is needed, but _after_ changing acl */
+                               sbuf.st_uid = newUID; /* OWNER@ in case of e_special */
+                               sbuf.st_gid = newGID; /* GROUP@ in case of e_special */
                        }
-                       DEBUG(10,("chown %s, %u, %u succeeded.\n",
-                               fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID));
-                       if (smbacl4_GetFileOwner(fsp, &sbuf))
-                               return False;
-                       need_chown = False;
-               } else { /* chown is needed, but _after_ changing acl */
-                       sbuf.st_uid = newUID; /* OWNER@ in case of e_special */
-                       sbuf.st_gid = newGID; /* GROUP@ in case of e_special */
                }
        }
 
index e058c9660c79f73669490e48054fee16af31b2b3..f89e149d0eb227e30c74c0871ce162134e6ab65d 100644 (file)
@@ -131,11 +131,11 @@ static int cap_chdir(vfs_handle_struct *handle, const char *path)
        return SMB_VFS_NEXT_CHDIR(handle, cappath);
 }
 
-static int cap_utime(vfs_handle_struct *handle, const char *path, struct utimbuf *times)
+static int cap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
 {
         pstring cappath;
        capencode(cappath, path);
-       return SMB_VFS_NEXT_UTIME(handle, cappath, times);
+       return SMB_VFS_NEXT_NTIMES(handle, cappath, ts);
 }
 
 
@@ -327,7 +327,7 @@ static vfs_op_tuple cap_op_tuples[] = {
        {SMB_VFS_OP(cap_chmod),                 SMB_VFS_OP_CHMOD,               SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(cap_chown),                 SMB_VFS_OP_CHOWN,               SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(cap_chdir),                 SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
-       {SMB_VFS_OP(cap_utime),                 SMB_VFS_OP_UTIME,               SMB_VFS_LAYER_TRANSPARENT},
+       {SMB_VFS_OP(cap_ntimes),                        SMB_VFS_OP_NTIMES,              SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(cap_symlink),                       SMB_VFS_OP_SYMLINK,             SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(cap_readlink),                      SMB_VFS_OP_READLINK,            SMB_VFS_LAYER_TRANSPARENT},
        {SMB_VFS_OP(cap_link),                          SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
index 478dab6cbedc896cc37a8e256e766c546fd2d8be..fe1ce830f7b7a5bba31476f89a3e1efb8b5fbd0d 100644 (file)
@@ -184,10 +184,10 @@ static char *catia_getwd(vfs_handle_struct *handle, char *buf)
         return SMB_VFS_NEXT_GETWD(handle, buf);
 }
 
-static int catia_utime(vfs_handle_struct *handle,
-                      const char *path, struct utimbuf *times)
+static int catia_ntimes(vfs_handle_struct *handle,
+                      const char *path, const struct timespec ts[2])
 {
-        return SMB_VFS_NEXT_UTIME(handle, path, times);
+        return SMB_VFS_NEXT_NTIMES(handle, path, ts);
 }
 
 static BOOL catia_symlink(vfs_handle_struct *handle,
@@ -278,7 +278,7 @@ SMB_VFS_LAYER_TRANSPARENT},
 SMB_VFS_LAYER_TRANSPARENT},
         {SMB_VFS_OP(catia_getwd),                       SMB_VFS_OP_GETWD,  
 SMB_VFS_LAYER_TRANSPARENT},
-        {SMB_VFS_OP(catia_utime),                       SMB_VFS_OP_UTIME,  
+        {SMB_VFS_OP(catia_ntimes),                       SMB_VFS_OP_NTIMES,  
 SMB_VFS_LAYER_TRANSPARENT},
         {SMB_VFS_OP(catia_symlink), SMB_VFS_OP_SYMLINK, 
 SMB_VFS_LAYER_TRANSPARENT},
index bd7bea5258a405e1e446dc90c97f116702ebd5f9..4febc064d9449bd225caae757728c793e6b42add 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    Wrap disk only vfs functions to sidestep dodgy compilers.
    Copyright (C) Tim Potter 1998
+   Copyright (C) Jeremy Allison 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
@@ -612,13 +613,35 @@ static char *vfswrap_getwd(vfs_handle_struct *handle,  char *path)
        return result;
 }
 
-static int vfswrap_utime(vfs_handle_struct *handle,  const char *path, struct utimbuf *times)
+/*********************************************************************
+ nsec timestamp resolution call. Convert down to whatever the underlying
+ system will support.
+**********************************************************************/
+
+static int vfswrap_ntimes(vfs_handle_struct *handle, const char *path, const struct timespec ts[2])
 {
        int result;
 
-       START_PROFILE(syscall_utime);
-       result = utime(path, times);
-       END_PROFILE(syscall_utime);
+       START_PROFILE(syscall_ntimes);
+#if defined(HAVE_UTIMES)
+       {
+               struct timeval tv[2];
+               tv[0] = convert_timespec_to_timeval(ts[0]);
+               tv[1] = convert_timespec_to_timeval(ts[1]);
+               result = utimes(path, tv);
+       }
+#elif defined(HAVE_UTIME)
+       {
+               struct utimebuf times;
+               times.actime = convert_timespec_to_time_t(ts[0]);
+               times.modtime = convert_timespec_to_time_t(ts[1]);
+               result = utime(path, times);
+       }
+#else
+       errno = ENOSYS;
+       result = -1;
+#endif
+       END_PROFILE(syscall_ntimes);
        return result;
 }
 
@@ -786,7 +809,7 @@ static BOOL vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, int fd
 static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp, int fd,
                                int leasetype)
 {
-       int result;
+       int result = -1;
 
        START_PROFILE(syscall_linux_setlease);
 
@@ -796,7 +819,8 @@ static int vfswrap_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
                return -1;
 
        result = linux_setlease(fd, leasetype);
-       
+#else
+       errno = ENOSYS;
 #endif
        END_PROFILE(syscall_linux_setlease);
        return result;
@@ -879,6 +903,12 @@ static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle,
        return NT_STATUS_OK;
 }
 
+static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags)
+{
+       errno = ENOSYS;
+       return -1;
+}
+
 static size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc)
 {
        size_t result;
@@ -1238,7 +1268,7 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_getwd),     SMB_VFS_OP_GETWD,
         SMB_VFS_LAYER_OPAQUE},
-       {SMB_VFS_OP(vfswrap_utime),     SMB_VFS_OP_UTIME,
+       {SMB_VFS_OP(vfswrap_ntimes),    SMB_VFS_OP_NTIMES,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_ftruncate), SMB_VFS_OP_FTRUNCATE,
         SMB_VFS_LAYER_OPAQUE},
@@ -1262,6 +1292,8 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_notify_watch),      SMB_VFS_OP_NOTIFY_WATCH,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_chflags),   SMB_VFS_OP_CHFLAGS,
+        SMB_VFS_LAYER_OPAQUE},
 
        /* NT ACL operations. */
 
index 6036e49fc15702097d57e7fce2c63d87f9dbec9a..62530fb09cedb1d204171f2e91901aa15b09fcd5 100644 (file)
@@ -151,8 +151,8 @@ static int smb_full_audit_chdir(vfs_handle_struct *handle,
                       const char *path);
 static char *smb_full_audit_getwd(vfs_handle_struct *handle,
                         char *path);
-static int smb_full_audit_utime(vfs_handle_struct *handle,
-                      const char *path, struct utimbuf *times);
+static int smb_full_audit_ntimes(vfs_handle_struct *handle,
+                      const char *path, const struct timespec ts[2]);
 static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp,
                           int fd, SMB_OFF_T len);
 static BOOL smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, int fd,
@@ -174,6 +174,15 @@ static int smb_full_audit_mknod(vfs_handle_struct *handle,
                       const char *pathname, mode_t mode, SMB_DEV_T dev);
 static char *smb_full_audit_realpath(vfs_handle_struct *handle,
                            const char *path, char *resolved_path);
+static NTSTATUS smb_full_audit_notify_watch(struct vfs_handle_struct *handle,
+                       struct sys_notify_context *ctx,
+                       struct notify_entry *e,
+                       void (*callback)(struct sys_notify_context *ctx,
+                                       void *private_data,
+                                       struct notify_event *ev),
+                       void *private_data, void *handle_p);
+static int smb_full_audit_chflags(vfs_handle_struct *handle,
+                           const char *path, uint flags);
 static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                int fd, uint32 security_info,
                                SEC_DESC **ppdesc);
@@ -375,7 +384,7 @@ static vfs_op_tuple audit_op_tuples[] = {
         SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_getwd),      SMB_VFS_OP_GETWD,
         SMB_VFS_LAYER_LOGGER},
-       {SMB_VFS_OP(smb_full_audit_utime),      SMB_VFS_OP_UTIME,
+       {SMB_VFS_OP(smb_full_audit_ntimes),     SMB_VFS_OP_NTIMES,
         SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_ftruncate),  SMB_VFS_OP_FTRUNCATE,
         SMB_VFS_LAYER_LOGGER},
@@ -397,6 +406,10 @@ static vfs_op_tuple audit_op_tuples[] = {
         SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_realpath),   SMB_VFS_OP_REALPATH,
         SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_full_audit_notify_watch),SMB_VFS_OP_NOTIFY_WATCH,
+        SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_full_audit_chflags),    SMB_VFS_OP_CHFLAGS,
+        SMB_VFS_LAYER_LOGGER},
 
        /* NT ACL operations. */
 
@@ -549,7 +562,7 @@ static struct {
        { SMB_VFS_OP_FCHOWN,    "fchown" },
        { SMB_VFS_OP_CHDIR,     "chdir" },
        { SMB_VFS_OP_GETWD,     "getwd" },
-       { SMB_VFS_OP_UTIME,     "utime" },
+       { SMB_VFS_OP_NTIMES,    "ntimes" },
        { SMB_VFS_OP_FTRUNCATE, "ftruncate" },
        { SMB_VFS_OP_LOCK,      "lock" },
        { SMB_VFS_OP_KERNEL_FLOCK,      "kernel_flock" },
@@ -560,6 +573,8 @@ static struct {
        { SMB_VFS_OP_LINK,      "link" },
        { SMB_VFS_OP_MKNOD,     "mknod" },
        { SMB_VFS_OP_REALPATH,  "realpath" },
+       { SMB_VFS_OP_NOTIFY_WATCH, "notify_watch" },
+       { SMB_VFS_OP_CHFLAGS,   "chflags" },
        { SMB_VFS_OP_FGET_NT_ACL,       "fget_nt_acl" },
        { SMB_VFS_OP_GET_NT_ACL,        "get_nt_acl" },
        { SMB_VFS_OP_FSET_NT_ACL,       "fset_nt_acl" },
@@ -1267,14 +1282,14 @@ static char *smb_full_audit_getwd(vfs_handle_struct *handle,
        return result;
 }
 
-static int smb_full_audit_utime(vfs_handle_struct *handle,
-                      const char *path, struct utimbuf *times)
+static int smb_full_audit_ntimes(vfs_handle_struct *handle,
+                      const char *path, const struct timespec ts[2])
 {
        int result;
 
-       result = SMB_VFS_NEXT_UTIME(handle, path, times);
+       result = SMB_VFS_NEXT_NTIMES(handle, path, ts);
 
-       do_log(SMB_VFS_OP_UTIME, (result >= 0), handle, "%s", path);
+       do_log(SMB_VFS_OP_NTIMES, (result >= 0), handle, "%s", path);
 
        return result;
 }
@@ -1405,6 +1420,35 @@ static char *smb_full_audit_realpath(vfs_handle_struct *handle,
        return result;
 }
 
+static NTSTATUS smb_full_audit_notify_watch(struct vfs_handle_struct *handle,
+                       struct sys_notify_context *ctx,
+                       struct notify_entry *e,
+                       void (*callback)(struct sys_notify_context *ctx,
+                                       void *private_data,
+                                       struct notify_event *ev),
+                       void *private_data, void *handle_p)
+{
+       NTSTATUS result;
+
+       result = SMB_VFS_NEXT_NOTIFY_WATCH(handle, ctx, e, callback, private_data, handle_p);
+
+       do_log(SMB_VFS_OP_NOTIFY_WATCH, NT_STATUS_IS_OK(result), handle, "");
+
+       return result;
+}
+
+static int smb_full_audit_chflags(vfs_handle_struct *handle,
+                           const char *path, uint flags)
+{
+       int result;
+
+       result = SMB_VFS_NEXT_CHFLAGS(handle, path, flags);
+
+       do_log(SMB_VFS_OP_CHFLAGS, (result != 0), handle, "%s", path);
+
+       return result;
+}
+
 static size_t smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp,
                                int fd, uint32 security_info,
                                SEC_DESC **ppdesc)
index 7176919a7dc01165b438cc01708d5e3a16df7831..efcc98167945c9e9059e192b9c7fd1196ac68299 100644 (file)
@@ -241,7 +241,7 @@ static int atalk_rename(struct vfs_handle_struct *handle, const char *oldname, c
 
        if (atalk_build_paths(ctx, handle->conn->origpath, oldname, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
-               return ret;
+               goto exit_rename;
 
        if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) {
                DEBUG(3, ("ATALK: %s has passed..\n", adbl_path));              
@@ -297,7 +297,7 @@ static int atalk_unlink(struct vfs_handle_struct *handle, const char *path)
 
        if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
-               return ret;
+               goto exit_unlink;
 
        if (S_ISDIR(orig_info.st_mode) || S_ISREG(orig_info.st_mode)) {
                DEBUG(3, ("ATALK: %s has passed..\n", adbl_path));
@@ -329,7 +329,7 @@ static int atalk_chmod(struct vfs_handle_struct *handle, const char *path, mode_
 
        if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
-               return ret;
+               goto exit_chmod;
 
        if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) {
                DEBUG(3, ("ATALK: %s has passed..\n", orig_path));              
@@ -361,7 +361,7 @@ static int atalk_chown(struct vfs_handle_struct *handle, const char *path, uid_t
 
        if (atalk_build_paths(ctx, handle->conn->origpath, path, &adbl_path, &orig_path,
          &adbl_info, &orig_info) != 0)
-               return ret;
+               goto exit_chown;
 
        if (!S_ISDIR(orig_info.st_mode) && !S_ISREG(orig_info.st_mode)) {
                DEBUG(3, ("ATALK: %s has passed..\n", orig_path));              
index 121454315fb82791a17f71815144131d7ca181ee..579cc94cf942f99254075ae3e2feae8e72f96b42 100644 (file)
@@ -153,17 +153,30 @@ static const char **recycle_noversions(vfs_handle_struct *handle)
        return tmp_lp;
 }
 
-static int recycle_maxsize(vfs_handle_struct *handle)
+static SMB_OFF_T recycle_maxsize(vfs_handle_struct *handle)
 {
-       int maxsize;
+       SMB_OFF_T maxsize;
        
-       maxsize = lp_parm_int(SNUM(handle->conn), "recycle", "maxsize", -1);
+       maxsize = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+                                           "recycle", "maxsize", NULL));
 
-       DEBUG(10, ("recycle: maxsize = %d\n", maxsize));
+       DEBUG(10, ("recycle: maxsize = %lu\n", (long unsigned int)maxsize));
        
        return maxsize;
 }
 
+static SMB_OFF_T recycle_minsize(vfs_handle_struct *handle)
+{
+       SMB_OFF_T minsize;
+       
+       minsize = conv_str_size(lp_parm_const_string(SNUM(handle->conn),
+                                           "recycle", "minsize", NULL));
+
+       DEBUG(10, ("recycle: minsize = %lu\n", (long unsigned int)minsize));
+       
+       return minsize;
+}
+
 static mode_t recycle_directory_mode(vfs_handle_struct *handle)
 {
        int dirmode;
@@ -351,18 +364,16 @@ static BOOL matchparam(const char **haystack_list, const char *needle)
 static void recycle_do_touch(vfs_handle_struct *handle, const char *fname, BOOL touch_mtime)
 {
        SMB_STRUCT_STAT st;
-       struct utimbuf tb;
-       time_t currtime;
+       struct timespec ts[2];
        
        if (SMB_VFS_NEXT_STAT(handle, fname, &st) != 0) {
                DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno)));
                return;
        }
-       currtime = time(&currtime);
-       tb.actime = currtime;
-       tb.modtime = touch_mtime ? currtime : st.st_mtime;
+       ts[0] = timespec_current(); /* atime */
+       ts[1] = touch_mtime ? ts[0] : get_mtimespec(&st); /* mtime */
 
-       if (SMB_VFS_NEXT_UTIME(handle, fname, &tb) == -1 ) {
+       if (SMB_VFS_NEXT_NTIMES(handle, fname, ts) == -1 ) {
                DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno)));
        }
 }
@@ -381,7 +392,7 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
        const char *base;
        char *repository = NULL;
        int i = 1;
-       int maxsize;
+       SMB_OFF_T maxsize, minsize;
        SMB_OFF_T file_size; /* space_avail;    */
        BOOL exist;
        int rc = -1;
@@ -431,6 +442,12 @@ static int recycle_unlink(vfs_handle_struct *handle, const char *file_name)
                rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
                goto done;
        }
+       minsize = recycle_minsize(handle);
+       if(minsize > 0 && file_size < minsize) {
+               DEBUG(3, ("recycle: File %s lowers minimum recycle size, purging... \n", file_name));
+               rc = SMB_VFS_NEXT_UNLINK(handle, file_name);
+               goto done;
+       }
 
        /* FIXME: this is wrong: moving files with rename does not change the disk space
         * allocation
index a58959afe4c36586e6055d84258c6307d593b293..c2a38fa979720fc4da12536f201ee19eb3742300 100644 (file)
@@ -297,7 +297,6 @@ NTSTATUS idmap_init(void)
                char *p = NULL;
                const char *q = NULL;           
 
-               DEBUG(0, ("WARNING: idmap backend is deprecated!\n"));
                compat = 1;
 
                if ( (compat_backend = talloc_strdup( idmap_ctx, *compat_list )) == NULL ) {
@@ -337,6 +336,15 @@ NTSTATUS idmap_init(void)
                const char *parm_backend;
                char *config_option;
 
+               /* ignore BUILTIN and local MACHINE domains */
+               if ( strequal(dom_list[i], "BUILTIN") 
+                    || strequal(dom_list[i], get_global_sam_name() ) ) 
+               {
+                       DEBUG(0,("idmap_init: Ignoring invalid domain %s\n", 
+                                dom_list[i]));
+                       continue;
+               }
+
                if (strequal(dom_list[i], lp_workgroup())) {
                        pri_dom_is_in_list = True;
                }
@@ -577,17 +585,22 @@ NTSTATUS idmap_init(void)
                        alloc_methods = get_alloc_methods(alloc_backends, alloc_backend);
                }
        }
-       if ( ! alloc_methods) {
-               DEBUG(0, ("ERROR: Could not get methods for alloc backend %s\n", alloc_backend));
-               ret = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       ret = alloc_methods->init(compat_params);
-       if ( ! NT_STATUS_IS_OK(ret)) {
-               DEBUG(0, ("ERROR: Initialization failed for alloc backend %s\n", alloc_backend));
-               ret = NT_STATUS_UNSUCCESSFUL;
-               goto done;
+       if ( alloc_methods) {
+               ret = alloc_methods->init(compat_params);
+               if ( ! NT_STATUS_IS_OK(ret)) {
+                       DEBUG(0, ("idmap_init: Initialization failed for alloc "
+                                 "backend %s\n", alloc_backend));
+                       ret = NT_STATUS_UNSUCCESSFUL;
+                       goto done;
+               }
+       } else {
+               DEBUG(2, ("idmap_init: Unable to get methods for alloc backend %s\n", 
+                         alloc_backend));
+               /* certain compat backends are just readonly */
+               if ( compat )
+                       ret = NT_STATUS_OK;
+               else
+                       ret = NT_STATUS_UNSUCCESSFUL;
        }
 
        /* cleanpu temporary strings */
@@ -595,7 +608,7 @@ NTSTATUS idmap_init(void)
        
        backend_init_status = NT_STATUS_OK;
        
-       return NT_STATUS_OK;
+       return ret;
 
 done:
        DEBUG(0, ("Aborting IDMAP Initialization ...\n"));
index 8cccbcecf4c48cb2c079961847abf77bd4a0867c..f74372eceab660a3b25bae75fe500885c8c0c777 100644 (file)
@@ -1283,6 +1283,9 @@ static NTSTATUS idmap_ldap_set_mapping(struct idmap_domain *dom, const struct id
                         sid, (unsigned long)map->xid.id, type));
                DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", 
                        ld_error ? ld_error : "(NULL)", ldap_err2string (rc)));
+               if (ld_error) {
+                       ldap_memfree(ld_error);
+               }
                ret = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
index d21c985feeef2de39bfbedb5e21f1da05f7195ca..66f9a0931443e124e09872ce3584721e8543e866 100644 (file)
@@ -436,7 +436,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
        /* Fill in request and send down pipe */
        init_request(request, req_type);
        
-       if (write_sock(request, sizeof(*request), 0) == -1) {
+       if (write_sock(request, sizeof(*request), 0, 1) == -1) {
                _pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!");
                close_sock();
                return PAM_SERVICE_ERR;
@@ -1517,7 +1517,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
        dictionary *d = NULL;
        char *username_ret = NULL;
        char *new_authtok_required = NULL;
-       char *combined_member = NULL;
        const char *real_username = NULL;
 
        /* parse arguments */
index 05d2a660e73b27b59f92047056ed8457deee5ea0..fb84373aa63e372dd4bb68c455505147d497a3ee 100644 (file)
@@ -33,6 +33,7 @@ BOOL winbind_on( void );
 /* Global variables.  These are effectively the client state information */
 
 int winbindd_fd = -1;           /* fd for winbindd socket */
+static int is_privileged = 0;
 
 /* Free a response structure */
 
@@ -287,7 +288,7 @@ static int winbind_named_pipe_sock(const char *dir)
 
 /* Connect to winbindd socket */
 
-static int winbind_open_pipe_sock(int recursing)
+static int winbind_open_pipe_sock(int recursing, int need_priv)
 {
 #ifdef HAVE_UNIXSOCKET
        static pid_t our_pid;
@@ -300,6 +301,10 @@ static int winbind_open_pipe_sock(int recursing)
                close_sock();
                our_pid = getpid();
        }
+
+       if ((need_priv != 0) && (is_privileged == 0)) {
+               close_sock();
+       }
        
        if (winbindd_fd != -1) {
                return winbindd_fd;
@@ -313,6 +318,8 @@ static int winbind_open_pipe_sock(int recursing)
                return -1;
        }
 
+       is_privileged = 0;
+
        /* version-check the socket */
 
        request.flags = WBFLAG_RECURSE;
@@ -329,9 +336,14 @@ static int winbind_open_pipe_sock(int recursing)
                if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) {
                        close(winbindd_fd);
                        winbindd_fd = fd;
+                       is_privileged = 1;
                }
        }
 
+       if ((need_priv != 0) && (is_privileged == 0)) {
+               return -1;
+       }
+
        SAFE_FREE(response.extra_data.data);
 
        return winbindd_fd;
@@ -342,7 +354,7 @@ static int winbind_open_pipe_sock(int recursing)
 
 /* Write data to winbindd socket */
 
-int write_sock(void *buffer, int count, int recursing)
+int write_sock(void *buffer, int count, int recursing, int need_priv)
 {
        int result, nwritten;
        
@@ -350,7 +362,7 @@ int write_sock(void *buffer, int count, int recursing)
        
  restart:
        
-       if (winbind_open_pipe_sock(recursing) == -1) {
+       if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
                return -1;
        }
        
@@ -536,7 +548,8 @@ BOOL winbind_env_set( void )
  * send simple types of requests 
  */
 
-NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
+NSS_STATUS winbindd_send_request(int req_type, int need_priv,
+                                struct winbindd_request *request)
 {
        struct winbindd_request lrequest;
 
@@ -555,12 +568,14 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
 
        init_request(request, req_type);
        
-       if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) {
+       if (write_sock(request, sizeof(*request),
+                      request->flags & WBFLAG_RECURSE, need_priv) == -1) {
                return NSS_STATUS_UNAVAIL;
        }
 
        if ((request->extra_len != 0) &&
-           (write_sock(request->extra_data.data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) {
+           (write_sock(request->extra_data.data, request->extra_len,
+                       request->flags & WBFLAG_RECURSE, need_priv) == -1)) {
                return NSS_STATUS_UNAVAIL;
        }
        
@@ -610,7 +625,25 @@ NSS_STATUS winbindd_request_response(int req_type,
        int count = 0;
 
        while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
-               status = winbindd_send_request(req_type, request);
+               status = winbindd_send_request(req_type, 0, request);
+               if (status != NSS_STATUS_SUCCESS) 
+                       return(status);
+               status = winbindd_get_response(response);
+               count += 1;
+       }
+
+       return status;
+}
+
+NSS_STATUS winbindd_priv_request_response(int req_type, 
+                                         struct winbindd_request *request,
+                                         struct winbindd_response *response)
+{
+       NSS_STATUS status = NSS_STATUS_UNAVAIL;
+       int count = 0;
+
+       while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
+               status = winbindd_send_request(req_type, 1, request);
                if (status != NSS_STATUS_SUCCESS) 
                        return(status);
                status = winbindd_get_response(response);
index 1d3d379af00d0f35b57eef58c6db7ae41b467244..d80aff37fa1d40f37b5e2c71945ced28730d99b1 100644 (file)
@@ -2,13 +2,16 @@
 #include "winbindd_nss.h"
 
 void init_request(struct winbindd_request *req,int rq_type);
-NSS_STATUS winbindd_send_request(int req_type,
+NSS_STATUS winbindd_send_request(int req_type, int need_priv,
                                 struct winbindd_request *request);
 NSS_STATUS winbindd_get_response(struct winbindd_response *response);
 NSS_STATUS winbindd_request_response(int req_type, 
                            struct winbindd_request *request,
                            struct winbindd_response *response);
-int write_sock(void *buffer, int count, int recursing);
+NSS_STATUS winbindd_priv_request_response(int req_type, 
+                                         struct winbindd_request *request,
+                                         struct winbindd_response *response);
+int write_sock(void *buffer, int count, int recursing, int need_priv);
 int read_reply(struct winbindd_response *response);
 void close_sock(void);
 void free_response(struct winbindd_response *response);
index 2fbf3e0df827b08f69ddfd0ab23f477549602edc..5c6679f04425a43bd28df470b91c80e1a582817c 100644 (file)
@@ -454,7 +454,7 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
        nsd_logprintf(NSD_LOG_MIN,
                "send_next_request (winbind) %d, timeout = %d sec\n",
                        rq->f_cmd_data, timeout);
-       status = winbindd_send_request((int)rq->f_cmd_data,request);
+       status = winbindd_send_request((int)rq->f_cmd_data,request,0);
        SAFE_FREE(request);
 
        if (status != NSS_STATUS_SUCCESS) {
index 3ddb041ba072bf9ab89eeeaea285e9db7cf7840f..3b518fe3206f6486669eb911dc67ae9780eeb001 100644 (file)
@@ -726,6 +726,15 @@ static void process_loop(void)
        int maxfd, listen_sock, listen_priv_sock, selret;
        struct timeval timeout, ev_timeout;
 
+       /* Open Sockets here to get stuff going ASAP */
+       listen_sock = open_winbindd_socket();
+       listen_priv_sock = open_winbindd_priv_socket();
+
+       if (listen_sock == -1 || listen_priv_sock == -1) {
+               perror("open_winbind_socket");
+               exit(1);
+       }
+
        /* We'll be doing this a lot */
 
        /* Handle messages */
@@ -745,14 +754,6 @@ static void process_loop(void)
 
        /* Initialise fd lists for select() */
 
-       listen_sock = open_winbindd_socket();
-       listen_priv_sock = open_winbindd_priv_socket();
-
-       if (listen_sock == -1 || listen_priv_sock == -1) {
-               perror("open_winbind_socket");
-               exit(1);
-       }
-
        maxfd = MAX(listen_sock, listen_priv_sock);
 
        FD_ZERO(&r_fds);
index b9e07a2321b87c60032a5c9092f4b0a74331d1ea..198c655b2d38a5da969bf1e30f0024422a0865d6 100644 (file)
@@ -40,6 +40,8 @@
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+#define WB_REPLACE_CHAR                '_'
+
 /* bits for fd_event.flags */
 #define EVENT_FD_READ 1
 #define EVENT_FD_WRITE 2
index ea6dc2870a02d6fd1c5f2266b2c6498f0a549d41..3925228efc6e0cabcc0a829792743c5467d28b07 100644 (file)
@@ -40,6 +40,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 {
        ADS_STRUCT *ads;
        ADS_STATUS status;
+       fstring dc_name;
+       struct in_addr dc_ip;   
 
        DEBUG(10,("ads_cached_connection\n"));
 
@@ -114,6 +116,12 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
 
        ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;
 
+       /* Setup the server affinity cache.  We don't reaally care
+          about the name.  Just setup affinity and the KRB5_CONFIG 
+          file. */
+
+       get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ip );
+       
        status = ads_connect(ads);
        if (!ADS_ERR_OK(status) || !ads->config.realm) {
                DEBUG(1,("ads_connect for domain %s failed: %s\n", 
@@ -607,7 +615,6 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
        const char *attrs[] = {"memberOf", NULL};
        size_t num_groups = 0;
        DOM_SID *group_sids = NULL;
-       char *escaped_dn;
        int i;
 
        DEBUG(3,("ads: lookup_usergroups_memberof\n"));
@@ -619,16 +626,9 @@ static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
                goto done;
        }
 
-       if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) {
-               status = NT_STATUS_NO_MEMORY;
-               goto done;
-       }
-
-       rc = ads_search_retry_extended_dn(ads, &res, escaped_dn, attrs, 
+       rc = ads_search_retry_extended_dn(ads, &res, user_dn, attrs, 
                                          ADS_EXTENDED_DN_HEX_STRING);
        
-       SAFE_FREE(escaped_dn);
-
        if (!ADS_ERR_OK(rc) || !res) {
                DEBUG(1,("lookup_usergroups_memberof ads_search member=%s: %s\n", 
                        user_dn, ads_errstr(rc)));
index d0904002dd96592935e828b7b2e466bded712bc0..f161587e7aaf65a55c3237e83a38641c60d27e75 100644 (file)
@@ -517,6 +517,7 @@ static NTSTATUS store_memory_creds(struct WINBINDD_MEMORY_CREDS *memcredp, const
        if ((mlock(memcredp->nt_hash, memcredp->len)) == -1) {
                DEBUG(0,("failed to mlock memory: %s (%d)\n", 
                        strerror(errno), errno));
+               SAFE_FREE(memcredp->nt_hash);
                return map_nt_error_from_unix(errno);
        }
 
index 6324de9a2d9dfae256b6750724ec69fda1e36ba4..26debd26745b9304e71dc7794c0eba360a8628e3 100644 (file)
@@ -573,8 +573,8 @@ void winbind_msg_online(int msg_type, struct process_id src,
                winbindd_flush_negative_conn_cache(domain);
                set_domain_online_request(domain);
 
-               /* Send an offline message to the idmap child when our
-                  primary domain goes offline */
+               /* Send an online message to the idmap child when our
+                  primary domain comes back online */
 
                if ( domain->primary ) {
                        struct winbindd_child *idmap = idmap_child();
index 7edb755f1c01c9b9fd2fea0afc3f7a73cdbecc88..9cf6cc12e0fddbc1875512b9d837691dd06587f1 100644 (file)
@@ -228,10 +228,12 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
         * from more than one domain, ie aliases. Thus we have to work it out
         * ourselves in a special routine. */
 
-       if (domain->internal)
-               return fill_passdb_alias_grmem(domain, group_sid,
+       if (domain->internal) {
+               result = fill_passdb_alias_grmem(domain, group_sid,
                                               num_gr_mem,
                                               gr_mem, gr_mem_len);
+               goto done;
+       }
        
        if ( !((group_name_type==SID_NAME_DOM_GRP) ||
                ((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
@@ -506,7 +508,7 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
 
        /* Get rid and name type from name */
 
-       ws_name_replace( name_group, '_' );
+       ws_name_replace( name_group, WB_REPLACE_CHAR );
         
        if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, domain->name,
                                         name_group, &group_sid, &name_type)) {
@@ -1273,6 +1275,8 @@ void winbindd_getgroups(struct winbindd_cli_state *state)
 
        s->state = state;
 
+       ws_name_return( state->request.data.username, WB_REPLACE_CHAR );
+
        if (!parse_domain_user_talloc(state->mem_ctx,
                                      state->request.data.username,
                                      &s->domname, &s->username)) {
index 2e679c37dcf73759a53c5f950bf58f0866aaca27..6ee548292ccf6d2342e3c47db4c2f0ddc735546b 100644 (file)
@@ -744,6 +744,8 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
 
        /* Parse domain and username */
        
+       ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
+
        if (!canonicalize_username(state->request.data.auth.user,
                               name_domain, name_user)) {
                set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
@@ -1332,6 +1334,8 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
 
        /* Parse domain and username */
        
+       ws_name_return( state->request.data.auth.user, WB_REPLACE_CHAR );
+
        parse_domain_user(state->request.data.auth.user, name_domain, name_user);
 
        if (domain->online == False) {
@@ -2088,7 +2092,9 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
 {
        struct winbindd_domain *domain;
        fstring name_domain, user;
-       
+       uid_t caller_uid = (uid_t)-1;
+       uid_t request_uid = state->request.data.logoff.uid;
+
        DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
                state->request.data.logoff.user));
 
@@ -2099,6 +2105,10 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
        state->request.data.logoff.krb5ccname
                [sizeof(state->request.data.logoff.krb5ccname)-1]='\0';
 
+       if (request_uid == (gid_t)-1) {
+               goto failed;
+       }
+
        if (!canonicalize_username(state->request.data.logoff.user, name_domain, user)) {
                goto failed;
        }
@@ -2107,6 +2117,28 @@ void winbindd_pam_logoff(struct winbindd_cli_state *state)
                goto failed;
        }
 
+       if ((sys_getpeereid(state->sock, &caller_uid)) != 0) {
+               DEBUG(1,("winbindd_pam_logoff: failed to check peerid: %s\n", 
+                       strerror(errno)));
+               goto failed;
+       }
+
+       switch (caller_uid) {
+               case -1:
+                       goto failed;
+               case 0:
+                       /* root must be able to logoff any user - gd */
+                       state->request.data.logoff.uid = request_uid;
+                       break;
+               default:
+                       if (caller_uid != request_uid) {
+                               DEBUG(1,("winbindd_pam_logoff: caller requested invalid uid\n"));
+                               goto failed;
+                       }
+                       state->request.data.logoff.uid = caller_uid;
+                       break;
+       }
+
        sendto_domain(state, domain);
        return;
 
index 11d9fe0dbbd91e8145e1529bc8f33d893dfa446b..3707f0311f83c0994cf26b9051adc9b5907f3a6c 100644 (file)
@@ -262,7 +262,7 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
                return NT_STATUS_NO_MEMORY;
        }
 
-       ws_name_return( full_name, '_' );
+       ws_name_return( full_name, WB_REPLACE_CHAR );
 
        DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", full_name?full_name:"", domain_name ));
 
@@ -317,7 +317,7 @@ NTSTATUS msrpc_sid_to_name(struct winbindd_domain *domain,
        *domain_name = domains[0];
        *name = names[0];
 
-       ws_name_replace( *name, '_' );  
+       ws_name_replace( *name, WB_REPLACE_CHAR );      
                
        DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name));
        return NT_STATUS_OK;
@@ -369,7 +369,7 @@ NTSTATUS msrpc_rids_to_names(struct winbindd_domain *domain,
        ret_names = *names;
        for (i=0; i<num_rids; i++) {
                if ((*types)[i] != SID_NAME_UNKNOWN) {
-                       ws_name_replace( ret_names[i], '_' );
+                       ws_name_replace( ret_names[i], WB_REPLACE_CHAR );
                        *domain_name = domains[i];
                }
        }
index 47a7364e3a7910310fc587f11ac3898efadfe96c..ce677198fff3c352ae1b2cf36769842d2a4aefcf 100644 (file)
@@ -243,7 +243,7 @@ static void getpwsid_queryuser_recv(void *private_data, BOOL success,
        strlower_m( username );
        s->username = talloc_strdup(s->state->mem_ctx, username);
 
-       ws_name_replace( s->username, '_' );
+       ws_name_replace( s->username, WB_REPLACE_CHAR );
         
        s->fullname = talloc_strdup(s->state->mem_ctx, full_name);
        s->homedir = talloc_strdup(s->state->mem_ctx, homedir);
@@ -262,7 +262,7 @@ static void getpwsid_sid2uid_recv(void *private_data, BOOL success, uid_t uid)
                talloc_get_type_abort(private_data, struct getpwsid_state);
 
        if (!success) {
-               DEBUG(5, ("Could not query user's %s\\%s uid\n",
+               DEBUG(5, ("Could not query uid for user %s\\%s\n",
                          s->domain->name, s->username));
                request_error(s->state);
                return;
@@ -289,7 +289,7 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
        if ( s->gid == (gid_t)-1 ) {
 
                if (!success) {
-                       DEBUG(5, ("Could not query user's %s\\%s\n gid",
+                       DEBUG(5, ("Could not query gid for user %s\\%s\n",
                                  s->domain->name, s->username));
                        goto failed;
                }
@@ -345,6 +345,8 @@ void winbindd_getpwnam(struct winbindd_cli_state *state)
        DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid,
                  state->request.data.username));
 
+       ws_name_return( state->request.data.username, WB_REPLACE_CHAR );
+
        if (!parse_domain_user(state->request.data.username, domname,
                               username)) {
                DEBUG(5, ("Could not parse domain user: %s\n",
index 5d6a0c4ff540eb16290d84ba04f42b7ceb5e94c2..85c1f4a9b64f47f039f0b79c6a3de513e2eb682e 100644 (file)
@@ -229,7 +229,6 @@ typedef struct {
        int winbind_cache_time;
        int winbind_max_idle_children;
        char **szWinbindNssInfo;
-       int iLockSpinCount;
        int iLockSpinTime;
        char *szLdapMachineSuffix;
        char *szLdapUserSuffix;
@@ -290,6 +289,7 @@ typedef struct {
        BOOL bClientNTLMv2Auth;
        BOOL bClientPlaintextAuth;
        BOOL bClientUseSpnego;
+       BOOL bDebugPrefixTimestamp;
        BOOL bDebugHiresTimestamp;
        BOOL bDebugPid;
        BOOL bDebugUid;
@@ -953,6 +953,7 @@ static struct parm_struct parm_table[] = {
        {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED}, 
        {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
        {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, 
+       {"debug prefix timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugPrefixTimestamp, NULL, NULL, FLAG_ADVANCED}, 
        {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED}, 
        {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED}, 
        {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED}, 
@@ -1156,7 +1157,6 @@ static struct parm_struct parm_table[] = {
        {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
        {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
-       {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
        {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, 
 
        {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, 
@@ -1269,14 +1269,14 @@ static struct parm_struct parm_table[] = {
 
        {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
        {"idmap domains", P_LIST, P_GLOBAL, &Globals.szIdmapDomains, NULL, NULL, FLAG_ADVANCED}, 
-       {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEPRECATED }, 
+       {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED }, 
        {"idmap alloc backend", P_STRING, P_GLOBAL, &Globals.szIdmapAllocBackend, NULL, NULL, FLAG_ADVANCED}, 
        {"idmap expire time", P_INTEGER, P_GLOBAL, &Globals.iIdmapExpireTime, NULL, NULL, FLAG_ADVANCED}, 
        {"idmap negative time", P_INTEGER, P_GLOBAL, &Globals.iIdmapNegativeTime, NULL, NULL, FLAG_ADVANCED}, 
-       {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEPRECATED }, 
-       {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE | FLAG_DEPRECATED }, 
-       {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEPRECATED }, 
-       {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE | FLAG_DEPRECATED }, 
+       {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED }, 
+       {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE }, 
+       {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED }, 
+       {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE }, 
        {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
        {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, 
@@ -1517,6 +1517,7 @@ static void init_globals(BOOL first_time_only)
        Globals.bSyslogOnly = False;
        Globals.bTimestampLogs = True;
        string_set(&Globals.szLogLevel, "0");
+       Globals.bDebugPrefixTimestamp = False;
        Globals.bDebugHiresTimestamp = False;
        Globals.bDebugPid = False;
        Globals.bDebugUid = False;
@@ -1557,7 +1558,6 @@ static void init_globals(BOOL first_time_only)
        Globals.map_to_guest = 0;       /* By Default, "Never" */
        Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
        Globals.enhanced_browsing = True; 
-       Globals.iLockSpinCount = 0; /* Unused. */
        Globals.iLockSpinTime = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
 #ifdef MMAP_BLACKLIST
        Globals.bUseMmap = False;
@@ -1945,6 +1945,7 @@ FN_GLOBAL_INTEGER(lp_client_schannel, &Globals.clientSchannel)
 FN_GLOBAL_INTEGER(lp_server_schannel, &Globals.serverSchannel)
 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
+FN_GLOBAL_BOOL(lp_debug_prefix_timestamp, &Globals.bDebugPrefixTimestamp)
 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
 FN_GLOBAL_BOOL(lp_debug_uid, &Globals.bDebugUid)
@@ -2010,7 +2011,6 @@ FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval)
 FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout)
 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
-FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
 FN_GLOBAL_INTEGER(lp_lock_spin_time, &Globals.iLockSpinTime)
 FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
 
index 0b596fc8d7f7bccbf751d3bf8a73cec3739d0c13..d76cc07ce1e06c4fb644f7f0f4b8c36867d0747c 100644 (file)
@@ -411,9 +411,15 @@ static BOOL wb_lookup_rids(TALLOC_CTX *mem_ctx,
                        names[i] = "";
                        types[i] = SID_NAME_UNKNOWN;
                }
+               TALLOC_FREE(tmp_ctx);
                return True;
        }
 
+       if (!(*domain_name = talloc_strdup(mem_ctx, *domain_name))) {
+               TALLOC_FREE(tmp_ctx);
+               return False;
+       }
+
        /*
         * winbind_lookup_rids allocates its own array. We've been given the
         * array, so copy it over
@@ -1115,7 +1121,7 @@ void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
  *THE LEGACY* convert uid_t to SID function.
 *****************************************************************/  
 
-void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
+static void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
 {
        uint32 rid;
        BOOL ret;
@@ -1149,7 +1155,7 @@ void legacy_uid_to_sid(DOM_SID *psid, uid_t uid)
  *THE LEGACY* convert gid_t to SID function.
 *****************************************************************/  
 
-void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
+static void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
 {
        BOOL ret;
 
@@ -1180,7 +1186,7 @@ void legacy_gid_to_sid(DOM_SID *psid, gid_t gid)
  *THE LEGACY* convert SID to uid function.
 *****************************************************************/  
 
-BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
+static BOOL legacy_sid_to_uid(const DOM_SID *psid, uid_t *puid)
 {
        enum lsa_SidType type;
        uint32 rid;
@@ -1229,7 +1235,7 @@ done:
  Group mapping is used for gids that maps to Wellknown SIDs
 *****************************************************************/  
 
-BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+static BOOL legacy_sid_to_gid(const DOM_SID *psid, gid_t *pgid)
 {
        uint32 rid;
        GROUP_MAP map;
index 533b936efd9186869844b4f7c6f685dae463aa7f..c4c53c306649343625be59d7a73ff6fea35bf1a4 100644 (file)
@@ -2049,14 +2049,25 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s
        TALLOC_FREE( attr_list );
 
        if (num_result == 0) {
+               char *escape_username;
                /* Check if we need to add an entry */
                DEBUG(3,("ldapsam_add_sam_account: Adding new user\n"));
                ldap_op = LDAP_MOD_ADD;
+
+               escape_username = escape_rdn_val_string_alloc(username);
+               if (!escape_username) {
+                       DEBUG(0, ("Out of memory!\n"));
+                       ldap_msgfree(result);
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                if (username[strlen(username)-1] == '$') {
-                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ());
+                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_machine_suffix ());
                } else {
-                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ());
+                       slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", escape_username, lp_ldap_user_suffix ());
                }
+
+               SAFE_FREE(escape_username);
        }
 
        if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd,
@@ -2415,11 +2426,22 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
                }
 
                for (memberuid = values; *memberuid != NULL; memberuid += 1) {
-                       filter = talloc_asprintf_append(filter, "(uid=%s)", *memberuid);
+                       char *escape_memberuid;
+
+                       escape_memberuid = escape_ldap_string_alloc(*memberuid);
+                       if (escape_memberuid == NULL) {
+                               ret = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
+                       
+                       filter = talloc_asprintf_append(filter, "(uid=%s)", escape_memberuid);
                        if (filter == NULL) {
+                               SAFE_FREE(escape_memberuid);
                                ret = NT_STATUS_NO_MEMORY;
                                goto done;
                        }
+
+                       SAFE_FREE(escape_memberuid);
                }
 
                filter = talloc_asprintf_append(filter, "))");
@@ -4773,6 +4795,8 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_SAMBASAMACCOUNT);
 
        if (add_posix) {
+               char *escape_name;
+
                DEBUG(3,("ldapsam_create_user: Creating new posix user\n"));
 
                /* retrieve the Domain Users group gid */
@@ -4799,12 +4823,21 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods,
                }
                uidstr = talloc_asprintf(tmp_ctx, "%d", uid);
                gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
+
+               escape_name = escape_rdn_val_string_alloc(name);
+               if (!escape_name) {
+                       DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
                if (is_machine) {
-                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_machine_suffix ());
+                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_machine_suffix ());
                } else {
-                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", name, lp_ldap_user_suffix ());
+                       dn = talloc_asprintf(tmp_ctx, "uid=%s,%s", escape_name, lp_ldap_user_suffix ());
                }
 
+               SAFE_FREE(escape_name);
+
                if (!homedir || !shell || !uidstr || !gidstr || !dn) {
                        DEBUG (0, ("ldapsam_create_user: Out of memory!\n"));
                        return NT_STATUS_NO_MEMORY;
@@ -4986,6 +5019,8 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
        }
 
        if (num_result == 0) {
+               char *escape_name;
+
                DEBUG(3,("ldapsam_create_user: Creating new posix group\n"));
 
                is_new_entry = True;
@@ -4997,7 +5032,16 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods,
                }
 
                gidstr = talloc_asprintf(tmp_ctx, "%d", gid);
-               dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", name, lp_ldap_group_suffix());
+
+               escape_name = escape_rdn_val_string_alloc(name);
+               if (!escape_name) {
+                       DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               dn = talloc_asprintf(tmp_ctx, "cn=%s,%s", escape_name, lp_ldap_group_suffix());
+
+               SAFE_FREE(escape_name);
 
                if (!gidstr || !dn) {
                        DEBUG (0, ("ldapsam_create_group: Out of memory!\n"));
@@ -5335,6 +5379,7 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
        uint32 num_result;
        LDAPMod **mods = NULL;
        char *filter;
+       char *escape_username;
        char *gidstr;
        const char *dn = NULL;
        gid_t gid;
@@ -5351,14 +5396,22 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods,
                DEBUG(0,("ldapsam_set_primary_group: Out of Memory!\n"));
                return NT_STATUS_NO_MEMORY;
        }
-       
+
+       escape_username = escape_ldap_string_alloc(pdb_get_username(sampass));
+       if (escape_username== NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
        filter = talloc_asprintf(mem_ctx,
                                 "(&(uid=%s)"
                                 "(objectClass=%s)"
                                 "(objectClass=%s))",
-                                pdb_get_username(sampass),
+                                escape_username,
                                 LDAP_OBJ_POSIXACCOUNT,
                                 LDAP_OBJ_SAMBASAMACCOUNT);
+
+       SAFE_FREE(escape_username);
+
        if (filter == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -5620,6 +5673,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
 
        dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
        if (!dn) {
+               ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -5636,6 +5690,7 @@ NTSTATUS pdb_init_ldapsam(struct pdb_methods **pdb_method, const char *location)
                if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
                        DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
                                  "read as a valid SID\n", domain_sid_string));
+                       ldap_msgfree(result);
                        return NT_STATUS_INVALID_PARAMETER;
                }
                found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
index 063e4b3e175925f5f859e60d0263dbcc9a5d0dae..8829ef2b0c2ff559bb737111fc34fefce86b2805 100644 (file)
@@ -1036,13 +1036,12 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
        char    *buf = NULL;
        ssize_t byte_count;
 
-       if ((buf=(char *)SMB_MALLOC(PE_HEADER_SIZE)) == NULL) {
-               DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
-                               fname, PE_HEADER_SIZE));
+       if ((buf=(char *)SMB_MALLOC(DOS_HEADER_SIZE)) == NULL) {
+               DEBUG(0,("get_file_version: PE file [%s] DOS Header malloc failed bytes = %d\n",
+                               fname, DOS_HEADER_SIZE));
                goto error_exit;
        }
 
-       /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
        if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
                DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %lu\n",
                         fname, (unsigned long)byte_count));
@@ -1064,7 +1063,8 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
                goto no_version_info;
        }
 
-       if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
+       /* Note: DOS_HEADER_SIZE and NE_HEADER_SIZE are incidentally same */
+       if ((byte_count = vfs_read_data(fsp, buf, NE_HEADER_SIZE)) < NE_HEADER_SIZE) {
                DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %lu\n",
                         fname, (unsigned long)byte_count));
                /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
@@ -1075,13 +1075,13 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32
        if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
                unsigned int num_sections;
                unsigned int section_table_bytes;
-               
-               if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
-                       DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
-                                       fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
-                       /* At this point, we assume the file is in error. It still could be somthing
-                        * else besides a PE file, but it unlikely at this point.
-                        */
+
+               /* Just skip over optional header to get to section table */
+               if (SMB_VFS_LSEEK(fsp, fsp->fh->fd,
+                               SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)-(NE_HEADER_SIZE-PE_HEADER_SIZE),
+                               SEEK_CUR) == (SMB_OFF_T)-1) {
+                       DEBUG(3,("get_file_version: File [%s] Windows optional header too short, errno = %d\n",
+                               fname, errno));
                        goto error_exit;
                }
 
@@ -1823,7 +1823,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);   
                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                        driver_unix_convert(new_name, conn, NULL, &st);
-                       if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                       if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                new_name, old_name));
@@ -1839,7 +1839,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &st);
-                               if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1857,7 +1857,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);   
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &st);
-                               if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1876,7 +1876,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                        slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);     
                        if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                driver_unix_convert(new_name, conn, NULL, &st);
-                               if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn, OPENX_FILE_EXISTS_TRUNCATE|
+                               if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
                                                OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                        DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
                                                        new_name, old_name));
@@ -1904,7 +1904,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
                                slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);    
                                if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
                                        driver_unix_convert(new_name, conn, NULL, &st);
-                                       if ( !NT_STATUS_IS_OK(copy_file(new_name, old_name, conn,
+                                       if ( !NT_STATUS_IS_OK(copy_file(conn, new_name, old_name,
                                                        OPENX_FILE_EXISTS_TRUNCATE|
                                                        OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
                                                DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
@@ -3034,7 +3034,7 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
 {
        ADS_STATUS ads_rc;
        LDAPMessage *res;
-       char *prt_dn = NULL, *srv_dn, *srv_cn_0;
+       char *prt_dn = NULL, *srv_dn, *srv_cn_0, *srv_cn_escaped, *sharename_escaped;
        char *srv_dn_utf8, **srv_cn_utf8;
        TALLOC_CTX *ctx;
        ADS_MODLIST mods;
@@ -3080,11 +3080,29 @@ static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
        ldap_memfree(srv_dn_utf8);
        ldap_memfree(srv_cn_utf8);
 
-       asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, 
-                printer->info_2->sharename, srv_dn);
+       srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
+       if (!srv_cn_escaped) {
+               SAFE_FREE(srv_cn_0);
+               ldap_memfree(srv_dn_utf8);
+               ads_destroy(&ads);
+               return WERR_SERVER_UNAVAILABLE;
+       }
+       sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
+       if (!sharename_escaped) {
+               SAFE_FREE(srv_cn_escaped);
+               SAFE_FREE(srv_cn_0);
+               ldap_memfree(srv_dn_utf8);
+               ads_destroy(&ads);
+               return WERR_SERVER_UNAVAILABLE;
+       }
+
+
+       asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
 
        SAFE_FREE(srv_dn);
        SAFE_FREE(srv_cn_0);
+       SAFE_FREE(srv_cn_escaped);
+       SAFE_FREE(sharename_escaped);
 
        /* build the ads mods */
        ctx = talloc_init("nt_printer_publish_ads");
@@ -3725,9 +3743,7 @@ static void map_to_os2_driver(fstring drivername)
 ****************************************************************************/
 static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char *servername, const char* sharename)
 {
-       int snum;
-
-       snum = lp_servicenumber(sharename);
+       int snum = lp_servicenumber(sharename);
 
        slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
        slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s", 
@@ -3751,6 +3767,15 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info, const char
        fstrcpy(info->printprocessor, "winprint");
        fstrcpy(info->datatype, "RAW");
 
+#ifdef HAVE_CUPS
+       if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
+               /* Pull the location and comment strings from cups if we don't
+                  already have one */
+               if ( !strlen(info->location) || !strlen(info->comment) )
+                       cups_pull_comment_location( info );
+       }
+#endif
+
        info->attributes = PRINTER_ATTRIBUTE_SAMBA;
 
        info->starttime = 0; /* Minutes since 12:00am GMT */
@@ -3846,6 +3871,15 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info, const char *servern
 
        fstrcpy(info->printername, printername);
 
+#ifdef HAVE_CUPS
+       if ( (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {           
+               /* Pull the location and comment strings from cups if we don't
+                  already have one */
+               if ( !strlen(info->location) || !strlen(info->comment) )
+                       cups_pull_comment_location( info );
+       }
+#endif
+
        len += unpack_devicemode(&info->devmode,dbuf.dptr+len, dbuf.dsize-len);
 
        /*
index 2c942627c6bae50efef8d824cc3b250c5e57824a..0fa73e5a6ca02c7dfa2c8271d3e4e13c15e62fab 100644 (file)
@@ -1198,6 +1198,145 @@ struct printif  cups_printif =
        cups_job_submit,
 };
 
+BOOL cups_pull_comment_location(NT_PRINTER_INFO_LEVEL_2 *printer)
+{
+       http_t          *http = NULL;           /* HTTP connection to server */
+       ipp_t           *request = NULL,        /* IPP Request */
+                       *response = NULL;       /* IPP Response */
+       ipp_attribute_t *attr;          /* Current attribute */
+       cups_lang_t     *language = NULL;       /* Default language */
+       char            *name,          /* printer-name attribute */
+                       *info,          /* printer-info attribute */
+                       *location;      /* printer-location attribute */
+       char            uri[HTTP_MAX_URI];
+       static const char *requested[] =/* Requested attributes */
+                       {
+                         "printer-name",
+                         "printer-info",
+                         "printer-location"
+                       };
+       BOOL ret = False;
+
+       DEBUG(5, ("pulling %s location\n", printer->sharename));
+
+       /*
+        * Make sure we don't ask for passwords...
+        */
+
+        cupsSetPasswordCB(cups_passwd_cb);
+
+       /*
+        * Try to connect to the server...
+        */
+
+       if ((http = cups_connect()) == NULL) {
+               goto out;
+       }
+
+       request = ippNew();
+
+       request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
+       request->request.op.request_id   = 1;
+
+       language = cupsLangDefault();
+
+       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+                     "attributes-charset", NULL, cupsLangEncoding(language));
+
+       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+                     "attributes-natural-language", NULL, language->language);
+
+       slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s",
+                lp_cups_server(), printer->sharename);
+
+       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+                     "printer-uri", NULL, uri);
+
+        ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+                     "requested-attributes",
+                     (sizeof(requested) / sizeof(requested[0])),
+                     NULL, requested);
+
+       /*
+        * Do the request and get back a response...
+        */
+
+       if ((response = cupsDoRequest(http, request, "/")) == NULL) {
+               DEBUG(0,("Unable to get printer attributes - %s\n",
+                        ippErrorString(cupsLastError())));
+               goto out;
+       }
+
+       for (attr = response->attrs; attr != NULL;) {
+               /*
+                * Skip leading attributes until we hit a printer...
+                */
+
+               while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
+                       attr = attr->next;
+
+               if (attr == NULL)
+                       break;
+
+               /*
+                * Pull the needed attributes from this printer...
+                */
+
+               name       = NULL;
+               info       = NULL;
+               location   = NULL;
+
+               while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) {
+                       /* Grab the comment if we don't have one */
+                       if ( (strcmp(attr->name, "printer-info") == 0)
+                            && (attr->value_tag == IPP_TAG_TEXT)
+                            && !strlen(printer->comment) ) 
+                       {
+                               DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n",
+                                        attr->values[0].string.text));                         
+                               pstrcpy(printer->comment,attr->values[0].string.text);
+                       }
+
+                       /* Grab the location if we don't have one */ 
+                       if ( (strcmp(attr->name, "printer-location") == 0)
+                            && (attr->value_tag == IPP_TAG_TEXT) 
+                            && !strlen(printer->location) )
+                       {
+                               DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n",
+                                        attr->values[0].string.text));                         
+                               fstrcpy(printer->location,attr->values[0].string.text);
+                       }
+
+                       attr = attr->next;
+               }
+
+               /*
+                * See if we have everything needed...
+                */
+
+               if (name == NULL)
+                       break;
+
+       }
+
+       ippDelete(response);
+       response = NULL;
+
+       ret = True;
+
+ out:
+       if (response)
+               ippDelete(response);
+
+       if (language)
+               cupsLangFree(language);
+
+       if (http)
+               httpClose(http);
+
+       return ret;
+}
+
 #else
  /* this keeps fussy compilers happy */
  void print_cups_dummy(void);
index 4568678739fd553e128913574182419d3e9cda4a..69c240061e16b60d22dbe0e8b1e1fac00c42e18d 100644 (file)
@@ -284,7 +284,7 @@ BOOL profile_setup(BOOL rdonly)
            "syscall_fchown",           /* PR_VALUE_SYSCALL_FCHOWN */
            "syscall_chdir",            /* PR_VALUE_SYSCALL_CHDIR */
            "syscall_getwd",            /* PR_VALUE_SYSCALL_GETWD */
-           "syscall_utime",            /* PR_VALUE_SYSCALL_UTIME */
+           "syscall_ntimes",           /* PR_VALUE_SYSCALL_NTIMES */
            "syscall_ftruncate",        /* PR_VALUE_SYSCALL_FTRUNCATE */
            "syscall_fcntl_lock",       /* PR_VALUE_SYSCALL_FCNTL_LOCK */
            "syscall_kernel_flock",     /* PR_VALUE_SYSCALL_KERNEL_FLOCK */
index 0d50e94d5777014c6635e9c0b58ca50a6ca9c1f1..7b4818b4b06363963afb10166a0943804e3d2176 100644 (file)
@@ -5,6 +5,8 @@
    Copyright (C) Tim Potter 2001
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
    Copyright (C) Jeremy Allison  2005.
+   Copyright (C) Gerald (Jerry) Carter        2006.
+
 
    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
@@ -537,38 +539,37 @@ WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_
 
        ZERO_STRUCTP(ctr);
 
-       ctr->switch_value = file_level;
+       ctr->level = file_level;
 
        ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
        
        switch(file_level) {
        case 3:
-               ctr->file.info3 = TALLOC_ARRAY(mem_ctx, SRV_FILE_INFO_3, ctr->num_entries);
-               if (ctr->file.info3 == NULL) {
+               if ( (ctr->file.info3 = TALLOC_ARRAY(mem_ctx, FILE_INFO_3, ctr->num_entries)) == NULL ) {
                        return WERR_NOMEM;
                }
 
-               memset(ctr->file.info3, 0, 
-                      sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
+               memset(ctr->file.info3, 0, sizeof(FILE_INFO_3) * ctr->num_entries);
 
                for (i = 0; i < r.ctr.num_entries; i++) {
-                       SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
+                       FILE_INFO_3 *info3 = &ctr->file.info3[i];
                        char *s;
                        
                        /* Copy pointer crap */
 
-                       memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3, 
-                              sizeof(FILE_INFO_3));
+                       memcpy(info3, &r.ctr.file.info3[i], sizeof(FILE_INFO_3));
 
                        /* Duplicate strings */
 
-                       s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
-                       if (s)
-                               init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE);
+                       if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].path)) != NULL ) {
+                               info3->path = TALLOC_P( mem_ctx, UNISTR2 );
+                               init_unistr2(info3->path, s, UNI_STR_TERMINATE);
+                       }
                
-                       s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
-                       if (s)
-                               init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE);
+                       if ( (s = unistr2_tdup(mem_ctx, r.ctr.file.info3[i].user)) != NULL ) {
+                               info3->user = TALLOC_P( mem_ctx, UNISTR2 );
+                               init_unistr2(info3->user, s, UNI_STR_TERMINATE);
+                       }
 
                }               
 
index 7d15eda630f908074d8e03717c5aa832215c21b3..8ed67872430734332c89330c456b3668a2260108 100644 (file)
@@ -7,6 +7,7 @@
  *  Copyright (C) Jeremy Allison                   1999,
  *  Copyright (C) Nigel Williams                   2001,
  *  Copyright (C) Jim McDonough (jmcd@us.ibm.com)   2002.
+ *  Copyright (C) Gerald (Jerry) Carter             2006.
  *  
  *  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
@@ -1588,64 +1589,17 @@ BOOL srv_io_r_net_share_del(const char *desc, SRV_R_NET_SHARE_DEL *q_n, prs_stru
  Inits a SESS_INFO_0_STR structure
 ********************************************************************/
 
-void init_srv_sess_info0_str(SESS_INFO_0_STR *ss0, const char *name)
+void init_srv_sess_info0( SESS_INFO_0 *ss0, const char *name )
 {
-       DEBUG(5,("init_srv_sess_info0_str\n"));
+       ZERO_STRUCTP( ss0 );
 
-       init_unistr2(&ss0->uni_name, name, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info0_str(const char *desc,  SESS_INFO_0_STR *ss0, prs_struct *ps, int depth)
-{
-       if (ss0 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info0_str");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_unistr2("", &ss0->uni_name, True, ps, depth))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Inits a SESS_INFO_0 structure
-********************************************************************/
-
-void init_srv_sess_info0(SESS_INFO_0 *ss0, const char *name)
-{
-       DEBUG(5,("init_srv_sess_info0: %s\n", name));
-
-       ss0->ptr_name = (name != NULL) ? 1 : 0;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info0(const char *desc, SESS_INFO_0 *ss0, prs_struct *ps, int depth)
-{
-       if (ss0 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info0");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_name", ps, depth, &ss0->ptr_name))
-               return False;
-
-       return True;
+       if ( name ) {
+               if ( (ss0->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+                       return;
+               }
+               init_unistr2( ss0->sharename, name, UNI_STR_TERMINATE );
+       }
 }
 
 /*******************************************************************
@@ -1681,13 +1635,15 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
 
                SMB_ASSERT_ARRAY(ss0->info_0, num_entries);
 
+               /* first the pointers */
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info0("", &ss0->info_0[i], ps, depth))
+                       if ( !prs_io_unistr2_p("", ps, depth, &ss0->info_0[i].sharename ) )
                                return False;
                }
 
+               /* now the strings */
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info0_str("", &ss0->info_0_str[i], ps, depth))
+                       if ( !prs_io_unistr2("sharename", ps, depth, ss0->info_0[i].sharename ))
                                return False;
                }
 
@@ -1698,54 +1654,33 @@ static BOOL srv_io_srv_sess_info_0(const char *desc, SRV_SESS_INFO_0 *ss0, prs_s
        return True;
 }
 
-/*******************************************************************
- Inits a SESS_INFO_1_STR structure
-********************************************************************/
-
-void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, const char *name, const char *user)
-{
-       DEBUG(5,("init_srv_sess_info1_str\n"));
-
-       init_unistr2(&ss1->uni_name, name, UNI_STR_TERMINATE);
-       init_unistr2(&ss1->uni_user, user, UNI_STR_TERMINATE);
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info1_str(const char *desc, SESS_INFO_1_STR *ss1, prs_struct *ps, int depth)
-{
-       if (ss1 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info1_str");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_unistr2("", &ss1->uni_name, True, ps, depth))
-               return False;
-       if(!smb_io_unistr2("", &(ss1->uni_user), True, ps, depth))
-               return False;
-
-       return True;
-}
-
 /*******************************************************************
  Inits a SESS_INFO_1 structure
 ********************************************************************/
 
-void init_srv_sess_info1(SESS_INFO_1 *ss1, 
-                               const char *name, const char *user,
-                               uint32 num_opens, uint32 open_time, uint32 idle_time,
-                               uint32 user_flags)
+void init_srv_sess_info1( SESS_INFO_1 *ss1, const char *name, const char *user,
+                          uint32 num_opens, uint32 open_time, uint32 idle_time,
+                          uint32 user_flags)
 {
        DEBUG(5,("init_srv_sess_info1: %s\n", name));
 
-       ss1->ptr_name = (name != NULL) ? 1 : 0;
-       ss1->ptr_user = (user != NULL) ? 1 : 0;
+       ZERO_STRUCTP( ss1 );
+
+       if ( name ) {
+               if ( (ss1->sharename = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+                       return;
+               }
+               init_unistr2( ss1->sharename, name, UNI_STR_TERMINATE );
+       }
+
+       if ( user ) {
+               if ( (ss1->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       DEBUG(0,("init_srv_sess_info0: talloc failed!\n"));
+                       return;
+               }
+               init_unistr2( ss1->username, user, UNI_STR_TERMINATE );
+       }
 
        ss1->num_opens  = num_opens;
        ss1->open_time  = open_time;
@@ -1753,37 +1688,6 @@ void init_srv_sess_info1(SESS_INFO_1 *ss1,
        ss1->user_flags = user_flags;
 }
 
-/*******************************************************************
-reads or writes a structure.
-********************************************************************/
-
-static BOOL srv_io_sess_info1(const char *desc, SESS_INFO_1 *ss1, prs_struct *ps, int depth)
-{
-       if (ss1 == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_sess_info1");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_name  ", ps, depth, &ss1->ptr_name))
-               return False;
-       if(!prs_uint32("ptr_user  ", ps, depth, &ss1->ptr_user))
-               return False;
-
-       if(!prs_uint32("num_opens ", ps, depth, &ss1->num_opens))
-               return False;
-       if(!prs_uint32("open_time ", ps, depth, &ss1->open_time))
-               return False;
-       if(!prs_uint32("idle_time ", ps, depth, &ss1->idle_time))
-               return False;
-       if(!prs_uint32("user_flags", ps, depth, &ss1->user_flags))
-               return False;
-
-       return True;
-}
 
 /*******************************************************************
  Reads or writes a structure.
@@ -1818,13 +1722,31 @@ static BOOL srv_io_srv_sess_info_1(const char *desc, SRV_SESS_INFO_1 *ss1, prs_s
 
                SMB_ASSERT_ARRAY(ss1->info_1, num_entries);
 
+               /* first the pointers and flags */
+
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info1("", &ss1->info_1[i], ps, depth))
+
+                       if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].sharename ))
+                               return False;
+                       if ( !prs_io_unistr2_p("", ps, depth, &ss1->info_1[i].username ))
+                               return False;
+
+                       if(!prs_uint32("num_opens ", ps, depth, &ss1->info_1[i].num_opens))
+                               return False;
+                       if(!prs_uint32("open_time ", ps, depth, &ss1->info_1[i].open_time))
+                               return False;
+                       if(!prs_uint32("idle_time ", ps, depth, &ss1->info_1[i].idle_time))
+                               return False;
+                       if(!prs_uint32("user_flags", ps, depth, &ss1->info_1[i].user_flags))
                                return False;
                }
 
+               /* now the strings */
+
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_sess_info1_str("", &ss1->info_1_str[i], ps, depth))
+                       if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].sharename ))
+                               return False;
+                       if ( !prs_io_unistr2("", ps, depth, ss1->info_1[i].username ))
                                return False;
                }
 
@@ -1883,37 +1805,13 @@ static BOOL srv_io_srv_sess_ctr(const char *desc, SRV_SESS_INFO_CTR **pp_ctr, pr
        return True;
 }
 
-/*******************************************************************
- Inits a SRV_Q_NET_SESS_ENUM structure.
-********************************************************************/
-
-void init_srv_q_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n, 
-                             const char *srv_name, const char *qual_name,
-                             const char *user_name, uint32 sess_level, 
-                             SRV_SESS_INFO_CTR *ctr, uint32 preferred_len,
-                             ENUM_HND *hnd)
-{
-       q_n->ctr = ctr;
-
-       DEBUG(5,("init_q_net_sess_enum\n"));
-
-       init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
-       init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name);
-       init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name);
-
-       q_n->sess_level    = sess_level;
-       q_n->preferred_len = preferred_len;
-
-       memcpy(&q_n->enum_hnd, hnd, sizeof(*hnd));
-}
-
 /*******************************************************************
  Reads or writes a structure.
 ********************************************************************/
 
-BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_struct *ps, int depth)
+BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_u, prs_struct *ps, int depth)
 {
-       if (q_n == NULL)
+       if (q_u == NULL)
                return False;
 
        prs_debug(ps, depth, desc, "srv_io_q_net_sess_enum");
@@ -1922,41 +1820,36 @@ BOOL srv_io_q_net_sess_enum(const char *desc, SRV_Q_NET_SESS_ENUM *q_n, prs_stru
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+       if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth))
+       if(!prs_pointer("qualifier", ps, depth, (void**)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
-       if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth))
+
+       if(!prs_pointer("username", ps, depth, (void**)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("sess_level", ps, depth, &q_n->sess_level))
+       if(!prs_uint32("sess_level", ps, depth, &q_u->sess_level))
                return False;
        
-       if (q_n->sess_level != (uint32)-1) {
-               if(!srv_io_srv_sess_ctr("sess_ctr", &q_n->ctr, ps, depth))
+       if (q_u->sess_level != (uint32)-1) {
+               if(!srv_io_srv_sess_ctr("sess_ctr", &q_u->ctr, ps, depth))
                        return False;
        }
 
-       if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+       if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len))
                return False;
 
-       if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+       if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth))
                return False;
 
        return True;
@@ -2433,23 +2326,11 @@ BOOL srv_io_r_net_conn_enum(const char *desc,  SRV_R_NET_CONN_ENUM *r_n, prs_str
        return True;
 }
 
-/*******************************************************************
- Inits a FILE_INFO_3_STR structure
-********************************************************************/
-
-void init_srv_file_info3_str(FILE_INFO_3_STR *fi3, const char *user_name, const char *path_name)
-{
-       DEBUG(5,("init_srv_file_info3_str\n"));
-
-       init_unistr2(&fi3->uni_path_name, path_name, UNI_STR_TERMINATE);
-       init_unistr2(&fi3->uni_user_name, user_name, UNI_STR_TERMINATE);
-}
-
 /*******************************************************************
  Reads or writes a structure.
 ********************************************************************/
 
-static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_struct *ps, int depth)
+static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3 *sh1, prs_struct *ps, int depth)
 {
        if (sh1 == NULL)
                return False;
@@ -2460,10 +2341,15 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_unistr2("", &sh1->uni_path_name, True, ps, depth))
-               return False;
-       if(!smb_io_unistr2("", &sh1->uni_user_name, True, ps, depth))
-               return False;
+       if ( sh1->path ) {
+               if(!smb_io_unistr2("", sh1->path, True, ps, depth))
+                       return False;
+       }
+
+       if ( sh1->user ) {
+               if(!smb_io_unistr2("", sh1->user, True, ps, depth))
+                       return False;
+       }
 
        return True;
 }
@@ -2472,18 +2358,26 @@ static BOOL srv_io_file_info3_str(const char *desc, FILE_INFO_3_STR *sh1, prs_st
  Inits a FILE_INFO_3 structure
 ********************************************************************/
 
-void init_srv_file_info3(FILE_INFO_3 *fl3,
-                        uint32 id, uint32 perms, uint32 num_locks,
-                        const char *path_name, const char *user_name)
+void init_srv_file_info3( FILE_INFO_3 *fl3, uint32 id, uint32 perms, uint32 num_locks,
+                          const char *user_name, const char *path_name )
 {
-       DEBUG(5,("init_srv_file_info3: %s %s\n", path_name, user_name));
-
        fl3->id        = id;    
        fl3->perms     = perms;
        fl3->num_locks = num_locks;
 
-       fl3->ptr_path_name = (path_name != NULL) ? 1 : 0;
-       fl3->ptr_user_name = (user_name != NULL) ? 1 : 0;
+        if ( path_name ) {
+                if ( (fl3->path = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                        return;
+                init_unistr2(fl3->path, path_name, UNI_STR_TERMINATE);
+        }
+
+        if ( user_name ) {
+                if ( (fl3->user = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                        return;
+                init_unistr2(fl3->user, user_name, UNI_STR_TERMINATE);
+        }
+
+       return;
 }
 
 /*******************************************************************
@@ -2492,6 +2386,8 @@ void init_srv_file_info3(FILE_INFO_3 *fl3,
 
 static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps, int depth)
 {
+       uint32 uni_p;
+
        if (fl3 == NULL)
                return False;
 
@@ -2507,10 +2403,24 @@ static BOOL srv_io_file_info3(const char *desc, FILE_INFO_3 *fl3, prs_struct *ps
                return False;
        if(!prs_uint32("num_locks    ", ps, depth, &fl3->num_locks))
                return False;
-       if(!prs_uint32("ptr_path_name", ps, depth, &fl3->ptr_path_name))
+
+       uni_p = fl3->path ? (uint32)fl3->path : 0;
+       if(!prs_uint32("ptr", ps, depth, &uni_p))
                return False;
-       if(!prs_uint32("ptr_user_name", ps, depth, &fl3->ptr_user_name))
+       if (UNMARSHALLING(ps)) {
+               if ( (fl3->path = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) {
+                       return False;
+               }
+       }
+
+       uni_p = fl3->user ? (uint32)fl3->user : 0;
+       if(!prs_uint32("ptr", ps, depth, &uni_p))
                return False;
+       if (UNMARSHALLING(ps)) {
+               if ( (fl3->user = PRS_ALLOC_MEM( ps, UNISTR2, 1)) == NULL ) {
+                       return False;
+               }
+       }
 
        return True;
 }
@@ -2528,55 +2438,53 @@ static BOOL srv_io_srv_file_ctr(const char *desc, SRV_FILE_INFO_CTR *ctr, prs_st
        depth++;
 
        if (UNMARSHALLING(ps)) {
-               memset(ctr, '\0', sizeof(SRV_FILE_INFO_CTR));
+               ZERO_STRUCTP(ctr);
        }
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("switch_value", ps, depth, &ctr->switch_value))
+       if(!prs_uint32("level", ps, depth, &ctr->level))
                return False;
-       if (ctr->switch_value != 3) {
-               DEBUG(5,("%s File info %d level not supported\n",
-                        tab_depth(depth), ctr->switch_value));
-       }
+
        if(!prs_uint32("ptr_file_info", ps, depth, &ctr->ptr_file_info))
                return False;
        if(!prs_uint32("num_entries", ps, depth, &ctr->num_entries))
                return False;
        if(!prs_uint32("ptr_entries", ps, depth, &ctr->ptr_entries))
                return False;
+
        if (ctr->ptr_entries == 0)
                return True;
-       if(!prs_uint32("num_entries2", ps, depth, 
-                      &ctr->num_entries2))
+
+       if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries2))
                return False;
 
-       switch (ctr->switch_value) {
+       switch (ctr->level) {
        case 3: {
-               SRV_FILE_INFO_3 *info3 = ctr->file.info3;
+               FILE_INFO_3 *info3 = ctr->file.info3;
                int num_entries = ctr->num_entries;
                int i;
 
                if (UNMARSHALLING(ps)) {
-                       if (!(info3 = PRS_ALLOC_MEM(ps, SRV_FILE_INFO_3, num_entries)))
+                       if (!(info3 = PRS_ALLOC_MEM(ps, FILE_INFO_3, num_entries)))
                                return False;
                        ctr->file.info3 = info3;
                }
 
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_file_info3("", &ctr->file.info3[i].info_3, ps, depth))
+                       if(!srv_io_file_info3("", &ctr->file.info3[i], ps, depth)) 
                                return False;
                }
+
                for (i = 0; i < num_entries; i++) {
-                       if(!srv_io_file_info3_str("", &ctr->file.info3[i].info_3_str, ps, depth))
+                       if(!srv_io_file_info3_str("", &ctr->file.info3[i], ps, depth))
                                return False;
                }
                break;
        }
        default:
-               DEBUG(5,("%s no file info at switch_value %d\n",
-                        tab_depth(depth), ctr->switch_value));
+               DEBUG(5,("%s no file info at switch_value %d\n", tab_depth(depth), ctr->level));
                break;
        }
                        
@@ -2594,13 +2502,28 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
                              uint32 preferred_len,
                              ENUM_HND *hnd)
 {
-       DEBUG(5,("init_q_net_file_enum\n"));
+       uint32 ptr;
 
-       init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
-       init_buf_unistr2(&q_n->uni_qual_name, &q_n->ptr_qual_name, qual_name);
-       init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name);
+       if ( srv_name ) {
+               if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                       return;
+               init_buf_unistr2(q_n->servername, &ptr, srv_name);
+       }
+
+       if ( qual_name ) {
+               if ( (q_n->qualifier = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                       return;
+               init_buf_unistr2(q_n->qualifier,  &ptr, qual_name);
+       }
+
+       if ( user_name ) {
+               if ( (q_n->username = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL )
+                       return;
+               init_buf_unistr2(q_n->username,   &ptr, user_name);
+       }
+
+       q_n->level = q_n->ctr.level = file_level;
 
-       q_n->file_level    = q_n->ctr.switch_value = file_level;
        q_n->preferred_len = preferred_len;
        q_n->ctr.ptr_file_info = 1;
        q_n->ctr.num_entries = 0;
@@ -2613,9 +2536,9 @@ void init_srv_q_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
  Reads or writes a structure.
 ********************************************************************/
 
-BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_struct *ps, int depth)
+BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_u, prs_struct *ps, int depth)
 {
-       if (q_n == NULL)
+       if (q_u == NULL)
                return False;
 
        prs_debug(ps, depth, desc, "srv_io_q_net_file_enum");
@@ -2624,41 +2547,33 @@ BOOL srv_io_q_net_file_enum(const char *desc, SRV_Q_NET_FILE_ENUM *q_n, prs_stru
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
+       if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
-               return False;
-
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_qual_name", ps, depth, &q_n->ptr_qual_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_qual_name, q_n->ptr_qual_name, ps, depth))
+       if(!prs_pointer("qualifier", ps, depth, (void**)&q_u->qualifier, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
-
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth))
+       if(!prs_pointer("username", ps, depth, (void**)&q_u->username, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
-
        if(!prs_align(ps))
                return False;
-       if(!prs_uint32("file_level", ps, depth, &q_n->file_level))
+
+       if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if (q_n->file_level != (uint32)-1) {
-               if(!srv_io_srv_file_ctr("file_ctr", &q_n->ctr, ps, depth))
+       if (q_u->level != (uint32)-1) {
+               if(!srv_io_srv_file_ctr("file_ctr", &q_u->ctr, ps, depth))
                        return False;
        }
 
-       if(!prs_uint32("preferred_len", ps, depth, &q_n->preferred_len))
+       if(!prs_uint32("preferred_len", ps, depth, &q_u->preferred_len))
                return False;
 
-       if(!smb_io_enum_hnd("enum_hnd", &q_n->enum_hnd, ps, depth))
+       if(!smb_io_enum_hnd("enum_hnd", &q_u->enum_hnd, ps, depth))
                return False;
 
        return True;
@@ -2679,10 +2594,10 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("file_level", ps, depth, &r_n->file_level))
+       if(!prs_uint32("level", ps, depth, &r_n->level))
                return False;
 
-       if (r_n->file_level != 0) {
+       if (r_n->level != 0) {
                if(!srv_io_srv_file_ctr("file_ctr", &r_n->ctr, ps, depth))
                        return False;
        }
@@ -2703,62 +2618,16 @@ BOOL srv_io_r_net_file_enum(const char *desc, SRV_R_NET_FILE_ENUM *r_n, prs_stru
 void init_srv_q_net_file_close(SRV_Q_NET_FILE_CLOSE *q_n, const char *server,
                               uint32 file_id)
 {
-       q_n->ptr_srv_name = 1;
-       init_unistr2(&q_n->uni_srv_name, server, UNI_STR_TERMINATE);
-       q_n->file_id = file_id;
-}
-
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_n,
-                            prs_struct *ps, int depth)
-{
-       if (q_n == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_q_net_file_close");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
-               return False;
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
-               return False;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("file_id", ps, depth, &q_n->file_id))
-               return False;
+       if ( server ) {
+               if ( (q_n->servername = TALLOC_P( get_talloc_ctx(), UNISTR2 )) == NULL ) {
+                       return;
+               }
+               init_unistr2(q_n->servername, server, UNI_STR_TERMINATE);
+       }
 
-       return True;
+       q_n->file_id = file_id;
 }
 
-/*******************************************************************
- Reads or writes a structure.
-********************************************************************/
-
-BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *q_n, 
-                            prs_struct *ps, int depth)
-{
-       if (q_n == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "srv_io_r_net_file_close");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_werror("status", ps, depth, &q_n->status))
-               return False;
-
-       return True;
-}      
-
 /*******************************************************************
  Inits a SRV_INFO_100 structure.
  ********************************************************************/
@@ -3410,25 +3279,6 @@ BOOL srv_io_r_net_disk_enum(const char *desc, SRV_R_NET_DISK_ENUM *r_n, prs_stru
        return True;
 }
 
-/*******************************************************************
- initialises a structure.
- ********************************************************************/
-
-BOOL init_srv_q_net_name_validate(SRV_Q_NET_NAME_VALIDATE *q_n, const char *srv_name, const char *share_name, int type) 
-{
-       uint32 ptr_share_name;
-
-       DEBUG(5,("init_srv_q_net_name_validate\n"));
-  
-       init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name);
-       init_buf_unistr2(&q_n->uni_name,     &ptr_share_name,    share_name);
-
-       q_n->type  = type;
-       q_n->flags = 0;
-
-       return True;
-}
-
 /*******************************************************************
  Reads or writes a structure.
  ********************************************************************/
@@ -3444,16 +3294,13 @@ BOOL srv_io_q_net_name_validate(const char *desc, SRV_Q_NET_NAME_VALIDATE *q_n,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name))
-               return False;
-
-       if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth))
+       if(!prs_pointer("servername", ps, depth, (void**)&q_n->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
                return False;
 
        if(!prs_align(ps))
                return False;
 
-       if(!smb_io_unistr2("", &q_n->uni_name, True, ps, depth))
+       if(!smb_io_unistr2("", &q_n->sharename, True, ps, depth))
                return False;
 
        if(!prs_align(ps))
@@ -3663,3 +3510,48 @@ void init_srv_q_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_u, const char *server)
        q_u->ptr_srv_name = 1;
        init_unistr2(&q_u->uni_srv_name, server, UNI_STR_TERMINATE);
 }
+
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL srv_io_q_net_file_close(const char *desc, SRV_Q_NET_FILE_CLOSE *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "srv_io_q_net_file_close");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2))
+               return False;
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("file_id", ps, depth, &q_u->file_id))
+               return False;
+               
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL srv_io_r_net_file_close(const char *desc, SRV_R_NET_FILE_CLOSE *r_n, 
+                              prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "srv_io_r_net_file_close");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_werror("status", ps, depth, &r_n->status))
+               return False;
+
+       return True;
+}
index 1a2ad38910a82a7fd4eb5d183ed6617a19c9a16a..e93b0077f0ce439c3589ca5d22a7ef99a058cf63 100644 (file)
@@ -43,6 +43,8 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
        struct current_user user;
        struct junction_map jn;
        struct referral* old_referral_list = NULL;
+       BOOL self_ref = False;
+       int consumedcnt = 0;
        BOOL exists = False;
 
        pstring dfspath, servername, sharename;
@@ -67,7 +69,7 @@ WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
        pstrcat(altpath, sharename);
 
        /* The following call can change the cwd. */
-       if(get_referred_path(p->mem_ctx, dfspath, &jn, NULL, NULL)) {
+       if(get_referred_path(p->mem_ctx, dfspath, &jn, &consumedcnt, &self_ref)) {
                exists = True;
                jn.referral_count += 1;
                old_referral_list = jn.referral_list;
@@ -106,6 +108,8 @@ WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u,
 {
        struct current_user user;
        struct junction_map jn;
+       BOOL self_ref = False;
+       int consumedcnt = 0;
        BOOL found = False;
 
        pstring dfspath, servername, sharename;
@@ -137,7 +141,7 @@ WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u,
        DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n",
                dfspath, servername, sharename));
 
-       if(!get_referred_path(p->mem_ctx, dfspath, &jn, NULL, NULL)) {
+       if(!get_referred_path(p->mem_ctx, dfspath, &jn, &consumedcnt, &self_ref)) {
                return WERR_DFS_NO_SUCH_VOL;
        }
 
@@ -346,6 +350,7 @@ WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u,
        int consumedcnt = sizeof(pstring);
        pstring path;
        BOOL ret = False;
+       BOOL self_ref = False;
        struct junction_map jn;
 
        unistr2_to_ascii(path, uni_path, sizeof(path)-1);
@@ -353,7 +358,7 @@ WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u,
                return WERR_DFS_NO_SUCH_SERVER;
   
        /* The following call can change the cwd. */
-       if(!get_referred_path(p->mem_ctx, path, &jn, &consumedcnt, NULL) || consumedcnt < strlen(path)) {
+       if(!get_referred_path(p->mem_ctx, path, &jn, &consumedcnt, &self_ref) || consumedcnt < strlen(path)) {
                vfs_ChDir(p->conn,p->conn->connectpath);
                return WERR_DFS_NO_SUCH_VOL;
        }
@@ -489,4 +494,3 @@ WERROR _dfs_SetInfo2(pipes_struct *p, NETDFS_Q_DFS_SETINFO2 *q_u, NETDFS_R_DFS_S
        /* FIXME: Implement your code here */
        return WERR_NOT_SUPPORTED;
 }
-
index 9cc8b72546f12c0f0efa3da3c44f5cbeef569934..26e06f60a176857d3bee71cf7d575ea81eed5920 100644 (file)
@@ -1169,6 +1169,13 @@ BOOL close_rpc_pipe_hnd(smb_np_struct *p)
                 p->name, p->pnum, pipes_open));  
 
        DLIST_REMOVE(Pipes, p);
+       
+       /* Remove from pipe open db */
+       
+       if ( !delete_pipe_opendb( p ) ) {
+               DEBUG(3,("close_rpc_pipe_hnd: failed to delete %s "
+                       "pipe from open db.\n", p->name));
+       }
 
        ZERO_STRUCTP(p);
 
index 07a89de5e61d4d9587cc70e5383eb610a08fac39..0b2e24fa899bff857b8c4abbdc96f0f56ed2b9bf 100644 (file)
@@ -3886,7 +3886,7 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
 
        init_samr_r_query_aliasmem(r_u, num_sids, sid, NT_STATUS_OK);
 
-       SAFE_FREE(sids);
+       TALLOC_FREE(sids);
 
        return NT_STATUS_OK;
 }
index 0b4eac5cc7304310857e6fa70dac9985a80d7c3e..e4f85d0bdb4db0aa2eb7204f4973080a14f6b67e 100644 (file)
@@ -6,6 +6,7 @@
  *  Copyright (C) Paul Ashton                       1997,
  *  Copyright (C) Jeremy Allison                    2001,
  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2003.
+ *  Copyright (C) Gera;d (Jerry) Carter             2006.
  *  
  *  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
@@ -550,6 +551,35 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+*******************************************************************/
+
+static BOOL api_srv_net_file_close(pipes_struct *p)
+{
+       SRV_Q_NET_FILE_CLOSE q_u;
+       SRV_R_NET_FILE_CLOSE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* Unmarshall the net file set info from Win9x */
+       if(!srv_io_q_net_file_close("", &q_u, data, 0)) {
+               DEBUG(0,("api_srv_net_file_close: Failed to unmarshall SRV_Q_NET_FILE_SET_SECDESC.\n"));
+               return False;
+       }
+
+       r_u.status = _srv_net_file_close(p, &q_u, &r_u);
+
+       if(!srv_io_r_net_file_close("", &r_u, rdata, 0)) {
+               DEBUG(0,("api_srv_net_file_close: Failed to marshall SRV_R_NET_FILE_SET_SECDESC.\n"));
+               return False;
+       }
+
+       return True;
+}
+
 /*******************************************************************
 \PIPE\srvsvc commands
 ********************************************************************/
@@ -573,7 +603,8 @@ static struct api_struct api_srv_cmds[] =
       { "SRV_NET_DISK_ENUM"         , SRV_NET_DISK_ENUM         , api_srv_net_disk_enum          },
       { "SRV_NET_NAME_VALIDATE"     , SRV_NET_NAME_VALIDATE     , api_srv_net_name_validate      },
       { "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc },
-      { "SRV_NET_FILE_SET_SECDESC"  , SRV_NET_FILE_SET_SECDESC  , api_srv_net_file_set_secdesc   }
+      { "SRV_NET_FILE_SET_SECDESC"  , SRV_NET_FILE_SET_SECDESC  , api_srv_net_file_set_secdesc   },
+      { "SRV_NET_FILE_CLOSE"        , SRV_NET_FILE_CLOSE        , api_srv_net_file_close         }
 };
 
 void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns )
index 06a8c77098d54855b467e24ebf341aaee4a86ff9..d03ab66b50d1ceda7671e199a0fd07256f5e635d 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) Andrew Tridgell              1992-1997,
  *  Copyright (C) Jeremy Allison               2001.
  *  Copyright (C) Nigel Williams               2001.
+ *  Copyright (C) Gerald (Jerry) Carter        2006.
  *  
  *  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
@@ -29,6 +30,174 @@ extern struct generic_mapping file_generic_mapping;
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
+/* Use for enumerating connections, pipes, & files */
+
+struct file_enum_count {
+       TALLOC_CTX *ctx;
+       int count;
+       FILE_INFO_3 *info;
+};
+
+struct sess_file_count {
+       pid_t pid;
+       uid_t uid;
+       int count;
+};
+
+/****************************************************************************
+ Count the entries belonging to a service in the connection db.
+****************************************************************************/
+
+static int pipe_enum_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *p)
+{
+       struct pipe_open_rec prec;
+       struct file_enum_count *fenum = (struct file_enum_count *)p;
+       if (dbuf.dsize != sizeof(struct pipe_open_rec))
+               return 0;
+
+       memcpy(&prec, dbuf.dptr, sizeof(struct pipe_open_rec));
+       if ( process_exists(prec.pid) ) {
+               FILE_INFO_3 *f;
+               int i = fenum->count;
+               pstring fullpath;
+               
+               snprintf( fullpath, sizeof(fullpath), "\\PIPE\\%s", prec.name );
+               
+               f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 );
+               if ( !f ) {
+                       DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
+                       return 1;
+               }
+               fenum->info = f;
+               
+               
+               init_srv_file_info3( &fenum->info[i], 
+                       (uint32)((procid_to_pid(&prec.pid)<<16) & prec.pnum),
+                       (FILE_READ_DATA|FILE_WRITE_DATA), 
+                       0,
+                       uidtoname( prec.uid ),
+                       fullpath );
+                       
+               fenum->count++;
+       }
+
+       return 0;
+}
+
+/*******************************************************************
+********************************************************************/
+
+static WERROR net_enum_pipes( TALLOC_CTX *ctx, FILE_INFO_3 **info, 
+                              uint32 *count, uint32 resume )
+{
+       struct file_enum_count fenum;
+       TDB_CONTEXT *conn_tdb = conn_tdb_ctx();
+
+       if ( !conn_tdb ) {
+               DEBUG(0,("net_enum_pipes: Failed to retrieve the connections tdb handle!\n"));
+               return WERR_ACCESS_DENIED;
+       }
+       
+       fenum.ctx = ctx;
+       fenum.count = *count;
+       fenum.info = *info;
+
+       if (tdb_traverse(conn_tdb, pipe_enum_fn, &fenum) == -1) {
+               DEBUG(0,("net_enum_pipes: traverse of connections.tdb failed with error %s.\n",
+                       tdb_errorstr(conn_tdb) ));
+               return WERR_NOMEM;
+       }
+       
+       *info  = fenum.info;
+       *count = fenum.count;
+       
+       return WERR_OK;}
+
+/*******************************************************************
+********************************************************************/
+
+/* global needed to make use of the share_mode_forall() callback */
+static struct file_enum_count f_enum_cnt;
+
+static void enum_file_fn( const struct share_mode_entry *e, 
+                          const char *sharepath, const char *fname, void *state )
+{
+       struct file_enum_count *fenum = &f_enum_cnt;
+       /* If the pid was not found delete the entry from connections.tdb */
+
+       if ( process_exists(e->pid) ) {
+               FILE_INFO_3 *f;
+               int i = fenum->count;
+               files_struct fsp;
+               struct byte_range_lock *brl;
+               int num_locks = 0;
+               pstring fullpath;
+               uint32 permissions;
+               
+               f = TALLOC_REALLOC_ARRAY( fenum->ctx, fenum->info, FILE_INFO_3, i+1 );                  
+               if ( !f ) {
+                       DEBUG(0,("conn_enum_fn: realloc failed for %d items\n", i+1));
+                       return;
+               }
+               fenum->info = f;
+
+               /* need to count the number of locks on a file */
+               
+               ZERO_STRUCT( fsp );             
+               fsp.dev   = e->dev;
+               fsp.inode = e->inode;
+               
+               if ( (brl = brl_get_locks(NULL,&fsp)) != NULL ) {
+                       num_locks = brl->num_locks;
+                       TALLOC_FREE( brl );
+               }
+               
+               if ( strcmp( fname, "." ) == 0 ) {
+                       pstr_sprintf( fullpath, "C:%s", sharepath );
+               } else {
+                       pstr_sprintf( fullpath, "C:%s/%s", sharepath, fname );
+               }
+               string_replace( fullpath, '/', '\\' );
+               
+               /* mask out create (what ever that is) */
+               permissions = e->share_access & (FILE_READ_DATA|FILE_WRITE_DATA);
+
+               /* now fill in the FILE_INFO_3 struct */
+               init_srv_file_info3( &fenum->info[i], 
+                       e->share_file_id,
+                       permissions,
+                       num_locks,
+                       uidtoname(e->uid),
+                       fullpath );
+                       
+               fenum->count++;
+       }
+
+       return;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+static WERROR net_enum_files( TALLOC_CTX *ctx, FILE_INFO_3 **info, 
+                              uint32 *count, uint32 resume )
+{
+       f_enum_cnt.ctx = ctx;
+       f_enum_cnt.count = *count;
+       f_enum_cnt.info = *info;
+       
+       share_mode_forall( enum_file_fn, NULL );
+       
+       *info  = f_enum_cnt.info;
+       *count = f_enum_cnt.count;
+       
+       return WERR_OK;
+}
+
 /*******************************************************************
  Utility function to get the 'type' of a share from an snum.
  ********************************************************************/
@@ -91,8 +260,9 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
        pstring passwd;
        int max_connections = lp_max_connections(snum);
        uint32 max_uses = max_connections!=0 ? max_connections : 0xffffffff;
-
+       int count = 0;
        char *net_name = lp_servicename(snum);
+       
        pstrcpy(remark, lp_comment(snum));
        standard_sub_conn(p->conn, remark,sizeof(remark));
        pstrcpy(path, "C:");
@@ -107,7 +277,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
 
        pstrcpy(passwd, "");
 
-       init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), remark, 0, max_uses, 1, path, passwd);
+       count = count_current_connections( net_name, False  );
+       init_srv_share_info2(&sh2->info_2, net_name, get_share_type(snum), 
+               remark, 0, max_uses, count, path, passwd);
+
        init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
 }
 
@@ -595,16 +768,6 @@ static void init_srv_r_net_share_get_info(pipes_struct *p, SRV_R_NET_SHARE_GET_I
        r_n->status = status;
 }
 
-/*******************************************************************
- fill in a sess info level 1 structure.
- ********************************************************************/
-
-static void init_srv_sess_0_info(SESS_INFO_0 *se0, SESS_INFO_0_STR *str0, char *name)
-{
-       init_srv_sess_info0(se0, name);
-       init_srv_sess_info0_str(str0, name);
-}
-
 /*******************************************************************
  fill in a sess info level 0 structure.
  ********************************************************************/
@@ -627,11 +790,7 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
 
        if (snum) {
                for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
-                       init_srv_sess_0_info(&ss0->info_0[num_entries],
-                                                                &ss0->info_0_str[num_entries], session_list[(*snum)].remote_machine);
-
-                       /* move on to creating next session */
-                       /* move on to creating next sess */
+                       init_srv_sess_info0( &ss0->info_0[num_entries], session_list[(*snum)].remote_machine);
                        num_entries++;
                }
 
@@ -652,17 +811,35 @@ static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *sto
 }
 
 /*******************************************************************
- fill in a sess info level 1 structure.
- ********************************************************************/
+********************************************************************/
+
+/* global needed to make use of the share_mode_forall() callback */
+static struct sess_file_count s_file_cnt;
+
+static void sess_file_fn( const struct share_mode_entry *e, 
+                          const char *sharepath, const char *fname, void *state )
+{
+       struct sess_file_count *sess = &s_file_cnt;
+       if ( (procid_to_pid(&e->pid) == sess->pid) && (sess->uid == e->uid) ) {
+               sess->count++;
+       }
+       
+       return;
+}
 
-static void init_srv_sess_1_info(SESS_INFO_1 *se1, SESS_INFO_1_STR *str1,
-                               char *name, char *user,
-                               uint32 num_opens,
-                               uint32 open_time, uint32 idle_time,
-                               uint32 usr_flgs)
+/*******************************************************************
+********************************************************************/
+
+static int net_count_files( uid_t uid, pid_t pid )
 {
-       init_srv_sess_info1(se1 , name, user, num_opens, open_time, idle_time, usr_flgs);
-       init_srv_sess_info1_str(str1, name, user);
+       s_file_cnt.count = 0;
+       s_file_cnt.uid = uid;
+       s_file_cnt.pid = pid;
+       
+       share_mode_forall( sess_file_fn, NULL );
+       
+       return s_file_cnt.count;
 }
 
 /*******************************************************************
@@ -673,43 +850,58 @@ static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *sto
 {
        struct sessionid *session_list;
        uint32 num_entries = 0;
-       (*stot) = list_sessions(&session_list);
+       time_t now = time(NULL);
 
+       if ( !snum ) {
+               ss1->num_entries_read = 0;
+               ss1->ptr_sess_info = 0;
+               ss1->num_entries_read2 = 0;
+               
+               (*stot) = 0;
+
+               return;
+       }
+       
        if (ss1 == NULL) {
                (*snum) = 0;
-               SAFE_FREE(session_list);
                return;
        }
 
-       DEBUG(5,("init_srv_sess_1_ss1\n"));
-
-       if (snum) {
-               for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
-                       init_srv_sess_1_info(&ss1->info_1[num_entries],
-                                            &ss1->info_1_str[num_entries],
-                                           session_list[*snum].remote_machine,
-                                            session_list[*snum].username,
-                                            1, 10, 5, 0);
-
-                       /* move on to creating next session */
-                       /* move on to creating next sess */
-                       num_entries++;
-               }
+       (*stot) = list_sessions(&session_list);
+       
 
-               ss1->num_entries_read  = num_entries;
-               ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
-               ss1->num_entries_read2 = num_entries;
-               
-               if ((*snum) >= (*stot)) {
-                       (*snum) = 0;
+       for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++) {
+               uint32 num_files;
+               uint32 connect_time;
+               struct passwd *pw = sys_getpwnam(session_list[*snum].username);
+               BOOL guest;
+                       
+               if ( !pw ) {
+                       DEBUG(10,("init_srv_sess_info_1: failed to find owner: %s\n",
+                               session_list[*snum].username));
+                       continue;
                }
-
-       } else {
-               ss1->num_entries_read = 0;
-               ss1->ptr_sess_info = 0;
-               ss1->num_entries_read2 = 0;
-               
-               (*stot) = 0;
+                               
+               connect_time = (uint32)(now - session_list[*snum].connect_start);
+               num_files = net_count_files(pw->pw_uid, session_list[*snum].pid);
+               guest = strequal( session_list[*snum].username, lp_guestaccount() );
+                                       
+               init_srv_sess_info1( &ss1->info_1[num_entries], 
+                                    session_list[*snum].remote_machine,
+                                    session_list[*snum].username, 
+                                    num_files,
+                                    connect_time,
+                                    0, 
+                                    guest);
+               num_entries++;
+       }
+
+       ss1->num_entries_read  = num_entries;
+       ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
+       ss1->num_entries_read2 = num_entries;
+       
+       if ((*snum) >= (*stot)) {
+               (*snum) = 0;
        }
 
        SAFE_FREE(session_list);
@@ -929,66 +1121,53 @@ static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
  makes a SRV_R_NET_FILE_ENUM structure.
 ********************************************************************/
 
-static WERROR init_srv_file_info_ctr(pipes_struct *p, SRV_FILE_INFO_CTR *ctr,
-                                    int switch_value, uint32 *resume_hnd, 
-                                    uint32 *total_entries)  
+static WERROR net_file_enum_3( SRV_R_NET_FILE_ENUM *r, uint32 resume_hnd )
 {
-       WERROR status = WERR_OK;
-       TALLOC_CTX *ctx = p->mem_ctx;
-       DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__));
-       *total_entries = 1; /* dummy entries only, for */
+       TALLOC_CTX *ctx = get_talloc_ctx();
+       SRV_FILE_INFO_CTR *ctr = &r->ctr;
 
-       ctr->switch_value = switch_value;
-       ctr->num_entries = *total_entries - *resume_hnd;
+       /* TODO -- Windows enumerates 
+          (b) active pipes
+          (c) open directories and files */
+
+       r->status = net_enum_files( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd );
+       if ( !W_ERROR_IS_OK(r->status))
+               goto done;
+               
+       r->status = net_enum_pipes( ctx, &ctr->file.info3, &ctr->num_entries, resume_hnd );
+       if ( !W_ERROR_IS_OK(r->status))
+               goto done;
+       
+       r->level = ctr->level = 3;
+       r->total_entries = ctr->num_entries;
+       /* ctr->num_entries = r->total_entries - resume_hnd; */
        ctr->num_entries2 = ctr->num_entries;
+       ctr->ptr_file_info = 1;
 
-       switch (switch_value) {
-       case 3: {
-               int i;
-               if (*total_entries > 0) {
-                       ctr->ptr_entries = 1;
-                       ctr->file.info3 = TALLOC_ARRAY(ctx, SRV_FILE_INFO_3, ctr->num_entries);
-               }
-               for (i=0 ;i<ctr->num_entries;i++) {
-                       init_srv_file_info3(&ctr->file.info3[i].info_3, i+*resume_hnd, 0x35, 0, "\\PIPE\\samr", "dummy user");
-                       init_srv_file_info3_str(&ctr->file.info3[i].info_3_str,  "\\PIPE\\samr", "dummy user");
-                       
-               }
-               ctr->ptr_file_info = 1;
-               *resume_hnd = 0;
-               break;
-       }
-       default:
-               DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n", switch_value));
-               (*resume_hnd = 0);
-               (*total_entries) = 0;
-               ctr->ptr_entries = 0;
-               status = WERR_UNKNOWN_LEVEL;
-               break;
-       }
+       r->status = WERR_OK;
 
-       return status;
+done:
+       if ( ctr->num_entries > 0 ) 
+               ctr->ptr_entries = 1;
+
+       init_enum_hnd(&r->enum_hnd, 0);
+
+       return r->status;
 }
 
 /*******************************************************************
- makes a SRV_R_NET_FILE_ENUM structure.
-********************************************************************/
+*******************************************************************/
 
-static void init_srv_r_net_file_enum(pipes_struct *p, SRV_R_NET_FILE_ENUM *r_n,
-                               uint32 resume_hnd, int file_level, int switch_value)  
+WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
 {
-       DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__));
-
-       r_n->file_level  = file_level;
-       if (file_level == 0)
-               r_n->status = WERR_UNKNOWN_LEVEL;
-       else
-               r_n->status = init_srv_file_info_ctr(p, &r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
-
-       if (!W_ERROR_IS_OK(r_n->status))
-               resume_hnd = 0;
-
-       init_enum_hnd(&r_n->enum_hnd, resume_hnd);
+       switch ( q_u->level ) {
+       case 3:
+               return net_file_enum_3( r_u, get_enum_hnd(&q_u->enum_hnd) );    
+       default:
+               return WERR_UNKNOWN_LEVEL;
+       }
+       
+       return WERR_OK;
 }
 
 /*******************************************************************
@@ -1074,25 +1253,6 @@ WERROR _srv_net_srv_set_info(pipes_struct *p, SRV_Q_NET_SRV_SET_INFO *q_u, SRV_R
        return r_u->status;
 }
 
-/*******************************************************************
-net file enum
-********************************************************************/
-
-WERROR _srv_net_file_enum(pipes_struct *p, SRV_Q_NET_FILE_ENUM *q_u, SRV_R_NET_FILE_ENUM *r_u)
-{
-       DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
-
-       /* set up the */
-       init_srv_r_net_file_enum(p, r_u,
-                               get_enum_hnd(&q_u->enum_hnd),
-                               q_u->file_level,
-                               q_u->ctr.switch_value);
-
-       DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
-
-       return r_u->status;
-}
-
 /*******************************************************************
 net conn enum
 ********************************************************************/
@@ -2102,7 +2262,7 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV
 
        switch ( q_u->type ) {
        case 0x9:
-               rpcstr_pull(sharename, q_u->uni_name.buffer, sizeof(sharename), q_u->uni_name.uni_str_len*2, 0);
+               rpcstr_pull(sharename, q_u->sharename.buffer, sizeof(sharename), q_u->sharename.uni_str_len*2, 0);
                if ( !validate_net_name( sharename, INVALID_SHARENAME_CHARS, sizeof(sharename) ) ) {
                        DEBUG(5,("_srv_net_name_validate: Bad sharename \"%s\"\n", sharename));
                        return WERR_INVALID_NAME;
@@ -2115,3 +2275,13 @@ WERROR _srv_net_name_validate(pipes_struct *p, SRV_Q_NET_NAME_VALIDATE *q_u, SRV
 
        return WERR_OK;
 }
+
+
+/********************************************************************
+********************************************************************/
+
+WERROR _srv_net_file_close(pipes_struct *p, SRV_Q_NET_FILE_CLOSE *q_u, SRV_R_NET_FILE_CLOSE *r_u)
+{
+       return WERR_ACCESS_DENIED;
+}
+
index e2a026c87bf866c73e25b4330a9d57e495c1252d..676d84835dea3d32e13a9aac0b45bd9cf0a72a96 100644 (file)
@@ -1858,6 +1858,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli,
        if ((argc < 1) || (argc > 3)) {
                printf("Usage: %s [rid|-d] [sec_info]\n", argv[0]);
                printf("\tSpecify rid for security on user, -d for security on domain\n");
+               talloc_destroy(ctx);
                return NT_STATUS_OK;
        }
        
index b826cd622afe2ed414f736979082ff5a4516e1ed..a123a542fd22d9ae2011be5cf7ee56dd9899f1a2 100644 (file)
@@ -373,9 +373,9 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
         * Ensure pending modtime is set after close.
         */
 
-       if(fsp->pending_modtime && fsp->pending_modtime_owner) {
+       if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) {
                set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
-       } else if (fsp->last_write_time) {
+       } else if (!null_timespec(fsp->last_write_time)) {
                set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
        }
 
index 2795b2a24b29fa10e1fdf1ec19a75f0f8bd98135..db3e155ae4783ede8053bc89becba4225ff65796 100644 (file)
@@ -1017,6 +1017,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
        }
 
        if (hide_unreadable || hide_unwriteable || hide_special) {
+               pstring link_target;
                char *entry = NULL;
 
                if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
@@ -1026,10 +1027,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
                /* If it's a dfs symlink, ignore _hide xxxx_ options */
                if (lp_host_msdfs() &&
                                lp_msdfs_root(SNUM(conn)) &&
-                                       /* We get away with NULL talloc ctx here as
-                                          we're not interested in the link contents
-                                          so we have nothing to free. */
-                               is_msdfs_link(NULL, conn, entry, NULL, NULL, NULL)) {
+                               is_msdfs_link(conn, entry, link_target, NULL)) {
                        SAFE_FREE(entry);
                        return True;
                }
index ad79bbacddf31382fa70e4331f6929ff1fbace8d..71d4fa179d4949fc72028c7fea89207994bc93af 100644 (file)
@@ -282,7 +282,7 @@ static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_
                }
 
                /* We want DOS semantics, ie allow non owner with write permission to change the
-                       bits on a file. Just like file_utime below.
+                       bits on a file. Just like file_ntimes below.
                */
 
                /* Check if we have write access. */
@@ -504,7 +504,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
                return -1;
 
        /* We want DOS semantics, ie allow non owner with write permission to change the
-               bits on a file. Just like file_utime below.
+               bits on a file. Just like file_ntimes below.
        */
 
        /* Check if we have write access. */
@@ -532,11 +532,11 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
 }
 
 /*******************************************************************
- Wrapper around dos_utime that possibly allows DOS semantics rather
+ Wrapper around the VFS ntimes that possibly allows DOS semantics rather
  than POSIX.
 *******************************************************************/
 
-int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times)
+int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2])
 {
        SMB_STRUCT_STAT sbuf;
        int ret = -1;
@@ -555,14 +555,17 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times
                return 0;
        }
 
-       if(SMB_VFS_UTIME(conn,fname, times) == 0)
+       if(SMB_VFS_NTIMES(conn, fname, ts) == 0) {
                return 0;
+       }
 
-       if((errno != EPERM) && (errno != EACCES))
+       if((errno != EPERM) && (errno != EACCES)) {
                return -1;
+       }
 
-       if(!lp_dos_filetimes(SNUM(conn)))
+       if(!lp_dos_filetimes(SNUM(conn))) {
                return -1;
+       }
 
        /* We have permission (given by the Samba admin) to
           break POSIX semantics and allow a user to change
@@ -574,7 +577,7 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times
        if (can_write_to_file(conn, fname, &sbuf)) {
                /* We are allowed to become root and change the filetime. */
                become_root();
-               ret = SMB_VFS_UTIME(conn,fname, times);
+               ret = SMB_VFS_NTIMES(conn, fname, ts);
                unbecome_root();
        }
 
@@ -585,16 +588,19 @@ int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times
  Change a filetime - possibly allowing DOS semantics.
 *******************************************************************/
 
-BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
+BOOL set_filetime(connection_struct *conn, const char *fname,
+               const struct timespec mtime)
 {
-       struct utimbuf times;
+       struct timespec ts[2];
 
-       if (null_mtime(mtime))
+       if (null_timespec(mtime)) {
                return(True);
+       }
 
-       times.modtime = times.actime = mtime;
+       ts[1] = mtime; /* mtime. */
+       ts[0] = ts[1]; /* atime. */
 
-       if (file_utime(conn, fname, &times)) {
+       if (file_ntimes(conn, fname, ts)) {
                DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
                return False;
        }
@@ -602,5 +608,5 @@ BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime)
        notify_fname(conn, NOTIFY_ACTION_MODIFIED,
                     FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
   
-       return(True);
-} 
+       return True;
+}
index e0945be8893e220031b13ce91899929ecf478aff..65238c0e9ee60bb0e7c47767e2182caaa2363319 100644 (file)
@@ -149,13 +149,13 @@ static ssize_t real_write_file(files_struct *fsp,const char *data, SMB_OFF_T pos
                 * The 99% solution will hopefully be good enough in this case. JRA.
                 */
 
-               if (fsp->pending_modtime) {
+               if (!null_timespec(fsp->pending_modtime)) {
                        set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime);
 
                        /* If we didn't get the "set modtime" call ourselves, we must
                           store the last write time to restore on close. JRA. */
                        if (!fsp->pending_modtime_owner) {
-                               fsp->last_write_time = time(NULL);
+                               fsp->last_write_time = timespec_current();
                        }
                }
 
index 66ef37bb0fa24ba07961bdc99adfc4ebe916b185..23fd47671b854876b3335d41c37cadf2802e910a 100644 (file)
@@ -383,11 +383,11 @@ files_struct *file_find_print(void)
  Record the owner of that modtime.
 ****************************************************************************/
 
-void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
+void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod)
 {
        files_struct *fsp;
 
-       if (null_mtime(pmod)) {
+       if (null_timespec(mod)) {
                return;
        }
 
@@ -395,7 +395,7 @@ void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
                if ( fsp->fh->fd != -1 &&
                                fsp->dev == tfsp->dev &&
                                fsp->inode == tfsp->inode ) {
-                       fsp->pending_modtime = pmod;
+                       fsp->pending_modtime = mod;
                        fsp->pending_modtime_owner = False;
                }
        }
index 2a19d6fb418896691bd5e0ee43587c5caf75acd6..284061331bf4cfdcbed36e1222bf431ff5b64f07 100644 (file)
@@ -1,8 +1,9 @@
 /* 
    Unix SMB/Netbios implementation.
    Version 3.0
-   MSDfs services for Samba
+   MSDFS services for Samba
    Copyright (C) Shirish Kalele 2000
+   Copyright (C) Jeremy Allison 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
 extern uint32 global_client_caps;
 
 /**********************************************************************
-  Parse the pathname  of the form \hostname\service\reqpath
-  into the dfs_path structure 
- **********************************************************************/
+ Parse a DFS pathname of the form \hostname\service\reqpath
+ into the dfs_path structure.
+ If POSIX pathnames is true, the pathname may also be of the
+ form /hostname/service/reqpath.
+ We cope with either here.
+
+ Unfortunately, due to broken clients who might set the
+ SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then
+ send a local path, we have to cope with that too....
 
-static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp)
+ JRA.
+**********************************************************************/
+
+static NTSTATUS parse_dfs_path(const char *pathname,
+                               BOOL allow_wcards,
+                               struct dfs_path *pdp,
+                               BOOL *ppath_contains_wcard)
 {
        pstring pathname_local;
-       char *p, *temp;
+       char *p,*temp;
+       NTSTATUS status = NT_STATUS_OK;
+       char sepchar;
+
+       ZERO_STRUCTP(pdp);
 
        pstrcpy(pathname_local,pathname);
        p = temp = pathname_local;
 
-       ZERO_STRUCTP(pdp);
+       pdp->posix_path = (lp_posix_pathnames() && *pathname == '/');
 
-       trim_char(temp,'\\','\\');
-       DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp));
+       sepchar = pdp->posix_path ? '/' : '\\';
 
-       /* now tokenize */
-       /* parse out hostname */
-       p = strchr_m(temp,'\\');
-       if(p == NULL) {
-               return False;
-       }
-       *p = '\0';
-       pstrcpy(pdp->hostname,temp);
-       DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname));
+       if (*pathname != sepchar) {
+               DEBUG(10,("parse_dfs_path: path %s doesn't start with %c\n",
+                       pathname, sepchar ));
+               /*
+                * Possibly client sent a local path by mistake.
+                * Try and convert to a local path.
+                */
 
-       /* parse out servicename */
-       temp = p+1;
-       p = strchr_m(temp,'\\');
-       if(p == NULL) {
-               pstrcpy(pdp->servicename,temp);
-               pdp->reqpath[0] = '\0';
-               return True;
+               pdp->hostname[0] = '\0';
+               pdp->servicename[0] = '\0';
+
+               /* We've got no info about separators. */
+               pdp->posix_path = lp_posix_pathnames();
+               p = temp;
+               DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n",
+                       temp));
+               goto local_path;
        }
-       *p = '\0';
-       pstrcpy(pdp->servicename,temp);
-       DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));
 
-       /* rest is reqpath */
-       check_path_syntax(pdp->reqpath, p+1);
+       trim_char(temp,sepchar,sepchar);
 
-       DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath));
-       return True;
-}
+       DEBUG(10,("parse_dfs_path: temp = |%s| after trimming %c's\n",
+               temp, sepchar));
 
-/**********************************************************************
- Parse the pathname  of the form /hostname/service/reqpath
- into the dfs_path structure 
- This code is dependent on the fact that check_path_syntax() will
- convert '\\' characters to '/'.
- When POSIX pathnames have been selected this doesn't happen, so we
- must look for the unaltered separator of '\\' instead of the modified '/'.
- JRA.
- **********************************************************************/
+       /* Now tokenize. */
+       /* Parse out hostname. */
+       p = strchr_m(temp,sepchar);
+       if(p == NULL) {
+               DEBUG(10,("parse_dfs_path: can't parse hostname from path %s\n",
+                       temp));
+               /*
+                * Possibly client sent a local path by mistake.
+                * Try and convert to a local path.
+                */
 
-static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards)
-{
-       pstring pathname_local;
-       char *p,*temp;
-       const char sepchar = lp_posix_pathnames() ? '\\' : '/';
+               pdp->hostname[0] = '\0';
+               pdp->servicename[0] = '\0';
 
-       pstrcpy(pathname_local,pathname);
-       p = temp = pathname_local;
+               p = temp;
+               DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n",
+                       temp));
+               goto local_path;
+       }
+       *p = '\0';
+       fstrcpy(pdp->hostname,temp);
+       DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname));
 
-       ZERO_STRUCTP(pdp);
+       /* If we got a hostname, is it ours (or an IP address) ? */
+       if (!is_myname_or_ipaddr(pdp->hostname)) {
+               /* Repair path. */
+               *p = sepchar;
+               DEBUG(10,("parse_dfs_path: hostname %s isn't ours. Try local path from path %s\n",
+                       pdp->hostname, temp));
+               /*
+                * Possibly client sent a local path by mistake.
+                * Try and convert to a local path.
+                */
 
-       trim_char(temp,sepchar,sepchar);
-       DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp));
+               pdp->hostname[0] = '\0';
+               pdp->servicename[0] = '\0';
 
-       /* now tokenize */
-       /* parse out hostname */
-       p = strchr_m(temp,sepchar);
-       if(p == NULL) {
-               return False;
+               p = temp;
+               DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n",
+                       temp));
+               goto local_path;
        }
-       *p = '\0';
-       pstrcpy(pdp->hostname,temp);
-       DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname));
 
-       /* parse out servicename */
+       /* Parse out servicename. */
        temp = p+1;
        p = strchr_m(temp,sepchar);
        if(p == NULL) {
-               pstrcpy(pdp->servicename,temp);
+               fstrcpy(pdp->servicename,temp);
                pdp->reqpath[0] = '\0';
-               return True;
+               return NT_STATUS_OK;
        }
        *p = '\0';
-       pstrcpy(pdp->servicename,temp);
-       DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename));
+       fstrcpy(pdp->servicename,temp);
+       DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));
+
+       p++;
+
+  local_path:
+
+       *ppath_contains_wcard = False;
 
-       /* rest is reqpath */
-       if (allow_wcards) {
-               BOOL path_contains_wcard;
-               check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard);
+       /* Rest is reqpath. */
+       if (pdp->posix_path) {
+               status = check_path_syntax_posix(pdp->reqpath, p);
        } else {
-               check_path_syntax(pdp->reqpath, p+1);
+               if (allow_wcards) {
+                       status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard);
+               } else {
+                       status = check_path_syntax(pdp->reqpath, p);
+               }
        }
 
-       DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath));
-       return True;
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10,("parse_dfs_path: '%s' failed with %s\n",
+                       p, nt_errstr(status) ));
+               return status;
+       }
+
+       DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath));
+       return NT_STATUS_OK;
 }
 
 /********************************************************
@@ -135,7 +170,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL
  Note this CHANGES CWD !!!! JRA.
 *********************************************************/
 
-static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
+static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path)
 {
        pstring connpath;
 
@@ -145,19 +180,19 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
        pstring_sub(connpath , "%S", lp_servicename(snum));
 
        /* needed for smbd_vfs_init() */
-       
-        if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) {
-                DEBUG(0,("talloc_init(connection_struct) failed!\n"));
-                return False;
-        }
 
-       if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) {
+       if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) {
+               DEBUG(0,("talloc_init(connection_struct) failed!\n"));
+               return False;
+       }
+
+       if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) {
                DEBUG(0, ("TALLOC failed\n"));
                return False;
        }
-       
+
        conn->params->service = snum;
-       
+
        set_conn_connectpath(conn, connpath);
 
        if (!smbd_vfs_init(conn)) {
@@ -184,11 +219,27 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path)
 
 /**********************************************************************
  Parse the contents of a symlink to verify if it is an msdfs referral
- A valid referral is of the form: msdfs:server1\share1,server2\share2
- talloc CTX can be NULL here if preflist and refcount pointers are null.
+ A valid referral is of the form:
+
+ msdfs:server1\share1,server2\share2
+ msdfs:server1\share1\pathname,server2\share2\pathname
+ msdfs:server1/share1,server2/share2
+ msdfs:server1/share1/pathname,server2/share2/pathname.
+
+ Note that the alternate paths returned here must be of the canonicalized
+ form:
+
+ \server\share or
+ \server\share\path\to\file,
+
+ even in posix path mode. This is because we have no knowledge if the
+ server we're referring to understands posix paths.
  **********************************************************************/
 
-static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist, int *refcount)
+static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx,
+                               char *target,
+                               struct referral **preflist,
+                               int *refcount)
 {
        pstring temp;
        char *prot;
@@ -196,45 +247,28 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist
        int count = 0, i;
        struct referral *reflist;
 
-       pstrcpy(temp,buf);
-  
+       pstrcpy(temp,target);
        prot = strtok(temp,":");
 
-       if (!strequal(prot, "msdfs")) {
-               return False;
-       }
-
-       /* No referral list requested. Just yes/no. */
-       if (!preflist) {
-               return True;
-       }
-
-       if (!ctx) {
-               DEBUG(0,("parse_symlink: logic error. TALLOC_CTX should not be null.\n"));
-               return True;
-       }
-
        /* parse out the alternate paths */
        while((count<MAX_REFERRAL_COUNT) &&
              ((alt_path[count] = strtok(NULL,",")) != NULL)) {
                count++;
        }
 
-       DEBUG(10,("parse_symlink: count=%d\n", count));
+       DEBUG(10,("parse_msdfs_symlink: count=%d\n", count));
 
-       reflist = *preflist = TALLOC_ARRAY(ctx, struct referral, count);
+       reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count);
        if(reflist == NULL) {
-               DEBUG(0,("parse_symlink: talloc failed!\n"));
+               DEBUG(0,("parse_msdfs_symlink: talloc failed!\n"));
                return False;
        }
        
        for(i=0;i<count;i++) {
                char *p;
 
-               /* replace all /'s in the alternate path by a \ */
-               for(p = alt_path[i]; *p && ((p = strchr_m(p,'/'))!=NULL); p++) {
-                       *p = '\\'; 
-               }
+               /* Canonicalize link target. Replace all /'s in the path by a \ */
+               string_replace(alt_path[i], '/', '\\');
 
                /* Remove leading '\\'s */
                p = alt_path[i];
@@ -244,35 +278,29 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist
 
                pstrcpy(reflist[i].alternate_path, "\\");
                pstrcat(reflist[i].alternate_path, p);
+
                reflist[i].proximity = 0;
                reflist[i].ttl = REFERRAL_TTL;
-               DEBUG(10, ("parse_symlink: Created alt path: %s\n", reflist[i].alternate_path));
-       }
-
-       if(refcount) {
-               *refcount = count;
+               DEBUG(10, ("parse_msdfs_symlink: Created alt path: %s\n", reflist[i].alternate_path));
+               *refcount += 1;
        }
 
        return True;
 }
  
 /**********************************************************************
- Returns true if the unix path is a valid msdfs symlink
talloc CTX can be NULL here if reflistp and refcnt pointers are null.
- **********************************************************************/
+ Returns true if the unix path is a valid msdfs symlink and also
returns the target string from inside the link.
+**********************************************************************/
 
-BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path,
-                  struct referral **reflistp, int *refcnt,
-                  SMB_STRUCT_STAT *sbufp)
+BOOL is_msdfs_link(connection_struct *conn,
+                       const char *path,
+                       pstring link_target,
+                       SMB_STRUCT_STAT *sbufp)
 {
        SMB_STRUCT_STAT st;
-       pstring referral;
        int referral_len = 0;
 
-       if (!path || !conn) {
-               return False;
-       }
-
        if (sbufp == NULL) {
                sbufp = &st;
        }
@@ -282,76 +310,59 @@ BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path,
                return False;
        }
   
-       if (S_ISLNK(sbufp->st_mode)) {
-               /* open the link and read it */
-               referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)-1);
-               if (referral_len == -1) {
-                       DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno)));
-                       return False;
-               }
+       if (!S_ISLNK(sbufp->st_mode)) {
+               DEBUG(5,("is_msdfs_link: %s is not a link.\n",path));
+               return False;
+       }
 
-               referral[referral_len] = '\0';
-               DEBUG(5,("is_msdfs_link: %s -> %s\n",path,referral));
-               if (parse_symlink(ctx, referral, reflistp, refcnt)) {
-                       return True;
-               }
+       /* open the link and read it */
+       referral_len = SMB_VFS_READLINK(conn, path, link_target, sizeof(pstring)-1);
+       if (referral_len == -1) {
+               DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n",
+                       path, strerror(errno)));
+               return False;
+       }
+       link_target[referral_len] = '\0';
+
+       DEBUG(5,("is_msdfs_link: %s -> %s\n",path, link_target));
+
+       if (!strnequal(link_target, "msdfs:", 6)) {
+               return False;
        }
-       return False;
+       return True;
 }
 
 /*****************************************************************
  Used by other functions to decide if a dfs path is remote,
-and to get the list of referred locations for that remote path.
+ and to get the list of referred locations for that remote path.
  
-findfirst_flag: For findfirsts, dfs links themselves are not
-redirected, but paths beyond the links are. For normal smb calls,
-even dfs links need to be redirected.
+ search_flag: For findfirsts, dfs links themselves are not
+ redirected, but paths beyond the links are. For normal smb calls,
+ even dfs links need to be redirected.
 
-self_referralp: clients expect a dfs referral for the same share when
-they request referrals for dfs roots on a server. 
+ consumedcntp: how much of the dfs path is being redirected. the client
+ should try the remaining path on the redirected server.
 
-consumedcntp: how much of the dfs path is being redirected. the client
-should try the remaining path on the redirected server.
-
-TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp
-are also NULL.
+ If this returns NT_STATUS_PATH_NOT_COVERED the contents of the msdfs
+ link redirect are in targetpath.
 *****************************************************************/
 
-static BOOL resolve_dfs_path(TALLOC_CTX *ctx,
-                       const char *dfspath, 
-                       struct dfs_path *dp, 
-                       connection_struct *conn,
-                       BOOL search_flag, 
-                       struct referral **reflistpp,
-                       int *refcntp,
-                       BOOL *self_referralp,
-                       int *consumedcntp)
+static NTSTATUS dfs_path_lookup(connection_struct *conn,
+                       const char *dfspath, /* Incoming complete dfs path */
+                       const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */
+                       BOOL search_flag, /* Called from a findfirst ? */
+                       int *consumedcntp,
+                       pstring targetpath)
 {
-       pstring localpath;
-       int consumed_level = 1;
-       char *p;
+       char *p = NULL;
+       char *q = NULL;
        SMB_STRUCT_STAT sbuf;
        NTSTATUS status;
-       pstring reqpath;
-
-       if (!dp || !conn) {
-               DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n"));
-               return False;
-       }
-
-       if (!ctx && (reflistpp || refcntp)) {
-               DEBUG(0,("resolve_dfs_path: logic error. TALLOC_CTX must not be NULL.\n"));
-       }
-
-       if (dp->reqpath[0] == '\0') {
-               if (self_referralp) {
-                       DEBUG(6,("resolve_dfs_path: self-referral. returning False\n"));
-                       *self_referralp = True;
-               }
-               return False;
-       }
+       pstring localpath;
+       pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */
 
-       DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath));
+       DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n",
+               conn->connectpath, pdp->reqpath));
 
        /* 
         * Note the unix path conversion here we're doing we can
@@ -365,144 +376,189 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx,
         * think this is needed. JRA.
         */
 
-       pstrcpy(localpath, dp->reqpath);
-
-       status = unix_convert(conn, localpath, False, NULL, &sbuf);
+       pstrcpy(localpath, pdp->reqpath);
+       status = unix_convert(conn, localpath, search_flag, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
-               return False;
+               return status;
        }
 
-       /* check if need to redirect */
-       if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) {
-               if ( search_flag ) {
-                       DEBUG(6,("resolve_dfs_path (FindFirst) No redirection "
+       /* Optimization - check if we can redirect the whole path. */
+
+       if (is_msdfs_link(conn, localpath, targetpath, NULL)) {
+               if (search_flag) {
+                       DEBUG(6,("dfs_path_lookup (FindFirst) No redirection "
                                 "for dfs link %s.\n", dfspath));
-                       return False;
+                       return NT_STATUS_OK;
                }
 
-               DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath));
+               DEBUG(6,("dfs_path_lookup: %s resolves to a "
+                       "valid dfs link %s.\n", dfspath, targetpath));
+
                if (consumedcntp) {
                        *consumedcntp = strlen(dfspath);
                }
-               return True;
+               return NT_STATUS_PATH_NOT_COVERED;
+       }
+
+       /* Prepare to test only for '/' components in the given path,
+        * so if a Windows path replace all '\\' characters with '/'.
+        * For a POSIX DFS path we know all separators are already '/'. */
+
+       pstrcpy(canon_dfspath, dfspath);
+       if (!pdp->posix_path) {
+               string_replace(canon_dfspath, '\\', '/');
+       }
+
+       /*
+        * Redirect if any component in the path is a link.
+        * We do this by walking backwards through the 
+        * local path, chopping off the last component
+        * in both the local path and the canonicalized
+        * DFS path. If we hit a DFS link then we're done.
+        */
+
+       p = strrchr_m(localpath, '/');
+       if (consumedcntp) {
+               q = strrchr_m(canon_dfspath, '/');
        }
 
-       /* redirect if any component in the path is a link */
-       pstrcpy(reqpath, localpath);
-       p = strrchr_m(reqpath, '/');
        while (p) {
                *p = '\0';
-               pstrcpy(localpath, reqpath);
-               if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) {
-                       DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath));
-
-                       /* To find the path consumed, we truncate the original
-                          DFS pathname passed to use to remove the last
-                          component. The length of the resulting string is
-                          the path consumed 
-                       */
-                       
+               if (q) {
+                       *q = '\0';
+               }
+
+               if (is_msdfs_link(conn, localpath, targetpath, NULL)) {
+                       DEBUG(4, ("dfs_path_lookup: Redirecting %s because "
+                               "parent %s is dfs link\n", dfspath, localpath));
+
                        if (consumedcntp) {
-                               char *q;
-                               pstring buf;
-                               pstrcpy(buf, dfspath);
-                               trim_char(buf, '\0', '\\');
-                               for (; consumed_level; consumed_level--) {
-                                       q = strrchr_m(buf, '\\');
-                                       if (q) {
-                                               *q = 0;
-                                       }
-                               }
-                               *consumedcntp = strlen(buf);
-                               DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp));
+                               *consumedcntp = strlen(canon_dfspath);
+                               DEBUG(10, ("dfs_path_lookup: Path consumed: %s "
+                                       "(%d)\n", canon_dfspath, *consumedcntp));
                        }
-                       
-                       return True;
+
+                       return NT_STATUS_PATH_NOT_COVERED;
+               }
+
+               /* Step back on the filesystem. */
+               p = strrchr_m(localpath, '/');
+
+               if (consumedcntp) {
+                       /* And in the canonicalized dfs path. */
+                       q = strrchr_m(canon_dfspath, '/');
                }
-               p = strrchr_m(reqpath, '/');
-               consumed_level++;
        }
 
-       return False;
+       return NT_STATUS_OK;
 }
 
 /*****************************************************************
-  Decides if a dfs pathname should be redirected or not.
-  If not, the pathname is converted to a tcon-relative local unix path
-
-  search_wcard_flag: this flag performs 2 functions bother related
-  to searches.  See resolve_dfs_path() and parse_processed_dfs_path()
-  for details.
+ Decides if a dfs pathname should be redirected or not.
+ If not, the pathname is converted to a tcon-relative local unix path
+
+ search_wcard_flag: this flag performs 2 functions bother related
+ to searches.  See resolve_dfs_path() and parse_dfs_path_XX()
+ for details.
+
+ This function can return NT_STATUS_OK, meaning use the returned path as-is
+ (mapped into a local path).
+ or NT_STATUS_NOT_COVERED meaning return a DFS redirect, or
+ any other NT_STATUS error which is a genuine error to be
+ returned to the client. 
 *****************************************************************/
 
-BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_flag )
+static NTSTATUS dfs_redirect( connection_struct *conn,
+                       pstring dfs_path,
+                       BOOL search_wcard_flag,
+                       BOOL *ppath_contains_wcard)
 {
+       NTSTATUS status;
        struct dfs_path dp;
+       pstring targetpath;
        
-       if (!conn || !pathname) {
-               return False;
+       status = parse_dfs_path(dfs_path, search_wcard_flag, &dp, ppath_contains_wcard);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (dp.reqpath[0] == '\0') {
+               pstrcpy(dfs_path, dp.reqpath);
+               DEBUG(5,("dfs_redirect: self-referral.\n"));
+               return NT_STATUS_OK;
        }
 
-       parse_processed_dfs_path(pathname, &dp, search_wcard_flag);
+       /* If dfs pathname for a non-dfs share, convert to tcon-relative
+          path and return OK */
 
-       /* if dfs pathname for a non-dfs share, convert to tcon-relative
-          path and return false */
        if (!lp_msdfs_root(SNUM(conn))) {
-               pstrcpy(pathname, dp.reqpath);
-               return False;
+               pstrcpy(dfs_path, dp.reqpath);
+               return NT_STATUS_OK;
        }
-       
-       if ( !( strequal(dp.servicename, lp_servicename(SNUM(conn))) 
-               || ( strequal(dp.servicename, HOMES_NAME) 
-                    && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) 
-       {
-               return False;
+
+       /* If it looked like a local path (zero hostname/servicename)
+        * just treat as a tcon-relative path. */ 
+
+       if (dp.hostname[0] == '\0' && dp.servicename[0] == '\0') { 
+               pstrcpy(dfs_path, dp.reqpath);
+               return NT_STATUS_OK;
        }
 
-       if (resolve_dfs_path(NULL, pathname, &dp, conn, search_wcard_flag,
-                            NULL, NULL, NULL, NULL)) {
-               DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname));
-               return True;
-       } else {
-               DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname));
+       if (!( strequal(dp.servicename, lp_servicename(SNUM(conn))) 
+                       || (strequal(dp.servicename, HOMES_NAME) 
+                       && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) {
 
-               /* Form non-dfs tcon-relative path */
-               pstrcpy(pathname, dp.reqpath);
+               /* The given sharename doesn't match this connection. */
 
-               DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname));
-               return False;
+               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+       }
+
+       status = dfs_path_lookup(conn, dfs_path, &dp,
+                       search_wcard_flag, NULL, targetpath);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
+                       DEBUG(3,("dfs_redirect: Redirecting %s\n", dfs_path));
+               } else {
+                       DEBUG(10,("dfs_redirect: dfs_path_lookup failed for %s with %s\n",
+                               dfs_path, nt_errstr(status) ));
+               }
+               return status;
        }
 
-       /* never reached */
+       DEBUG(3,("dfs_redirect: Not redirecting %s.\n", dfs_path));
+
+       /* Form non-dfs tcon-relative path */
+       pstrcpy(dfs_path, dp.reqpath);
+
+       DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", dfs_path));
+       return NT_STATUS_OK;
 }
 
 /**********************************************************************
  Return a self referral.
 **********************************************************************/
 
-static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn,
-                       int *consumedcntp, BOOL *self_referralp)
+static BOOL self_ref(TALLOC_CTX *ctx,
+                       const char *dfs_path,
+                       struct junction_map *jucn,
+                       int *consumedcntp,
+                       BOOL *self_referralp)
 {
        struct referral *ref;
 
-       if (self_referralp != NULL) {
-               *self_referralp = True;
-       }
+       *self_referralp = True;
 
        jucn->referral_count = 1;
-       if((ref = TALLOC_P(ctx, struct referral)) == NULL) {
-               DEBUG(0,("self_ref: malloc failed for referral\n"));
+       if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) {
+               DEBUG(0,("self_ref: talloc failed for referral\n"));
                return False;
        }
 
-       pstrcpy(ref->alternate_path,pathname);
+       pstrcpy(ref->alternate_path,dfs_path);
        ref->proximity = 0;
        ref->ttl = REFERRAL_TTL;
        jucn->referral_list = ref;
-       if (consumedcntp) {
-               *consumedcntp = strlen(pathname);
-       }
-
+       *consumedcntp = strlen(dfs_path);
        return True;
 }
 
@@ -511,40 +567,39 @@ static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map
  junction_map structure.
 **********************************************************************/
 
-BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn,
-                      int *consumedcntp, BOOL *self_referralp)
+BOOL get_referred_path(TALLOC_CTX *ctx,
+                       const char *dfs_path,
+                       struct junction_map *jucn,
+                       int *consumedcntp,
+                       BOOL *self_referralp)
 {
-       struct dfs_path dp;
-
        struct connection_struct conns;
        struct connection_struct *conn = &conns;
+       struct dfs_path dp;
        pstring conn_path;
+       pstring targetpath;
        int snum;
+       NTSTATUS status;
        BOOL ret = False;
-       BOOL self_referral = False;
-
-       if (!pathname || !jucn) {
-               return False;
-       }
+       BOOL dummy;
 
        ZERO_STRUCT(conns);
 
-       if (self_referralp) {
-               *self_referralp = False;
-       } else {
-               self_referralp = &self_referral;
-       }
+       *self_referralp = False;
 
-       parse_dfs_path(pathname, &dp);
+       status = parse_dfs_path(dfs_path, False, &dp, &dummy);
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
 
        /* Verify hostname in path */
        if (!is_myname_or_ipaddr(dp.hostname)) {
                DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n",
-                       dp.hostname, pathname));
+                       dp.hostname, dfs_path));
                return False;
        }
 
-       pstrcpy(jucn->service_name, dp.servicename);
+       fstrcpy(jucn->service_name, dp.servicename);
        pstrcpy(jucn->volume_name, dp.reqpath);
 
        /* Verify the share is a dfs root */
@@ -556,8 +611,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
        }
 
        if (!lp_msdfs_root(snum)) {
-               DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n",
-                        dp.servicename, pathname));
+               DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n",
+                        dp.servicename, dfs_path));
                goto out;
        }
 
@@ -569,15 +624,23 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
         */
 
        if (dp.reqpath[0] == '\0') {
-
-               struct referral* ref;
+               struct referral *ref;
 
                if (*lp_msdfs_proxy(snum) == '\0') {
-                       return self_ref(ctx, pathname, jucn, consumedcntp, self_referralp);
+                       return self_ref(ctx,
+                                       dfs_path,
+                                       jucn,
+                                       consumedcntp,
+                                       self_referralp);
                }
 
+               /* 
+                * It's an msdfs proxy share. Redirect to
+                * the configured target share.
+                */
+
                jucn->referral_count = 1;
-               if ((ref = TALLOC_P(ctx, struct referral)) == NULL) {
+               if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) {
                        DEBUG(0, ("malloc failed for referral\n"));
                        goto out;
                }
@@ -589,9 +652,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
                ref->proximity = 0;
                ref->ttl = REFERRAL_TTL;
                jucn->referral_list = ref;
-               if (consumedcntp) {
-                       *consumedcntp = strlen(pathname);
-               }
+               *consumedcntp = strlen(dfs_path);
                ret = True;
                goto out;
        }
@@ -601,23 +662,27 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma
                return False;
        }
 
-       /* If not remote & not a self referral, return False */
-       if (!resolve_dfs_path(ctx, pathname, &dp, conn, False, 
-                             &jucn->referral_list, &jucn->referral_count,
-                             self_referralp, consumedcntp)) {
-               if (!*self_referralp) {
-                       DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname));
-                       goto out;
-               }
+       /* If this is a DFS path dfs_lookup should return
+        * NT_STATUS_PATH_NOT_COVERED. */
+
+       status = dfs_path_lookup(conn, dfs_path, &dp,
+                       False, consumedcntp, targetpath);
+
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {
+               DEBUG(3,("get_referred_path: No valid referrals for path %s\n",
+                       dfs_path));
+               goto out;
        }
-       
-       /* if self_referral, fill up the junction map */
-       if (*self_referralp) {
-               if (self_ref(ctx, pathname, jucn, consumedcntp, self_referralp) == False) {
-                       goto out;
-               }
+
+       /* We know this is a valid dfs link. Parse the targetpath. */
+       if (!parse_msdfs_symlink(ctx, targetpath,
+                               &jucn->referral_list,
+                               &jucn->referral_count)) {
+               DEBUG(3,("get_referred_path: failed to parse symlink "
+                       "target %s\n", targetpath ));
+               goto out;
        }
-       
+
        ret = True;
 
 out:
@@ -626,10 +691,11 @@ out:
        return ret;
 }
 
-static int setup_ver2_dfs_referral(char *pathname, char **ppdata, 
-                                  struct junction_map *junction,
-                                  int consumedcnt,
-                                  BOOL self_referral)
+static int setup_ver2_dfs_referral(const char *pathname,
+                               char **ppdata, 
+                               struct junction_map *junction,
+                               int consumedcnt,
+                               BOOL self_referral)
 {
        char* pdata = *ppdata;
 
@@ -641,7 +707,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
        int reply_size = 0;
        int i=0;
 
-       DEBUG(10,("setting up version2 referral\nRequested path:\n"));
+       DEBUG(10,("Setting up version2 referral\nRequested path:\n"));
 
        requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring),
                                       STR_TERMINATE);
@@ -675,7 +741,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
 
        pdata = (char *)SMB_REALLOC(pdata,reply_size);
        if(pdata == NULL) {
-               DEBUG(0,("malloc failed for Realloc!\n"));
+               DEBUG(0,("Realloc failed!\n"));
                return -1;
        }
        *ppdata = pdata;
@@ -726,10 +792,11 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata,
        return reply_size;
 }
 
-static int setup_ver3_dfs_referral(char *pathname, char **ppdata, 
-                                  struct junction_map *junction,
-                                  int consumedcnt,
-                                  BOOL self_referral)
+static int setup_ver3_dfs_referral(const char *pathname,
+                               char **ppdata, 
+                               struct junction_map *junction,
+                               int consumedcnt,
+                               BOOL self_referral)
 {
        char* pdata = *ppdata;
 
@@ -810,17 +877,23 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata,
 }
 
 /******************************************************************
- Set up the Dfs referral for the dfs pathname
+ Set up the DFS referral for the dfs pathname. This call returns
+ the amount of the path covered by this server, and where the
+ client should be redirected to. This is the meat of the
+ TRANS2_GET_DFS_REFERRAL call.
 ******************************************************************/
 
-int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char **ppdata)
+int setup_dfs_referral(connection_struct *orig_conn,
+                       const char *dfs_path,
+                       int max_referral_level,
+                       char **ppdata)
 {
        struct junction_map junction;
-       int consumedcnt;
+       int consumedcnt = 0;
        BOOL self_referral = False;
-       pstring buf;
        int reply_size = 0;
-       char *pathnamep = pathname;
+       char *pathnamep = NULL;
+       pstring local_dfs_path;
        TALLOC_CTX *ctx;
 
        if (!(ctx=talloc_init("setup_dfs_referral"))) {
@@ -830,21 +903,24 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref
        ZERO_STRUCT(junction);
 
        /* get the junction entry */
-       if (!pathnamep) {
+       if (!dfs_path) {
                talloc_destroy(ctx);
                return -1;
        }
 
-       /* Trim pathname sent by client so it begins with only one backslash.
-          Two backslashes confuse some dfs clients
+       /* 
+        * Trim pathname sent by client so it begins with only one backslash.
+        * Two backslashes confuse some dfs clients
         */
-       while (pathnamep[0] == '\\' && pathnamep[1] == '\\') {
+
+       pstrcpy(local_dfs_path, dfs_path);
+       pathnamep = local_dfs_path;
+       while (IS_DIRECTORY_SEP(pathnamep[0]) && IS_DIRECTORY_SEP(pathnamep[1])) {
                pathnamep++;
        }
 
-       pstrcpy(buf, pathnamep);
        /* The following call can change cwd. */
-       if (!get_referred_path(ctx, buf, &junction, &consumedcnt, &self_referral)) {
+       if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) {
                vfs_ChDir(orig_conn,orig_conn->connectpath);
                talloc_destroy(ctx);
                return -1;
@@ -902,31 +978,40 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref
  **********************************************************************/
 
 /*********************************************************************
- Creates a junction structure from a Dfs pathname
+ Creates a junction structure from a DFS pathname
 **********************************************************************/
 
-BOOL create_junction(const char *pathname, struct junction_map *jucn)
+BOOL create_junction(const char *dfs_path, struct junction_map *jucn)
 {
-        struct dfs_path dp;
+       int snum;
+       BOOL dummy;
+       struct dfs_path dp;
  
-        parse_dfs_path(pathname,&dp);
+       NTSTATUS status = parse_dfs_path(dfs_path, False, &dp, &dummy);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
 
-        /* check if path is dfs : validate first token */
+       /* check if path is dfs : validate first token */
        if (!is_myname_or_ipaddr(dp.hostname)) {
                DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n",
-                       dp.hostname, pathname));
+                       dp.hostname, dfs_path));
                return False;
        }
 
        /* Check for a non-DFS share */
-       if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) {
-               DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename));
+       snum = lp_servicenumber(dp.servicename);
+
+       if(snum < 0 || !lp_msdfs_root(snum)) {
+               DEBUG(4,("create_junction: %s is not an msdfs root.\n",
+                       dp.servicename));
                return False;
        }
 
-       pstrcpy(jucn->service_name,dp.servicename);
+       fstrcpy(jucn->service_name,dp.servicename);
        pstrcpy(jucn->volume_name,dp.reqpath);
-       pstrcpy(jucn->comment, lp_comment(lp_servicenumber(dp.servicename)));
+       pstrcpy(jucn->comment, lp_comment(snum));
        return True;
 }
 
@@ -934,16 +1019,14 @@ BOOL create_junction(const char *pathname, struct junction_map *jucn)
  Forms a valid Unix pathname from the junction 
  **********************************************************************/
 
-static BOOL junction_to_local_path(struct junction_map *jucn, char *path,
-                                  int max_pathlen, connection_struct *conn)
+static BOOL junction_to_local_path(struct junction_map *jucn,
+                               char *path,
+                               int max_pathlen,
+                               connection_struct *conn_out)
 {
        int snum;
        pstring conn_path;
 
-       if(!path || !jucn) {
-               return False;
-       }
-
        snum = lp_servicenumber(jucn->service_name);
        if(snum < 0) {
                return False;
@@ -954,7 +1037,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, char *path,
        safe_strcat(path, jucn->volume_name, max_pathlen-1);
 
        pstrcpy(conn_path, lp_pathname(snum));
-       if (!create_conn_struct(conn, snum, conn_path)) {
+       if (!create_conn_struct(conn_out, snum, conn_path)) {
                return False;
        }
 
@@ -977,11 +1060,12 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)
                return False;
        }
   
-       /* form the msdfs_link contents */
+       /* Form the msdfs_link contents */
        pstrcpy(msdfs_link, "msdfs:");
        for(i=0; i<jucn->referral_count; i++) {
                char* refpath = jucn->referral_list[i].alternate_path;
       
+               /* Alternate paths always use Windows separators. */
                trim_char(refpath, '\\', '\\');
                if(*refpath == '\0') {
                        if (i == 0) {
@@ -999,7 +1083,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)
                }
        }
 
-       DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link));
+       DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n",
+               path, msdfs_link));
 
        if(exists) {
                if(SMB_VFS_UNLINK(conn,path)!=0) {
@@ -1015,7 +1100,7 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)
        
        
        ret = True;
-       
+
 out:
 
        conn_free_internal(conn);
@@ -1042,13 +1127,16 @@ BOOL remove_msdfs_link(struct junction_map *jucn)
        return ret;
 }
 
-static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain)
+static int form_junctions(TALLOC_CTX *ctx,
+                               int snum,
+                               struct junction_map *jucn,
+                               int jn_remain)
 {
        int cnt = 0;
        SMB_STRUCT_DIR *dirp;
-       chardname;
+       char *dname;
        pstring connect_path;
-       charservice_name = lp_servicename(snum);
+       char *service_name = lp_servicename(snum);
        connection_struct conn;
        struct referral *ref = NULL;
  
@@ -1076,13 +1164,13 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
           DO NOT REMOVE THIS: NT clients will not work with us
           if this is not present
        */ 
-       pstrcpy(jucn[cnt].service_name, service_name);
+       fstrcpy(jucn[cnt].service_name, service_name);
        jucn[cnt].volume_name[0] = '\0';
        jucn[cnt].referral_count = 1;
 
-       ref = jucn[cnt].referral_list = TALLOC_P(ctx, struct referral);
+       ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral);
        if (jucn[cnt].referral_list == NULL) {
-               DEBUG(0, ("Malloc failed!\n"));
+               DEBUG(0, ("talloc failed!\n"));
                goto out;
        }
 
@@ -1093,9 +1181,10 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
                cnt++;
                goto out;
        }
-               
-       slprintf(ref->alternate_path, sizeof(pstring)-1,
-                "\\\\%s\\%s", get_local_machine_name(), service_name);
+
+       pstr_sprintf(ref->alternate_path, "\\\\%s\\%s",
+                       get_local_machine_name(),
+                       service_name);
        cnt++;
 
        /* Now enumerate all dfs links */
@@ -1105,16 +1194,22 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn,
        }
 
        while ((dname = vfs_readdirname(&conn, dirp)) != NULL) {
+               pstring link_target;
                if (cnt >= jn_remain) {
                        SMB_VFS_CLOSEDIR(&conn,dirp);
                        DEBUG(2, ("ran out of MSDFS junction slots"));
                        goto out;
                }
-               if (is_msdfs_link(ctx, &conn, dname, &jucn[cnt].referral_list,
-                                 &jucn[cnt].referral_count, NULL)) {
-                       pstrcpy(jucn[cnt].service_name, service_name);
-                       pstrcpy(jucn[cnt].volume_name, dname);
-                       cnt++;
+               if (is_msdfs_link(&conn, dname, link_target, NULL)) {
+                       if (parse_msdfs_symlink(ctx,
+                                       link_target,
+                                       &jucn[cnt].referral_list,
+                                       &jucn[cnt].referral_count)) {
+
+                               fstrcpy(jucn[cnt].service_name, service_name);
+                               pstrcpy(jucn[cnt].volume_name, dname);
+                               cnt++;
+                       }
                }
        }
        
@@ -1148,3 +1243,33 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)
        }
        return jn_count;
 }
+
+/******************************************************************************
+ Core function to resolve a dfs pathname.
+******************************************************************************/
+
+NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name)
+{
+       NTSTATUS status = NT_STATUS_OK;
+       BOOL dummy;
+       if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) {
+               status = dfs_redirect(conn, name, False, &dummy);
+       }
+       return status;
+}
+
+/******************************************************************************
+ Core function to resolve a dfs pathname possibly containing a wildcard.
+ This function is identical to the above except for the BOOL param to
+ dfs_redirect but I need this to be separate so it's really clear when
+ we're allowing wildcards and when we're not. JRA.
+******************************************************************************/
+
+NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard)
+{
+       NTSTATUS status = NT_STATUS_OK;
+       if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) {
+               status = dfs_redirect(conn, name, True, ppath_contains_wcard);
+       }
+       return status;
+}
index fb5610b20bb2a2449d9597e1e5d8fb0e220f7281..bc7c75aab4cecbfaefefc861c6f235a1337ff9c1 100644 (file)
@@ -259,7 +259,9 @@ static int reply_nt1(char *inbuf, char *outbuf)
        if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) &&
                ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) ) 
        {
-               set_remote_arch( RA_VISTA );            
+               if (get_remote_arch() != RA_SAMBA) {
+                       set_remote_arch( RA_VISTA );
+               }
        }
 
        /* do spnego in user level security if the client
index 5fb414de4ccc0ef0d29d9bbc896604f632c725dd..ff17d455f39e6923024ca7080adabeae45b2ebcd 100644 (file)
 
 #ifdef HAVE_INOTIFY
 
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
 #include <linux/inotify.h>
 #include <asm/unistd.h>
 
index 19710d1dcdd0e0d60591f87c7ea9bb38e0eeb7b9..2a49e1f4a644edc22d5901fdf4d6413c05b97446 100644 (file)
@@ -353,7 +353,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
                return(ERROR_DOS(ERRSRV,ERRnofids));
        }
 
-       /* TODO: Add pipe to db */
+       /* Add pipe to db */
        
        if ( !store_pipe_opendb( p ) ) {
                DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
@@ -469,7 +469,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
        SMB_OFF_T file_len = 0;
        SMB_STRUCT_STAT sbuf;
        int info = 0;
-       files_struct *fsp=NULL;
+       files_struct *fsp = NULL;
        char *p = NULL;
        struct timespec c_timespec;
        struct timespec a_timespec;
@@ -491,7 +491,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
                        (unsigned int)create_options,
                        (unsigned int)root_dir_fid ));
 
-       /* If it's an IPC, use the pipe handler. */
+       /*
+        * If it's an IPC, use the pipe handler.
+        */
 
        if (IS_IPC(conn)) {
                if (lp_nt_pipe_support()) {
@@ -502,7 +504,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                        return(ERROR_DOS(ERRDOS,ERRnoaccess));
                }
        }
-                       
+
        if (create_options & FILE_OPEN_BY_FILE_ID) {
                END_PROFILE(SMBntcreateX);
                return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
@@ -522,7 +524,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
 
                if(!dir_fsp) {
                        END_PROFILE(SMBntcreateX);
-                       return(ERROR_DOS(ERRDOS,ERRbadfid));
+                       return ERROR_DOS(ERRDOS,ERRbadfid);
                }
 
                if(!dir_fsp->is_directory) {
@@ -533,7 +535,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                return ERROR_NT(status);
                        }
 
-                       /* 
+                       /*
                         * Check to see if this is a mac fork of some kind.
                         */
 
@@ -564,7 +566,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                 * Ensure it ends in a '\'.
                 */
 
-               if(fname[dir_name_len-1] != '\\' && fname[dir_name_len-1] != '/') {
+               if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
                        pstrcat(fname, "/");
                        dir_name_len++;
                }
@@ -582,7 +584,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                        return ERROR_NT(status);
                }
 
-               /* 
+               /*
                 * Check to see if this is a mac fork of some kind.
                 */
 
@@ -613,7 +615,14 @@ int reply_ntcreate_and_X(connection_struct *conn,
         * Now contruct the smb_open_mode value from the filename, 
         * desired access and the share access.
         */
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntcreateX);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
        if (oplock_request) {
@@ -664,19 +673,19 @@ int reply_ntcreate_and_X(connection_struct *conn,
                }
        }
 
-       /* 
+       /*
         * If it's a request for a directory open, deal with it separately.
         */
 
        if(create_options & FILE_DIRECTORY_FILE) {
-               oplock_request = 0;
-               
+
                /* Can't open a temp directory. IFS kit test. */
                if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                }
 
+               oplock_request = 0;
                status = open_directory(conn, fname, &sbuf,
                                        access_mask,
                                        share_access,
@@ -695,7 +704,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
                        END_PROFILE(SMBntcreateX);
                        return ERROR_NT(status);
                }
+
        } else {
+
                /*
                 * Ordinary file case.
                 */
@@ -721,6 +732,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                        new_file_attributes,
                                        oplock_request,
                                        &info, &fsp);
+
                if (!NT_STATUS_IS_OK(status)) { 
                        /* We cheat here. There are two cases we
                         * care about. One is a directory rename,
@@ -773,7 +785,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                        return ERROR_NT(status);
                                }
                        } else {
-
                                restore_case_semantics(conn, file_attributes);
                                END_PROFILE(SMBntcreateX);
                                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -786,7 +797,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
        }
                
        restore_case_semantics(conn, file_attributes);
-               
+
        file_len = sbuf.st_size;
        fattr = dos_mode(conn,fname,&sbuf);
        if(fattr == 0) {
@@ -827,11 +838,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
         * and we granted one (by whatever means) - set the
         * correct bit for extended oplock reply.
         */
-       
+
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                extended_oplock_granted = True;
        }
-       
+
        if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                extended_oplock_granted = True;
        }
@@ -871,8 +882,8 @@ int reply_ntcreate_and_X(connection_struct *conn,
                SIVAL(p,0,info);
        }
        p += 4;
-       
-       /* Create time. */  
+
+       /* Create time. */
        c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
        a_timespec = get_atimespec(&sbuf);
        m_timespec = get_mtimespec(&sbuf);
@@ -883,7 +894,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                dos_filetime_timespec(&m_timespec);
        }
 
-       put_long_date_timespec(p, c_timespec);
+       put_long_date_timespec(p, c_timespec); /* create time. */
        p += 8;
        put_long_date_timespec(p, a_timespec); /* access time */
        p += 8;
@@ -1252,15 +1263,27 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        }
 
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
-       oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+       if (oplock_request) {
+               oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
+       }
 
+       /*
+        * Ordinary file or directory.
+        */
+               
        /*
         * Check if POSIX semantics are wanted.
         */
-
+               
        new_file_attributes = set_posix_case_semantics(conn, file_attributes);
     
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, fname, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1273,7 +1296,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                restore_case_semantics(conn, file_attributes);
                return ERROR_NT(status);
        }
-    
+
        /* This is the correct thing to do (check every time) but can_delete is
           expensive (it may have to read the parent directory permissions). So
           for now we're not doing it unless we have a strong hint the client
@@ -1317,14 +1340,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
                }
 
-               oplock_request = 0;
-
                /*
                 * We will get a create directory here if the Win32
                 * app specified a security descriptor in the 
                 * CreateDirectory() call.
                 */
 
+               oplock_request = 0;
                status = open_directory(conn, fname, &sbuf,
                                        access_mask,
                                        share_access,
@@ -1464,11 +1486,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
         * and we granted one (by whatever means) - set the
         * correct bit for extended oplock reply.
         */
-    
+
        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
                extended_oplock_granted = True;
        }
-  
+
        if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
                extended_oplock_granted = True;
        }
@@ -1592,15 +1614,15 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return status;
        }
 
-        /* Source must already exist. */
-       if (!VALID_STAT(sbuf1)) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
        status = check_name(conn, oldname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
+        /* Source must already exist. */
+       if (!VALID_STAT(sbuf1)) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
        /* Ensure attributes match. */
        fattr = dos_mode(conn,oldname,&sbuf1);
        if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
@@ -1612,16 +1634,16 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                return status;
        }
 
-       /* Disallow if newname already exists. */
-       if (VALID_STAT(sbuf2)) {
-               return NT_STATUS_OBJECT_NAME_COLLISION;
-       }
-
        status = check_name(conn, newname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
+       /* Disallow if newname already exists. */
+       if (VALID_STAT(sbuf2)) {
+               return NT_STATUS_OBJECT_NAME_COLLISION;
+       }
+
        /* No links from a directory. */
        if (S_ISDIR(sbuf1.st_mode)) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -1675,7 +1697,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
        close_file(fsp1,NORMAL_CLOSE);
 
        /* Ensure the modtime is set correctly on the destination file. */
-       fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
+       fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1));
 
        status = close_file(fsp2,NORMAL_CLOSE);
 
@@ -1708,15 +1730,15 @@ int reply_ntrename(connection_struct *conn,
        pstring newname;
        char *p;
        NTSTATUS status;
-       BOOL path1_contains_wcard = False;
-       BOOL path2_contains_wcard = False;
+       BOOL src_has_wcard = False;
+       BOOL dest_has_wcard = False;
        uint32 attrs = SVAL(inbuf,smb_vwv0);
        uint16 rename_type = SVAL(inbuf,smb_vwv1);
 
        START_PROFILE(SMBntrename);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
                return ERROR_NT(status);
@@ -1734,23 +1756,38 @@ int reply_ntrename(connection_struct *conn,
        }
 
        p++;
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBntrename);
                return ERROR_NT(status);
        }
        
-       RESOLVE_DFSPATH(oldname, conn, inbuf, outbuf);
-       RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
-       
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntrename);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
+
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntrename);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
+
        DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
        
        switch(rename_type) {
                case RENAME_FLAG_RENAME:
-                       status = rename_internals(conn, oldname, newname, attrs, False, path1_contains_wcard);
+                       status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard);
                        break;
                case RENAME_FLAG_HARD_LINK:
-                       if (path1_contains_wcard || path2_contains_wcard) {
+                       if (src_has_wcard || dest_has_wcard) {
                                /* No wildcards. */
                                status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
@@ -1758,7 +1795,7 @@ int reply_ntrename(connection_struct *conn,
                        }
                        break;
                case RENAME_FLAG_COPY:
-                       if (path1_contains_wcard || path2_contains_wcard) {
+                       if (src_has_wcard || dest_has_wcard) {
                                /* No wildcards. */
                                status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
                        } else {
@@ -1899,7 +1936,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        pstring new_name;
        files_struct *fsp = NULL;
        BOOL replace_if_exists = False;
-       BOOL path_contains_wcard = False;
+       BOOL dest_has_wcard = False;
        NTSTATUS status;
 
         if(parameter_count < 5) {
@@ -1909,13 +1946,14 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        fsp = file_fsp(params, 0);
        replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
        CHECK_FSP(fsp, conn);
-       srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4, STR_TERMINATE, &status, &path_contains_wcard);
+       srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4,
+                       STR_TERMINATE, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
 
        status = rename_internals(conn, fsp->fsp_name,
-                                 new_name, 0, replace_if_exists, path_contains_wcard);
+                                 new_name, 0, replace_if_exists, False, dest_has_wcard);
 
        if (!NT_STATUS_IS_OK(status)) {
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
index 13ec9f952fe6bf78c5c76b6984b34353fa8b61ec..c7a7086894e6837ad269a8c591d2c3a697490884 100644 (file)
@@ -1903,7 +1903,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                                uint32 file_attributes,
                                SMB_STRUCT_STAT *psbuf)
 {
-       int ret= -1;
        mode_t mode;
        char *parent_dir;
        const char *dirname;
@@ -1931,7 +1930,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
                mode = unix_mode(conn, aDIR, name, parent_dir);
        }
 
-       if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
+       if (SMB_VFS_MKDIR(conn, name, mode) != 0) {
                return map_nt_error_from_unix(errno);
        }
 
index 52660da2ffe405b35625fc8c7d3728c1fcb1620a..58756a0b5a6883441f97a655c5dea196dddbf026 100644 (file)
@@ -300,7 +300,5 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
                return ERROR_DOS(ERRDOS,ERRbadfid);
        }
        
-       /* TODO: REMOVE PIPE FROM DB */
-
        return(outsize);
 }
index 14941e649903767c2cab0b44da639577dec25c31..836801ba82c22502ad055621e8fbc772381f7974 100644 (file)
@@ -1148,6 +1148,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
        unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
        char *inbuf2, *outbuf2;
        int outsize2;
+       int new_size;
        char inbuf_saved[smb_wct];
        char outbuf_saved[smb_wct];
        int outsize = smb_len(outbuf) + 4;
@@ -1198,6 +1199,20 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
        /* create the in buffer */
        SCVAL(inbuf2,smb_com,smb_com2);
 
+       /* work out the new size for the in buffer. */
+       new_size = size - (inbuf2 - inbuf);
+       if (new_size < 0) {
+               DEBUG(0,("chain_reply: chain packet size incorrect (orig size = %d, "
+                       "offset = %d)\n",
+                       size,
+                       (inbuf2 - inbuf) ));
+               exit_server_cleanly("Bad chained packet");
+               return(-1);
+       }
+
+       /* And set it in the header. */
+       smb_setlen(inbuf2, new_size);
+
        /* create the out buffer */
        construct_reply_common(inbuf2, outbuf2);
 
@@ -1205,7 +1220,7 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
        show_msg(inbuf2);
 
        /* process the request */
-       outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size,
+       outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size,
                                bufsize-chain_size);
 
        /* copy the new reply and request headers over the old ones, but
@@ -1219,8 +1234,10 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
 
        {
                int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf);
-               if (ofs < 0) ofs = 0;
-                       memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
+               if (ofs < 0) {
+                       ofs = 0;
+               }
+               memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs);
        }
 
        return outsize2;
index c48bebb0c6c74899f49f291682f70a737cf4fda8..14b16e1ae23a7665056696b6fa3d7d0136d2482e 100644 (file)
@@ -44,9 +44,12 @@ extern BOOL global_encrypted_passwords_negotiated;
  set.
 ****************************************************************************/
 
+/* Custom version for processing POSIX paths. */
+#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
+
 NTSTATUS check_path_syntax_internal(pstring destname,
                                    const pstring srcname,
-                                   BOOL windows_path,
+                                   BOOL posix_path,
                                    BOOL *p_last_component_contains_wcard)
 {
        char *d = destname;
@@ -57,12 +60,12 @@ NTSTATUS check_path_syntax_internal(pstring destname,
        *p_last_component_contains_wcard = False;
 
        while (*s) {
-               if (IS_DIRECTORY_SEP(*s)) {
+               if (IS_PATH_SEP(*s,posix_path)) {
                        /*
                         * Safe to assume is not the second part of a mb char as this is handled below.
                         */
                        /* Eat multiple '/' or '\\' */
-                       while (IS_DIRECTORY_SEP(*s)) {
+                       while (IS_PATH_SEP(*s,posix_path)) {
                                s++;
                        }
                        if ((d != destname) && (*s != '\0')) {
@@ -77,7 +80,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
                }
 
                if (start_of_name_component) {
-                       if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
+                       if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
                                /* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
 
                                /*
@@ -107,8 +110,8 @@ NTSTATUS check_path_syntax_internal(pstring destname,
                                /* We're still at the start of a name component, just the previous one. */
                                continue;
 
-                       } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
-                               if (!windows_path) {
+                       } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
+                               if (posix_path) {
                                        /* Eat the '.' */
                                        s++;
                                        continue;
@@ -118,7 +121,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
                }
 
                if (!(*s & 0x80)) {
-                       if (windows_path) {
+                       if (!posix_path) {
                                if (*s <= 0x1f) {
                                        return NT_STATUS_OBJECT_NAME_INVALID;
                                }
@@ -176,7 +179,7 @@ NTSTATUS check_path_syntax_internal(pstring destname,
 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
 {
        BOOL ignore;
-       return check_path_syntax_internal(destname, srcname, True, &ignore);
+       return check_path_syntax_internal(destname, srcname, False, &ignore);
 }
 
 /****************************************************************************
@@ -187,7 +190,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
 
 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
 {
-       return check_path_syntax_internal(destname, srcname, True, p_contains_wcard);
+       return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
 }
 
 /****************************************************************************
@@ -196,10 +199,10 @@ NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *
  set (a safe assumption).
 ****************************************************************************/
 
-static NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
 {
        BOOL ignore;
-       return check_path_syntax_internal(destname, srcname, False, &ignore);
+       return check_path_syntax_internal(destname, srcname, True, &ignore);
 }
 
 /****************************************************************************
@@ -224,6 +227,16 @@ size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t de
 
        *contains_wcard = False;
 
+       if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
+               /* 
+                * For a DFS path the function parse_dfs_path()
+                * will do the path processing, just make a copy.
+                */
+               pstrcpy(dest, tmppath);
+               *err = NT_STATUS_OK;
+               return ret;
+       }
+
        if (lp_posix_pathnames()) {
                *err = check_path_syntax_posix(dest, tmppath);
        } else {
@@ -251,6 +264,17 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len
        } else {
                ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
        }
+
+       if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
+               /* 
+                * For a DFS path the function parse_dfs_path()
+                * will do the path processing, just make a copy.
+                */
+               pstrcpy(dest, tmppath);
+               *err = NT_STATUS_OK;
+               return ret;
+       }
+
        if (lp_posix_pathnames()) {
                *err = check_path_syntax_posix(dest, tmppath);
        } else {
@@ -631,7 +655,14 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
+       if (!NT_STATUS_IS_OK(status)) {
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       END_PROFILE(SMBcheckpath);
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               goto path_err;
+       }
 
        DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
 
@@ -710,7 +741,14 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBgetatr);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
   
        /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
                under WfWg - weird! */
@@ -789,7 +827,14 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBsetatr);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
   
        status = unix_convert(conn, fname, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -797,6 +842,12 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBsetatr);
+               return ERROR_NT(status);
+       }
+
        if (fname[0] == '.' && fname[1] == '\0') {
                /*
                 * Not sure here is the right place to catch this
@@ -806,12 +857,6 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(NT_STATUS_ACCESS_DENIED);
        }
 
-       status = check_name(conn, fname);
-       if (!NT_STATUS_IS_OK(status)) {
-               END_PROFILE(SMBsetatr);
-               return ERROR_NT(status);
-       }
-
        mode = SVAL(inbuf,smb_vwv0);
        mtime = srv_make_unix_date3(inbuf+smb_vwv1);
   
@@ -827,7 +872,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                }
        }
 
-       if (!set_filetime(conn,fname,mtime)) {
+       if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
                END_PROFILE(SMBsetatr);
                return UNIXERROR(ERRDOS, ERRnoaccess);
        }
@@ -944,7 +989,14 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(nt_status);
        }
 
-       RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
+       nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               END_PROFILE(SMBsearch);
+               if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(nt_status);
+       }
   
        p++;
        status_len = SVAL(p, 0);
@@ -954,16 +1006,13 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
 
        if (status_len == 0) {
                SMB_STRUCT_STAT sbuf;
-               pstring dir2;
 
                pstrcpy(directory,path);
-               pstrcpy(dir2,path);
                nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
                if (!NT_STATUS_IS_OK(nt_status)) {
                        END_PROFILE(SMBsearch);
                        return ERROR_NT(nt_status);
                }
-               unix_format(dir2);
 
                nt_status = check_name(conn, directory);
                if (!NT_STATUS_IS_OK(nt_status)) {
@@ -971,23 +1020,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                        return ERROR_NT(nt_status);
                }
 
-               p = strrchr_m(dir2,'/');
-               if (p == NULL) {
-                       pstrcpy(mask,dir2);
-                       *dir2 = 0;
-               } else {
-                       *p = 0;
-                       pstrcpy(mask,p+1);
-               }
-
                p = strrchr_m(directory,'/');
                if (!p) {
-                       *directory = 0;
+                       pstrcpy(mask,directory);
+                       pstrcpy(directory,".");
                } else {
                        *p = 0;
+                       pstrcpy(mask,p+1);
                }
 
-               if (strlen(directory) == 0) {
+               if (*directory == '\0') {
                        pstrcpy(directory,".");
                }
                memset((char *)status,'\0',21);
@@ -1007,6 +1049,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                }
                string_set(&conn->dirpath,dptr_path(dptr_num));
                pstrcpy(mask, dptr_wcard(dptr_num));
+               /*
+                * For a 'continue' search we have no string. So
+                * check from the initial saved string.
+                */
+               mask_contains_wcard = ms_has_wild(mask);
        }
 
        p = smb_buf(outbuf) + 3;
@@ -1202,7 +1249,14 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBopen);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, fname, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1210,6 +1264,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
     
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBopen);
+               return ERROR_NT(status);
+       }
+
        if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
                        &access_mask, &share_mode, &create_disposition, &create_options)) {
                END_PROFILE(SMBopen);
@@ -1320,7 +1380,14 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBopenX);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, fname, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1328,6 +1395,12 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBopenX);
+               return ERROR_NT(status);
+       }
+
        if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
                                &access_mask,
                                &share_mode,
@@ -1470,7 +1543,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        int com;
        int outsize = 0;
        uint32 fattr = SVAL(inbuf,smb_vwv0);
-       struct utimbuf times;
+       struct timespec ts[2];
        files_struct *fsp;
        int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
        SMB_STRUCT_STAT sbuf;
@@ -1484,7 +1557,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  
        com = SVAL(inbuf,smb_com);
 
-       times.modtime = srv_make_unix_date3(inbuf + smb_vwv1);
+       ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
 
        srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1492,7 +1565,14 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBcreate);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, fname, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -1500,6 +1580,12 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBcreate);
+               return ERROR_NT(status);
+       }
+
        if (fattr & aVOLID) {
                DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
        }
@@ -1531,8 +1617,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
  
-       times.actime = sbuf.st_atime;
-       file_utime(conn, fname, &times);
+       ts[0] = get_atimespec(&sbuf); /* atime. */
+       file_ntimes(conn, fname, ts);
 
        outsize = set_message(outbuf,1,0,True);
        SSVAL(outbuf,smb_vwv0,fsp->fnum);
@@ -1582,13 +1668,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                pstrcat(fname,"TMXXXXXX");
        }
 
-       RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBctemp);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, fname, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBctemp);
                return ERROR_NT(status);
        }
+
+       status = check_name(conn, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBctemp);
+               return ERROR_NT(status);
+       }
   
        tmpfd = smb_mkstemp(fname);
        if (tmpfd == -1) {
@@ -1858,6 +1957,12 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                if (dirtype == 0) {
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
+
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
                status = can_delete(conn,directory,dirtype,can_defer);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
@@ -1920,6 +2025,13 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
                        }
                                
                        slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
+
+                       status = check_name(conn, fname);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               CloseDir(dir_hnd);
+                               return status;
+                       }
+
                        status = can_delete(conn, fname, dirtype, can_defer);
                        if (!NT_STATUS_IS_OK(status)) {
                                continue;
@@ -1966,8 +2078,15 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                END_PROFILE(SMBunlink);
                return ERROR_NT(status);
        }
-       
-       RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+
+       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBunlink);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
        
        DEBUG(3,("reply_unlink : %s\n",name));
        
@@ -3109,7 +3228,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
 {
        NTSTATUS status = NT_STATUS_OK;
        int outsize = 0;
-       time_t mtime;
        files_struct *fsp = NULL;
        START_PROFILE(SMBclose);
 
@@ -3151,8 +3269,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
                 * Take care of any time sent in the close.
                 */
 
-               mtime = srv_make_unix_date3(inbuf+smb_vwv1);
-               fsp_set_pending_modtime(fsp, mtime);
+               fsp_set_pending_modtime(fsp,
+                               convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
 
                /*
                 * close_file() returns the unix errno if an error
@@ -3185,7 +3303,7 @@ int reply_writeclose(connection_struct *conn,
        NTSTATUS close_status = NT_STATUS_OK;
        SMB_OFF_T startpos;
        char *data;
-       time_t mtime;
+       struct timespec mtime;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBwriteclose);
 
@@ -3196,7 +3314,7 @@ int reply_writeclose(connection_struct *conn,
 
        numtowrite = SVAL(inbuf,smb_vwv1);
        startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
-       mtime = srv_make_unix_date3(inbuf+smb_vwv4);
+       mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
        data = smb_buf(inbuf) + 1;
   
        if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
@@ -3206,7 +3324,7 @@ int reply_writeclose(connection_struct *conn,
   
        nwritten = write_file(fsp,data,startpos,numtowrite);
 
-       set_filetime(conn, fsp->fsp_name,mtime);
+       set_filetime(conn, fsp->fsp_name, mtime);
   
        /*
         * More insanity. W2K only closes the file if writelen > 0.
@@ -3598,7 +3716,14 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBmkdir);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, directory, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -3606,6 +3731,12 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBmkdir);
+               return ERROR_NT(status);
+       }
+  
        status = create_directory(conn, directory);
 
        DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
@@ -3810,7 +3941,14 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_NT(status);
        }
 
-       RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBrmdir);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        status = unix_convert(conn, directory, False, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(status)) {
@@ -3854,7 +3992,6 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
        char *p,*p2, *pname1, *pname2;
        int available_space, actual_space;
        
-
        pname1 = strrchr_m(name1,'/');
        pname2 = strrchr_m(name2,'/');
 
@@ -4008,6 +4145,11 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
                return status;
        }
 
+       status = check_name(conn, newname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+  
        /* Ensure newname contains a '/' */
        if(strrchr_m(newname,'/') == 0) {
                pstring tmpstr;
@@ -4152,9 +4294,13 @@ static void notify_rename(connection_struct *conn, BOOL is_dir,
  code. 
 ****************************************************************************/
 
-NTSTATUS rename_internals(connection_struct *conn, pstring name,
-                         pstring newname, uint32 attrs,
-                         BOOL replace_if_exists, BOOL has_wild)
+NTSTATUS rename_internals(connection_struct *conn,
+                               pstring name,
+                               pstring newname,
+                               uint32 attrs,
+                               BOOL replace_if_exists,
+                               BOOL src_has_wild,
+                               BOOL dest_has_wild)
 {
        pstring directory;
        pstring mask;
@@ -4165,20 +4311,22 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
        NTSTATUS status = NT_STATUS_OK;
        SMB_STRUCT_STAT sbuf1, sbuf2;
        struct share_mode_lock *lck = NULL;
+       struct smb_Dir *dir_hnd = NULL;
+       const char *dname;
+       long offset = 0;
+       pstring destname;
 
        *directory = *mask = 0;
 
        ZERO_STRUCT(sbuf1);
        ZERO_STRUCT(sbuf2);
 
-       status = unix_convert(conn, name, has_wild, last_component_src,
-                             &sbuf1);
+       status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       status = unix_convert(conn, newname, True, last_component_dest,
-                             &sbuf2);
+       status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -4212,10 +4360,11 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
                mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+       }
 
-       if (!has_wild) {
+       if (!src_has_wild) {
                /*
                 * No wildcards - just process the one file.
                 */
@@ -4242,6 +4391,21 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
                          conn->short_case_preserve, directory, 
                          newname, last_component_dest, is_short_name));
 
+               /* Ensure the source name is valid for us to access. */
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               /* The dest name still may have wildcards. */
+               if (dest_has_wild) {
+                       if (!resolve_wildcards(directory,newname)) {
+                               DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n", 
+                                         directory,newname));
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+                               
                /*
                 * Check for special case with case preserving and not
                 * case sensitive, if directory and newname are identical,
@@ -4276,8 +4440,12 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
                        }
                }
        
-               resolve_wildcards(directory,newname);
-       
+               /* Ensure the dest name is valid for us to access. */
+               status = check_name(conn, newname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
                /*
                 * The source object must exist.
                 */
@@ -4369,136 +4537,130 @@ NTSTATUS rename_internals(connection_struct *conn, pstring name,
                        nt_errstr(status), directory,newname));
 
                return status;
-       } else {
-               /*
-                * Wildcards - process each file that matches.
-                */
-               struct smb_Dir *dir_hnd = NULL;
-               const char *dname;
-               long offset = 0;
-               pstring destname;
-               
-               if (strequal(mask,"????????.???"))
-                       pstrcpy(mask,"*");
+       }
+
+       /*
+        * Wildcards - process each file that matches.
+        */
+       if (strequal(mask,"????????.???")) {
+               pstrcpy(mask,"*");
+       }
                        
-               status = check_name(conn, directory);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
        
-               dir_hnd = OpenDir(conn, directory, mask, attrs);
-               if (dir_hnd == NULL) {
-                       return map_nt_error_from_unix(errno);
-               }
+       dir_hnd = OpenDir(conn, directory, mask, attrs);
+       if (dir_hnd == NULL) {
+               return map_nt_error_from_unix(errno);
+       }
                
-               status = NT_STATUS_NO_SUCH_FILE;
-               /*
-                * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                * - gentest fix. JRA
-                */
+       status = NT_STATUS_NO_SUCH_FILE;
+       /*
+        * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+        * - gentest fix. JRA
+        */
                        
-               while ((dname = ReadDirName(dir_hnd, &offset))) {
-                       pstring fname;
-                       BOOL sysdir_entry = False;
+       while ((dname = ReadDirName(dir_hnd, &offset))) {
+               pstring fname;
+               BOOL sysdir_entry = False;
 
-                       pstrcpy(fname,dname);
+               pstrcpy(fname,dname);
                                
-                       /* Quick check for "." and ".." */
-                       if (fname[0] == '.') {
-                               if (!fname[1]
-                                   || (fname[1] == '.' && !fname[2])) {
-                                       if (attrs & aDIR) {
-                                               sysdir_entry = True;
-                                       } else {
-                                               continue;
-                                       }
+               /* Quick check for "." and ".." */
+               if (fname[0] == '.') {
+                       if (!fname[1] || (fname[1] == '.' && !fname[2])) {
+                               if (attrs & aDIR) {
+                                       sysdir_entry = True;
+                               } else {
+                                       continue;
                                }
                        }
+               }
 
-                       if (!is_visible_file(conn, directory, dname, &sbuf1,
-                                            False)) {
-                               continue;
-                       }
+               if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
+                       continue;
+               }
 
-                       if(!mask_match(fname, mask, conn->case_sensitive)) {
-                               continue;
-                       }
+               if(!mask_match(fname, mask, conn->case_sensitive)) {
+                       continue;
+               }
                                
-                       if (sysdir_entry) {
-                               status = NT_STATUS_OBJECT_NAME_INVALID;
-                               break;
-                       }
+               if (sysdir_entry) {
+                       status = NT_STATUS_OBJECT_NAME_INVALID;
+                       break;
+               }
 
-                       status = NT_STATUS_ACCESS_DENIED;
-                       slprintf(fname, sizeof(fname)-1, "%s/%s", directory,
-                                dname);
-                       if (!vfs_object_exist(conn, fname, &sbuf1)) {
-                               status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
-                               DEBUG(6, ("rename %s failed. Error %s\n",
-                                         fname, nt_errstr(status)));
-                               continue;
-                       }
-                       status = can_rename(conn,fname,attrs,&sbuf1);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               DEBUG(6, ("rename %s refused\n", fname));
-                               continue;
-                       }
-                       pstrcpy(destname,newname);
+               status = NT_STATUS_ACCESS_DENIED;
+               slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+
+               /* Ensure the source name is valid for us to access. */
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               if (!vfs_object_exist(conn, fname, &sbuf1)) {
+                       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       DEBUG(6, ("rename %s failed. Error %s\n",
+                                 fname, nt_errstr(status)));
+                       continue;
+               }
+               status = can_rename(conn,fname,attrs,&sbuf1);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(6, ("rename %s refused\n", fname));
+                       continue;
+               }
+               pstrcpy(destname,newname);
                        
-                       if (!resolve_wildcards(fname,destname)) {
-                               DEBUG(6, ("resolve_wildcards %s %s failed\n", 
-                                         fname, destname));
-                               continue;
-                       }
+               if (!resolve_wildcards(fname,destname)) {
+                       DEBUG(6, ("resolve_wildcards %s %s failed\n", 
+                                 fname, destname));
+                       continue;
+               }
                                
-                       if (strcsequal(fname,destname)) {
-                               rename_open_files(conn, NULL, sbuf1.st_dev,
-                                                 sbuf1.st_ino, newname);
-                               DEBUG(3,("rename_internals: identical names "
-                                        "in wildcard rename %s - success\n",
-                                        fname));
-                               count++;
-                               status = NT_STATUS_OK;
-                               continue;
-                       }
+               /* Ensure the dest name is valid for us to access. */
+               status = check_name(conn, destname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
 
-                       if (!replace_if_exists
-                           && vfs_file_exist(conn,destname, NULL)) {
-                               DEBUG(6,("file_exist %s\n", destname));
-                               status = NT_STATUS_OBJECT_NAME_COLLISION;
-                               continue;
-                       }
+               if (strcsequal(fname,destname)) {
+                       rename_open_files(conn, NULL, sbuf1.st_dev,
+                                         sbuf1.st_ino, newname);
+                       DEBUG(3,("rename_internals: identical names "
+                                "in wildcard rename %s - success\n",
+                                fname));
+                       count++;
+                       status = NT_STATUS_OK;
+                       continue;
+               }
+
+               if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
+                       DEBUG(6,("file_exist %s\n", destname));
+                       status = NT_STATUS_OBJECT_NAME_COLLISION;
+                       continue;
+               }
                                
-                       if (rename_path_prefix_equal(fname, destname)) {
-                               return NT_STATUS_SHARING_VIOLATION;
-                       }
+               if (rename_path_prefix_equal(fname, destname)) {
+                       return NT_STATUS_SHARING_VIOLATION;
+               }
 
-                       lck = get_share_mode_lock(NULL, sbuf1.st_dev,
-                                                 sbuf1.st_ino, NULL, NULL);
+               lck = get_share_mode_lock(NULL, sbuf1.st_dev,
+                                         sbuf1.st_ino, NULL, NULL);
 
-                       if (!SMB_VFS_RENAME(conn,fname,destname)) {
-                               rename_open_files(conn, lck, sbuf1.st_dev,
-                                                 sbuf1.st_ino, newname);
-                               count++;
-                               status = NT_STATUS_OK;
-                       }
-                       TALLOC_FREE(lck);
-                       DEBUG(3,("rename_internals: doing rename on %s -> "
-                                "%s\n",fname,destname));
+               if (!SMB_VFS_RENAME(conn,fname,destname)) {
+                       rename_open_files(conn, lck, sbuf1.st_dev,
+                                         sbuf1.st_ino, newname);
+                       count++;
+                       status = NT_STATUS_OK;
                }
-               CloseDir(dir_hnd);
+               TALLOC_FREE(lck);
+               DEBUG(3,("rename_internals: doing rename on %s -> "
+                        "%s\n",fname,destname));
        }
-
-#if 0
-       /* Don't think needed any more - JRA. */
-               if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
-                       if (!rcdest && bad_path_dest) {
-                               if (ms_has_wild(last_component_dest))
-                                       return NT_STATUS_OBJECT_NAME_INVALID;
-                               return NT_STATUS_OBJECT_PATH_NOT_FOUND;
-                       }
-               }
-#endif
+       CloseDir(dir_hnd);
 
        if (count == 0 && NT_STATUS_IS_OK(status)) {
                status = map_nt_error_from_unix(errno);
@@ -4520,30 +4682,45 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        char *p;
        uint32 attrs = SVAL(inbuf,smb_vwv0);
        NTSTATUS status;
-       BOOL path1_contains_wcard = False;
-       BOOL path2_contains_wcard = False;
+       BOOL src_has_wcard = False;
+       BOOL dest_has_wcard = False;
 
        START_PROFILE(SMBmv);
 
        p = smb_buf(inbuf) + 1;
-       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path1_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        p++;
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path2_contains_wcard);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                return ERROR_NT(status);
        }
        
-       RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
-       RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
+       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBmv);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
+
+       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBmv);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
        
        DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
        
-       status = rename_internals(conn, name, newname, attrs, False, path1_contains_wcard);
+       status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBmv);
                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4567,8 +4744,12 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
  * TODO: check error codes on all callers
  */
 
-NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
-                  int count, BOOL target_is_directory)
+NTSTATUS copy_file(connection_struct *conn,
+                       char *src,
+                       char *dest1,
+                       int ofun,
+                       int count,
+                       BOOL target_is_directory)
 {
        SMB_STRUCT_STAT src_sbuf, sbuf2;
        SMB_OFF_T ret=-1;
@@ -4653,7 +4834,7 @@ NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
        close_file(fsp1,NORMAL_CLOSE);
 
        /* Ensure the modtime is set correctly on the destination file. */
-       fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
+       fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
 
        /*
         * As we are opening fsp1 read-only we only expect
@@ -4688,14 +4869,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        int count=0;
        int error = ERRnoaccess;
        int err = 0;
-       BOOL has_wild;
-       BOOL exists=False;
        int tid2 = SVAL(inbuf,smb_vwv0);
        int ofun = SVAL(inbuf,smb_vwv1);
        int flags = SVAL(inbuf,smb_vwv2);
        BOOL target_is_directory=False;
-       BOOL path_contains_wcard1 = False;
-       BOOL path_contains_wcard2 = False;
+       BOOL source_has_wild = False;
+       BOOL dest_has_wild = False;
        SMB_STRUCT_STAT sbuf1, sbuf2;
        NTSTATUS status;
        START_PROFILE(SMBcopy);
@@ -4703,12 +4882,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        *directory = *mask = 0;
 
        p = smb_buf(inbuf);
-       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard1);
+       p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
        }
-       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &path_contains_wcard2);
+       p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -4723,16 +4902,31 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                return ERROR_DOS(ERRSRV,ERRinvdevice);
        }
 
-       RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
-       RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
+       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBcopy);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
-       status = unix_convert(conn, name, path_contains_wcard1, NULL, &sbuf1);
+       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
                return ERROR_NT(status);
        }
 
-       status = unix_convert(conn, newname, path_contains_wcard2, NULL, &sbuf2);
+       status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBcopy);
+               return ERROR_NT(status);
+       }
+
+       status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
                END_PROFILE(SMBcopy);
                return ERROR_NT(status);
@@ -4776,25 +4970,38 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
         * Tine Smukavec <valentin.smukavec@hermes.si>.
         */
 
-       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params))
+       if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
                mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+       }
 
-       has_wild = path_contains_wcard1;
-
-       if (!has_wild) {
+       if (!source_has_wild) {
                pstrcat(directory,"/");
                pstrcat(directory,mask);
-               if (resolve_wildcards(directory,newname)
-                   && NT_STATUS_IS_OK(status = copy_file(
-                                              directory,newname,conn,ofun,
-                                              count,target_is_directory))) 
-                       count++;
-               if(!count && !NT_STATUS_IS_OK(status)) {
-                       END_PROFILE(SMBcopy);
+               if (dest_has_wild) {
+                       if (!resolve_wildcards(directory,newname)) {
+                               END_PROFILE(SMBcopy);
+                               return ERROR_NT(NT_STATUS_NO_MEMORY);
+                       }
+               }
+
+               status = check_name(conn, directory);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
+               }
+               
+               status = check_name(conn, newname);
+               if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
-               if (!count) {
-                       exists = vfs_file_exist(conn,directory,NULL);
+               
+               status = copy_file(conn,directory,newname,ofun,
+                                       count,target_is_directory);
+
+               if(!NT_STATUS_IS_OK(status)) {
+                       END_PROFILE(SMBcopy);
+                       return ERROR_NT(status);
+               } else {
+                       count++;
                }
        } else {
                struct smb_Dir *dir_hnd = NULL;
@@ -4833,13 +5040,27 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
                        error = ERRnoaccess;
                        slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
                        pstrcpy(destname,newname);
-                       if (resolve_wildcards(fname,destname) &&
-                                       NT_STATUS_IS_OK(status = copy_file(
-                                               fname,destname,conn,ofun,
-                                               count,target_is_directory))) {
+                       if (!resolve_wildcards(fname,destname)) {
+                               continue;
+                       }
+
+                       status = check_name(conn, fname);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return ERROR_NT(status);
+                       }
+               
+                       status = check_name(conn, destname);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               return ERROR_NT(status);
+                       }
+               
+                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
+
+                       status = copy_file(conn,fname,destname,ofun,
+                                       count,target_is_directory);
+                       if (NT_STATUS_IS_OK(status)) {
                                count++;
                        }
-                       DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
                }
                CloseDir(dir_hnd);
        }
@@ -4888,7 +5109,14 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
                return ERROR_NT(status);
        }
   
-       RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
+       if (!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(pathworks_setdir);
+               if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(status);
+       }
 
        if (strlen(newdir) != 0) {
                if (!vfs_directory_exist(conn,newdir,NULL)) {
@@ -5440,7 +5668,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
 
 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
 {
-       struct utimbuf unix_times;
+       struct timespec ts[2];
        int outsize = 0;
        files_struct *fsp = file_fsp(inbuf,smb_vwv0);
        START_PROFILE(SMBsetattrE);
@@ -5457,15 +5685,15 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
         * time as UNIX can't set this.
         */
 
-       unix_times.actime = srv_make_unix_date2(inbuf+smb_vwv3);
-       unix_times.modtime = srv_make_unix_date2(inbuf+smb_vwv5);
+       ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
+       ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
   
        /* 
         * Patch from Ray Frush <frush@engr.colostate.edu>
         * Sometimes times are sent as zero - ignore them.
         */
 
-       if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+       if (null_timespec(ts[0]) && null_timespec(ts[1])) {
                /* Ignore request */
                if( DEBUGLVL( 3 ) ) {
                        dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
@@ -5473,20 +5701,22 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
                }
                END_PROFILE(SMBsetattrE);
                return(outsize);
-       } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+       } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
                /* set modify time = to access time if modify time was unset */
-               unix_times.modtime = unix_times.actime;
+               ts[1] = ts[0];
        }
 
        /* Set the date on this file */
        /* Should we set pending modtime here ? JRA */
-       if(file_utime(conn, fsp->fsp_name, &unix_times)) {
+       if(file_ntimes(conn, fsp->fsp_name, ts)) {
                END_PROFILE(SMBsetattrE);
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
   
-       DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
-               fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
+       DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
+               fsp->fnum,
+               (unsigned int)ts[0].tv_sec,
+               (unsigned int)ts[1].tv_sec));
 
        END_PROFILE(SMBsetattrE);
        return(outsize);
index 7a5f8be47ff711b676115c4be8010756fbbd84ca..ff1b2821cca307711ff7dda25c46333546b7354e 100644 (file)
@@ -158,13 +158,76 @@ static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
 
 
 #ifdef HAVE_KRB5
+
+#if 0
+/* Experiment that failed. See "only happens with a KDC" comment below. */
+/****************************************************************************
+ Cerate a clock skew error blob for a Windows client.
+****************************************************************************/
+
+static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
+{
+       krb5_context context = NULL;
+       krb5_error_code kerr = 0;
+       krb5_data reply;
+       krb5_principal host_princ = NULL;
+       char *host_princ_s = NULL;
+       BOOL ret = False;
+
+       *pblob_out = data_blob(NULL,0);
+
+       initialize_krb5_error_table();
+       kerr = krb5_init_context(&context);
+       if (kerr) {
+               return False;
+       }
+       /* Create server principal. */
+       asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
+       if (!host_princ_s) {
+               goto out;
+       }
+       strlower_m(host_princ_s);
+
+       kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
+       if (kerr) {
+               DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
+                       host_princ_s, error_message(kerr) ));
+               goto out;
+       }
+       
+       kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
+       if (kerr) {
+               DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
+                       error_message(kerr) ));
+               goto out;
+       }
+
+       *pblob_out = data_blob(reply.data, reply.length);
+       kerberos_free_data_contents(context,&reply);
+       ret = True;
+
+  out:
+
+       if (host_princ_s) {
+               SAFE_FREE(host_princ_s);
+       }
+       if (host_princ) {
+               krb5_free_principal(context, host_princ);
+       }
+       krb5_free_context(context);
+       return ret;
+}
+#endif
+
 /****************************************************************************
-reply to a session setup spnego negotiate packet for kerberos
+ Reply to a session setup spnego negotiate packet for kerberos.
 ****************************************************************************/
+
 static int reply_spnego_kerberos(connection_struct *conn, 
                                 char *inbuf, char *outbuf,
                                 int length, int bufsize,
-                                DATA_BLOB *secblob)
+                                DATA_BLOB *secblob,
+                                BOOL *p_invalidate_vuid)
 {
        TALLOC_CTX *mem_ctx;
        DATA_BLOB ticket;
@@ -191,9 +254,13 @@ static int reply_spnego_kerberos(connection_struct *conn,
        ZERO_STRUCT(ap_rep_wrapped);
        ZERO_STRUCT(response);
 
+       /* Normally we will always invalidate the intermediate vuid. */
+       *p_invalidate_vuid = True;
+
        mem_ctx = talloc_init("reply_spnego_kerberos");
-       if (mem_ctx == NULL)
+       if (mem_ctx == NULL) {
                return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
+       }
 
        if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
                talloc_destroy(mem_ctx);
@@ -205,9 +272,50 @@ static int reply_spnego_kerberos(connection_struct *conn,
        data_blob_free(&ticket);
 
        if (!NT_STATUS_IS_OK(ret)) {
-               DEBUG(1,("Failed to verify incoming ticket!\n"));       
+#if 0
+               /* Experiment that failed. See "only happens with a KDC" comment below. */
+
+               if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
+
+                       /*
+                        * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
+                        * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
+                        * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
+                        * clock and continues rather than giving an error. JRA.
+                        * -- Looks like this only happens with a KDC. JRA.
+                        */
+
+                       BOOL ok = make_krb5_skew_error(&ap_rep);
+                       if (!ok) {
+                               talloc_destroy(mem_ctx);
+                               return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+                       }
+                       ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
+                       response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
+                       reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+
+                       /*
+                        * In this one case we don't invalidate the intermediate vuid.
+                        * as we're expecting the client to re-use it for the next
+                        * sessionsetupX packet. JRA.
+                        */
+
+                       *p_invalidate_vuid = False;
+
+                       data_blob_free(&ap_rep);
+                       data_blob_free(&ap_rep_wrapped);
+                       data_blob_free(&response);
+                       talloc_destroy(mem_ctx);
+                       return -1; /* already replied */
+               }
+#else
+               if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
+                       ret = NT_STATUS_LOGON_FAILURE;
+               }
+#endif
+               DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret))); 
                talloc_destroy(mem_ctx);
-               return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+               return ERROR_NT(nt_status_squash(ret));
        }
 
        DEBUG(3,("Ticket name is [%s]\n", client));
@@ -523,32 +631,19 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
 }
 
 /****************************************************************************
- Reply to a session setup spnego negotiate packet.
+ Is this a krb5 mechanism ?
 ****************************************************************************/
 
-static int reply_spnego_negotiate(connection_struct *conn, 
-                                 char *inbuf,
-                                 char *outbuf,
-                                 uint16 vuid,
-                                 int length, int bufsize,
-                                 DATA_BLOB blob1,
-                                 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
 {
        char *OIDs[ASN1_MAX_OIDS];
-       DATA_BLOB secblob;
        int i;
-       DATA_BLOB chal;
-#ifdef HAVE_KRB5
-       BOOL got_kerberos_mechanism = False;
-#endif
-       NTSTATUS nt_status;
 
-       /* parse out the OIDs and the first sec blob */
-       if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
-               /* Kill the intermediate vuid */
-               invalidate_vuid(vuid);
+       *p_is_krb5 = False;
 
-               return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
+       /* parse out the OIDs and the first sec blob */
+       if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
+               return NT_STATUS_LOGON_FAILURE;
        }
 
        /* only look at the first OID for determining the mechToken --
@@ -564,24 +659,53 @@ static int reply_spnego_negotiate(connection_struct *conn,
 #ifdef HAVE_KRB5       
        if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
            strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
-               got_kerberos_mechanism = True;
+               *p_is_krb5 = True;
        }
 #endif
                
        for (i=0;OIDs[i];i++) {
-               DEBUG(3,("Got OID %s\n", OIDs[i]));
+               DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
                free(OIDs[i]);
        }
-       DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Reply to a session setup spnego negotiate packet.
+****************************************************************************/
+
+static int reply_spnego_negotiate(connection_struct *conn, 
+                                 char *inbuf,
+                                 char *outbuf,
+                                 uint16 vuid,
+                                 int length, int bufsize,
+                                 DATA_BLOB blob1,
+                                 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
+{
+       DATA_BLOB secblob;
+       DATA_BLOB chal;
+       BOOL got_kerberos_mechanism = False;
+       NTSTATUS status;
+
+       status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
+       if (!NT_STATUS_IS_OK(status)) {
+               /* Kill the intermediate vuid */
+               invalidate_vuid(vuid);
+               return ERROR_NT(nt_status_squash(status));
+       }
+
+       DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
 
 #ifdef HAVE_KRB5
        if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
+               BOOL destroy_vuid = True;
                int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
-                                               length, bufsize, &secblob);
+                                               length, bufsize, &secblob, &destroy_vuid);
                data_blob_free(&secblob);
-               /* Kill the intermediate vuid */
-               invalidate_vuid(vuid);
-
+               if (destroy_vuid) {
+                       /* Kill the intermediate vuid */
+                       invalidate_vuid(vuid);
+               }
                return ret;
        }
 #endif
@@ -590,28 +714,27 @@ static int reply_spnego_negotiate(connection_struct *conn,
                auth_ntlmssp_end(auth_ntlmssp_state);
        }
 
-       nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
-       if (!NT_STATUS_IS_OK(nt_status)) {
+       status = auth_ntlmssp_start(auth_ntlmssp_state);
+       if (!NT_STATUS_IS_OK(status)) {
                /* Kill the intermediate vuid */
                invalidate_vuid(vuid);
-
-               return ERROR_NT(nt_status_squash(nt_status));
+               return ERROR_NT(nt_status_squash(status));
        }
 
-       nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 
+       status = auth_ntlmssp_update(*auth_ntlmssp_state, 
                                        secblob, &chal);
 
        data_blob_free(&secblob);
 
        reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
-                            &chal, nt_status, True);
+                            &chal, status, True);
 
        data_blob_free(&chal);
 
        /* already replied */
        return -1;
 }
-       
+
 /****************************************************************************
  Reply to a session setup spnego auth packet.
 ****************************************************************************/
@@ -622,8 +745,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
                             DATA_BLOB blob1,
                             AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
 {
-       DATA_BLOB auth, auth_reply;
-       NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
+       DATA_BLOB auth = data_blob(NULL,0);
+       DATA_BLOB auth_reply = data_blob(NULL,0);
+       DATA_BLOB secblob = data_blob(NULL,0);
+       NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
 
        if (!spnego_parse_auth(blob1, &auth)) {
 #if 0
@@ -634,6 +759,33 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
 
                return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
        }
+
+       if (auth.data[0] == ASN1_APPLICATION(0)) {
+               /* Might be a second negTokenTarg packet */
+
+               BOOL got_krb5_mechanism = False;
+               status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
+               if (NT_STATUS_IS_OK(status)) {
+                       DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
+#ifdef HAVE_KRB5
+                       if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
+                               BOOL destroy_vuid = True;
+                               int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
+                                                               length, bufsize, &secblob, &destroy_vuid);
+                               data_blob_free(&secblob);
+                               data_blob_free(&auth);
+                               if (destroy_vuid) {
+                                       /* Kill the intermediate vuid */
+                                       invalidate_vuid(vuid);
+                               }
+                               return ret;
+                       }
+#endif
+               }
+       }
+
+       /* If we get here it wasn't a negTokenTarg auth packet. */
+       data_blob_free(&secblob);
        
        if (!*auth_ntlmssp_state) {
                /* Kill the intermediate vuid */
@@ -643,14 +795,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
        }
        
-       nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 
+       status = auth_ntlmssp_update(*auth_ntlmssp_state, 
                                        auth, &auth_reply);
 
        data_blob_free(&auth);
 
        reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
                             auth_ntlmssp_state,
-                            &auth_reply, nt_status, True);
+                            &auth_reply, status, True);
                
        data_blob_free(&auth_reply);
 
index 5bbd618231b5336d529fad09dcbeafe2f4ba0a4a..deb5db1bafea8a0f554f98a83d89ca6849ef0d06 100644 (file)
@@ -5,6 +5,7 @@
    Copyright (C) Stefan (metze) Metzmacher     2003
    Copyright (C) Volker Lendecke               2005
    Copyright (C) Steve French                  2005
+   Copyright (C) James Peach                   2007
 
    Extensively modified by Andrew Tridgell, 1995
 
@@ -34,6 +35,16 @@ extern struct current_user current_user;
 #define get_file_size(sbuf) ((sbuf).st_size)
 #define DIR_ENTRY_SAFETY_MARGIN 4096
 
+static char *store_file_unix_basic(connection_struct *conn,
+                               char *pdata,
+                               files_struct *fsp,
+                               const SMB_STRUCT_STAT *psbuf);
+
+static char *store_file_unix_basic_info2(connection_struct *conn,
+                               char *pdata,
+                               files_struct *fsp,
+                               const SMB_STRUCT_STAT *psbuf);
+
 /********************************************************************
  Roundup a value to the nearest allocation roundup size boundary.
  Only do this for Windows clients.
@@ -56,7 +67,7 @@ SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
  account sparse files.
 ********************************************************************/
 
-SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
 {
        SMB_BIG_UINT ret;
 
@@ -1191,15 +1202,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                                        continue;
                                }
                        } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+                               pstring link_target;
 
                                /* Needed to show the msdfs symlinks as 
                                 * directories */
 
                                if(lp_host_msdfs() && 
                                   lp_msdfs_root(SNUM(conn)) &&
-                                  ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
-
-                                       DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
+                                  ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
+                                       DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
+                                               "as a directory\n",
+                                               pathreal));
                                        sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
 
                                } else {
@@ -1578,51 +1591,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                /* CIFS UNIX Extension. */
 
                case SMB_FIND_FILE_UNIX:
-                       DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+               case SMB_FIND_FILE_UNIX_INFO2:
                        p+= 4;
                        SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
 
                        /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
-                       SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
-                       p+= 8;
-
-                       SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
-                       p+= 8;
-
-                       put_long_date_timespec(p,get_ctimespec(&sbuf));       /* Inode change Time 64 Bit */
-                       put_long_date_timespec(p+8,get_atimespec(&sbuf));     /* Last access time 64 Bit */
-                       put_long_date_timespec(p+16,get_mtimespec(&sbuf));    /* Last modification time 64 Bit */
-                       p+= 24;
-
-                       SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,unix_filetype(sbuf.st_mode));
-                       p+= 4;
-
-                       SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
-                       p+= 8;
 
-                       SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
-                       SIVAL(p,4,0);
-                       p+= 8;
-
-                       SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
-                       SIVAL(p,4,0);
-                       p+= 8;
+                       if (info_level == SMB_FIND_FILE_UNIX) {
+                               DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+                               p = store_file_unix_basic(conn, p,
+                                                       NULL, &sbuf);
+                       } else {
+                               DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
+                               p = store_file_unix_basic_info2(conn, p,
+                                                       NULL, &sbuf);
+                       }
 
                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
                        p += len;
@@ -1732,6 +1715,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
                        break;
                case SMB_FIND_FILE_UNIX:
+               case SMB_FIND_FILE_UNIX_INFO2:
                        if (!lp_unix_extensions()) {
                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
                        }
@@ -1745,7 +1729,13 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
                return ERROR_NT(ntstatus);
        }
 
-       RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
+       ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
+                       return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+               }
+               return ERROR_NT(ntstatus);
+       }
 
        ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
        if (!NT_STATUS_IS_OK(ntstatus)) {
@@ -2037,6 +2027,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
                        break;
                case SMB_FIND_FILE_UNIX:
+               case SMB_FIND_FILE_UNIX_INFO2:
                        if (!lp_unix_extensions()) {
                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
                        }
@@ -2232,7 +2223,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
                                        char **pparams, int total_params, char **ppdata, int total_data,
                                        unsigned int max_data_bytes)
 {
-       char *pdata = *ppdata;
+       char *pdata;
        char *params = *pparams;
        uint16 info_level;
        int data_len, len;
@@ -2530,6 +2521,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                                        CIFS_UNIX_POSIX_ACLS_CAP|
                                        CIFS_UNIX_POSIX_PATHNAMES_CAP|
                                        CIFS_UNIX_FCNTL_LOCKS_CAP|
+                                       CIFS_UNIX_EXTATTR_CAP|
                                        CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
                        break;
 
@@ -2566,6 +2558,114 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
                        break;
                }
 
+               case SMB_QUERY_POSIX_WHOAMI:
+               {
+                       uint32_t flags = 0;
+                       uint32_t sid_bytes;
+                       int i;
+
+                       if (!lp_unix_extensions()) {
+                               return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+                       }
+
+                       if (max_data_bytes < 40) {
+                               return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+                       }
+
+                       /* We ARE guest if global_sid_Builtin_Guests is
+                        * in our list of SIDs.
+                        */
+                       if (nt_token_check_sid(&global_sid_Builtin_Guests,
+                                   current_user.nt_user_token)) {
+                               flags |= SMB_WHOAMI_GUEST;
+                       }
+
+                       /* We are NOT guest if global_sid_Authenticated_Users
+                        * is in our list of SIDs.
+                        */
+                       if (nt_token_check_sid(&global_sid_Authenticated_Users,
+                                   current_user.nt_user_token)) {
+                               flags &= ~SMB_WHOAMI_GUEST;
+                       }
+
+                       /* NOTE: 8 bytes for UID/GID, irrespective of native
+                        * platform size. This matches
+                        * SMB_QUERY_FILE_UNIX_BASIC and friends.
+                        */
+                       data_len = 4 /* flags */
+                           + 4 /* flag mask */
+                           + 8 /* uid */
+                           + 8 /* gid */
+                           + 4 /* ngroups */
+                           + 4 /* num_sids */
+                           + 4 /* SID bytes */
+                           + 4 /* pad/reserved */
+                           + (current_user.ut.ngroups * 8)
+                               /* groups list */
+                           + (current_user.nt_user_token->num_sids *
+                                   SID_MAX_SIZE)
+                               /* SID list */;
+
+                       SIVAL(pdata, 0, flags);
+                       SIVAL(pdata, 4, SMB_WHOAMI_MASK);
+                       SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
+                       SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
+
+
+                       if (data_len >= max_data_bytes) {
+                               /* Potential overflow, skip the GIDs and SIDs. */
+
+                               SIVAL(pdata, 24, 0); /* num_groups */
+                               SIVAL(pdata, 28, 0); /* num_sids */
+                               SIVAL(pdata, 32, 0); /* num_sid_bytes */
+                               SIVAL(pdata, 36, 0); /* reserved */
+
+                               data_len = 40;
+                               break;
+                       }
+
+                       SIVAL(pdata, 24, current_user.ut.ngroups);
+                       SIVAL(pdata, 28,
+                               current_user.nt_user_token->num_sids);
+
+                       /* We walk the SID list twice, but this call is fairly
+                        * infrequent, and I don't expect that it's performance
+                        * sensitive -- jpeach
+                        */
+                       for (i = 0, sid_bytes = 0;
+                           i < current_user.nt_user_token->num_sids; ++i) {
+                               sid_bytes +=
+                                   sid_size(&current_user.nt_user_token->user_sids[i]);
+                       }
+
+                       /* SID list byte count */
+                       SIVAL(pdata, 32, sid_bytes);
+
+                       /* 4 bytes pad/reserved - must be zero */
+                       SIVAL(pdata, 36, 0);
+                       data_len = 40;
+
+                       /* GID list */
+                       for (i = 0; i < current_user.ut.ngroups; ++i) {
+                               SBIG_UINT(pdata, data_len,
+                                       (SMB_BIG_UINT)current_user.ut.groups[i]);
+                               data_len += 8;
+                       }
+
+                       /* SID list */
+                       for (i = 0;
+                           i < current_user.nt_user_token->num_sids; ++i) {
+                               int sid_len =
+                                   sid_size(&current_user.nt_user_token->user_sids[i]);
+
+                               sid_linearize(pdata + data_len, sid_len,
+                                   &current_user.nt_user_token->user_sids[i]);
+                               data_len += sid_len;
+                       }
+
+                       break;
+               }
+
                case SMB_MAC_QUERY_FS_INFO:
                        /*
                         * Thursby MAC extension... ONLY on NTFS filesystems
@@ -2871,7 +2971,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
 static char *store_file_unix_basic(connection_struct *conn,
                                char *pdata,
                                files_struct *fsp,
-                               SMB_STRUCT_STAT *psbuf)
+                               const SMB_STRUCT_STAT *psbuf)
 {
        DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
        DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
@@ -2920,6 +3020,121 @@ static char *store_file_unix_basic(connection_struct *conn,
        return pdata;
 }
 
+/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
+ * the chflags(2) (or equivalent) flags.
+ *
+ * XXX: this really should be behind the VFS interface. To do this, we would
+ * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
+ * Each VFS module could then implement it's own mapping as appropriate for the
+ * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
+ */
+static const struct {unsigned stat_fflag; unsigned smb_fflag;}
+       info2_flags_map[] =
+{
+#ifdef UF_NODUMP
+    { UF_NODUMP, EXT_DO_NOT_BACKUP },
+#endif
+
+#ifdef UF_IMMUTABLE
+    { UF_IMMUTABLE, EXT_IMMUTABLE },
+#endif
+
+#ifdef UF_APPEND
+    { UF_APPEND, EXT_OPEN_APPEND_ONLY },
+#endif
+
+#ifdef UF_HIDDEN
+    { UF_HIDDEN, EXT_HIDDEN },
+#endif
+
+    /* Do not remove. We need to guarantee that this array has at least one
+     * entry to build on HP-UX.
+     */
+    { 0, 0 }
+
+};
+
+static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
+                               uint32 *smb_fflags, uint32 *smb_fmask)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+           *smb_fmask |= info2_flags_map[i].smb_fflag;
+           if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
+                   *smb_fflags |= info2_flags_map[i].smb_fflag;
+           }
+       }
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
+                               const uint32 smb_fflags,
+                               const uint32 smb_fmask,
+                               int *stat_fflags)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+       uint32 max_fmask = 0;
+       int i;
+
+       *stat_fflags = psbuf->st_flags;
+
+       /* For each flags requested in smb_fmask, check the state of the
+        * corresponding flag in smb_fflags and set or clear the matching
+        * stat flag.
+        */
+
+       for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+           max_fmask |= info2_flags_map[i].smb_fflag;
+           if (smb_fmask & info2_flags_map[i].smb_fflag) {
+                   if (smb_fflags & info2_flags_map[i].smb_fflag) {
+                           *stat_fflags |= info2_flags_map[i].stat_fflag;
+                   } else {
+                           *stat_fflags &= ~info2_flags_map[i].stat_fflag;
+                   }
+           }
+       }
+
+       /* If smb_fmask is asking to set any bits that are not supported by
+        * our flag mappings, we should fail.
+        */
+       if ((smb_fmask & max_fmask) != smb_fmask) {
+               return False;
+       }
+
+       return True;
+#else
+       return False;
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+
+/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
+ * of file flags and birth (create) time.
+ */
+static char *store_file_unix_basic_info2(connection_struct *conn,
+                               char *pdata,
+                               files_struct *fsp,
+                               const SMB_STRUCT_STAT *psbuf)
+{
+       uint32 file_flags = 0;
+       uint32 flags_mask = 0;
+
+       pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
+
+       /* Create (birth) time 64 bit */
+       put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
+       pdata += 8;
+
+       map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
+       SIVAL(pdata, 0, file_flags); /* flags */
+       SIVAL(pdata, 4, flags_mask); /* mask */
+       pdata += 8;
+
+       return pdata;
+}
+
 /****************************************************************************
  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
  file name or file id).
@@ -2970,6 +3185,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
 
+               if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+               }
+
                if(fsp && (fsp->fake_file_handle)) {
                        /*
                         * This is actually for the QUOTA_FAKE_FILE --metze
@@ -3026,12 +3245,22 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
 
+               if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+                       return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+               }
+
                srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
                if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
 
-               RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+               status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                               return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                       }
+                       return ERROR_NT(status);
+               }
 
                status = unix_convert(conn, fname, False, NULL, &sbuf);
                if (!NT_STATUS_IS_OK(status)) {
@@ -3175,18 +3404,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        allocation_size = get_allocation_size(conn,fsp,&sbuf);
 
        if (fsp) {
-               if (fsp->pending_modtime) {
+               if (!null_timespec(fsp->pending_modtime)) {
                        /* the pending modtime overrides the current modtime */
-                       mtime_ts.tv_sec = fsp->pending_modtime;
-                       mtime_ts.tv_nsec = 0;
+                       mtime_ts = fsp->pending_modtime;
                }
        } else {
                /* Do we have this path open ? */
                files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
-               if (fsp1 && fsp1->pending_modtime) {
+               if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
                        /* the pending modtime overrides the current modtime */
-                       mtime_ts.tv_sec = fsp1->pending_modtime;
-                       mtime_ts.tv_nsec = 0;
+                       mtime_ts = fsp1->pending_modtime;
                }
                if (fsp1 && fsp1->initial_allocation_size) {
                        allocation_size = get_allocation_size(conn, fsp1, &sbuf);
@@ -3539,6 +3766,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 
                        break;
 
+               case SMB_QUERY_FILE_UNIX_INFO2:
+
+                       pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
+                       data_size = PTR_DIFF(pdata,(*ppdata));
+
+                       {
+                               int i;
+                               DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
+
+                               for (i=0; i<100; i++)
+                                       DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
+                               DEBUG(4,("\n"));
+                       }
+
+                       break;
+
                case SMB_QUERY_FILE_UNIX_LINK:
                        {
                                pstring buffer;
@@ -3743,17 +3986,22 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return status;
        }
 
+       status = check_name(conn, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        /* source must already exist. */
        if (!VALID_STAT(sbuf1)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
-       status = check_name(conn, oldname);
+       status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
        if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_ACCESS_DENIED;
+               return status;
        }
 
-       status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+       status = check_name(conn, newname);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -3763,11 +4011,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
                return NT_STATUS_OBJECT_NAME_COLLISION;
        }
 
-       status = check_name(conn, newname);
-       if (!NT_STATUS_IS_OK(status)) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        /* No links from a directory. */
        if (S_ISDIR(sbuf1.st_mode)) {
                return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -3798,7 +4041,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                                files_struct *fsp,
                                const char *fname,
                                const SMB_STRUCT_STAT *psbuf,
-                               struct utimbuf tvs)
+                               struct timespec ts[2])
 {
        uint32 action =
                FILE_NOTIFY_CHANGE_LAST_ACCESS
@@ -3810,26 +4053,30 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
        }
 
        /* get some defaults (no modifications) if any info is zero or -1. */
-       if (null_mtime(tvs.actime)) {
-               tvs.actime = psbuf->st_atime;
+       if (null_timespec(ts[0])) {
+               ts[0] = get_atimespec(psbuf);
                action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
        }
 
-       if (null_mtime(tvs.modtime)) {
-               tvs.modtime = psbuf->st_mtime;
+       if (null_timespec(ts[1])) {
+               ts[1] = get_mtimespec(psbuf);
                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
        }
 
-       DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
-       DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
+       DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
+       DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
 
        /*
         * Try and set the times of this file if
         * they are different from the current values.
         */
 
-       if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
-               return NT_STATUS_OK;
+       {
+               struct timespec mts = get_mtimespec(psbuf);
+               struct timespec ats = get_atimespec(psbuf);
+               if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+                       return NT_STATUS_OK;
+               }
        }
 
        if(fsp != NULL) {
@@ -3843,15 +4090,16 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
                 * away and will set it on file close and after a write. JRA.
                 */
 
-               if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
-                       DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
-                       fsp_set_pending_modtime(fsp, tvs.modtime);
+               if (!null_timespec(ts[1])) {
+                       DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
+                               time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+                       fsp_set_pending_modtime(fsp, ts[1]);
                }
 
        }
        DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
 
-       if(file_utime(conn, fname, &tvs)!=0) {
+       if(file_ntimes(conn, fname, ts)!=0) {
                return map_nt_error_from_unix(errno);
        }
        if (action != 0) {
@@ -4030,6 +4278,12 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
        delete_on_close = (CVAL(pdata,0) ? True : False);
        dosmode = dos_mode(conn, fname, psbuf);
 
+       DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
+               "delete_on_close = %u\n",
+               fsp->fsp_name,
+               (unsigned int)dosmode,
+               (unsigned int)delete_on_close ));
+
        status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
  
        if (!NT_STATUS_IS_OK(status)) {
@@ -4132,7 +4386,6 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
                pstring rel_name;
                char *last_dirp = NULL;
 
-               unix_format(link_target);
                if (*link_target == '/') {
                        /* No absolute paths allowed. */
                        return NT_STATUS_ACCESS_DENIED;
@@ -4186,7 +4439,10 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
                return status;
        }
 
-       RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
+       status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
                fname, oldname));
@@ -4211,6 +4467,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        uint32 len;
        pstring newname;
        pstring base_name;
+       BOOL dest_has_wcard = False;
        NTSTATUS status = NT_STATUS_OK;
        char *p;
 
@@ -4226,12 +4483,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+       srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
-       RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
+       status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        /* Check the new name has no '/' characters. */
        if (strchr_m(newname, '/')) {
@@ -4255,7 +4515,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
        } else {
                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
                        fname, newname ));
-               status = rename_internals(conn, fname, base_name, 0, overwrite, False);
+               status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
        }
 
        return status;
@@ -4305,6 +4565,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
+               fname ? fname : fsp->fsp_name,
+               (unsigned int)num_file_acls,
+               (unsigned int)num_def_acls));
+
        if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
                        pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
                return map_nt_error_from_unix(errno);
@@ -4386,6 +4651,14 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
        count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
 #endif /* HAVE_LONGLONG */
 
+       DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
+                       "lock_pid = %u, count = %.0f, offset = %.0f\n",
+               fsp->fsp_name,
+               (unsigned int)lock_type,
+               (unsigned int)lock_pid,
+               (double)count,
+               (double)offset ));
+
        if (lock_type == UNLOCK_LOCK) {
                status = do_unlock(fsp,
                                lock_pid,
@@ -4439,22 +4712,25 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
                                        const char *fname,
                                        const SMB_STRUCT_STAT *psbuf)
 {
-       struct utimbuf tvs;
+       struct timespec ts[2];
 
        if (total_data < 12) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* access time */
-       tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
+       ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
        /* write time */
-       tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
+       ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+
+       DEBUG(10,("smb_set_info_standard: file %s\n",
+               fname ? fname : fsp->fsp_name ));
 
        return smb_set_file_time(conn,
                                fsp,
                                fname,
                                psbuf,
-                               tvs);
+                               ts);
 }
 
 /****************************************************************************
@@ -4469,10 +4745,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
                                        SMB_STRUCT_STAT *psbuf)
 {
        /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
-       time_t write_time;
-       time_t changed_time;
+       struct timespec write_time;
+       struct timespec changed_time;
        uint32 dosmode = 0;
-       struct utimbuf tvs;
+       struct timespec ts[2];
        NTSTATUS status = NT_STATUS_OK;
 
        if (total_data < 36) {
@@ -4492,26 +4768,31 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
        /* Ignore create time at offset pdata. */
 
        /* access time */
-       tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
+       ts[0] = interpret_long_date(pdata+8);
 
-       write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
-       changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
+       write_time = interpret_long_date(pdata+16);
+       changed_time = interpret_long_date(pdata+24);
 
-       tvs.modtime = MIN(write_time, changed_time);
+       /* mtime */
+       ts[1] = timespec_min(&write_time, &changed_time);
 
-       if (write_time > tvs.modtime && write_time != (time_t)-1) {
-               tvs.modtime = write_time;
+       if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
+               ts[1] = write_time;
        }
+
        /* Prefer a defined time to an undefined one. */
-       if (null_mtime(tvs.modtime)) {
-               tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
+       if (null_timespec(ts[1])) {
+               ts[1] = null_timespec(write_time) ? changed_time : write_time;
        }
 
+       DEBUG(10,("smb_set_file_basic_info: file %s\n",
+               fname ? fname : fsp->fsp_name ));
+
        return smb_set_file_time(conn,
                                fsp,
                                fname,
                                psbuf,
-                               tvs);
+                               ts);
 }
 
 /****************************************************************************
@@ -4725,7 +5006,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
                                        const char *fname,
                                        SMB_STRUCT_STAT *psbuf)
 {
-       struct utimbuf tvs;
+       struct timespec ts[2];
        uint32 raw_unixmode;
        mode_t unixmode;
        SMB_OFF_T size = 0;
@@ -4752,8 +5033,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
 #endif /* LARGE_SMB_OFF_T */
        }
 
-       tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
-       tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
+       ts[0] = interpret_long_date(pdata+24); /* access_time */
+       ts[1] = interpret_long_date(pdata+32); /* modification_time */
        set_owner = (uid_t)IVAL(pdata,40);
        set_grp = (gid_t)IVAL(pdata,48);
        raw_unixmode = IVAL(pdata,84);
@@ -4796,8 +5077,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                /* Ensure we don't try and change anything else. */
                raw_unixmode = SMB_MODE_NO_CHANGE;
                size = get_file_size(*psbuf);
-               tvs.modtime = psbuf->st_mtime;
-               tvs.actime = psbuf->st_atime;
+               ts[0] = get_atimespec(psbuf);
+               ts[1] = get_mtimespec(psbuf);
                /* 
                 * We continue here as we might want to change the 
                 * owner uid/gid.
@@ -4876,7 +5157,68 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                                fsp,
                                fname,
                                psbuf,
-                               tvs);
+                               ts);
+}
+
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_INFO2.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
+                                       const char *pdata,
+                                       int total_data,
+                                       files_struct *fsp,
+                                       const char *fname,
+                                       SMB_STRUCT_STAT *psbuf)
+{
+       NTSTATUS status;
+       uint32 smb_fflags;
+       uint32 smb_fmask;
+
+       if (total_data < 116) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* Start by setting all the fields that are common between UNIX_BASIC
+        * and UNIX_INFO2.
+        */
+       status = smb_set_file_unix_basic(conn, pdata, total_data,
+                               fsp, fname, psbuf);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       smb_fflags = IVAL(pdata, 108);
+       smb_fmask = IVAL(pdata, 112);
+
+       /* NB: We should only attempt to alter the file flags if the client
+        * sends a non-zero mask.
+        */
+       if (smb_fmask != 0) {
+               int stat_fflags = 0;
+
+               if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
+                           &stat_fflags)) {
+                       /* Client asked to alter a flag we don't understand. */
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               if (fsp && fsp->fh->fd != -1) {
+                       /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
+                       return NT_STATUS_NOT_SUPPORTED;
+               } else {
+                       if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
+                               return map_nt_error_from_unix(errno);
+                       }
+               }
+       }
+
+       /* XXX: need to add support for changing the create_time here. You
+        * can do this for paths on Darwin with setattrlist(2). The right way
+        * to hook this up is probably by extending the VFS utimes interface.
+        */
+
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
@@ -4896,13 +5238,16 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
        mode_t unixmode = (mode_t)0;
        files_struct *fsp = NULL;
        uint16 info_level_return = 0;
+       int info;
        char *pdata = *ppdata;
 
-       if (total_data < 10) {
+       if (total_data < 18) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        raw_unixmode = IVAL(pdata,8);
+       /* Next 4 bytes are not yet defined. */
+
        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -4910,6 +5255,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
 
        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
 
+       DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
+               fname, (unsigned int)unixmode ));
+
        status = open_directory(conn,
                                fname,
                                psbuf,
@@ -4918,19 +5266,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
                                FILE_CREATE,
                                0,
                                mod_unixmode,
-                               NULL,
+                               &info,
                                &fsp);
 
         if (NT_STATUS_IS_OK(status)) {
                 close_file(fsp, NORMAL_CLOSE);
         }
 
-       info_level_return = SVAL(pdata,12);
+       info_level_return = SVAL(pdata,16);
  
        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+               *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+       } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
+               *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
        } else {
-               *pdata_return_size = 8;
+               *pdata_return_size = 12;
        }
 
        /* Realloc the data size */
@@ -4941,15 +5291,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
        }
 
        SSVAL(pdata,0,NO_OPLOCK_RETURN);
-       SSVAL(pdata,2,0);
-
-       if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
-               SSVAL(pdata,6,0); /* Padding. */
-               store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
-       } else {
-               SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
-               SSVAL(pdata,6,0); /* Padding. */
+       SSVAL(pdata,2,0); /* No fnum. */
+       SIVAL(pdata,4,info); /* Was directory created. */
+
+       switch (info_level_return) {
+       case SMB_QUERY_FILE_UNIX_BASIC:
+               SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+               SSVAL(pdata,10,0); /* Padding. */
+               store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+       case SMB_QUERY_FILE_UNIX_INFO2:
+               SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+               SSVAL(pdata,10,0); /* Padding. */
+               store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+       default:
+               SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+               SSVAL(pdata,10,0); /* Padding. */
        }
 
        return status;
@@ -4982,7 +5338,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        int info = 0;
        uint16 info_level_return = 0;
 
-       if (total_data < 14) {
+       if (total_data < 18) {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
@@ -5034,6 +5390,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        }
 
        raw_unixmode = IVAL(pdata,8);
+       /* Next 4 bytes are not yet defined. */
+
        status = unix_perms_from_wire(conn,
                                psbuf,
                                raw_unixmode,
@@ -5056,6 +5414,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                mod_unixmode |= FILE_FLAG_NO_BUFFERING;
        }
 
+       DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
+               fname,
+               (unsigned int)wire_open_mode,
+               (unsigned int)unixmode ));
+
        status = open_file_ntcreate(conn,
                                fname,
                                psbuf,
@@ -5080,12 +5443,16 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
                extended_oplock_granted = True;
        }
 
-       info_level_return = SVAL(pdata,12);
+       info_level_return = SVAL(pdata,16);
  
+       /* Allocate the correct return size. */
+
        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+               *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+       } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
+               *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
        } else {
-               *pdata_return_size = 8;
+               *pdata_return_size = 12;
        }
 
        /* Realloc the data size */
@@ -5109,13 +5476,20 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
        }
 
        SSVAL(pdata,2,fsp->fnum);
-       if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
-               SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
-               SSVAL(pdata,6,0); /* padding. */
-               store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
-       } else {
-               SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
-               SSVAL(pdata,6,0); /* padding. */
+       SIVAL(pdata,4,info); /* Was file created etc. */
+
+       switch (info_level_return) {
+       case SMB_QUERY_FILE_UNIX_BASIC:
+               SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+               SSVAL(pdata,10,0); /* padding. */
+               store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+       case SMB_QUERY_FILE_UNIX_INFO2:
+               SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+               SSVAL(pdata,10,0); /* padding. */
+               store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+       default:
+               SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+               SSVAL(pdata,10,0); /* padding. */
        }
        return NT_STATUS_OK;
 }
@@ -5132,12 +5506,28 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
 {
        NTSTATUS status = NT_STATUS_OK;
        files_struct *fsp = NULL;
+       uint16 flags = 0;
        int info = 0;
 
+       if (total_data < 2) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       flags = SVAL(pdata,0);
+
        if (!VALID_STAT(*psbuf)) {
                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
        }
 
+       if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
+                       !VALID_STAT_OF_DIR(*psbuf)) {
+               return NT_STATUS_NOT_A_DIRECTORY;
+       }
+
+       DEBUG(10,("smb_posix_unlink: %s %s\n",
+               (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
+               fname));
+
        if (VALID_STAT_OF_DIR(*psbuf)) {
                status = open_directory(conn,
                                        fname,
@@ -5150,17 +5540,34 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
                                        &info,                          
                                        &fsp);
        } else {
+               char del = 1;
+
                status = open_file_ntcreate(conn,
                                fname,
                                psbuf,
                                DELETE_ACCESS,
                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
                                FILE_OPEN,
-                               FILE_DELETE_ON_CLOSE,
+                               0,
                                FILE_FLAG_POSIX_SEMANTICS|0777,
-                               INTERNAL_OPEN_ONLY,
+                               0, /* No oplock, but break existing ones. */
                                &info,
                                &fsp);
+               /* 
+                * For file opens we must set the delete on close
+                * after the open.
+                */
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               status = smb_set_file_disposition_info(conn,
+                                                       &del,
+                                                       1,
+                                                       fsp,
+                                                       fname,
+                                                       psbuf);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -5251,13 +5658,24 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        return ERROR_NT(status);
                }
 
-               RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+               status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+                               return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+                       }
+                       return ERROR_NT(status);
+               }
 
                status = unix_convert(conn, fname, False, NULL, &sbuf);
                if (!NT_STATUS_IS_OK(status)) {
                        return ERROR_NT(status);
                }
 
+               status = check_name(conn, fname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ERROR_NT(status);
+               }
+
                /*
                 * For CIFS UNIX extensions the target name may not exist.
                 */
@@ -5266,12 +5684,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
                        return UNIXERROR(ERRDOS,ERRbadpath);
                }    
-
-               status = check_name(conn, fname);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return ERROR_NT(status);
-               }
-
        }
 
        if (!CAN_WRITE(conn)) {
@@ -5294,9 +5706,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
 
        SSVAL(params,0,0);
 
-       if (fsp && fsp->pending_modtime) {
+       if (fsp && !null_timespec(fsp->pending_modtime)) {
                /* the pending modtime overrides the current modtime */
-               sbuf.st_mtime = fsp->pending_modtime;
+               set_mtimespec(&sbuf, fsp->pending_modtime);
        }
 
        switch (info_level) {
@@ -5417,6 +5829,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        break;
                }
 
+               case SMB_SET_FILE_UNIX_INFO2:
+               {
+                       status = smb_set_file_unix_info2(conn,
+                                                       pdata,
+                                                       total_data,
+                                                       fsp,
+                                                       fname,
+                                                       &sbuf);
+                       break;
+               }
+
                case SMB_SET_FILE_UNIX_LINK:
                {
                        if (tran_call != TRANSACT2_SETPATHINFO) {
@@ -5576,6 +5999,12 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(status);
        }
 
+       status = check_name(conn, directory);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+               return ERROR_NT(status);
+       }
+
        /* Any data in this call is an EA list. */
        if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
                return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
@@ -5607,12 +6036,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
 
-       status = check_name(conn, directory);
-       if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
-               return ERROR_NT(status);
-       }
-
        status = create_directory(conn, directory);
 
        if (!NT_STATUS_IS_OK(status)) {
index 3f0c35331b23401f4c507488421080a9146bb278..c7fd3f66564795b05a410563e300cc224e4f9e2d 100644 (file)
@@ -263,6 +263,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        tdb->map_size = st.st_size;
        tdb->device = st.st_dev;
        tdb->inode = st.st_ino;
+       tdb->max_dead_records = 0;
        tdb_mmap(tdb);
        if (locked) {
                if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
@@ -321,6 +322,15 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
        }
 }
 
+/*
+ * Set the maximum number of dead records per hash chain
+ */
+
+void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
+{
+       tdb->max_dead_records = max_dead;
+}
+
 /**
  * Close a database.
  *
index bf4c01d1b3aa03ae23dbe291e179825b9c0dd9f3..bf43701d2edfa9752360eeb6c94068331c7b90d5 100644 (file)
@@ -258,6 +258,66 @@ int tdb_do_delete(struct tdb_context *tdb, tdb_off_t rec_ptr, struct list_struct
        return 0;
 }
 
+static int tdb_count_dead(struct tdb_context *tdb, u32 hash)
+{
+       int res = 0;
+       tdb_off_t rec_ptr;
+       struct list_struct rec;
+       
+       /* read in the hash top */
+       if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+               return 0;
+
+       while (rec_ptr) {
+               if (tdb_rec_read(tdb, rec_ptr, &rec) == -1)
+                       return 0;
+
+               if (rec.magic == TDB_DEAD_MAGIC) {
+                       res += 1;
+               }
+               rec_ptr = rec.next;
+       }
+       return res;
+}
+
+/*
+ * Purge all DEAD records from a hash chain
+ */
+static int tdb_purge_dead(struct tdb_context *tdb, u32 hash)
+{
+       int res = -1;
+       struct list_struct rec;
+       tdb_off_t rec_ptr;
+
+       if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+               return -1;
+       }
+       
+       /* read in the hash top */
+       if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+               goto fail;
+
+       while (rec_ptr) {
+               tdb_off_t next;
+
+               if (tdb_rec_read(tdb, rec_ptr, &rec) == -1) {
+                       goto fail;
+               }
+
+               next = rec.next;
+
+               if (rec.magic == TDB_DEAD_MAGIC
+                   && tdb_do_delete(tdb, rec_ptr, &rec) == -1) {
+                       goto fail;
+               }
+               rec_ptr = next;
+       }
+       res = 0;
+ fail:
+       tdb_unlock(tdb, -1, F_WRLCK);
+       return res;
+}
+
 /* delete an entry in the database given a key */
 static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
 {
@@ -265,9 +325,42 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash)
        struct list_struct rec;
        int ret;
 
-       if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec)))
-               return -1;
-       ret = tdb_do_delete(tdb, rec_ptr, &rec);
+       if (tdb->max_dead_records != 0) {
+
+               /*
+                * Allow for some dead records per hash chain, mainly for
+                * tdb's with a very high create/delete rate like locking.tdb.
+                */
+
+               if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
+                       return -1;
+
+               if (tdb_count_dead(tdb, hash) >= tdb->max_dead_records) {
+                       /*
+                        * Don't let the per-chain freelist grow too large,
+                        * delete all existing dead records
+                        */
+                       tdb_purge_dead(tdb, hash);
+               }
+
+               if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) {
+                       tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
+                       return -1;
+               }
+
+               /*
+                * Just mark the record as dead.
+                */
+               rec.magic = TDB_DEAD_MAGIC;
+               ret = tdb_rec_write(tdb, rec_ptr, &rec);
+       }
+       else {
+               if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK,
+                                                  &rec)))
+                       return -1;
+
+               ret = tdb_do_delete(tdb, rec_ptr, &rec);
+       }
 
        if (ret == 0) {
                tdb_increment_seqnum(tdb);
@@ -284,6 +377,35 @@ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
        return tdb_delete_hash(tdb, key, hash);
 }
 
+/*
+ * See if we have a dead record around with enough space
+ */
+static tdb_off_t tdb_find_dead(struct tdb_context *tdb, u32 hash,
+                              struct list_struct *r, tdb_len_t length)
+{
+       tdb_off_t rec_ptr;
+       
+       /* read in the hash top */
+       if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
+               return 0;
+
+       /* keep looking until we find the right record */
+       while (rec_ptr) {
+               if (tdb_rec_read(tdb, rec_ptr, r) == -1)
+                       return 0;
+
+               if (TDB_DEAD(r) && r->rec_len >= length) {
+                       /*
+                        * First fit for simple coding, TODO: change to best
+                        * fit
+                        */
+                       return rec_ptr;
+               }
+               rec_ptr = r->next;
+       }
+       return 0;
+}
+
 /* store an element in the database, replacing any existing element
    with the same key 
 
@@ -316,8 +438,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
        } else {
                /* first try in-place update, on modify or replace. */
                if (tdb_update_hash(tdb, key, hash, dbuf) == 0) {
-                       ret = 0;
-                       goto fail; /* Well, not really failed */
+                       goto done;
                }
                if (tdb->ecode == TDB_ERR_NOEXIST &&
                    flag == TDB_MODIFY) {
@@ -347,9 +468,56 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
        if (dbuf.dsize)
                memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
 
+       if (tdb->max_dead_records != 0) {
+               /*
+                * Allow for some dead records per hash chain, look if we can
+                * find one that can hold the new record. We need enough space
+                * for key, data and tailer. If we find one, we don't have to
+                * consult the central freelist.
+                */
+               rec_ptr = tdb_find_dead(
+                       tdb, hash, &rec,
+                       key.dsize + dbuf.dsize + sizeof(tdb_off_t));
+
+               if (rec_ptr != 0) {
+                       rec.key_len = key.dsize;
+                       rec.data_len = dbuf.dsize;
+                       rec.full_hash = hash;
+                       rec.magic = TDB_MAGIC;
+                       if (tdb_rec_write(tdb, rec_ptr, &rec) == -1
+                           || tdb->methods->tdb_write(
+                                   tdb, rec_ptr + sizeof(rec),
+                                   p, key.dsize + dbuf.dsize) == -1) {
+                               goto fail;
+                       }
+                       goto done;
+               }
+       }
+
+       /*
+        * We have to allocate some space from the freelist, so this means we
+        * have to lock it. Use the chance to purge all the DEAD records from
+        * the hash chain under the freelist lock.
+        */
+
+       if (tdb_lock(tdb, -1, F_WRLCK) == -1) {
+               goto fail;
+       }
+
+       if ((tdb->max_dead_records != 0)
+           && (tdb_purge_dead(tdb, hash) == -1)) {
+               tdb_unlock(tdb, -1, F_WRLCK);
+               goto fail;
+       }
+
        /* we have to allocate some space */
-       if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec)))
+       rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec);
+
+       tdb_unlock(tdb, -1, F_WRLCK);
+
+       if (rec_ptr == 0) {
                goto fail;
+       }
 
        /* Read hash top into next ptr */
        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec.next) == -1)
@@ -368,6 +536,7 @@ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
                goto fail;
        }
 
+ done:
        ret = 0;
  fail:
        if (ret == 0) {
index 7fc136c6a70980dafb6d59b35adad41c9eed100e..10bc6dacdcfbf4d49a1255b1add5dc728d301afd 100644 (file)
@@ -169,6 +169,7 @@ struct tdb_context {
        const struct tdb_methods *methods;
        struct tdb_transaction *transaction;
        int page_size;
+       int max_dead_records;
 };
 
 
index a0f6f983824c6647fe42e2879b9a459e668a69eb..51bf709f44212f11b16543f4d8bf3bf942b18571 100644 (file)
@@ -94,6 +94,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
                         int open_flags, mode_t mode,
                         const struct tdb_logging_context *log_ctx,
                         tdb_hash_func hash_fn);
+void tdb_set_max_dead(struct tdb_context *tdb, int max_dead);
 
 int tdb_reopen(struct tdb_context *tdb);
 int tdb_reopen_all(int parent_longlived);
index 6cecd693f835497d5a857af6edd69d1cb753194b..455ca1c82c7bff21b5a64292fa25c5d346f50f4f 100644 (file)
@@ -783,14 +783,14 @@ static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
 
 static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv)
 {
-       struct utimbuf times;
+       struct timespec ts[2];
        if (argc != 4) {
                printf("Usage: utime <path> <access> <modify>\n");
                return NT_STATUS_OK;
        }
-       times.actime = atoi(argv[2]);
-       times.modtime = atoi(argv[3]);
-       if (SMB_VFS_UTIME(vfs->conn, argv[1], &times) != 0) {
+       ts[0] = convert_time_t_to_timespec(atoi(argv[2]));
+       ts[1] = convert_time_t_to_timespec(atoi(argv[3]));
+       if (SMB_VFS_NTIMES(vfs->conn, argv[1], ts) != 0) {
                printf("utime: error=%d (%s)\n", errno, strerror(errno));
                return NT_STATUS_UNSUCCESSFUL;
        }
index 4b894fbfc34bdf346006d9959e876628036676e3..121679ed8cc44b70620fb30651a89d8a6e49ada9 100644 (file)
@@ -229,12 +229,15 @@ again:
                goto again;
        }
        if (status == NSS_STATUS_NOTFOUND) {
+               SAFE_FREE(buf);
                return NULL;
        }
        if (status != NSS_STATUS_SUCCESS) {
                report_nss_error("getgrnam", status);
+               SAFE_FREE(buf);
                return NULL;
        }
+       SAFE_FREE(buf);
        return &grp;
 }
 
@@ -266,12 +269,15 @@ again:
                goto again;
        }
        if (status == NSS_STATUS_NOTFOUND) {
+               SAFE_FREE(buf);
                return NULL;
        }
        if (status != NSS_STATUS_SUCCESS) {
                report_nss_error("getgrgid", status);
+               SAFE_FREE(buf);
                return NULL;
        }
+       SAFE_FREE(buf);
        return &grp;
 }
 
index 794449461228e8980f67a6bc4558b2f35a0595ca..5ab28438f213ce82d251030bd27b03f06c96ff90 100644 (file)
@@ -4479,6 +4479,7 @@ static BOOL run_eatest(int dummy)
        printf("starting eatest\n");
        
        if (!torture_open_connection(&cli, 0)) {
+               talloc_destroy(mem_ctx);
                return False;
        }
        
@@ -4490,6 +4491,7 @@ static BOOL run_eatest(int dummy)
 
        if (fnum == -1) {
                printf("open failed - %s\n", cli_errstr(cli));
+               talloc_destroy(mem_ctx);
                return False;
        }
 
@@ -4500,6 +4502,7 @@ static BOOL run_eatest(int dummy)
                memset(ea_val, (char)i+1, i+1);
                if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) {
                        printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+                       talloc_destroy(mem_ctx);
                        return False;
                }
        }
@@ -4512,6 +4515,7 @@ static BOOL run_eatest(int dummy)
                memset(ea_val, (char)i+1, i+1);
                if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) {
                        printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+                       talloc_destroy(mem_ctx);
                        return False;
                }
        }
@@ -4545,6 +4549,7 @@ static BOOL run_eatest(int dummy)
                slprintf(ea_name, sizeof(ea_name), "ea_%d", i);
                if (!cli_set_ea_path(cli, fname, ea_name, "", 0)) {
                        printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+                       talloc_destroy(mem_ctx);
                        return False;
                }
        }
index 02a0b68932c31637508630804386c7d31aad04b8..52af6e68d77708007ce6aef9a2ad7d78e022b515 100644 (file)
@@ -1117,6 +1117,72 @@ done:
        return status;
 }
 
+/*******************************************************************
+ Set a machines dNSHostName and servicePrincipalName attributes
+ ********************************************************************/
+
+static ADS_STATUS net_set_os_attributes(TALLOC_CTX *ctx, ADS_STRUCT *ads_s, 
+                                       const char *os_name, const char *os_version )
+{
+       ADS_STATUS status = ADS_ERROR(LDAP_SERVER_DOWN);
+       char *new_dn;
+       ADS_MODLIST mods;
+       LDAPMessage *res = NULL;
+       char *dn_string = NULL;
+       const char *machine_name = global_myname();
+       int count;
+       char *os_sp = NULL;
+       
+       if ( !os_name || !os_version ) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       
+       /* Find our DN */
+       
+       status = ads_find_machine_acct(ads_s, &res, machine_name);
+       if (!ADS_ERR_OK(status)) 
+               return status;
+               
+       if ( (count = ads_count_replies(ads_s, res)) != 1 ) {
+               DEBUG(1,("net_set_machine_spn: %d entries returned!\n", count));
+               return ADS_ERROR(LDAP_NO_MEMORY);       
+       }
+       
+       if ( (dn_string = ads_get_dn(ads_s, res)) == NULL ) {
+               DEBUG(1, ("ads_add_machine_acct: ads_get_dn returned NULL (malloc failure?)\n"));
+               goto done;
+       }
+       
+       new_dn = talloc_strdup(ctx, dn_string);
+       ads_memfree(ads_s, dn_string);
+       if (!new_dn) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       
+       /* now do the mods */
+       
+       if (!(mods = ads_init_mods(ctx))) {
+               goto done;
+       }
+
+       os_sp = talloc_asprintf( ctx, "Samba %s", SAMBA_VERSION_STRING );
+       
+       /* fields of primary importance */
+       
+       ads_mod_str(ctx, &mods, "operatingSystem", os_name);
+       ads_mod_str(ctx, &mods, "operatingSystemVersion", os_version);
+       if ( os_sp )
+               ads_mod_str(ctx, &mods, "operatingSystemServicePack", os_sp);
+
+       status = ads_gen_mod(ads_s, new_dn, mods);
+
+done:
+       ads_msgfree(ads_s, res);
+       TALLOC_FREE( os_sp );   
+       
+       return status;
+}
+
 /*******************************************************************
   join a domain using ADS (LDAP mods)
  ********************************************************************/
@@ -1386,6 +1452,8 @@ int net_ads_join(int argc, const char **argv)
        int i;
        fstring dc_name;
        struct in_addr dcip;
+       const char *os_name = NULL;
+       const char *os_version = NULL;
        
        nt_status = check_ads_config();
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1427,7 +1495,21 @@ int net_ads_join(int argc, const char **argv)
                }
                else if ( !StrnCaseCmp(argv[i], "createcomputer", strlen("createcomputer")) ) {
                        if ( (create_in_ou = get_string_param(argv[i])) == NULL ) {
-                               d_fprintf(stderr, "Please supply a valid OU path\n");
+                               d_fprintf(stderr, "Please supply a valid OU path.\n");
+                               nt_status = NT_STATUS_INVALID_PARAMETER;
+                               goto fail;
+                       }               
+               }
+               else if ( !StrnCaseCmp(argv[i], "osName", strlen("osName")) ) {
+                       if ( (os_name = get_string_param(argv[i])) == NULL ) {
+                               d_fprintf(stderr, "Please supply a operating system name.\n");
+                               nt_status = NT_STATUS_INVALID_PARAMETER;
+                               goto fail;
+                       }               
+               }
+               else if ( !StrnCaseCmp(argv[i], "osVer", strlen("osVer")) ) {
+                       if ( (os_version = get_string_param(argv[i])) == NULL ) {
+                               d_fprintf(stderr, "Please supply a valid operating system version.\n");
                                nt_status = NT_STATUS_INVALID_PARAMETER;
                                goto fail;
                        }               
@@ -1546,7 +1628,18 @@ int net_ads_join(int argc, const char **argv)
                }
        }
 
+       /* Try to set the operatingSystem attributes if asked */
+
+       if ( os_name && os_version ) {
+               status = net_set_os_attributes( ctx, ads, os_name, os_version );
+               if ( !ADS_ERR_OK(status) )  {
+                       d_fprintf(stderr, "Failed to set operatingSystem attributes.  "
+                                 "Are you a Domain Admin?\n");
+               }
+       }
+
        /* Now build the keytab, using the same ADS connection */
+
        if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
                DEBUG(1,("Error creating host keytab!\n"));
        }
@@ -1819,13 +1912,16 @@ static int net_ads_printer_publish(int argc, const char **argv)
        TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
        ADS_MODLIST mods = ads_init_mods(mem_ctx);
        char *prt_dn, *srv_dn, **srv_cn;
+       char *srv_cn_escaped = NULL, *printername_escaped = NULL;
        LDAPMessage *res = NULL;
 
        if (!ADS_ERR_OK(ads_startup(True, &ads))) {
+               talloc_destroy(mem_ctx);
                return -1;
        }
 
        if (argc < 1) {
+               talloc_destroy(mem_ctx);
                return net_ads_printer_usage(argc, argv);
        }
        
@@ -1853,6 +1949,7 @@ static int net_ads_printer_publish(int argc, const char **argv)
                d_fprintf(stderr, "Unable to open a connnection to %s to obtain data "
                         "for %s\n", servername, printername);
                ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
                return -1;
        }
 
@@ -1864,37 +1961,60 @@ static int net_ads_printer_publish(int argc, const char **argv)
                d_fprintf(stderr, "Could not find machine account for server %s\n", 
                         servername);
                ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
                return -1;
        }
 
        srv_dn = ldap_get_dn((LDAP *)ads->ld, (LDAPMessage *)res);
        srv_cn = ldap_explode_dn(srv_dn, 1);
 
-       asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
+       srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn[0]);
+       printername_escaped = escape_rdn_val_string_alloc(printername);
+       if (!srv_cn_escaped || !printername_escaped) {
+               SAFE_FREE(srv_cn_escaped);
+               SAFE_FREE(printername_escaped);
+               d_fprintf(stderr, "Internal error, out of memory!");
+               ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
+               return -1;
+       }
+
+       asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, printername_escaped, srv_dn);
+
+       SAFE_FREE(srv_cn_escaped);
+       SAFE_FREE(printername_escaped);
 
        pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
        if (!pipe_hnd) {
                d_fprintf(stderr, "Unable to open a connnection to the spoolss pipe on %s\n",
                         servername);
+               SAFE_FREE(prt_dn);
                ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
                return -1;
        }
 
        if (!W_ERROR_IS_OK(get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
                                                              printername))) {
+               SAFE_FREE(prt_dn);
                ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
                return -1;
        }
 
         rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
         if (!ADS_ERR_OK(rc)) {
                 d_fprintf(stderr, "ads_publish_printer: %s\n", ads_errstr(rc));
+               SAFE_FREE(prt_dn);
                ads_destroy(&ads);
+               talloc_destroy(mem_ctx);
                 return -1;
         }
  
         d_printf("published printer\n");
+       SAFE_FREE(prt_dn);
        ads_destroy(&ads);
+       talloc_destroy(mem_ctx);
  
        return 0;
 }
@@ -2158,6 +2278,7 @@ static int net_ads_dn_usage(int argc, const char **argv)
                "The DN standard LDAP DN, and the attributes are a list of LDAP fields \n"\
                "to show in the results\n\n"\
                "Example: net ads dn 'CN=administrator,CN=Users,DC=my,DC=domain' sAMAccountName\n\n"
+               "Note: the DN must be provided properly escaped. See RFC 4514 for details\n\n"
                );
        net_common_flags_usage(argc, argv);
        return -1;
index 1865aee3d41be1f18e16f9b380025bb4388fd8f3..83cc2fe8fcf2d797f4d034a3701a9adb33b60340 100644 (file)
@@ -351,6 +351,7 @@ static int net_ads_gpo_add_link(int argc, const char **argv)
 
        if (argc < 2) {
                printf("usage: net ads gpo addlink <linkdn> <gpodn> [options]\n");
+               printf("note: DNs must be provided properly escaped.\n      See RFC 4514 for details\n");
                return -1;
        }
 
index 34e87ddbd21d4cd6f27377c68ac130e9e5e13fbc..56aee3be91a04ed6d6d55299124bad69b592e962 100644 (file)
@@ -3585,15 +3585,23 @@ static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state
  **/
 BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
 {
+       struct cli_state *targetcli;
+       pstring targetpath;
 
        DEBUG(3,("calling cli_list with mask: %s\n", mask));
 
-       if (cli_list(cp_clistate->cli_share_src, mask, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
-               d_fprintf(stderr, "listing %s failed with error: %s\n", 
+       if ( !cli_resolve_path( "", cp_clistate->cli_share_src, mask, &targetcli, targetpath ) ) {
+               d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
                        mask, cli_errstr(cp_clistate->cli_share_src));
                return False;
        }
 
+       if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
+               d_fprintf(stderr, "listing %s failed with error: %s\n", 
+                       mask, cli_errstr(targetcli));
+               return False;
+       }
+
        return True;
 }
 
@@ -4934,12 +4942,12 @@ static int rpc_file_close(int argc, const char **argv)
  * @param str3   strings for FILE_INFO_3
  **/
 
-static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
+static void display_file_info_3( FILE_INFO_3 *info3 )
 {
        fstring user = "", path = "";
 
-       rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
-       rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
+       rpcstr_pull_unistr2_fstring(user, info3->user);
+       rpcstr_pull_unistr2_fstring(path, info3->path);
 
        d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
                 info3->id, user, info3->perms, info3->num_locks, path);
@@ -4994,8 +5002,7 @@ static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
                 "\nFileId  Opened by            Perms  Locks  Path"\
                 "\n------  ---------            -----  -----  ---- \n");
        for (i = 0; i < ctr.num_entries; i++)
-               display_file_info_3(&ctr.file.info3[i].info_3, 
-                                   &ctr.file.info3[i].info_3_str);
+               display_file_info_3(&ctr.file.info3[i]);
  done:
        return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
@@ -6072,6 +6079,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        if (!pipe_hnd) {
                DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
                        nt_errstr(nt_status) ));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        };
@@ -6081,6 +6089,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        };
@@ -6093,6 +6102,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        }
@@ -6112,6 +6122,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
                if (NT_STATUS_IS_ERR(nt_status)) {
                        DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
                                nt_errstr(nt_status)));
+                       cli_shutdown(cli);
                        talloc_destroy(mem_ctx);
                        return -1;
                };
@@ -6133,6 +6144,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        };
@@ -6151,6 +6163,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
        if (!pipe_hnd) {
                DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        };
@@ -6161,6 +6174,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        };
@@ -6173,6 +6187,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't open domain object. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                talloc_destroy(mem_ctx);
                return -1;
        };
@@ -6191,6 +6206,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
                if (NT_STATUS_IS_ERR(nt_status)) {
                        DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
                                nt_errstr(nt_status)));
+                       cli_shutdown(cli);
                        talloc_destroy(mem_ctx);
                        return -1;
                };
index 8800cb36060a52f537996d21fbe201a5d5b40d51..bf397803bc544a6432ae4a469af5e8db892a8e46 100644 (file)
@@ -1043,6 +1043,7 @@ static int net_sam_provision(int argc, const char **argv)
                        d_fprintf(stderr, "Failed to add Domain Users group to ldap directory\n");
                }
        } else {
+               domusers_gid = gmap.gid;
                d_printf("found!\n");
        }       
 
@@ -1096,6 +1097,7 @@ domu_done:
                        d_fprintf(stderr, "Failed to add Domain Admins group to ldap directory\n");
                }
        } else {
+               domadmins_gid = gmap.gid;
                d_printf("found!\n");
        }
 
@@ -1124,7 +1126,7 @@ doma_done:
                d_printf("Adding the Administrator user.\n");
 
                if (domadmins_gid == -1) {
-                       d_fprintf(stderr, "Can't create Administrtor user, Domain Admins group not available!\n");
+                       d_fprintf(stderr, "Can't create Administrator user, Domain Admins group not available!\n");
                        goto done;
                }
                if (!winbind_allocate_uid(&uid)) {
@@ -1238,8 +1240,12 @@ doma_done:
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "displayName", pwd->pw_name);
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "uidNumber", uidstr);
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "gidNumber", gidstr);
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+               if ((pwd->pw_dir != NULL) && (pwd->pw_dir[0] != '\0')) {
+                       smbldap_set_mod(&mods, LDAP_MOD_ADD, "homeDirectory", pwd->pw_dir);
+               }
+               if ((pwd->pw_shell != NULL) && (pwd->pw_shell[0] != '\0')) {
+                       smbldap_set_mod(&mods, LDAP_MOD_ADD, "loginShell", pwd->pw_shell);
+               }
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaSID", sid_string_static(&sid));
                smbldap_set_mod(&mods, LDAP_MOD_ADD, "sambaAcctFlags",
                                pdb_encode_acct_ctrl(ACB_NORMAL|ACB_DISABLED,
@@ -1261,7 +1267,7 @@ doma_done:
        pwd = getpwnam_alloc(NULL, lp_guestaccount());
        if (!pwd) {
                d_fprintf(stderr, "Failed to find just created Guest account!\n"
-                                 "   Is nssswitch properly configured?!\n");
+                                 "   Is nss properly configured?!\n");
                goto failed;
        }
 
index c68c9f6e2fb365a0790b779c929d69ec2b2ae573..bfc30eac78a4dd96b07db3bdd66d40d99222eb14 100644 (file)
@@ -104,7 +104,7 @@ static int show_share(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
        d_printf("%-10.10s   %s   %-12s  %s",
               crec.name,procid_str_static(&crec.pid),
               crec.machine,
-              time_to_asc(&crec.start));
+              time_to_asc(crec.start));
 
        return 0;
 }
@@ -173,7 +173,7 @@ static int show_share_parseable(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
                 guest ? "" : gidtoname(ids->entries[i].gid),
                 crec.machine, 
                 guest ? "" : ids->entries[i].hostname,
-                time_to_asc(&crec.start));
+                time_to_asc(crec.start));
 
        return 0;
 }
index 1e7b361e860ca45faadb8171ecebf31e691b9139..1f0a915574df018e49314390601285016721f192 100644 (file)
@@ -2303,7 +2303,8 @@ enum {
                }
        }
 
-       if (opt_domain == NULL || !*opt_domain) {
+       /* Note: if opt_domain is "" then send no domain */
+       if (opt_domain == NULL) {
                opt_domain = get_winbind_domain();
        }
 
index d79ab187a3b6aff677704de616446857559251eb..d1a87260fa90003cd9228073c76eab0eec7e78e3 100644 (file)
@@ -573,6 +573,7 @@ static int new_user (struct pdb_methods *in, const char *username,
                        
                        if (sscanf(user_sid, "%d", &u_rid) != 1) {
                                fprintf(stderr, "Error passed string is not a complete user SID or RID!\n");
+                               TALLOC_FREE(sam_pwent);
                                return -1;
                        }
                        sid_copy(&u_sid, get_global_sam_sid());
index ec1e101e061764272a0ae79630c15ef963d97b8e..060079a57351e65d906e196d8a47508bc046005f 100644 (file)
@@ -1145,22 +1145,12 @@ int main(int argc, const char **argv)
        poptContext pc;
        int opt;
 
-       static struct poptOption wbinfo_options[] = {
+       static struct poptOption long_options[] = {
+               POPT_AUTOHELP
                { "timeout", 't', POPT_ARG_INT, &timeout, 't', 
                  "Set timeout value in seconds", "TIMEOUT" },
 
-               { "configfile", 's', POPT_ARG_STRING, NULL, 's', 
-                 "Use alternative configuration file", "CONFIGFILE" },
-
-               POPT_TABLEEND
-       };
-
-       struct poptOption options[] = {
-               { NULL, 0, POPT_ARG_INCLUDE_TABLE, wbinfo_options, 0, 
-                 "Options" },
-
-               POPT_AUTOHELP
-               POPT_COMMON_VERSION
+               POPT_COMMON_SAMBA
                POPT_TABLEEND
        };
 
@@ -1171,7 +1161,7 @@ int main(int argc, const char **argv)
        /* Parse command line arguments using popt */
 
        pc = poptGetContext(
-               "smbcontrol", argc, (const char **)argv, options, 0);
+               "smbcontrol", argc, (const char **)argv, long_options, 0);
 
        poptSetOtherOptionHelp(pc, "[OPTION...] <destination> <message-type> "
                               "<parameters>");
@@ -1182,11 +1172,6 @@ int main(int argc, const char **argv)
        while ((opt = poptGetNextOpt(pc)) != -1) {
                switch(opt) {
                case 't':       /* --timeout */
-                       argc -= 2;
-                       break;
-               case 's':       /* --configfile */
-                       pstrcpy(dyn_CONFIGFILE, poptGetOptArg(pc));
-                       argc -= 2;
                        break;
                default:
                        fprintf(stderr, "Invalid option\n");
@@ -1200,7 +1185,10 @@ int main(int argc, const char **argv)
            correct value in the above switch statement. */
 
        argv = (const char **)poptGetArgs(pc);
-       argc--;                 /* Don't forget about argv[0] */
+       argc = 0;
+       while (argv[argc] != NULL) {
+               argc++;
+       }
 
        if (argc == 1)
                usage(&pc);
index 4f66501511b6ab8954ac875bfe06bb2aa7ce7cfb..deba6a9523bad0aa61cefea67fbeb475baa04ce4 100644 (file)
@@ -162,7 +162,7 @@ static void print_share_mode(const struct share_mode_entry *e,
                        d_printf("NONE            ");
                }
 
-               d_printf(" %s   %s   %s",sharepath, fname, time_to_asc((time_t *)&e->time.tv_sec));
+               d_printf(" %s   %s   %s",sharepath, fname, time_to_asc((time_t)e->time.tv_sec));
        }
 }
 
@@ -207,7 +207,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
        d_printf("%-10s   %s   %-12s  %s",
               crec.name,procid_str_static(&crec.pid),
               crec.machine,
-              time_to_asc(&crec.start));
+              time_to_asc(crec.start));
 
        return 0;
 }
index 9224fc176cb1362242168feb3697f00c85c6fd88..b4c4940f3fd5b817d5e7c328b0fd44ab12f543e6 100644 (file)
@@ -113,8 +113,8 @@ BOOL status_profile_dump(BOOL verbose)
        d_printf("chdir_time:                     %u\n", profile_p->syscall_chdir_time);
        d_printf("getwd_count:                    %u\n", profile_p->syscall_getwd_count);
        d_printf("getwd_time:                     %u\n", profile_p->syscall_getwd_time);
-       d_printf("utime_count:                    %u\n", profile_p->syscall_utime_count);
-       d_printf("utime_time:                     %u\n", profile_p->syscall_utime_time);
+       d_printf("ntimes_count:                   %u\n", profile_p->syscall_ntimes_count);
+       d_printf("ntimes_time:                    %u\n", profile_p->syscall_ntimes_time);
        d_printf("ftruncate_count:                %u\n", profile_p->syscall_ftruncate_count);
        d_printf("ftruncate_time:                 %u\n", profile_p->syscall_ftruncate_time);
        d_printf("fcntl_lock_count:               %u\n", profile_p->syscall_fcntl_lock_count);
index 459b679d8172b249f24429388db2447972713e23..a88e5debd0e3a9c636b4d87764d5ba409401dd15 100644 (file)
@@ -101,7 +101,7 @@ static char *mapPid2Machine (struct process_id pid)
 static char *tstring(time_t t)
 {
        static pstring buf;
-       pstrcpy(buf, time_to_asc(&t));
+       pstrcpy(buf, time_to_asc(t));
        all_string_sub(buf," ","&nbsp;",sizeof(buf));
        return buf;
 }