summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-02-25 14:08:30 +0000
committerGerald Carter <jerry@samba.org>2005-02-25 14:08:30 +0000
commit70cd25be8b07743816b9376f9d219453f0f906fc (patch)
tree073f3d33dac8c96b0d4c7b809b3dc86b91023214
parent1d58e0d7811acc335f09128ae757f5f76a51644d (diff)
downloadsamba-70cd25be8b07743816b9376f9d219453f0f906fc.tar.gz
r5555: current with 3.0 tree as of r5548; getting ready for 3.0.12pre1
-rw-r--r--examples/auth/Makefile8
-rw-r--r--examples/pdb/Makefile8
-rw-r--r--packaging/Debian/debian-stable/changelog20
-rw-r--r--packaging/Debian/debian-stable/control13
-rw-r--r--packaging/Debian/debian-stable/mount.cifs.files2
-rw-r--r--packaging/Debian/debian-stable/patches/fhs.patch16
-rwxr-xr-xpackaging/Debian/debian-stable/rules5
-rw-r--r--packaging/Debian/debian-stable/samba.files3
-rw-r--r--packaging/Fedora/samba.spec.tmpl9
-rw-r--r--packaging/RedHat/samba.spec.tmpl4
-rw-r--r--packaging/SuSE/README2
-rw-r--r--source/Makefile.in2
-rw-r--r--source/VERSION4
-rw-r--r--source/auth/auth_sam.c14
-rw-r--r--source/auth/auth_util.c51
-rwxr-xr-xsource/autogen.sh6
-rw-r--r--source/client/client.c540
-rw-r--r--source/client/clitar.c30
-rwxr-xr-xsource/client/mount.cifs.c6
-rw-r--r--source/client/smbmnt.c3
-rw-r--r--source/client/smbspool.c6
-rw-r--r--source/groupdb/mapping.c10
-rw-r--r--source/include/adt_tree.h29
-rw-r--r--source/include/client.h1
-rw-r--r--source/include/includes.h1
-rw-r--r--source/include/local.h3
-rw-r--r--source/include/msdfs.h6
-rw-r--r--source/include/passdb.h14
-rw-r--r--source/include/rpc_lsa.h4
-rw-r--r--source/include/rpc_samr.h4
-rw-r--r--source/include/smb.h4
-rw-r--r--source/include/smb_macros.h2
-rw-r--r--source/include/smbldap.h4
-rw-r--r--source/lib/account_pol.c4
-rw-r--r--source/lib/adt_tree.c79
-rw-r--r--source/lib/afs.c4
-rw-r--r--source/lib/interface.c7
-rw-r--r--source/lib/privileges.c14
-rw-r--r--source/lib/smbldap.c21
-rw-r--r--source/lib/time.c544
-rw-r--r--source/lib/util.c9
-rw-r--r--source/lib/util_seaccess.c39
-rw-r--r--source/lib/util_str.c4
-rw-r--r--source/lib/util_unistr.c24
-rw-r--r--source/libads/ldap.c2
-rw-r--r--source/libsmb/cliconnect.c12
-rw-r--r--source/libsmb/clidfs.c600
-rw-r--r--source/libsmb/clientgen.c4
-rw-r--r--source/libsmb/clilist.c10
-rw-r--r--source/libsmb/cliprint.c105
-rw-r--r--source/libsmb/clirap.c74
-rw-r--r--source/libsmb/clisecdesc.c9
-rw-r--r--source/libsmb/ntlmssp.c13
-rw-r--r--source/libsmb/ntlmssp_sign.c6
-rw-r--r--source/nmbd/nmbd_packets.c13
-rw-r--r--source/nsswitch/winbind_nss_linux.c8
-rw-r--r--source/nsswitch/winbindd_cm.c150
-rw-r--r--source/nsswitch/winbindd_pam.c12
-rw-r--r--source/nsswitch/winbindd_rpc.c4
-rw-r--r--source/nsswitch/winbindd_util.c5
-rw-r--r--source/param/loadparm.c7
-rw-r--r--source/param/params.c806
-rw-r--r--source/passdb/passdb.c88
-rw-r--r--source/passdb/pdb_interface.c148
-rw-r--r--source/passdb/pdb_ldap.c265
-rw-r--r--source/printing/print_cups.c19
-rw-r--r--source/python/py_smb.c104
-rw-r--r--source/python/py_spoolss.h3
-rw-r--r--source/python/py_spoolss_drivers.c2
-rw-r--r--source/python/py_spoolss_drivers_conv.c53
-rw-r--r--source/registry/reg_cachehook.c9
-rw-r--r--source/registry/reg_objects.c2
-rw-r--r--source/rpc_client/cli_dfs.c10
-rw-r--r--source/rpc_client/cli_samr.c11
-rw-r--r--source/rpc_client/cli_wkssvc.c2
-rw-r--r--source/rpc_parse/parse_net.c14
-rw-r--r--source/rpc_parse/parse_samr.c12
-rw-r--r--source/rpc_server/srv_lsa_hnd.c4
-rw-r--r--source/rpc_server/srv_lsa_nt.c21
-rw-r--r--source/rpc_server/srv_samr.c1
-rw-r--r--source/rpc_server/srv_samr_nt.c376
-rw-r--r--source/rpcclient/cmd_samr.c44
-rw-r--r--source/sam/idmap_ldap.c16
-rw-r--r--source/sam/idmap_rid.c3
-rw-r--r--source/smbd/dfree.c10
-rw-r--r--source/smbd/dir.c652
-rw-r--r--source/smbd/filename.c12
-rw-r--r--source/smbd/notify_hash.c18
-rw-r--r--source/smbd/nttrans.c53
-rw-r--r--source/smbd/posix_acls.c157
-rw-r--r--source/smbd/reply.c158
-rw-r--r--source/smbd/service.c27
-rw-r--r--source/smbd/sesssetup.c8
-rw-r--r--source/smbd/trans2.c171
-rw-r--r--source/tdb/tdb.c7
-rw-r--r--source/torture/torture.c47
-rw-r--r--source/utils/net.c46
-rw-r--r--source/utils/net_groupmap.c18
-rw-r--r--source/utils/net_help.c2
-rw-r--r--source/utils/net_rpc.c34
-rw-r--r--source/utils/net_rpc_printer.c23
-rw-r--r--source/utils/net_rpc_samsync.c2
-rw-r--r--source/utils/pdbedit.c4
-rw-r--r--source/utils/profiles.c9
-rw-r--r--source/utils/status.c2
105 files changed, 3995 insertions, 2095 deletions
diff --git a/examples/auth/Makefile b/examples/auth/Makefile
index 21d18de0758..d6dbc28f40e 100644
--- a/examples/auth/Makefile
+++ b/examples/auth/Makefile
@@ -9,7 +9,7 @@ SAMBA_INCL = ../../source/include
UBIQX_SRC = ../../source/ubiqx
SMBWR_SRC = ../../source/smbwrapper
CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g
-AUTH_OBJS = auth_skel.so
+AUTH_OBJS = auth_skel.la
# Default target
@@ -17,8 +17,8 @@ default: $(AUTH_OBJS)
# Pattern rules
-%.so: %.lo
- $(LIBTOOL) --mode=link $(CC) -shared -o $@ $< $(LDFLAGS)
+%.la: %.lo
+ $(LIBTOOL) --mode=link $(CC) -module -o $@ $< $(LDFLAGS)
%.lo: %.c
$(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
@@ -28,4 +28,4 @@ default: $(AUTH_OBJS)
clean:
rm -rf .libs
rm -f core *~ *% *.bak \
- $(AUTH_OBJS) $(AUTH_OBJS:.so=.o) $(AUTH_OBJS:.so=.lo)
+ $(AUTH_OBJS) $(AUTH_OBJS:.la=.o) $(AUTH_OBJS:.la=.lo)
diff --git a/examples/pdb/Makefile b/examples/pdb/Makefile
index 10980ae62e2..09d901d374b 100644
--- a/examples/pdb/Makefile
+++ b/examples/pdb/Makefile
@@ -9,7 +9,7 @@ SAMBA_INCL = ../../source/include
UBIQX_SRC = ../../source/ubiqx
SMBWR_SRC = ../../source/smbwrapper
CFLAGS = -I$(SAMBA_SRC) -I$(SAMBA_INCL) -I$(UBIQX_SRC) -I$(SMBWR_SRC) -Wall -g -I/usr/include/heimdal -fPIC
-PDB_OBJS = test.so
+PDB_OBJS = test.la
# Default target
@@ -17,8 +17,8 @@ default: $(PDB_OBJS)
# Pattern rules
-%.so: %.lo
- $(LIBTOOL) --mode=link $(CC) -shared -o $@ $< $(LDFLAGS)
+%.la: %.lo
+ $(LIBTOOL) --mode=link $(CC) -module -o $@ $< $(LDFLAGS) -rpath /usr/lib/samba/pdb/
%.lo: %.c
$(LIBTOOL) --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) -c $<
@@ -28,4 +28,4 @@ default: $(PDB_OBJS)
clean:
rm -rf .libs
rm -f core *~ *% *.bak \
- $(PDB_OBJS) $(PDB_OBJS:.so=.o) $(PDB_OBJS:.so=.lo)
+ $(PDB_OBJS) $(PDB_OBJS:.la=.o) $(PDB_OBJS:.la=.lo)
diff --git a/packaging/Debian/debian-stable/changelog b/packaging/Debian/debian-stable/changelog
index 9e37af4bfbf..96f60fa1751 100644
--- a/packaging/Debian/debian-stable/changelog
+++ b/packaging/Debian/debian-stable/changelog
@@ -1,3 +1,23 @@
+samba (3.0.11-1) stable; urgency=low
+
+ * samba 3.0.11 release
+
+ -- Simo Sorce <idra@samba.org> Mon, 07 February 2005 09:22:00 +0100
+
+samba (3.0.10-1) stable; urgency=low
+
+ * samba 3.0.10 release
+
+ -- Simo Sorce <idra@samba.org> Mon, 26 December 2004 13:50:00 +0100
+
+samba (3.0.9-1) stable; urgency=low
+
+ * samba 3.0.9 release
+ * added profiles utility to main .deb
+ * added mount.cifs .deb
+
+ -- Simo Sorce <idra@samba.org> Mon, 26 November 2004 12:13:00 +0100
+
samba (3.0.8-1) stable; urgency=low
* samba 3.0.8 release
diff --git a/packaging/Debian/debian-stable/control b/packaging/Debian/debian-stable/control
index 498a1d30da9..4ef4445695a 100644
--- a/packaging/Debian/debian-stable/control
+++ b/packaging/Debian/debian-stable/control
@@ -28,6 +28,7 @@ Description: a LanManager-like file and printer server for Unix
swat - Samba Web Administration Tool
samba-doc - Samba documentation.
smbfs - Mount and umount commands for the smbfs (kernels 2.2.x and above).
+ mount.cifs - Mount and unmount commnads for cifsvfs (kernels 2.6.x and above).
libpam-smbpass - pluggable authentication module for SMB password database
libsmbclient - Shared library that allows applications to talk to SMB servers
libsmbclient-dev - libsmbclient shared libraries
@@ -121,6 +122,18 @@ Description: mount and umount commands for the smbfs (for kernels >= than 2.2.x)
version. If you are using a 2.0.x kernel please upgrade or use the
latest Samba 2.0.7 Debian package.
+Package: mount.cifs
+Section: otherosfs
+Priority: optional
+Architecture: any
+Depends: netbase (>= 2.02), samba-common (= ${Source-Version}), ${shlibs:Depends}
+Description: mount and umount commands for the cifsvfs (for kernels >= than 2.6.x)
+ CIFS-VFS is a filesystem which understands the CIFS/SMB protocol.
+ This is the protocol Windows for Workgroups, Windows NT or
+ LAN Manager use to talk to each other. It was inspired by
+ samba, the program by Andrew Tridgell that turns any unix
+ site into a file server for DOS or Windows clients.
+
Package: libpam-smbpass
Section: admin
Priority: extra
diff --git a/packaging/Debian/debian-stable/mount.cifs.files b/packaging/Debian/debian-stable/mount.cifs.files
new file mode 100644
index 00000000000..d5bb66ede4b
--- /dev/null
+++ b/packaging/Debian/debian-stable/mount.cifs.files
@@ -0,0 +1,2 @@
+sbin/mount.cifs
+usr/share/man/man8/mount.cifs.8
diff --git a/packaging/Debian/debian-stable/patches/fhs.patch b/packaging/Debian/debian-stable/patches/fhs.patch
index df6ddec2dfc..760306a3c3c 100644
--- a/packaging/Debian/debian-stable/patches/fhs.patch
+++ b/packaging/Debian/debian-stable/patches/fhs.patch
@@ -380,18 +380,6 @@ diff -uNr samba-3.0.0beta2.orig/source/passdb/pdb_tdb.c samba-3.0.0beta2/source/
tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
}
-diff -uNr samba-3.0.0beta2.orig/source/passdb/privileges.c samba-3.0.0beta2/source/passdb/privileges.c
---- samba-3.0.0beta2.orig/source/passdb/privileges.c 2003-06-07 12:57:35.000000000 -0500
-+++ samba-3.0.0beta2/source/passdb/privileges.c 2003-07-02 23:19:02.000000000 -0500
-@@ -62,7 +62,7 @@
- /* initialise the privilege database */
- BOOL privilege_init(void)
- {
-- tdb = tdb_open_log(lock_path("privilege.tdb"), 0, TDB_DEFAULT,
-+ tdb = tdb_open_log(state_path("privilege.tdb"), 0, TDB_DEFAULT,
- O_RDWR|O_CREAT, 0600);
- if (!tdb) {
- DEBUG(0,("Failed to open privilege database\n"));
diff -uNr samba-3.0.0beta2.orig/source/passdb/secrets.c samba-3.0.0beta2/source/passdb/secrets.c
--- samba-3.0.0beta2.orig/source/passdb/secrets.c 2003-07-02 23:26:47.000000000 -0500
+++ samba-3.0.0beta2/source/passdb/secrets.c 2003-07-02 23:19:02.000000000 -0500
@@ -512,8 +500,8 @@ diff -uNr samba-3.0.0beta2.orig/source/sam/idmap_tdb.c samba-3.0.0beta2/source/s
BOOL tdb_is_new = False;
/* use the old database if present */
-- tdbfile = strdup(lock_path("winbindd_idmap.tdb"));
-+ tdbfile = strdup(state_path("winbindd_idmap.tdb"));
+- tdbfile = SMB_STRDUP(lock_path("winbindd_idmap.tdb"));
++ tdbfile = SMB_STRDUP(state_path("winbindd_idmap.tdb"));
if (!tdbfile) {
DEBUG(0, ("idmap_init: out of memory!\n"));
return NT_STATUS_NO_MEMORY;
diff --git a/packaging/Debian/debian-stable/rules b/packaging/Debian/debian-stable/rules
index 91e77e6d0fd..f17ea75c015 100755
--- a/packaging/Debian/debian-stable/rules
+++ b/packaging/Debian/debian-stable/rules
@@ -97,6 +97,7 @@ build-stamp:
$(MAKE) -C source headers
$(MAKE) -C source all nsswitch/libnss_wins.so python_ext
+ $(MAKE) -C source client/mount.cifs
touch build-stamp
@@ -168,6 +169,10 @@ install: build
ln -s smbmount.8 $(DESTDIR)/usr/share/man/man8/mount.smb.8
ln -s smbmount.8 $(DESTDIR)/usr/share/man/man8/mount.smbfs.8
+ # Install mount.cifs and its man page
+ install -m 0755 source/client/mount.cifs $(DESTDIR)/sbin/
+ install -m 0644 docs/manpages/mount.cifs.8 $(DESTDIR)/usr/share/man/man8/
+
# For CUPS to support printing to samba printers, it's necessary
# to make the following symlink (according to
# Erich Schubert <debian@vitavonni.de> in #109509):
diff --git a/packaging/Debian/debian-stable/samba.files b/packaging/Debian/debian-stable/samba.files
index f52e6c5e4f7..4a08fa6af7f 100644
--- a/packaging/Debian/debian-stable/samba.files
+++ b/packaging/Debian/debian-stable/samba.files
@@ -3,6 +3,7 @@ usr/bin/smbstatus
usr/bin/smbcontrol
usr/bin/tdbbackup
usr/bin/pdbedit
+usr/bin/profiles
usr/sbin/smbd
usr/sbin/nmbd
usr/sbin/mksmbpasswd
@@ -10,10 +11,10 @@ usr/lib/samba/vfs
usr/share/man/man1/smbcontrol.1
usr/share/man/man1/smbstatus.1
usr/share/man/man1/testprns.1
+usr/share/man/man1/profiles.1
usr/share/man/man5/smbpasswd.5
usr/share/man/man8/nmbd.8
usr/share/man/man8/pdbedit.8
usr/share/man/man8/smbd.8
usr/share/man/man8/mksmbpasswd.8
usr/share/man/man8/tdbbackup.8
-
diff --git a/packaging/Fedora/samba.spec.tmpl b/packaging/Fedora/samba.spec.tmpl
index f587232a0cd..7fde5c0e9a5 100644
--- a/packaging/Fedora/samba.spec.tmpl
+++ b/packaging/Fedora/samba.spec.tmpl
@@ -32,7 +32,7 @@ Requires: logrotate >= 3.4 initscripts >= 5.54-1
BuildRoot: %{_tmppath}/%{name}-%{version}-root
Prereq: /sbin/chkconfig /bin/mktemp /usr/bin/killall
Prereq: fileutils sed /etc/init.d
-BuildRequires: pam-devel, readline-devel, ncurses-devel, fileutils, libacl-devel, openldap-devel, krb5-devel
+BuildRequires: pam-devel, readline-devel, ncurses-devel, fileutils, libacl-devel, openldap-devel, krb5-devel, cups-devel
# Working around perl dependency problem from docs
@@ -120,10 +120,12 @@ CFLAGS="$RPM_OPT_FLAGS" ./configure \
--with-sambabook=%{_datadir}/swat/using_samba \
--with-swatdir=%{_datadir}/swat \
--with-libsmbclient \
- --with-acl-support
+ --with-acl-support \
+ --with-shared-modules=idmap_rid \
+ --enable-cups=yes
make showlayout
make proto
-make %{?_smp_mflags} all nsswitch/libnss_wins.so debug2html
+make %{?_smp_mflags} all modules nsswitch/libnss_wins.so debug2html
%install
@@ -354,6 +356,7 @@ fi
%{_libdir}/libsmbclient.a
%{_libdir}/libsmbclient.so
%{_libdir}/samba/charset/CP*.so
+%{_libdir}/samba/idmap/idmap*.so
%{_includedir}/libsmbclient.h
%{_bindir}/testparm
%{_bindir}/testprns
diff --git a/packaging/RedHat/samba.spec.tmpl b/packaging/RedHat/samba.spec.tmpl
index aa811dbe761..d5124d05edb 100644
--- a/packaging/RedHat/samba.spec.tmpl
+++ b/packaging/RedHat/samba.spec.tmpl
@@ -96,9 +96,10 @@ CFLAGS="$RPM_OPT_FLAGS $EXTRA" ./configure \
--with-utmp \
--with-sambabook=%{prefix}/share/swat/using_samba \
--with-swatdir=%{prefix}/share/swat \
+ --with-shared-modules=idmap_rid \
--with-libsmbclient
make -j${NUMCPU} proto
-make -j${NUMCPU} all nsswitch/libnss_wins.so
+make -j${NUMCPU} all modules nsswitch/libnss_wins.so
make -j${NUMCPU} debug2html
# Remove some permission bits to avoid to many dependencies
@@ -430,6 +431,7 @@ fi
%attr(755,root,root) /lib/libnss_wins.s*
%attr(755,root,root) %{prefix}/lib/samba/vfs/*.so
%attr(755,root,root) %{prefix}/lib/samba/charset/*.so
+%attr(755,root,root) %{prefix}/lib/samba/idmap/*.so
#%attr(755,root,root) %{prefix}/lib/samba/pdb/*.so
%attr(755,root,root) %{prefix}/lib/samba/*.dat
%attr(755,root,root) %{prefix}/lib/samba/*.msg
diff --git a/packaging/SuSE/README b/packaging/SuSE/README
index ac3ca4b19d9..e2100ef60c8 100644
--- a/packaging/SuSE/README
+++ b/packaging/SuSE/README
@@ -1,4 +1,3 @@
-### SuSE readme begin
Dear SuSE user,
prebuilt Samba RPMs for all SuSE Linux versions are available at:
@@ -16,5 +15,4 @@ product Samba 3.0, then select 'component' Packaging and set 'assign to'
to <lmuelle@suse.de>.
Have a lot of fun...
-### SuSE readme end
diff --git a/source/Makefile.in b/source/Makefile.in
index 466958b5abb..eb39dbf88bf 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -245,7 +245,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
libsmb/clistr.o lib/util_seaccess.o \
- libsmb/cliquota.o libsmb/clifsinfo.o \
+ libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \
libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
libsmb/clioplock.o $(ERRORMAP_OBJ) libsmb/clirap2.o \
$(DOSERR_OBJ) \
diff --git a/source/VERSION b/source/VERSION
index f4c79d16ec7..bd34be8040c 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -19,7 +19,7 @@
########################################################
SAMBA_VERSION_MAJOR=3
SAMBA_VERSION_MINOR=0
-SAMBA_VERSION_RELEASE=11
+SAMBA_VERSION_RELEASE=12
########################################################
# For 'pre' releases the version will be #
@@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=11
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=
+SAMBA_VERSION_PRE_RELEASE=1
########################################################
# For 'rc' releases the version will be #
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index 2633cc92c37..db05ac97f88 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -170,9 +170,13 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
if (*workstation_list) {
BOOL invalid_ws = True;
+ fstring tok;
const char *s = workstation_list;
+
+ const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name.str);
+ if (machine_name == NULL)
+ return NT_STATUS_NO_MEMORY;
- fstring tok;
while (next_token(&s, tok, ",", sizeof(tok))) {
DEBUG(10,("sam_account_ok: checking for workstation match %s and %s (len=%d)\n",
@@ -181,6 +185,14 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
invalid_ws = False;
break;
}
+ if (tok[0] == '@') {
+ DEBUG(10,("sam_account_ok: checking for workstation %s in group: %s\n",
+ machine_name, tok + 1));
+ if (user_in_group_list(machine_name, tok + 1, NULL, 0)) {
+ invalid_ws = False;
+ break;
+ }
+ }
}
if (invalid_ws)
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index 4a23ec8adc5..f3c01a58ca6 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -50,7 +50,7 @@ static int smb_create_user(const char *domain, const char *unix_username, const
if (homedir)
all_string_sub(add_script, "%H", homedir, sizeof(pstring));
ret = smbrun(add_script,NULL);
- DEBUG(3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
+ DEBUG(ret ? 0 : 3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
return ret;
}
@@ -61,7 +61,6 @@ static int smb_create_user(const char *domain, const char *unix_username, const
void auth_add_user_script(const char *domain, const char *username)
{
- uint32 rid;
/*
* User validated ok against Domain controller.
* If the admin wants us to try and create a UNIX
@@ -79,7 +78,6 @@ void auth_add_user_script(const char *domain, const char *username)
if ( !winbind_create_user(username, NULL) ) {
DEBUG(5,("auth_add_user_script: winbindd_create_user() failed\n"));
- rid = 0;
}
}
}
@@ -592,6 +590,39 @@ static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *gro
debug_nt_user_token(DBGC_AUTH, 10, ptoken);
+ if ((lp_log_nt_token_command() != NULL) &&
+ (strlen(lp_log_nt_token_command()) > 0)) {
+ TALLOC_CTX *mem_ctx;
+ char *command;
+ fstring sidstr;
+ char *user_sidstr, *group_sidstr;
+
+ mem_ctx = talloc_init("setnttoken");
+ if (mem_ctx == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ sid_to_string(sidstr, &ptoken->user_sids[0]);
+ user_sidstr = talloc_strdup(mem_ctx, sidstr);
+
+ group_sidstr = talloc_strdup(mem_ctx, "");
+ for (i=1; i<ptoken->num_sids; i++) {
+ sid_to_string(sidstr, &ptoken->user_sids[i]);
+ group_sidstr = talloc_asprintf(mem_ctx, "%s %s",
+ group_sidstr, sidstr);
+ }
+
+ command = strdup(lp_log_nt_token_command());
+ command = realloc_string_sub(command, "%s", user_sidstr);
+ command = realloc_string_sub(command, "%t", group_sidstr);
+ DEBUG(8, ("running command: [%s]\n", command));
+ if (smbrun(command, NULL) != 0) {
+ DEBUG(0, ("Could not log NT token\n"));
+ nt_status = NT_STATUS_ACCESS_DENIED;
+ }
+ talloc_destroy(mem_ctx);
+ SAFE_FREE(command);
+ }
+
*token = ptoken;
return nt_status;
@@ -1482,7 +1513,19 @@ BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
{
DOM_SID domain_sid;
- sid_copy( &domain_sid, get_global_sam_sid() );
+ /* if we are a domain member, the get the domain SID, else for
+ a DC or standalone server, use our own SID */
+
+ if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
+ if ( !secrets_fetch_domain_sid( lp_workgroup(), &domain_sid ) ) {
+ DEBUG(1,("nt_token_check_domain_rid: Cannot lookup SID for domain [%s]\n",
+ lp_workgroup()));
+ return False;
+ }
+ }
+ else
+ sid_copy( &domain_sid, get_global_sam_sid() );
+
sid_append_rid( &domain_sid, rid );
return nt_token_check_sid( &domain_sid, token );\
diff --git a/source/autogen.sh b/source/autogen.sh
index 3c2011e5a7e..3422d7cebfa 100755
--- a/source/autogen.sh
+++ b/source/autogen.sh
@@ -16,7 +16,7 @@ AUTOCONFFOUND="0"
##
for i in $TESTAUTOHEADER; do
if which $i > /dev/null 2>&1; then
- if [ `$i --version | head -n 1 | cut -d. -f 2 | tr -d [:alpha:]` -ge 53 ]; then
+ if test `$i --version | head -n 1 | cut -d. -f 2 | tr -d [:alpha:]` -ge 53; then
AUTOHEADER=$i
AUTOHEADERFOUND="1"
break
@@ -30,7 +30,7 @@ done
for i in $TESTAUTOCONF; do
if which $i > /dev/null 2>&1; then
- if [ `$i --version | head -n 1 | cut -d. -f 2 | tr -d [:alpha:]` -ge 53 ]; then
+ if test `$i --version | head -n 1 | cut -d. -f 2 | tr -d [:alpha:]` -ge 53; then
AUTOCONF=$i
AUTOCONFFOUND="1"
break
@@ -42,7 +42,7 @@ done
##
## do we have it?
##
-if [ "$AUTOCONFFOUND" = "0" -o "$AUTOHEADERFOUND" = "0" ]; then
+if test "$AUTOCONFFOUND" = "0" -o "$AUTOHEADERFOUND" = "0"; then
echo "$0: need autoconf 2.53 or later to build samba from SVN" >&2
exit 1
fi
diff --git a/source/client/client.c b/source/client/client.c
index a0804449985..55e9f1a71d9 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -1,9 +1,10 @@
/*
Unix SMB/CIFS implementation.
SMB client
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Simo Sorce 2001-2002
- Copyright (C) Jelmer Vernooij 2003
+ Copyright (C) Andrew Tridgell 1994-1998
+ Copyright (C) Simo Sorce 2001-2002
+ Copyright (C) Jelmer Vernooij 2003
+ Copyright (C) Gerald (Jerry) Carter 2004
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
@@ -28,7 +29,6 @@
#define REGISTER 0
#endif
-struct cli_state *cli;
extern BOOL in_client;
static int port = 0;
pstring cur_dir = "\\";
@@ -36,9 +36,7 @@ static pstring cd_path = "";
static pstring service;
static pstring desthost;
static pstring username;
-static pstring password;
-static BOOL use_kerberos;
-static BOOL got_pass;
+static pstring calling_name;
static BOOL grepable=False;
static char *cmdstr = NULL;
@@ -61,7 +59,6 @@ time_t newer_than = 0;
static int archive_level = 0;
static BOOL translation = False;
-
static BOOL have_ip;
/* clitar bits insert */
@@ -97,10 +94,11 @@ static unsigned int put_total_time_ms = 0;
/* totals globals */
static double dir_total;
-#define USENMB
+/* root cli_state connection */
+
+struct cli_state *cli;
+
-/* some forward declarations */
-static struct cli_state *do_connect(const char *server, const char *share);
/****************************************************************************
Write to a local file with CR/LF->LF translation if appropriate. Return the
@@ -216,9 +214,15 @@ static void send_message(void)
static int do_dskattr(void)
{
int total, bsize, avail;
+ struct cli_state *targetcli;
+ pstring targetpath;
+
+ if ( !cli_resolve_path( cli, cur_dir, &targetcli, targetpath ) ) {
+ d_printf("Error in dskattr: %s\n", cli_errstr(cli));
+ }
- if (!cli_dskattr(cli, &bsize, &total, &avail)) {
- d_printf("Error in dskattr: %s\n",cli_errstr(cli));
+ if (!cli_dskattr(targetcli, &bsize, &total, &avail)) {
+ d_printf("Error in dskattr: %s\n",cli_errstr(targetcli));
return 1;
}
@@ -248,31 +252,67 @@ static int do_cd(char *newdir)
char *p = newdir;
pstring saved_dir;
pstring dname;
+ pstring targetpath;
+ struct cli_state *targetcli;
+ SMB_STRUCT_STAT sbuf;
+ uint32 attributes;
dos_format(newdir);
- /* Save the current directory in case the
- new directory is invalid */
+ /* Save the current directory in case the new directory is invalid */
+
pstrcpy(saved_dir, cur_dir);
+
if (*p == '\\')
pstrcpy(cur_dir,p);
else
pstrcat(cur_dir,p);
+
if (*(cur_dir+strlen(cur_dir)-1) != '\\') {
pstrcat(cur_dir, "\\");
}
+
dos_clean_name(cur_dir);
- pstrcpy(dname,cur_dir);
+ pstrcpy( dname, cur_dir );
pstrcat(cur_dir,"\\");
dos_clean_name(cur_dir);
- if (!strequal(cur_dir,"\\")) {
- if (!cli_chkpath(cli, dname)) {
- d_printf("cd %s: %s\n", dname, cli_errstr(cli));
+ if ( !cli_resolve_path( cli, dname, &targetcli, targetpath ) ) {
+ d_printf("cd %s: %s\n", dname, cli_errstr(cli));
+ pstrcpy(cur_dir,saved_dir);
+ goto out;
+ }
+
+
+ if ( strequal(targetpath,"\\" ) )
+ return 0;
+
+ /* use a trans2_qpathinfo to test directories for modern servers */
+
+ if ( targetcli->protocol >= PROTOCOL_LANMAN2 ) {
+ if ( !cli_qpathinfo_basic( targetcli, targetpath, &sbuf, &attributes ) ) {
+ d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
pstrcpy(cur_dir,saved_dir);
+ goto out;
}
+
+ if ( !(attributes&FILE_ATTRIBUTE_DIRECTORY) ) {
+ d_printf("cd %s: not a directory\n", dname);
+ pstrcpy(cur_dir,saved_dir);
+ goto out;
+ }
}
-
+ else {
+ pstrcat( targetpath, "\\" );
+ dos_clean_name( targetpath );
+
+ if ( !cli_chkpath(targetcli, targetpath) ) {
+ d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
+ pstrcpy(cur_dir,saved_dir);
+ }
+ }
+
+out:
pstrcpy(cd_path,cur_dir);
return 0;
@@ -286,7 +326,7 @@ static int cmd_cd(void)
{
pstring buf;
int rc = 0;
-
+
if (next_token_nr(NULL,buf,NULL,sizeof(buf)))
rc = do_cd(buf);
else
@@ -510,6 +550,8 @@ static void do_list_helper(file_info *f, const char *mask, void *state)
void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs)
{
static int in_do_list = 0;
+ struct cli_state *targetcli;
+ pstring targetpath;
if (in_do_list && rec) {
fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
@@ -536,7 +578,15 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
*/
pstring head;
pstrcpy(head, do_list_queue_head());
- cli_list(cli, head, attribute, do_list_helper, NULL);
+
+ /* check for dfs */
+
+ if ( !cli_resolve_path( cli, head, &targetcli, targetpath ) ) {
+ d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
+ continue;
+ }
+
+ cli_list(targetcli, targetpath, attribute, do_list_helper, NULL);
remove_do_list_queue_head();
if ((! do_list_queue_empty()) && (fn == display_finfo)) {
char* next_file = do_list_queue_head();
@@ -555,9 +605,15 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
}
}
} else {
- if (cli_list(cli, mask, attribute, do_list_helper, NULL) == -1) {
- d_printf("%s listing %s\n", cli_errstr(cli), mask);
+ /* check for dfs */
+
+ if ( cli_resolve_path( cli, mask, &targetcli, targetpath ) ) {
+ if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1)
+ d_printf("%s listing %s\n", cli_errstr(targetcli), targetpath);
}
+ else
+ d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli));
+
}
in_do_list = 0;
@@ -656,14 +712,23 @@ static int do_get(char *rname, char *lname, BOOL reget)
off_t start = 0;
off_t nread = 0;
int rc = 0;
+ struct cli_state *targetcli;
+ pstring targetname;
- GetTimeOfDay(&tp_start);
if (lowercase) {
strlower_m(lname);
}
- fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE);
+ if ( !cli_resolve_path( cli, rname, &targetcli, targetname ) ) {
+ d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
+ return 1;
+ }
+
+
+ GetTimeOfDay(&tp_start);
+
+ fnum = cli_open(targetcli, targetname, O_RDONLY, DENY_NONE);
if (fnum == -1) {
d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
@@ -693,11 +758,11 @@ static int do_get(char *rname, char *lname, BOOL reget)
}
- if (!cli_qfileinfo(cli, fnum,
+ if (!cli_qfileinfo(targetcli, fnum,
&attr, &size, NULL, NULL, NULL, NULL, NULL) &&
- !cli_getattrE(cli, fnum,
+ !cli_getattrE(targetcli, fnum,
&attr, &size, NULL, NULL, NULL)) {
- d_printf("getattrib: %s\n",cli_errstr(cli));
+ d_printf("getattrib: %s\n",cli_errstr(targetcli));
return 1;
}
@@ -706,12 +771,12 @@ static int do_get(char *rname, char *lname, BOOL reget)
if(!(data = (char *)SMB_MALLOC(read_size))) {
d_printf("malloc fail for size %d\n", read_size);
- cli_close(cli, fnum);
+ cli_close(targetcli, fnum);
return 1;
}
while (1) {
- int n = cli_read(cli, fnum, data, nread + start, read_size);
+ int n = cli_read(targetcli, fnum, data, nread + start, read_size);
if (n <= 0)
break;
@@ -734,7 +799,7 @@ static int do_get(char *rname, char *lname, BOOL reget)
SAFE_FREE(data);
- if (!cli_close(cli, fnum)) {
+ if (!cli_close(targetcli, fnum)) {
d_printf("Error %s closing remote file\n",cli_errstr(cli));
rc = 1;
}
@@ -948,9 +1013,17 @@ static int cmd_mget(void)
static BOOL do_mkdir(char *name)
{
- if (!cli_mkdir(cli, name)) {
+ struct cli_state *targetcli;
+ pstring targetname;
+
+ if ( !cli_resolve_path( cli, name, &targetcli, targetname ) ) {
+ d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
+ return False;
+ }
+
+ if (!cli_mkdir(targetcli, targetname)) {
d_printf("%s making remote directory %s\n",
- cli_errstr(cli),name);
+ cli_errstr(targetcli),name);
return(False);
}
@@ -980,7 +1053,7 @@ static BOOL do_altname(char *name)
static int cmd_quit(void)
{
- cli_shutdown(cli);
+ cli_cm_shutdown();
exit(0);
/* NOTREACHED */
return 0;
@@ -1064,25 +1137,32 @@ static int do_put(char *rname, char *lname, BOOL reput)
char *buf = NULL;
int maxwrite = io_bufsize;
int rc = 0;
-
struct timeval tp_start;
+ struct cli_state *targetcli;
+ pstring targetname;
+
+ if ( !cli_resolve_path( cli, rname, &targetcli, targetname ) ) {
+ d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
+ return 1;
+ }
+
GetTimeOfDay(&tp_start);
if (reput) {
- fnum = cli_open(cli, rname, O_RDWR|O_CREAT, DENY_NONE);
+ fnum = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE);
if (fnum >= 0) {
- if (!cli_qfileinfo(cli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
- !cli_getattrE(cli, fnum, NULL, &start, NULL, NULL, NULL)) {
+ if (!cli_qfileinfo(targetcli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
+ !cli_getattrE(targetcli, fnum, NULL, &start, NULL, NULL, NULL)) {
d_printf("getattrib: %s\n",cli_errstr(cli));
return 1;
}
}
} else {
- fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+ fnum = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
}
if (fnum == -1) {
- d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
+ d_printf("%s opening remote file %s\n",cli_errstr(targetcli),rname);
return 1;
}
@@ -1130,7 +1210,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
break;
}
- ret = cli_write(cli, fnum, 0, buf, nread + start, n);
+ ret = cli_write(targetcli, fnum, 0, buf, nread + start, n);
if (n != ret) {
d_printf("Error writing file: %s\n", cli_errstr(cli));
@@ -1141,7 +1221,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
nread += n;
}
- if (!cli_close(cli, fnum)) {
+ if (!cli_close(targetcli, fnum)) {
d_printf("%s closing remote file %s\n",cli_errstr(cli),rname);
x_fclose(f);
SAFE_FREE(buf);
@@ -1172,7 +1252,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
}
if (f == x_stdin) {
- cli_shutdown(cli);
+ cli_cm_shutdown();
exit(0);
}
@@ -1562,6 +1642,8 @@ static int cmd_open(void)
{
pstring mask;
pstring buf;
+ struct cli_state *targetcli;
+ pstring targetname;
pstrcpy(mask,cur_dir);
@@ -1571,7 +1653,12 @@ static int cmd_open(void)
}
pstrcat(mask,buf);
- cli_nt_create(cli, mask, FILE_READ_DATA);
+ if ( !cli_resolve_path( cli, mask, &targetcli, targetname ) ) {
+ d_printf("open %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ cli_nt_create(targetcli, targetname, FILE_READ_DATA);
return 0;
}
@@ -1585,6 +1672,8 @@ static int cmd_rmdir(void)
{
pstring mask;
pstring buf;
+ struct cli_state *targetcli;
+ pstring targetname;
pstrcpy(mask,cur_dir);
@@ -1594,9 +1683,14 @@ static int cmd_rmdir(void)
}
pstrcat(mask,buf);
- if (!cli_rmdir(cli, mask)) {
+ if ( !cli_resolve_path( cli, mask, &targetcli, targetname ) ) {
+ d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_rmdir(targetcli, targetname)) {
d_printf("%s removing remote directory file %s\n",
- cli_errstr(cli),mask);
+ cli_errstr(targetcli),mask);
}
return 0;
@@ -1610,12 +1704,9 @@ static int cmd_link(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");
- return 1;
- }
-
pstrcpy(oldname,cur_dir);
pstrcpy(newname,cur_dir);
@@ -1628,8 +1719,18 @@ static int cmd_link(void)
pstrcat(oldname,buf);
pstrcat(newname,buf2);
- if (!cli_unix_hardlink(cli, oldname, newname)) {
- d_printf("%s linking files (%s -> %s)\n", cli_errstr(cli), newname, oldname);
+ if ( !cli_resolve_path( cli, oldname, &targetcli, targetname ) ) {
+ d_printf("link %s: %s\n", oldname, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
+ d_printf("Server doesn't support UNIX CIFS calls.\n");
+ return 1;
+ }
+
+ if (!cli_unix_hardlink(targetcli, targetname, newname)) {
+ d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
return 1;
}
@@ -1679,12 +1780,9 @@ static int cmd_chmod(void)
pstring src;
mode_t mode;
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");
- return 1;
- }
-
pstrcpy(src,cur_dir);
if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
@@ -1696,9 +1794,19 @@ static int cmd_chmod(void)
mode = (mode_t)strtol(buf, NULL, 8);
pstrcat(src,buf2);
- if (!cli_unix_chmod(cli, src, mode)) {
+ if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ d_printf("chmod %s: %s\n", src, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
+ d_printf("Server doesn't support UNIX CIFS calls.\n");
+ return 1;
+ }
+
+ if (!cli_unix_chmod(targetcli, targetname, mode)) {
d_printf("%s chmod file %s 0%o\n",
- cli_errstr(cli), src, (unsigned int)mode);
+ cli_errstr(targetcli), src, (unsigned int)mode);
return 1;
}
@@ -1822,13 +1930,29 @@ static int cmd_getfacl(void)
uint16 num_file_acls = 0;
uint16 num_dir_acls = 0;
uint16 i;
+ struct cli_state *targetcli;
+ pstring targetname;
- if (!SERVER_HAS_UNIX_CIFS(cli)) {
- d_printf("Server doesn't support UNIX CIFS calls.\n");
+ pstrcpy(src,cur_dir);
+
+ if (!next_token_nr(NULL,name,NULL,sizeof(name))) {
+ d_printf("stat file\n");
return 1;
}
- if (!cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh)) {
+ pstrcat(src,name);
+
+ if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ d_printf("stat %s: %s\n", src, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
+ d_printf("Server doesn't support UNIX CIFS calls.\n");
+ return 1;
+ }
+
+ if (!cli_unix_extensions_version(targetcli, &major, &minor, &caplow, &caphigh)) {
d_printf("Can't get UNIX CIFS version from server.\n");
return 1;
}
@@ -1838,24 +1962,16 @@ static int cmd_getfacl(void)
return 1;
}
- pstrcpy(src,cur_dir);
-
- if (!next_token_nr(NULL,name,NULL,sizeof(name))) {
- d_printf("stat file\n");
- return 1;
- }
-
- pstrcat(src,name);
- if (!cli_unix_stat(cli, src, &sbuf)) {
+ if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
d_printf("%s getfacl doing a stat on file %s\n",
- cli_errstr(cli), src);
+ cli_errstr(targetcli), src);
return 1;
}
- if (!cli_unix_getfacl(cli, src, &rb_size, &retbuf)) {
+ if (!cli_unix_getfacl(targetcli, targetname, &rb_size, &retbuf)) {
d_printf("%s getfacl file %s\n",
- cli_errstr(cli), src);
+ cli_errstr(targetcli), src);
return 1;
}
@@ -1973,6 +2089,8 @@ static int cmd_stat(void)
pstring src, name;
fstring mode_str;
SMB_STRUCT_STAT sbuf;
+ struct cli_state *targetcli;
+ pstring targetname;
if (!SERVER_HAS_UNIX_CIFS(cli)) {
d_printf("Server doesn't support UNIX CIFS calls.\n");
@@ -1988,9 +2106,15 @@ static int cmd_stat(void)
pstrcat(src,name);
- if (!cli_unix_stat(cli, src, &sbuf)) {
+
+ if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ d_printf("stat %s: %s\n", src, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!cli_unix_stat(targetcli, targetname, &sbuf)) {
d_printf("%s stat file %s\n",
- cli_errstr(cli), src);
+ cli_errstr(targetcli), src);
return 1;
}
@@ -2043,12 +2167,9 @@ static int cmd_chown(void)
uid_t uid;
gid_t gid;
pstring buf, buf2, buf3;
+ struct cli_state *targetcli;
+ pstring targetname;
- if (!SERVER_HAS_UNIX_CIFS(cli)) {
- d_printf("Server doesn't support UNIX CIFS calls.\n");
- return 1;
- }
-
pstrcpy(src,cur_dir);
if (!next_token_nr(NULL,buf,NULL,sizeof(buf)) ||
@@ -2062,9 +2183,20 @@ static int cmd_chown(void)
gid = (gid_t)atoi(buf2);
pstrcat(src,buf3);
- if (!cli_unix_chown(cli, src, uid, gid)) {
+ if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ d_printf("chown %s: %s\n", src, cli_errstr(cli));
+ return 1;
+ }
+
+
+ if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
+ d_printf("Server doesn't support UNIX CIFS calls.\n");
+ return 1;
+ }
+
+ if (!cli_unix_chown(targetcli, targetname, uid, gid)) {
d_printf("%s chown file %s uid=%d, gid=%d\n",
- cli_errstr(cli), src, (int)uid, (int)gid);
+ cli_errstr(targetcli), src, (int)uid, (int)gid);
return 1;
}
@@ -2108,6 +2240,8 @@ static int cmd_hardlink(void)
{
pstring src,dest;
pstring buf,buf2;
+ struct cli_state *targetcli;
+ pstring targetname;
pstrcpy(src,cur_dir);
pstrcpy(dest,cur_dir);
@@ -2121,8 +2255,18 @@ static int cmd_hardlink(void)
pstrcat(src,buf);
pstrcat(dest,buf2);
- if (!cli_nt_hardlink(cli, src, dest)) {
- d_printf("%s doing an NT hard link of files\n",cli_errstr(cli));
+ if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
+ return 1;
+ }
+
+ if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
+ d_printf("Server doesn't support UNIX CIFS calls.\n");
+ return 1;
+ }
+
+ if (!cli_nt_hardlink(targetcli, targetname, dest)) {
+ d_printf("%s doing an NT hard link of files\n",cli_errstr(targetcli));
return 1;
}
@@ -2424,6 +2568,8 @@ static void server_fn(const char *name, uint32 m,
static BOOL list_servers(const char *wk_grp)
{
+ fstring state;
+
if (!cli->server_domain)
return False;
@@ -2431,16 +2577,18 @@ static BOOL list_servers(const char *wk_grp)
d_printf("\n\tServer Comment\n");
d_printf("\t--------- -------\n");
};
+ fstrcpy( state, "Server" );
cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn,
- "Server");
+ state);
if (!grepable) {
d_printf("\n\tWorkgroup Master\n");
d_printf("\t--------- -------\n");
};
+ fstrcpy( state, "Workgroup" );
cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
- server_fn, "Workgroup");
+ server_fn, state);
return True;
}
@@ -2477,15 +2625,14 @@ static int cmd_logon(void)
pstrcpy(l_username, buf);
- if (!next_token_nr(NULL,buf2,NULL,sizeof(buf))) {
+ if (!next_token_nr(NULL,buf2,NULL,sizeof(buf)))
+ {
char *pass = getpass("Password: ");
- if (pass) {
+ if (pass)
pstrcpy(l_password, pass);
- got_pass = 1;
- }
- } else {
+ }
+ else
pstrcpy(l_password, buf2);
- }
if (!cli_session_setup(cli, l_username,
l_password, strlen(l_password),
@@ -2499,6 +2646,36 @@ static int cmd_logon(void)
return 0;
}
+
+/****************************************************************************
+ list active connections
+****************************************************************************/
+
+static int cmd_list_connect(void)
+{
+ cli_cm_display();
+
+ return 0;
+}
+
+/****************************************************************************
+ display the current active client connection
+****************************************************************************/
+
+static int cmd_show_connect( void )
+{
+ struct cli_state *targetcli;
+ pstring targetpath;
+
+ if ( !cli_resolve_path( cli, cur_dir, &targetcli, targetpath ) ) {
+ d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
+ return 1;
+ }
+
+ d_printf("//%s/%s\n", targetcli->desthost, targetcli->share);
+ return 0;
+}
+
/* Some constants for completing filename arguments */
#define COMPL_NONE 0 /* No completions */
@@ -2570,6 +2747,8 @@ static struct
{"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
{"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
{"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
+ {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
+ {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
/* Yes, this must be here, see crh's comment above. */
{"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
@@ -2644,7 +2823,7 @@ static int process_command_string(char *cmd)
/* establish the connection if not already */
if (!cli) {
- cli = do_connect(desthost, service);
+ cli = cli_cm_open(desthost, service, True);
if (!cli)
return 0;
}
@@ -2952,123 +3131,6 @@ static int process_stdin(void)
return rc;
}
-/*****************************************************
- Return a connection to a server.
-*******************************************************/
-
-static struct cli_state *do_connect(const char *server, const char *share)
-{
- struct cli_state *c;
- struct nmb_name called, calling;
- const char *server_n;
- struct in_addr ip;
- pstring servicename;
- char *sharename;
-
- /* 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 NULL;
- *sharename = 0;
- sharename++;
- }
-
- server_n = server;
-
- zero_ip(&ip);
-
- make_nmb_name(&calling, global_myname(), 0x0);
- make_nmb_name(&called , server, name_type);
-
- again:
- zero_ip(&ip);
- if (have_ip) ip = dest_ip;
-
- /* have to open a new connection */
- if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) ||
- !cli_connect(c, server_n, &ip)) {
- d_printf("Connection to %s failed\n", server_n);
- return NULL;
- }
-
- c->protocol = max_protocol;
- c->use_kerberos = use_kerberos;
- cli_setup_signing_state(c, cmdline_auth_info.signing_state);
-
-
- if (!cli_session_request(c, &calling, &called)) {
- char *p;
- d_printf("session request to %s failed (%s)\n",
- called.name, cli_errstr(c));
- cli_shutdown(c);
- if ((p=strchr_m(called.name, '.'))) {
- *p = 0;
- goto again;
- }
- if (strcmp(called.name, "*SMBSERVER")) {
- make_nmb_name(&called , "*SMBSERVER", 0x20);
- goto again;
- }
- return NULL;
- }
-
- DEBUG(4,(" session request ok\n"));
-
- if (!cli_negprot(c)) {
- d_printf("protocol negotiation failed\n");
- cli_shutdown(c);
- return NULL;
- }
-
- if (!got_pass) {
- char *pass = getpass("Password: ");
- if (pass) {
- pstrcpy(password, pass);
- got_pass = 1;
- }
- }
-
- if (!cli_session_setup(c, username,
- password, strlen(password),
- password, strlen(password),
- lp_workgroup())) {
- /* if a password was not supplied then try again with a null username */
- if (password[0] || !username[0] || use_kerberos ||
- !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) {
- d_printf("session setup failed: %s\n", cli_errstr(c));
- if (NT_STATUS_V(cli_nt_error(c)) ==
- NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
- d_printf("did you forget to run kinit?\n");
- cli_shutdown(c);
- return NULL;
- }
- d_printf("Anonymous login successful\n");
- }
-
- if (*c->server_domain) {
- DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
- c->server_domain,c->server_os,c->server_type));
- } else if (*c->server_os || *c->server_type){
- DEBUG(1,("OS=[%s] Server=[%s]\n",
- c->server_os,c->server_type));
- }
- DEBUG(4,(" session setup ok\n"));
-
- if (!cli_send_tconX(c, sharename, "?????",
- password, strlen(password)+1)) {
- d_printf("tree connect failed: %s\n", cli_errstr(c));
- cli_shutdown(c);
- return NULL;
- }
-
- DEBUG(4,(" tconx ok\n"));
-
- return c;
-}
-
/****************************************************************************
Process commands from the client.
****************************************************************************/
@@ -3077,7 +3139,7 @@ static int process(char *base_directory)
{
int rc = 0;
- cli = do_connect(desthost, service);
+ cli = cli_cm_open(desthost, service, True);
if (!cli) {
return 1;
}
@@ -3090,7 +3152,7 @@ static int process(char *base_directory)
process_stdin();
}
- cli_shutdown(cli);
+ cli_cm_shutdown();
return rc;
}
@@ -3100,7 +3162,7 @@ static int process(char *base_directory)
static int do_host_query(char *query_host)
{
- cli = do_connect(query_host, "IPC$");
+ cli = cli_cm_open(query_host, "IPC$", True);
if (!cli)
return 1;
@@ -3111,9 +3173,9 @@ static int do_host_query(char *query_host)
/* Workgroups simply don't make sense over anything
else but port 139... */
- cli_shutdown(cli);
- port = 139;
- cli = do_connect(query_host, "IPC$");
+ cli_cm_shutdown();
+ cli_cm_set_port( 139 );
+ cli = cli_cm_open(query_host, "IPC$", True);
}
if (cli == NULL) {
@@ -3123,12 +3185,11 @@ static int do_host_query(char *query_host)
list_servers(lp_workgroup());
- cli_shutdown(cli);
+ cli_cm_shutdown();
return(0);
}
-
/****************************************************************************
Handle a tar operation.
****************************************************************************/
@@ -3139,7 +3200,7 @@ static int do_tar_op(char *base_directory)
/* do we already have a connection? */
if (!cli) {
- cli = do_connect(desthost, service);
+ cli = cli_cm_open(desthost, service, True);
if (!cli)
return 1;
}
@@ -3150,7 +3211,7 @@ static int do_tar_op(char *base_directory)
ret=process_tar();
- cli_shutdown(cli);
+ cli_cm_shutdown();
return(ret);
}
@@ -3166,7 +3227,7 @@ static int do_message_op(void)
fstring server_name;
char name_type_hex[10];
- make_nmb_name(&calling, global_myname(), 0x0);
+ make_nmb_name(&calling, calling_name, 0x0);
make_nmb_name(&called , desthost, name_type);
fstrcpy(server_name, desthost);
@@ -3174,7 +3235,8 @@ static int do_message_op(void)
fstrcat(server_name, name_type_hex);
zero_ip(&ip);
- if (have_ip) ip = dest_ip;
+ if (have_ip)
+ ip = dest_ip;
if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, port) != port) ||
!cli_connect(cli, server_name, &ip)) {
@@ -3184,12 +3246,12 @@ static int do_message_op(void)
if (!cli_session_request(cli, &calling, &called)) {
d_printf("session request failed\n");
- cli_shutdown(cli);
+ cli_cm_shutdown();
return 1;
}
send_message();
- cli_shutdown(cli);
+ cli_cm_shutdown();
return 0;
}
@@ -3250,6 +3312,7 @@ static int do_message_op(void)
not it was set by a command line option */
set_global_myworkgroup( "" );
+ set_global_myname( "" );
/* set default debug level to 0 regardless of what smb.conf sets */
setup_logging( "smbclient", True );
@@ -3271,9 +3334,10 @@ static int do_message_op(void)
* to port 139 instead of port 445. srl,crh
*/
name_type = 0x03;
+ cli_cm_set_dest_name_type( name_type );
pstrcpy(desthost,poptGetOptArg(pc));
- if( 0 == port )
- port = 139;
+ if( !port )
+ cli_cm_set_port( 139 );
message = True;
break;
case 'I':
@@ -3282,6 +3346,8 @@ static int do_message_op(void)
if (is_zero_ip(dest_ip))
exit(1);
have_ip = True;
+
+ cli_cm_set_dest_ip( dest_ip );
}
break;
case 'E':
@@ -3330,6 +3396,8 @@ static int do_message_op(void)
}
poptGetArg(pc);
+
+ if ( have_ip )
/*
* Don't load debug level from smb.conf. It should be
@@ -3344,6 +3412,7 @@ static int do_message_op(void)
everything)? */
fstrcpy( new_workgroup, lp_workgroup() );
+ pstrcpy( calling_name, global_myname() );
if ( override_logfile )
setup_logging( lp_logfile(), False );
@@ -3358,6 +3427,9 @@ static int do_message_op(void)
if ( strlen(new_workgroup) != 0 )
set_global_myworkgroup( new_workgroup );
+ if ( strlen(calling_name) != 0 )
+ set_global_myname( calling_name );
+
if(poptPeekArg(pc)) {
pstrcpy(service,poptGetArg(pc));
/* Convert any '/' characters in the service name to '\' characters */
@@ -3387,11 +3459,10 @@ static int do_message_op(void)
poptFreeContext(pc);
- pstrcpy(username, cmdline_auth_info.username);
- pstrcpy(password, cmdline_auth_info.password);
+ /* store the username an password for dfs support */
- use_kerberos = cmdline_auth_info.use_kerberos;
- got_pass = cmdline_auth_info.got_pass;
+ cli_cm_set_credentials( &cmdline_auth_info );
+ pstrcpy(username, cmdline_auth_info.username);
DEBUG(3,("Client started (version %s).\n", SAMBA_VERSION_STRING));
@@ -3417,8 +3488,9 @@ static int do_message_op(void)
*p = 0;
p++;
sscanf(p, "%x", &name_type);
+ cli_cm_set_dest_name_type( name_type );
}
-
+
return do_host_query(qhost);
}
diff --git a/source/client/clitar.c b/source/client/clitar.c
index a92be1abe38..14ebffb60ff 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -87,9 +87,6 @@ static BOOL tar_reset=False;
static BOOL tar_excl=True;
/* use regular expressions for search on file names */
static BOOL tar_re_search=False;
-#ifdef HAVE_REGEX_H
-regex_t *preg;
-#endif
/* Do not dump anything, just calculate sizes */
static BOOL dry_run=False;
/* Dump files with System attribute */
@@ -797,11 +794,7 @@ static void do_tar(file_info *finfo)
DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) ||
-#ifdef HAVE_REGEX_H
- (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) {
-#else
(tar_re_search && mask_match_list(exclaim, cliplist, clipn, True))) {
-#endif
DEBUG(3,("Skipping file %s\n", exclaim));
return;
}
@@ -1150,11 +1143,7 @@ static void do_tarput(void)
/* Well, now we have a header, process the file ... */
/* Should we skip the file? We have the long name as well here */
skip = clipn && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl) ||
-#ifdef HAVE_REGEX_H
- (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
-#else
(tar_re_search && mask_match_list(finfo.name, cliplist, clipn, True)));
-#endif
DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
if (skip) {
@@ -1748,25 +1737,6 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
}
if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
-#ifdef HAVE_REGEX_H
- int errcode;
-
- if ((preg = (regex_t *)SMB_MALLOC(65536)) == NULL) {
-
- DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
- return;
- }
-
- if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
- char errstr[1024];
- size_t errlen;
-
- errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
- DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
- return;
- }
-#endif
-
clipn=argc-Optind-1;
cliplist=argv+Optind+1;
newOptind += clipn;
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index 1793a9ed7fe..d648629f9c3 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -290,7 +290,11 @@ static int parse_options(char * options, int * filesys_flags)
value++;
}
- if (strncmp(data, "user", 4) == 0) {
+ if (strncmp(data, "users",5) == 0) {
+ if(!value || !*value) {
+ strncpy(data,",,,,,",5);
+ }
+ } else if (strncmp(data, "user", 4) == 0) {
if (!value || !*value) {
if(data[4] == '\0') {
if(verboseflag)
diff --git a/source/client/smbmnt.c b/source/client/smbmnt.c
index 06dd3e5c023..6625b308c5e 100644
--- a/source/client/smbmnt.c
+++ b/source/client/smbmnt.c
@@ -101,7 +101,8 @@ fullpath(const char *p)
}
if (realpath(p, path) == NULL) {
- fprintf(stderr,"Failed to find real path for mount point\n");
+ fprintf(stderr,"Failed to find real path for mount point %s: %s\n",
+ p, strerror(errno));
exit(1);
}
return strdup(path);
diff --git a/source/client/smbspool.c b/source/client/smbspool.c
index f838c5de5bf..5df6bfe407e 100644
--- a/source/client/smbspool.c
+++ b/source/client/smbspool.c
@@ -339,7 +339,7 @@ smb_print(struct cli_state *cli, /* I - SMB connection */
if ((fnum = cli_open(cli, title, O_RDWR | O_CREAT | O_TRUNC, DENY_NONE)) == -1)
{
- fprintf(stderr, "ERROR: %s opening remote file %s\n",
+ fprintf(stderr, "ERROR: %s opening remote spool %s\n",
cli_errstr(cli), title);
return (1);
}
@@ -357,7 +357,7 @@ smb_print(struct cli_state *cli, /* I - SMB connection */
{
if (cli_write(cli, fnum, 0, buffer, tbytes, nbytes) != nbytes)
{
- fprintf(stderr, "ERROR: Error writing file: %s\n", cli_errstr(cli));
+ fprintf(stderr, "ERROR: Error writing spool: %s\n", cli_errstr(cli));
break;
}
@@ -366,7 +366,7 @@ smb_print(struct cli_state *cli, /* I - SMB connection */
if (!cli_close(cli, fnum))
{
- fprintf(stderr, "ERROR: %s closing remote file %s\n",
+ fprintf(stderr, "ERROR: %s closing remote spool %s\n",
cli_errstr(cli), title);
return (1);
}
diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c
index e574a7cf204..1c29cc77c42 100644
--- a/source/groupdb/mapping.c
+++ b/source/groupdb/mapping.c
@@ -975,7 +975,7 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
pstrcpy(add_script, lp_addgroup_script());
pstring_sub(add_script, "%g", unix_group);
ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
- DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
+ DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
if (ret != 0)
return ret;
@@ -1022,7 +1022,7 @@ int smb_delete_group(char *unix_group)
pstrcpy(del_script, lp_delgroup_script());
pstring_sub(del_script, "%g", unix_group);
ret = smbrun(del_script,NULL);
- DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
+ DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
return ret;
}
@@ -1050,7 +1050,7 @@ int smb_set_primary_group(const char *unix_group, const char* unix_user)
all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
ret = smbrun(add_script,NULL);
- DEBUG(3,("smb_set_primary_group: "
+ DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
"Running the command `%s' gave %d\n",add_script,ret));
return ret;
}
@@ -1082,7 +1082,7 @@ int smb_add_user_group(char *unix_group, char *unix_user)
pstring_sub(add_script, "%g", unix_group);
pstring_sub(add_script, "%u", unix_user);
ret = smbrun(add_script,NULL);
- DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
+ DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret));
return ret;
}
@@ -1113,7 +1113,7 @@ int smb_delete_user_group(const char *unix_group, const char *unix_user)
pstring_sub(del_script, "%g", unix_group);
pstring_sub(del_script, "%u", unix_user);
ret = smbrun(del_script,NULL);
- DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
+ DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
return ret;
}
diff --git a/source/include/adt_tree.h b/source/include/adt_tree.h
index 12e2ea5cc53..2fbfb55e889 100644
--- a/source/include/adt_tree.h
+++ b/source/include/adt_tree.h
@@ -21,6 +21,14 @@
#ifndef ADT_TREE_H
#define ADT_TREE_H
+#ifndef _BOOL
+typedef int BOOL;
+#define _BOOL
+#endif
+
+
+/* data structure used to build the tree */
+
typedef struct _tree_node {
struct _tree_node *parent;
struct _tree_node **children;
@@ -35,4 +43,25 @@ typedef struct _tree_root {
void (*free_func)(void *p);
} SORTED_TREE;
+/*
+ * API
+ */
+
+/* initializer and desctrutor */
+SORTED_TREE* pathtree_init( void *data_p, int (cmp_fn)(void*, void*), void (free_fn)(void*) );
+void pathtree_destroy( SORTED_TREE *tree );
+
+/* add a new path component */
+
+BOOL pathtree_add( SORTED_TREE *tree, const char *path, void *data_p );
+
+/* search path */
+
+void* pathtree_find( SORTED_TREE *tree, char *key );
+
+/* debug (print) functions */
+
+void pathtree_print_keys( SORTED_TREE *tree, int debug );
+
+
#endif
diff --git a/source/include/client.h b/source/include/client.h
index 8ae8faf90dc..61c420c06b1 100644
--- a/source/include/client.h
+++ b/source/include/client.h
@@ -106,6 +106,7 @@ struct cli_state {
int initialised;
int win95;
uint32 capabilities;
+ BOOL dfsroot;
TALLOC_CTX *mem_ctx;
diff --git a/source/include/includes.h b/source/include/includes.h
index 45c7133f1ea..982eee18862 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -802,7 +802,6 @@ extern int errno;
#include "messages.h"
#include "charset.h"
#include "dynconfig.h"
-#include "adt_tree.h"
#include "util_getent.h"
diff --git a/source/include/local.h b/source/include/local.h
index 7ac2e256120..7d5baa21fa8 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -198,9 +198,6 @@
/* the maximum age in seconds of a password. Should be a lp_ parameter */
#define MAX_PASSWORD_AGE (21*24*60*60)
-/* Allocation roundup. */
-#define SMB_ROUNDUP_ALLOCATION_SIZE 0x100000
-
/* shall we deny oplocks to clients that get timeouts? */
#define FASCIST_OPLOCK_BACKOFF 1
diff --git a/source/include/msdfs.h b/source/include/msdfs.h
index 32aa7ecef25..eaefa81c5b8 100644
--- a/source/include/msdfs.h
+++ b/source/include/msdfs.h
@@ -37,6 +37,12 @@
/* Maximum number of referrals for each Dfs volume */
#define MAX_REFERRAL_COUNT 256
+typedef struct _client_referral {
+ uint32 proximity;
+ uint32 ttl;
+ pstring dfspath;
+} CLIENT_DFS_REFERRAL;
+
struct referral
{
pstring alternate_path; /* contains the path referred */
diff --git a/source/include/passdb.h b/source/include/passdb.h
index 1b9ccc50ee4..3c244e7625b 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -241,7 +241,7 @@ struct acct_info
* this SAMBA will load. Increment this if *ANY* changes are made to the interface.
*/
-#define PASSDB_INTERFACE_VERSION 6
+#define PASSDB_INTERFACE_VERSION 7
typedef struct pdb_context
{
@@ -287,6 +287,12 @@ typedef struct pdb_context
GROUP_MAP **rmap, int *num_entries,
BOOL unix_only);
+ NTSTATUS (*pdb_enum_group_members)(struct pdb_context *context,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *group,
+ uint32 **member_rids,
+ int *num_members);
+
NTSTATUS (*pdb_enum_group_memberships)(struct pdb_context *context,
const char *username,
gid_t primary_gid,
@@ -385,6 +391,12 @@ typedef struct pdb_methods
GROUP_MAP **rmap, int *num_entries,
BOOL unix_only);
+ NTSTATUS (*enum_group_members)(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *group,
+ uint32 **member_rids,
+ int *num_members);
+
NTSTATUS (*enum_group_memberships)(struct pdb_methods *methods,
const char *username,
gid_t primary_gid,
diff --git a/source/include/rpc_lsa.h b/source/include/rpc_lsa.h
index c0425271b32..01add64727c 100644
--- a/source/include/rpc_lsa.h
+++ b/source/include/rpc_lsa.h
@@ -390,8 +390,8 @@ typedef struct lsa_trans_name_info
} LSA_TRANS_NAME;
-/* This number purly arbitary - just to prevent a client from requesting large amounts of memory */
-#define MAX_LOOKUP_SIDS 256
+/* This number is based on Win2k and later maximum response allowed */
+#define MAX_LOOKUP_SIDS 20480
/* LSA_TRANS_NAME_ENUM - LSA Translated Name Enumeration container */
typedef struct lsa_trans_name_enum_info
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index a007bcd2e57..e041ee26f0b 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -540,7 +540,7 @@ typedef struct sam_unknown_info_6_info
typedef struct sam_unknown_info_7_info
{
- uint16 unknown_0; /* 0x0003 */
+ uint16 server_role;
} SAM_UNK_INFO_7;
@@ -580,7 +580,7 @@ typedef struct sam_unknown_info_2_inf
UINT64_S seq_num;
uint32 unknown_4; /* 0x0000 0001 */
- uint32 unknown_5; /* 0x0000 0003 */
+ uint32 server_role;
uint32 unknown_6; /* 0x0000 0001 */
uint32 num_domain_usrs; /* number of users in domain */
uint32 num_domain_grps; /* number of domain groups in domain */
diff --git a/source/include/smb.h b/source/include/smb.h
index eb7214ecbfe..ff645134109 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -466,6 +466,8 @@ typedef struct
#include "smb_acls.h"
#include "vfs.h"
+struct dptr_struct;
+
typedef struct connection_struct
{
struct connection_struct *next, *prev;
@@ -475,7 +477,7 @@ typedef struct connection_struct
BOOL force_user;
BOOL force_group;
struct vuid_cache vuid_cache;
- void *dirptr;
+ struct dptr_struct *dirptr;
BOOL printer;
BOOL ipc;
BOOL read_only; /* Attributes for the current user of the share. */
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index 4fa9ffa5ace..b1ac617f5cf 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -178,8 +178,6 @@
/* this is how errors are generated */
#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__)
-#define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x))
-
/* Extra macros added by Ying Chen at IBM - speed increase by inlining. */
#define smb_buf(buf) (((char *)(buf)) + smb_size + CVAL(buf,smb_wct)*2)
#define smb_buflen(buf) (SVAL(buf,smb_vwv0 + (int)CVAL(buf, smb_wct)*2))
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index adb51430dc6..d005104dea4 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -120,8 +120,8 @@ extern ATTRIB_MAP_ENTRY sidmap_attr_list[];
have to worry about LDAP structure types */
const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key );
-char** get_attr_list( ATTRIB_MAP_ENTRY table[] );
-void free_attr_list( char **list );
+const char** get_attr_list( ATTRIB_MAP_ENTRY table[] );
+void free_attr_list( const char **list );
void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value);
void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
LDAPMod ***mods,
diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c
index 72d6e77ddda..5997d9180ae 100644
--- a/source/lib/account_pol.c
+++ b/source/lib/account_pol.c
@@ -118,8 +118,8 @@ static const struct {
{AP_MIN_PASSWORD_LEN, "min password length"},
{AP_PASSWORD_HISTORY, "password history"},
{AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"},
- {AP_MAX_PASSWORD_AGE, "maximum password age"},
- {AP_MIN_PASSWORD_AGE,"minimum password age"},
+ {AP_MAX_PASSWORD_AGE, "maximum password age (seconds since 1970)"},
+ {AP_MIN_PASSWORD_AGE,"minimum password age (seconds since 1970)"},
{AP_LOCK_ACCOUNT_DURATION, "lockout duration"},
{AP_RESET_COUNT_TIME, "reset count minutes"},
{AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"},
diff --git a/source/lib/adt_tree.c b/source/lib/adt_tree.c
index a5d6380377e..ad763c2be19 100644
--- a/source/lib/adt_tree.c
+++ b/source/lib/adt_tree.c
@@ -19,6 +19,7 @@
*/
#include "includes.h"
+#include "adt_tree.h"
/**************************************************************************
@@ -53,7 +54,7 @@ static BOOL trim_tree_keypath( char *path, char **base, char **new_path )
for comparision of two children
*************************************************************************/
-SORTED_TREE* sorted_tree_init( void *data_p,
+ SORTED_TREE* pathtree_init( void *data_p,
int (cmp_fn)(void*, void*),
void (free_fn)(void*) )
{
@@ -83,7 +84,7 @@ SORTED_TREE* sorted_tree_init( void *data_p,
Delete a tree and free all allocated memory
*************************************************************************/
-static void sorted_tree_destroy_children( TREE_NODE *root )
+static void pathtree_destroy_children( TREE_NODE *root )
{
int i;
@@ -92,7 +93,7 @@ static void sorted_tree_destroy_children( TREE_NODE *root )
for ( i=0; i<root->num_children; i++ )
{
- sorted_tree_destroy_children( root->children[i] );
+ pathtree_destroy_children( root->children[i] );
}
SAFE_FREE( root->children );
@@ -105,10 +106,10 @@ static void sorted_tree_destroy_children( TREE_NODE *root )
Delete a tree and free all allocated memory
*************************************************************************/
-void sorted_tree_destroy( SORTED_TREE *tree )
+ void pathtree_destroy( SORTED_TREE *tree )
{
if ( tree->root )
- sorted_tree_destroy_children( tree->root );
+ pathtree_destroy_children( tree->root );
if ( tree->free_func )
tree->free_func( tree->root );
@@ -120,7 +121,7 @@ void sorted_tree_destroy( SORTED_TREE *tree )
Find the next child given a key string
*************************************************************************/
-static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key )
+static TREE_NODE* pathtree_birth_child( TREE_NODE *node, char* key )
{
TREE_NODE *infant = NULL;
TREE_NODE **siblings;
@@ -144,7 +145,7 @@ static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key )
/* first child */
if ( node->num_children == 1 ) {
- DEBUG(11,("sorted_tree_birth_child: First child of node [%s]! [%s]\n",
+ DEBUG(11,("pathtree_birth_child: First child of node [%s]! [%s]\n",
node->key ? node->key : "NULL", infant->key ));
node->children[0] = infant;
}
@@ -161,14 +162,14 @@ static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key )
for ( i = node->num_children-1; i>=1; i-- )
{
- DEBUG(11,("sorted_tree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n",
+ DEBUG(11,("pathtree_birth_child: Looking for crib; infant -> [%s], child -> [%s]\n",
infant->key, node->children[i-1]->key));
/* the strings should never match assuming that we
- have called sorted_tree_find_child() first */
+ have called pathtree_find_child() first */
if ( StrCaseCmp( infant->key, node->children[i-1]->key ) > 0 ) {
- DEBUG(11,("sorted_tree_birth_child: storing infant in i == [%d]\n",
+ DEBUG(11,("pathtree_birth_child: storing infant in i == [%d]\n",
i));
node->children[i] = infant;
break;
@@ -179,7 +180,7 @@ static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key )
node->children[i] = node->children[i-1];
}
- DEBUG(11,("sorted_tree_birth_child: Exiting loop (i == [%d])\n", i ));
+ DEBUG(11,("pathtree_birth_child: Exiting loop (i == [%d])\n", i ));
/* if we haven't found the correct slot yet, the child
will be first in the list */
@@ -195,24 +196,24 @@ static TREE_NODE* sorted_tree_birth_child( TREE_NODE *node, char* key )
Find the next child given a key string
*************************************************************************/
-static TREE_NODE* sorted_tree_find_child( TREE_NODE *node, char* key )
+static TREE_NODE* pathtree_find_child( TREE_NODE *node, char* key )
{
TREE_NODE *next = NULL;
int i, result;
if ( !node ) {
- DEBUG(0,("sorted_tree_find_child: NULL node passed into function!\n"));
+ DEBUG(0,("pathtree_find_child: NULL node passed into function!\n"));
return NULL;
}
if ( !key ) {
- DEBUG(0,("sorted_tree_find_child: NULL key string passed into function!\n"));
+ DEBUG(0,("pathtree_find_child: NULL key string passed into function!\n"));
return NULL;
}
for ( i=0; i<node->num_children; i++ )
{
- DEBUG(11,("sorted_tree_find_child: child key => [%s]\n",
+ DEBUG(11,("pathtree_find_child: child key => [%s]\n",
node->children[i]->key));
result = StrCaseCmp( node->children[i]->key, key );
@@ -228,7 +229,7 @@ static TREE_NODE* sorted_tree_find_child( TREE_NODE *node, char* key )
break;
}
- DEBUG(11,("sorted_tree_find_child: %s [%s]\n",
+ DEBUG(11,("pathtree_find_child: %s [%s]\n",
next ? "Found" : "Did not find", key ));
return next;
@@ -238,22 +239,22 @@ static TREE_NODE* sorted_tree_find_child( TREE_NODE *node, char* key )
Add a new node into the tree given a key path and a blob of data
*************************************************************************/
-BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p )
+ BOOL pathtree_add( SORTED_TREE *tree, const char *path, void *data_p )
{
char *str, *base, *path2;
TREE_NODE *current, *next;
BOOL ret = True;
- DEBUG(8,("sorted_tree_add: Enter\n"));
+ DEBUG(8,("pathtree_add: Enter\n"));
if ( !path || *path != '/' ) {
- DEBUG(0,("sorted_tree_add: Attempt to add a node with a bad path [%s]\n",
+ DEBUG(0,("pathtree_add: Attempt to add a node with a bad path [%s]\n",
path ? path : "NULL" ));
return False;
}
if ( !tree ) {
- DEBUG(0,("sorted_tree_add: Attempt to add a node to an uninitialized tree!\n"));
+ DEBUG(0,("pathtree_add: Attempt to add a node to an uninitialized tree!\n"));
return False;
}
@@ -262,7 +263,7 @@ BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p )
path++;
path2 = SMB_STRDUP( path );
if ( !path2 ) {
- DEBUG(0,("sorted_tree_add: strdup() failed on string [%s]!?!?!\n", path));
+ DEBUG(0,("pathtree_add: strdup() failed on string [%s]!?!?!\n", path));
return False;
}
@@ -286,11 +287,11 @@ BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p )
/* iterate to the next child--birth it if necessary */
- next = sorted_tree_find_child( current, base );
+ next = pathtree_find_child( current, base );
if ( !next ) {
- next = sorted_tree_birth_child( current, base );
+ next = pathtree_birth_child( current, base );
if ( !next ) {
- DEBUG(0,("sorted_tree_add: Failed to create new child!\n"));
+ DEBUG(0,("pathtree_add: Failed to create new child!\n"));
ret = False;
goto done;
}
@@ -310,10 +311,10 @@ BOOL sorted_tree_add( SORTED_TREE *tree, const char *path, void *data_p )
current->data_p = data_p;
- DEBUG(10,("sorted_tree_add: Successfully added node [%s] to tree\n",
+ DEBUG(10,("pathtree_add: Successfully added node [%s] to tree\n",
path ));
- DEBUG(8,("sorted_tree_add: Exit\n"));
+ DEBUG(8,("pathtree_add: Exit\n"));
done:
SAFE_FREE( path2 );
@@ -325,7 +326,7 @@ done:
Recursive routine to print out all children of a TREE_NODE
*************************************************************************/
-static void sorted_tree_print_children( TREE_NODE *node, int debug, const char *path )
+static void pathtree_print_children( TREE_NODE *node, int debug, const char *path )
{
int i;
int num_children;
@@ -347,7 +348,7 @@ static void sorted_tree_print_children( TREE_NODE *node, int debug, const char *
num_children = node->num_children;
for ( i=0; i<num_children; i++ )
- sorted_tree_print_children( node->children[i], debug, path2 );
+ pathtree_print_children( node->children[i], debug, path2 );
}
@@ -356,7 +357,7 @@ static void sorted_tree_print_children( TREE_NODE *node, int debug, const char *
Dump the kys for a tree to the log file
*************************************************************************/
-void sorted_tree_print_keys( SORTED_TREE *tree, int debug )
+ void pathtree_print_keys( SORTED_TREE *tree, int debug )
{
int i;
int num_children = tree->root->num_children;
@@ -366,7 +367,7 @@ void sorted_tree_print_keys( SORTED_TREE *tree, int debug )
tree->root->data_p ? "data" : "NULL" ));
for ( i=0; i<num_children; i++ ) {
- sorted_tree_print_children( tree->root->children[i], debug,
+ pathtree_print_children( tree->root->children[i], debug,
tree->root->key ? tree->root->key : "ROOT/" );
}
@@ -378,23 +379,23 @@ void sorted_tree_print_keys( SORTED_TREE *tree, int debug )
the tree
*************************************************************************/
-void* sorted_tree_find( SORTED_TREE *tree, char *key )
+ void* pathtree_find( SORTED_TREE *tree, char *key )
{
char *keystr, *base, *str, *p;
TREE_NODE *current;
void *result = NULL;
- DEBUG(10,("sorted_tree_find: Enter [%s]\n", key ? key : "NULL" ));
+ DEBUG(10,("pathtree_find: Enter [%s]\n", key ? key : "NULL" ));
/* sanity checks first */
if ( !key ) {
- DEBUG(0,("sorted_tree_find: Attempt to search tree using NULL search string!\n"));
+ DEBUG(0,("pathtree_find: Attempt to search tree using NULL search string!\n"));
return NULL;
}
if ( !tree ) {
- DEBUG(0,("sorted_tree_find: Attempt to search an uninitialized tree using string [%s]!\n",
+ DEBUG(0,("pathtree_find: Attempt to search an uninitialized tree using string [%s]!\n",
key ? key : "NULL" ));
return NULL;
}
@@ -410,7 +411,7 @@ void* sorted_tree_find( SORTED_TREE *tree, char *key )
keystr = SMB_STRDUP( key );
if ( !keystr ) {
- DEBUG(0,("sorted_tree_find: strdup() failed on string [%s]!?!?!\n", key));
+ DEBUG(0,("pathtree_find: strdup() failed on string [%s]!?!?!\n", key));
return NULL;
}
@@ -428,12 +429,12 @@ void* sorted_tree_find( SORTED_TREE *tree, char *key )
trim_tree_keypath( p, &base, &str );
- DEBUG(11,("sorted_tree_find: [loop] base => [%s], new_path => [%s]\n",
+ DEBUG(11,("pathtree_find: [loop] base => [%s], new_path => [%s]\n",
base, str));
/* iterate to the next child */
- current = sorted_tree_find_child( current, base );
+ current = pathtree_find_child( current, base );
/*
* the idea is that the data_p for a parent should
@@ -452,11 +453,11 @@ void* sorted_tree_find( SORTED_TREE *tree, char *key )
/* result should be the data_p from the lowest match node in the tree */
if ( result )
- DEBUG(11,("sorted_tree_find: Found data_p!\n"));
+ DEBUG(11,("pathtree_find: Found data_p!\n"));
SAFE_FREE( keystr );
- DEBUG(10,("sorted_tree_find: Exit\n"));
+ DEBUG(10,("pathtree_find: Exit\n"));
return result;
}
diff --git a/source/lib/afs.c b/source/lib/afs.c
index 5ff027ee01d..7f79429b9ed 100644
--- a/source/lib/afs.c
+++ b/source/lib/afs.c
@@ -214,12 +214,16 @@ BOOL afs_login(connection_struct *conn)
char *cell;
BOOL result;
char *ticket_str;
+ DOM_SID user_sid;
struct ClearToken ct;
pstrcpy(afs_username, lp_afs_username_map());
standard_sub_conn(conn, afs_username, sizeof(afs_username));
+ if (NT_STATUS_IS_OK(uid_to_sid(&user_sid, conn->uid)))
+ pstring_sub(afs_username, "%s", sid_string_static(&user_sid));
+
/* The pts command always generates completely lower-case user
* names. */
strlower_m(afs_username);
diff --git a/source/lib/interface.c b/source/lib/interface.c
index 8cf11b85039..2bd7d6ddbe0 100644
--- a/source/lib/interface.c
+++ b/source/lib/interface.c
@@ -60,10 +60,12 @@ static void add_interface(struct in_addr ip, struct in_addr nmask)
return;
}
+#if !defined(__s390__)
if (ip_equal(nmask, allones_ip)) {
DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip)));
return;
}
+#endif
iface = SMB_MALLOC_P(struct interface);
if (!iface) return;
@@ -196,7 +198,10 @@ void load_interfaces(void)
exit(1);
}
for (i=0;i<total_probed;i++) {
- if (probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
+ if (
+#if !defined(__s390__)
+ probed_ifaces[i].netmask.s_addr != allones_ip.s_addr &&
+#endif
probed_ifaces[i].ip.s_addr != loopback_ip.s_addr) {
add_interface(probed_ifaces[i].ip,
probed_ifaces[i].netmask);
diff --git a/source/lib/privileges.c b/source/lib/privileges.c
index 3960faecaa9..5a5afa4d72c 100644
--- a/source/lib/privileges.c
+++ b/source/lib/privileges.c
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
Privileges handling functions
- Copyright (C) Jean François Micouleau 1998-2001
+ Copyright (C) Jean François Micouleau 1998-2001
Copyright (C) Simo Sorce 2002-2003
Copyright (C) Gerald (Jerry) Carter 2004
@@ -27,8 +27,8 @@
#define GENERATE_LUID_LOW(x) (x)+1;
-static SE_PRIV se_priv_all = SE_ALL_PRIVS;
-static SE_PRIV se_priv_end = SE_END;
+static const SE_PRIV se_priv_all = SE_ALL_PRIVS;
+static const SE_PRIV se_priv_end = SE_END;
/* Define variables for all privileges so we can use the
SE_PRIV* in the various se_priv_XXX() functions */
@@ -230,8 +230,8 @@ static BOOL get_privileges( const DOM_SID *sid, SE_PRIV *mask )
SMB_ASSERT( data.dsize == sizeof( SE_PRIV ) );
se_priv_copy( mask, (SE_PRIV*)data.dptr );
-
-
+ SAFE_FREE(data.dptr);
+
return True;
}
@@ -503,7 +503,7 @@ NTSTATUS privilege_enumerate_accounts(DOM_SID **sids, int *num_sids)
Add privilege to sid
****************************************************************************/
-BOOL grant_privilege(const DOM_SID *sid, SE_PRIV *priv_mask)
+BOOL grant_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
{
SE_PRIV old_mask, new_mask;
@@ -548,7 +548,7 @@ BOOL grant_privilege_by_name(DOM_SID *sid, const char *name)
Remove privilege from sid
****************************************************************************/
-BOOL revoke_privilege(const DOM_SID *sid, SE_PRIV *priv_mask)
+BOOL revoke_privilege(const DOM_SID *sid, const SE_PRIV *priv_mask)
{
SE_PRIV mask;
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index 7aeecb89d6f..fec6cc23a89 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -230,16 +230,16 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
Return the list of attribute names from a mapping table
**********************************************************************/
- char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
+ const char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
{
- char **names;
+ const char **names;
int i = 0;
while ( table[i].attrib != LDAP_ATTR_LIST_END )
i++;
i++;
- names = SMB_MALLOC_ARRAY( char*, i );
+ names = SMB_MALLOC_ARRAY( const char*, i );
if ( !names ) {
DEBUG(0,("get_attr_list: out of memory\n"));
return NULL;
@@ -259,7 +259,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
Cleanup
********************************************************************/
- void free_attr_list( char **list )
+ void free_attr_list( const char **list )
{
int i = 0;
@@ -888,7 +888,7 @@ static int smbldap_open(struct smbldap_state *ldap_state)
socklen_t len = sizeof(addr);
int sd;
if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 &&
- getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
+ ((getpeername(sd, (struct sockaddr *) &addr, &len) < 0) || addr.sun_family == AF_LOCAL)) {
/* the other end has died. reopen. */
ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL);
ldap_state->ldap_struct = NULL;
@@ -962,8 +962,6 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
if (*rc != LDAP_SERVER_DOWN)
goto no_next;
- now = time(NULL);
-
if (now >= endtime) {
smbldap_close(ldap_state);
*rc = LDAP_TIMEOUT;
@@ -986,7 +984,6 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
*attempts += 1;
- smbldap_close(ldap_state);
open_rc = smbldap_open(ldap_state);
if (open_rc == LDAP_SUCCESS) {
@@ -1017,7 +1014,7 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
int smbldap_search(struct smbldap_state *ldap_state,
const char *base, int scope, const char *filter,
- char *attrs[], int attrsonly,
+ const char *attrs[], int attrsonly,
LDAPMessage **res)
{
int rc = LDAP_SERVER_DOWN;
@@ -1154,7 +1151,7 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
run the search by name.
******************************************************************/
int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter,
- char **search_attr, LDAPMessage ** result)
+ const char **search_attr, LDAPMessage ** result)
{
int scope = LDAP_SCOPE_SUBTREE;
int rc;
@@ -1261,7 +1258,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
int ldap_op;
LDAPMessage *result = NULL;
int num_result;
- char **attr_list;
+ const char **attr_list;
uid_t u_low, u_high;
gid_t g_low, g_high;
uint32 rid_low, rid_high;
@@ -1376,7 +1373,7 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
pstring filter;
int rc;
- char **attr_list;
+ const char **attr_list;
int count;
pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))",
diff --git a/source/lib/time.c b/source/lib/time.c
index e7b537151ff..84004a099be 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -56,8 +56,9 @@ time_t get_time_t_max(void)
}
/*******************************************************************
-a gettimeofday wrapper
+ A gettimeofday wrapper.
********************************************************************/
+
void GetTimeOfDay(struct timeval *tval)
{
#ifdef HAVE_GETTIMEOFDAY_TZ
@@ -70,43 +71,45 @@ void GetTimeOfDay(struct timeval *tval)
#define TM_YEAR_BASE 1900
/*******************************************************************
-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 + (TM_YEAR_BASE - 1);
- int by = b->tm_year + (TM_YEAR_BASE - 1);
- int intervening_leap_days =
- (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
- int years = ay - by;
- int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
- int hours = 24*days + (a->tm_hour - b->tm_hour);
- int minutes = 60*hours + (a->tm_min - b->tm_min);
- int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
+ int ay = a->tm_year + (TM_YEAR_BASE - 1);
+ int by = b->tm_year + (TM_YEAR_BASE - 1);
+ int intervening_leap_days = (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
+ int years = ay - by;
+ int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
+ int hours = 24*days + (a->tm_hour - b->tm_hour);
+ int minutes = 60*hours + (a->tm_min - b->tm_min);
+ int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
- return seconds;
+ return seconds;
}
/*******************************************************************
- 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.
+******************************************************************/
+
static int TimeZone(time_t t)
{
- struct tm *tm = gmtime(&t);
- struct tm tm_utc;
- if (!tm)
- return 0;
- tm_utc = *tm;
- tm = localtime(&t);
- if (!tm)
- return 0;
- return tm_diff(&tm_utc,tm);
-
+ struct tm *tm = gmtime(&t);
+ struct tm tm_utc;
+ if (!tm)
+ return 0;
+ tm_utc = *tm;
+ tm = localtime(&t);
+ if (!tm)
+ return 0;
+ return tm_diff(&tm_utc,tm);
}
static BOOL done_serverzone_init;
-/* Return the smb serverzone value */
+/*******************************************************************
+ Return the smb serverzone value.
+******************************************************************/
static int get_serverzone(void)
{
@@ -127,7 +130,9 @@ static int get_serverzone(void)
return serverzone;
}
-/* Re-read the smb serverzone value */
+/*******************************************************************
+ Re-read the smb serverzone value.
+******************************************************************/
static struct timeval start_time_hires;
@@ -161,175 +166,182 @@ void get_process_uptime(struct timeval *ret_time)
}
/*******************************************************************
-return the same value as TimeZone, but it should be more efficient.
+ Return the same value as TimeZone, but it should be more efficient.
-We keep a table of DST offsets to prevent calling localtime() on each
-call of this function. This saves a LOT of time on many unixes.
+ We keep a table of DST offsets to prevent calling localtime() on each
+ call of this function. This saves a LOT of time on many unixes.
-Updated by Paul Eggert <eggert@twinsun.com>
+ Updated by Paul Eggert <eggert@twinsun.com>
********************************************************************/
+
static int TimeZoneFaster(time_t t)
{
- static struct dst_table {time_t start,end; int zone;} *tdt, *dst_table = NULL;
- static int table_size = 0;
- int i;
- int zone = 0;
+ static struct dst_table {time_t start,end; int zone;} *tdt, *dst_table = NULL;
+ static int table_size = 0;
+ int i;
+ int zone = 0;
- if (t == 0) t = time(NULL);
+ if (t == 0)
+ t = time(NULL);
- /* Tunis has a 8 day DST region, we need to be careful ... */
+ /* Tunis has a 8 day DST region, we need to be careful ... */
#define MAX_DST_WIDTH (365*24*60*60)
#define MAX_DST_SKIP (7*24*60*60)
- for (i=0;i<table_size;i++)
- if (t >= dst_table[i].start && t <= dst_table[i].end) break;
-
- if (i<table_size) {
- zone = dst_table[i].zone;
- } else {
- time_t low,high;
-
- zone = TimeZone(t);
- tdt = SMB_REALLOC_ARRAY(dst_table, struct dst_table, i+1);
- if (!tdt) {
- DEBUG(0,("TimeZoneFaster: out of memory!\n"));
- SAFE_FREE(dst_table);
- table_size = 0;
- } else {
- dst_table = tdt;
- table_size++;
-
- dst_table[i].zone = zone;
- dst_table[i].start = dst_table[i].end = t;
+ for (i=0;i<table_size;i++)
+ if (t >= dst_table[i].start && t <= dst_table[i].end)
+ break;
+
+ if (i<table_size) {
+ zone = dst_table[i].zone;
+ } else {
+ time_t low,high;
+
+ zone = TimeZone(t);
+ tdt = SMB_REALLOC_ARRAY(dst_table, struct dst_table, i+1);
+ if (!tdt) {
+ DEBUG(0,("TimeZoneFaster: out of memory!\n"));
+ SAFE_FREE(dst_table);
+ table_size = 0;
+ } else {
+ dst_table = tdt;
+ table_size++;
+
+ dst_table[i].zone = zone;
+ dst_table[i].start = dst_table[i].end = t;
- /* no entry will cover more than 6 months */
- low = t - MAX_DST_WIDTH/2;
- if (t < low)
- low = TIME_T_MIN;
+ /* no entry will cover more than 6 months */
+ low = t - MAX_DST_WIDTH/2;
+ if (t < low)
+ low = TIME_T_MIN;
- high = t + MAX_DST_WIDTH/2;
- if (high < t)
- high = TIME_T_MAX;
+ high = t + MAX_DST_WIDTH/2;
+ if (high < t)
+ high = TIME_T_MAX;
- /* widen the new entry using two bisection searches */
- while (low+60*60 < dst_table[i].start) {
- if (dst_table[i].start - low > MAX_DST_SKIP*2)
- t = dst_table[i].start - MAX_DST_SKIP;
- else
- t = low + (dst_table[i].start-low)/2;
- if (TimeZone(t) == zone)
- dst_table[i].start = t;
- else
- low = t;
- }
-
- while (high-60*60 > dst_table[i].end) {
- if (high - dst_table[i].end > MAX_DST_SKIP*2)
- t = dst_table[i].end + MAX_DST_SKIP;
- else
- t = high - (high-dst_table[i].end)/2;
- if (TimeZone(t) == zone)
- dst_table[i].end = t;
- else
- high = t;
- }
+ /* widen the new entry using two bisection searches */
+ while (low+60*60 < dst_table[i].start) {
+ if (dst_table[i].start - low > MAX_DST_SKIP*2)
+ t = dst_table[i].start - MAX_DST_SKIP;
+ else
+ t = low + (dst_table[i].start-low)/2;
+ if (TimeZone(t) == zone)
+ dst_table[i].start = t;
+ else
+ low = t;
+ }
+
+ while (high-60*60 > dst_table[i].end) {
+ if (high - dst_table[i].end > MAX_DST_SKIP*2)
+ t = dst_table[i].end + MAX_DST_SKIP;
+ else
+ t = high - (high-dst_table[i].end)/2;
+ if (TimeZone(t) == zone)
+ dst_table[i].end = t;
+ else
+ high = t;
+ }
#if 0
DEBUG(1,("Added DST entry from %s ",
asctime(localtime(&dst_table[i].start))));
DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)),
dst_table[i].zone));
#endif
- }
- }
- return zone;
+ }
+ }
+ return zone;
}
/****************************************************************************
- return the UTC offset in seconds west of UTC, adjusted for extra time offset
- **************************************************************************/
+ Return the UTC offset in seconds west of UTC, adjusted for extra time offset.
+**************************************************************************/
+
int TimeDiff(time_t t)
{
- return TimeZoneFaster(t) + 60*extra_time_offset;
+ return TimeZoneFaster(t) + 60*extra_time_offset;
}
-
/****************************************************************************
- return the UTC offset in seconds west of UTC, adjusted for extra time
- offset, for a local time value. If ut = lt + LocTimeDiff(lt), then
- lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
- daylight savings transitions because some local times are ambiguous.
- LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
- +**************************************************************************/
+ Return the UTC offset in seconds west of UTC, adjusted for extra time
+ offset, for a local time value. If ut = lt + LocTimeDiff(lt), then
+ lt = ut - TimeDiff(ut), but the converse does not necessarily hold near
+ daylight savings transitions because some local times are ambiguous.
+ LocTimeDiff(t) equals TimeDiff(t) except near daylight savings transitions.
+**************************************************************************/
+
static int LocTimeDiff(time_t lte)
{
- time_t lt = lte - 60*extra_time_offset;
- int d = TimeZoneFaster(lt);
- time_t t = lt + d;
+ time_t lt = lte - 60*extra_time_offset;
+ int d = TimeZoneFaster(lt);
+ time_t t = lt + d;
- /* if overflow occurred, ignore all the adjustments so far */
- if (((lte < lt) ^ (extra_time_offset < 0)) | ((t < lt) ^ (d < 0)))
- t = lte;
+ /* if overflow occurred, ignore all the adjustments so far */
+ if (((lte < lt) ^ (extra_time_offset < 0)) | ((t < lt) ^ (d < 0)))
+ t = lte;
- /* now t should be close enough to the true UTC to yield the right answer */
- return TimeDiff(t);
+ /* now t should be close enough to the true UTC to yield the right answer */
+ return TimeDiff(t);
}
-
/****************************************************************************
-try to optimise the localtime call, it can be quite expensive on some machines
+ Try to optimise the localtime call, it can be quite expensive on some machines.
****************************************************************************/
+
struct tm *LocalTime(time_t *t)
{
- time_t t2 = *t;
+ time_t t2 = *t;
- t2 -= TimeDiff(t2);
+ t2 -= TimeDiff(t2);
- return(gmtime(&t2));
+ return(gmtime(&t2));
}
#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
/****************************************************************************
-interpret an 8 byte "filetime" structure to a time_t
-It's originally in "100ns units since jan 1st 1601"
+ Interpret an 8 byte "filetime" structure to a time_t
+ It's originally in "100ns units since jan 1st 1601"
+
+ An 8 byte value of 0xffffffffffffffff will be returned as (time_t)0.
-It appears to be kludge-GMT (at least for file listings). This means
-its the GMT you get by taking a localtime and adding the
-serverzone. This is NOT the same as GMT in some cases. This routine
-converts this to real GMT.
+ It appears to be kludge-GMT (at least for file listings). This means
+ its the GMT you get by taking a localtime and adding the
+ serverzone. This is NOT the same as GMT in some cases. This routine
+ converts this to real GMT.
****************************************************************************/
+
time_t nt_time_to_unix(NTTIME *nt)
{
- double d;
- time_t ret;
- /* The next two lines are a fix needed for the
- broken SCO compiler. JRA. */
- time_t l_time_min = TIME_T_MIN;
- time_t l_time_max = TIME_T_MAX;
+ double d;
+ time_t ret;
+ /* The next two lines are a fix needed for the
+ broken SCO compiler. JRA. */
+ time_t l_time_min = TIME_T_MIN;
+ time_t l_time_max = TIME_T_MAX;
- if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff))
- return(0);
+ if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff))
+ return(0);
- d = ((double)nt->high)*4.0*(double)(1<<30);
- d += (nt->low&0xFFF00000);
- d *= 1.0e-7;
+ d = ((double)nt->high)*4.0*(double)(1<<30);
+ d += (nt->low&0xFFF00000);
+ d *= 1.0e-7;
- /* now adjust by 369 years to make the secs since 1970 */
- d -= TIME_FIXUP_CONSTANT;
+ /* now adjust by 369 years to make the secs since 1970 */
+ d -= TIME_FIXUP_CONSTANT;
- if (d <= l_time_min)
- return (l_time_min);
+ if (d <= l_time_min)
+ return (l_time_min);
- if (d >= l_time_max)
- return (l_time_max);
+ if (d >= l_time_max)
+ return (l_time_max);
- ret = (time_t)(d+0.5);
+ ret = (time_t)(d+0.5);
- /* this takes us from kludge-GMT to real GMT */
- ret -= get_serverzone();
- ret += LocTimeDiff(ret);
+ /* this takes us from kludge-GMT to real GMT */
+ ret -= get_serverzone();
+ ret += LocTimeDiff(ret);
- return(ret);
+ return(ret);
}
/****************************************************************************
@@ -374,38 +386,42 @@ time_t nt_time_to_unix_abs(NTTIME *nt)
}
/****************************************************************************
-interprets an nt time into a unix time_t
+ Interprets an nt time into a unix time_t.
+ Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
+ will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
****************************************************************************/
+
time_t interpret_long_date(char *p)
{
NTTIME nt;
nt.low = IVAL(p,0);
nt.high = IVAL(p,4);
+ if (nt.low == 0xFFFFFFFF && nt.high == 0xFFFFFFFF) {
+ return (time_t)-1;
+ }
return nt_time_to_unix(&nt);
}
/****************************************************************************
-put a 8 byte filetime from a time_t
-This takes real GMT as input and converts to kludge-GMT
+ Put a 8 byte filetime from a time_t
+ This takes real GMT as input and converts to kludge-GMT
****************************************************************************/
+
void unix_to_nt_time(NTTIME *nt, time_t t)
{
double d;
- if (t==0)
- {
+ if (t==0) {
nt->low = 0;
nt->high = 0;
return;
}
- if (t == TIME_T_MAX)
- {
+ if (t == TIME_T_MAX) {
nt->low = 0xffffffff;
nt->high = 0x7fffffff;
return;
}
- if (t == -1)
- {
+ if (t == -1) {
nt->low = 0xffffffff;
nt->high = 0xffffffff;
return;
@@ -465,9 +481,10 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
}
/****************************************************************************
-take a Unix time and convert to an NTTIME structure and place in buffer
-pointed to by p.
+ Take a Unix time and convert to an NTTIME structure and place in buffer
+ pointed to by p.
****************************************************************************/
+
void put_long_date(char *p,time_t t)
{
NTTIME nt;
@@ -477,181 +494,191 @@ void put_long_date(char *p,time_t t)
}
/****************************************************************************
-check if it's a null mtime
+ Check if it's a null mtime.
****************************************************************************/
+
BOOL null_mtime(time_t mtime)
{
- if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
- return(True);
- return(False);
+ if (mtime == 0 || mtime == (time_t)0xFFFFFFFF || mtime == (time_t)-1)
+ return(True);
+ return(False);
}
/*******************************************************************
- create a 16 bit dos packed date
+ Create a 16 bit dos packed date.
********************************************************************/
+
static uint16 make_dos_date1(struct tm *t)
{
- uint16 ret=0;
- ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
- ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
- return(ret);
+ uint16 ret=0;
+ ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
+ ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
+ return(ret);
}
/*******************************************************************
- create a 16 bit dos packed time
+ Create a 16 bit dos packed time.
********************************************************************/
+
static uint16 make_dos_time1(struct tm *t)
{
- uint16 ret=0;
- ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
- ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
- return(ret);
+ uint16 ret=0;
+ ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
+ ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
+ return(ret);
}
/*******************************************************************
- create a 32 bit dos packed date/time from some parameters
- This takes a GMT time and returns a packed localtime structure
+ Create a 32 bit dos packed date/time from some parameters.
+ This takes a GMT time and returns a packed localtime structure.
********************************************************************/
+
static uint32 make_dos_date(time_t unixdate)
{
- struct tm *t;
- uint32 ret=0;
+ struct tm *t;
+ uint32 ret=0;
- t = LocalTime(&unixdate);
- if (!t)
- return 0xFFFFFFFF;
+ t = LocalTime(&unixdate);
+ if (!t)
+ return 0xFFFFFFFF;
- ret = make_dos_date1(t);
- ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
+ ret = make_dos_date1(t);
+ ret = ((ret&0xFFFF)<<16) | make_dos_time1(t);
- return(ret);
+ return(ret);
}
/*******************************************************************
-put a dos date into a buffer (time/date format)
-This takes GMT time and puts local time in the buffer
+ Put a dos date into a buffer (time/date format).
+ This takes GMT time and puts local time in the buffer.
********************************************************************/
+
void put_dos_date(char *buf,int offset,time_t unixdate)
{
- uint32 x = make_dos_date(unixdate);
- SIVAL(buf,offset,x);
+ uint32 x = make_dos_date(unixdate);
+ SIVAL(buf,offset,x);
}
/*******************************************************************
-put a dos date into a buffer (date/time format)
-This takes GMT time and puts local time in the buffer
+ Put a dos date into a buffer (date/time format).
+ This takes GMT time and puts local time in the buffer.
********************************************************************/
+
void put_dos_date2(char *buf,int offset,time_t unixdate)
{
- uint32 x = make_dos_date(unixdate);
- x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
- SIVAL(buf,offset,x);
+ uint32 x = make_dos_date(unixdate);
+ x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
+ SIVAL(buf,offset,x);
}
/*******************************************************************
-put a dos 32 bit "unix like" date into a buffer. This routine takes
-GMT and converts it to LOCAL time before putting it (most SMBs assume
-localtime for this sort of date)
+ Put a dos 32 bit "unix like" date into a buffer. This routine takes
+ GMT and converts it to LOCAL time before putting it (most SMBs assume
+ localtime for this sort of date)
********************************************************************/
+
void put_dos_date3(char *buf,int offset,time_t unixdate)
{
- if (!null_mtime(unixdate))
- unixdate -= TimeDiff(unixdate);
- SIVAL(buf,offset,unixdate);
+ if (!null_mtime(unixdate))
+ unixdate -= TimeDiff(unixdate);
+ SIVAL(buf,offset,unixdate);
}
/*******************************************************************
- interpret a 32 bit dos packed date/time to some parameters
+ Interpret a 32 bit dos packed date/time to some parameters.
********************************************************************/
+
static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
{
- uint32 p0,p1,p2,p3;
+ uint32 p0,p1,p2,p3;
- p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
- p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
+ p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
+ p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
- *second = 2*(p0 & 0x1F);
- *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
- *hour = (p1>>3)&0xFF;
- *day = (p2&0x1F);
- *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
- *year = ((p3>>1)&0xFF) + 80;
+ *second = 2*(p0 & 0x1F);
+ *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
+ *hour = (p1>>3)&0xFF;
+ *day = (p2&0x1F);
+ *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
+ *year = ((p3>>1)&0xFF) + 80;
}
/*******************************************************************
- create a unix date (int GMT) from a dos date (which is actually in
- localtime)
+ Create a unix date (int GMT) from a dos date (which is actually in
+ localtime).
********************************************************************/
+
time_t make_unix_date(void *date_ptr)
{
- uint32 dos_date=0;
- struct tm t;
- time_t ret;
+ uint32 dos_date=0;
+ struct tm t;
+ time_t ret;
- dos_date = IVAL(date_ptr,0);
+ dos_date = IVAL(date_ptr,0);
- if (dos_date == 0) return(0);
+ if (dos_date == 0)
+ return(0);
- interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
- &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
- t.tm_isdst = -1;
+ interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
+ &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
+ t.tm_isdst = -1;
- /* mktime() also does the local to GMT time conversion for us */
- ret = mktime(&t);
+ /* mktime() also does the local to GMT time conversion for us */
+ ret = mktime(&t);
- return(ret);
+ return(ret);
}
/*******************************************************************
-like make_unix_date() but the words are reversed
+ Like make_unix_date() but the words are reversed.
********************************************************************/
+
time_t make_unix_date2(void *date_ptr)
{
- uint32 x,x2;
+ uint32 x,x2;
- x = IVAL(date_ptr,0);
- x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
- SIVAL(&x,0,x2);
+ x = IVAL(date_ptr,0);
+ x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
+ SIVAL(&x,0,x2);
- return(make_unix_date((void *)&x));
+ return(make_unix_date((void *)&x));
}
/*******************************************************************
- create a unix GMT date from a dos date in 32 bit "unix like" format
- these generally arrive as localtimes, with corresponding DST
- ******************************************************************/
+ Create a unix GMT date from a dos date in 32 bit "unix like" format
+ these generally arrive as localtimes, with corresponding DST.
+******************************************************************/
+
time_t make_unix_date3(void *date_ptr)
{
- time_t t = (time_t)IVAL(date_ptr,0);
- if (!null_mtime(t))
- t += LocTimeDiff(t);
- return(t);
+ time_t t = (time_t)IVAL(date_ptr,0);
+ if (!null_mtime(t))
+ t += LocTimeDiff(t);
+ return(t);
}
-
/***************************************************************************
-return a HTTP/1.0 time string
- ***************************************************************************/
+ Return a HTTP/1.0 time string.
+***************************************************************************/
+
char *http_timestring(time_t t)
{
- static fstring buf;
- struct tm *tm = LocalTime(&t);
+ static fstring buf;
+ struct tm *tm = LocalTime(&t);
- if (!tm)
- slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t);
- else
+ if (!tm)
+ slprintf(buf,sizeof(buf)-1,"%ld seconds since the Epoch",(long)t);
+ else
#ifndef HAVE_STRFTIME
- fstrcpy(buf, asctime(tm));
- if(buf[strlen(buf)-1] == '\n')
- buf[strlen(buf)-1] = 0;
+ fstrcpy(buf, asctime(tm));
+ if(buf[strlen(buf)-1] == '\n')
+ buf[strlen(buf)-1] = 0;
#else /* !HAVE_STRFTIME */
- strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
+ strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
#endif /* !HAVE_STRFTIME */
- return buf;
+ return buf;
}
-
-
/****************************************************************************
Return the date and time as a string
****************************************************************************/
@@ -710,32 +737,32 @@ char *timestring(BOOL hires)
}
/****************************************************************************
- return the best approximation to a 'create time' under UNIX from a stat
- structure.
+ Return the best approximation to a 'create time' under UNIX from a stat
+ structure.
****************************************************************************/
time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
{
- time_t ret, ret1;
+ time_t ret, ret1;
- if(S_ISDIR(st->st_mode) && fake_dirs)
- return (time_t)315493200L; /* 1/1/1980 */
+ if(S_ISDIR(st->st_mode) && fake_dirs)
+ return (time_t)315493200L; /* 1/1/1980 */
- ret = MIN(st->st_ctime, st->st_mtime);
- ret1 = MIN(ret, st->st_atime);
+ ret = MIN(st->st_ctime, st->st_mtime);
+ ret1 = MIN(ret, st->st_atime);
- if(ret1 != (time_t)0)
- return ret1;
+ if(ret1 != (time_t)0)
+ return ret1;
- /*
- * One of ctime, mtime or atime was zero (probably atime).
- * Just return MIN(ctime, mtime).
- */
- return ret;
+ /*
+ * One of ctime, mtime or atime was zero (probably atime).
+ * Just return MIN(ctime, mtime).
+ */
+ return ret;
}
/****************************************************************************
-initialise an NTTIME to -1, which means "unknown" or "don't expire"
+ Initialise an NTTIME to -1, which means "unknown" or "don't expire".
****************************************************************************/
void init_nt_time(NTTIME *nt)
@@ -745,8 +772,9 @@ void init_nt_time(NTTIME *nt)
}
/****************************************************************************
-check if NTTIME is 0
+ Check if NTTIME is 0.
****************************************************************************/
+
BOOL nt_time_is_zero(NTTIME *nt)
{
if(nt->high==0)
@@ -754,6 +782,10 @@ BOOL nt_time_is_zero(NTTIME *nt)
return False;
}
+/****************************************************************************
+ Return a timeval difference in usec.
+****************************************************************************/
+
SMB_BIG_INT usec_time_diff(struct timeval *larget, struct timeval *smallt)
{
SMB_BIG_INT sec_diff = larget->tv_sec - smallt->tv_sec;
diff --git a/source/lib/util.c b/source/lib/util.c
index 455f87aaab8..42ead313a92 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -617,7 +617,7 @@ void unix_clean_name(char *s)
Make a dir struct.
****************************************************************************/
-void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date, BOOL case_sensitive)
+void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,int mode,time_t date)
{
char *p;
pstring mask2;
@@ -641,7 +641,7 @@ void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T si
put_dos_date(buf,22,date);
SSVAL(buf,26,size & 0xFFFF);
SSVAL(buf,28,(size >> 16)&0xFFFF);
- push_ascii(buf+30,fname,12, case_sensitive ? 0 : STR_UPPER);
+ push_ascii(buf+30,fname,12,0);
DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
}
@@ -1534,6 +1534,11 @@ void smb_panic2(const char *why, BOOL decrement_pid_count )
ZERO_ARRAY(names);
ZERO_ARRAY(namebuf);
+ /* We need to be root so we can open our /proc entry to walk
+ * our stack. It also helps when we want to dump core.
+ */
+ become_root();
+
for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
names[i] = namebuf + (i * NAMESIZE);
}
diff --git a/source/lib/util_seaccess.c b/source/lib/util_seaccess.c
index cb0f46e2f9d..b5a9010b5c4 100644
--- a/source/lib/util_seaccess.c
+++ b/source/lib/util_seaccess.c
@@ -316,42 +316,3 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token,
return False;
}
-
-/*******************************************************************
- samr_make_sam_obj_sd
- ********************************************************************/
-
-NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid;
- DOM_SID act_sid;
-
- SEC_ACE ace[3];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_SAM_EXECUTE | GENERIC_RIGHTS_SAM_READ);
- init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
- init_sec_access(&mask, GENERIC_RIGHTS_SAM_ALL_ACCESS);
- init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 60fe1306c8e..f99c2d1fb32 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -1558,8 +1558,8 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
size_t strnlen(const char *s, size_t n)
{
- int i;
- for (i=0; s[i] && i<n; i++)
+ size_t i;
+ for (i=0; i<n && s[i] != '\0'; i++)
/* noop */ ;
return i;
}
diff --git a/source/lib/util_unistr.c b/source/lib/util_unistr.c
index bb9d69b164d..55a21ebcbbc 100644
--- a/source/lib/util_unistr.c
+++ b/source/lib/util_unistr.c
@@ -454,16 +454,20 @@ smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n)
smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
{
smb_ucs2_t *r;
- size_t slen, inslen;
+ size_t inslen;
+
+ if (!s || !*s || !ins || !*ins)
+ return NULL;
- if (!s || !*s || !ins || !*ins) return NULL;
- slen = strlen_w(s);
inslen = strlen_w(ins);
r = (smb_ucs2_t *)s;
+
while ((r = strchr_w(r, *ins))) {
- if (strncmp_w(r, ins, inslen) == 0) return r;
+ if (strncmp_w(r, ins, inslen) == 0)
+ return r;
r++;
}
+
return NULL;
}
@@ -736,16 +740,20 @@ smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
{
smb_ucs2_t *r;
- size_t slen, inslen;
+ size_t inslen;
+
+ if (!s || !*s || !ins || !*ins)
+ return NULL;
- if (!s || !*s || !ins || !*ins) return NULL;
- slen = strlen_w(s);
inslen = strlen(ins);
r = (smb_ucs2_t *)s;
+
while ((r = strchr_w(r, UCS2_CHAR(*ins)))) {
- if (strncmp_wa(r, ins, inslen) == 0) return r;
+ if (strncmp_wa(r, ins, inslen) == 0)
+ return r;
r++;
}
+
return NULL;
}
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index c9bba725246..6e1b011c37c 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -112,7 +112,7 @@ static int ldap_search_with_timeout(LDAP *ld,
TODO : add a negative connection cache in here leveraged off of the one
found in the rpc code. --jerry
*/
-static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
+BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
{
char *srv;
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 78cf9028c68..01a92a89ba4 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -151,7 +151,7 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
if (cli->use_level_II_oplocks)
capabilities |= CAP_LEVEL_II_OPLOCKS;
- capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX));
+ capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
return capabilities;
}
@@ -972,6 +972,9 @@ BOOL cli_send_tconX(struct cli_state *cli,
/* almost certainly win95 - enable bug fixes */
cli->win95 = True;
}
+
+ if ( cli->protocol >= PROTOCOL_LANMAN2 )
+ cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS);
cli->cnum = SVAL(cli->inbuf,smb_tid);
return True;
@@ -993,7 +996,12 @@ BOOL cli_tdis(struct cli_state *cli)
if (!cli_receive_smb(cli))
return False;
- return !cli_is_error(cli);
+ if (cli_is_error(cli)) {
+ return False;
+ }
+
+ cli->cnum = -1;
+ return True;
}
/****************************************************************************
diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c
new file mode 100644
index 00000000000..1b0860b675d
--- /dev/null
+++ b/source/libsmb/clidfs.c
@@ -0,0 +1,600 @@
+/*
+ Unix SMB/CIFS implementation.
+ client connect/disconnect routines
+ Copyright (C) Andrew Tridgell 1994-1998
+ Copyright (C) Gerald (Jerry) Carter 2004
+
+ 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.
+*/
+
+#define NO_SYSLOG
+
+#include "includes.h"
+
+
+struct client_connection {
+ struct client_connection *prev, *next;
+ struct cli_state *cli;
+};
+
+/* global state....globals reek! */
+
+static pstring username;
+static pstring password;
+static BOOL use_kerberos;
+static BOOL got_pass;
+static int signing_state;
+
+static int port;
+static int name_type = 0x20;
+static int max_protocol = PROTOCOL_NT1;
+static BOOL have_ip;
+static struct in_addr dest_ip;
+
+static struct client_connection *connections;
+
+/********************************************************************
+ Return a connection to a server.
+********************************************************************/
+
+static struct cli_state *do_connect( const char *server, const char *share,
+ BOOL show_sessetup )
+{
+ struct cli_state *c;
+ struct nmb_name called, calling;
+ const char *server_n;
+ struct in_addr ip;
+ pstring servicename;
+ char *sharename;
+
+ /* 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 NULL;
+ *sharename = 0;
+ sharename++;
+ }
+
+ server_n = server;
+
+ zero_ip(&ip);
+
+ make_nmb_name(&calling, global_myname(), 0x0);
+ make_nmb_name(&called , server, name_type);
+
+ again:
+ zero_ip(&ip);
+ if (have_ip)
+ ip = dest_ip;
+
+ /* have to open a new connection */
+ if (!(c=cli_initialise(NULL)) || (cli_set_port(c, port) != port) ||
+ !cli_connect(c, server_n, &ip)) {
+ d_printf("Connection to %s failed\n", server_n);
+ return NULL;
+ }
+
+ c->protocol = max_protocol;
+ c->use_kerberos = use_kerberos;
+ cli_setup_signing_state(c, signing_state);
+
+
+ if (!cli_session_request(c, &calling, &called)) {
+ char *p;
+ d_printf("session request to %s failed (%s)\n",
+ called.name, cli_errstr(c));
+ cli_shutdown(c);
+ if ((p=strchr_m(called.name, '.'))) {
+ *p = 0;
+ goto again;
+ }
+ if (strcmp(called.name, "*SMBSERVER")) {
+ make_nmb_name(&called , "*SMBSERVER", 0x20);
+ goto again;
+ }
+ return NULL;
+ }
+
+ DEBUG(4,(" session request ok\n"));
+
+ if (!cli_negprot(c)) {
+ d_printf("protocol negotiation failed\n");
+ cli_shutdown(c);
+ return NULL;
+ }
+
+ if (!got_pass) {
+ char *pass = getpass("Password: ");
+ if (pass) {
+ pstrcpy(password, pass);
+ got_pass = 1;
+ }
+ }
+
+ if (!cli_session_setup(c, username,
+ password, strlen(password),
+ password, strlen(password),
+ lp_workgroup())) {
+ /* if a password was not supplied then try again with a null username */
+ if (password[0] || !username[0] || use_kerberos ||
+ !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) {
+ d_printf("session setup failed: %s\n", cli_errstr(c));
+ if (NT_STATUS_V(cli_nt_error(c)) ==
+ NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED))
+ d_printf("did you forget to run kinit?\n");
+ cli_shutdown(c);
+ return NULL;
+ }
+ d_printf("Anonymous login successful\n");
+ }
+
+ if ( show_sessetup ) {
+ if (*c->server_domain) {
+ DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",
+ c->server_domain,c->server_os,c->server_type));
+ } else if (*c->server_os || *c->server_type){
+ DEBUG(1,("OS=[%s] Server=[%s]\n",
+ c->server_os,c->server_type));
+ }
+ }
+ DEBUG(4,(" session setup ok\n"));
+
+ if (!cli_send_tconX(c, sharename, "?????",
+ password, strlen(password)+1)) {
+ d_printf("tree connect failed: %s\n", cli_errstr(c));
+ cli_shutdown(c);
+ return NULL;
+ }
+
+ DEBUG(4,(" tconx ok\n"));
+
+ return c;
+}
+
+/********************************************************************
+ Add a new connection to the list
+********************************************************************/
+
+static struct cli_state* cli_cm_connect( const char *server, const char *share,
+ BOOL show_hdr )
+{
+ struct client_connection *node;
+
+ node = SMB_XMALLOC_P( struct client_connection );
+
+ node->cli = do_connect( server, share, show_hdr );
+
+ if ( !node->cli ) {
+ SAFE_FREE( node );
+ return NULL;
+ }
+
+ DLIST_ADD( connections, node );
+
+ return node->cli;
+
+}
+
+/********************************************************************
+ Return a connection to a server.
+********************************************************************/
+
+static struct cli_state* cli_cm_find( const char *server, const char *share )
+{
+ struct client_connection *p;
+
+ for ( p=connections; p; p=p->next ) {
+ if ( strequal(server, p->cli->desthost) && strequal(share,p->cli->share) )
+ return p->cli;
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ open a client connection to a \\server\share. Set's the current *cli
+ 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 *c;
+
+ /* try to reuse an existing connection */
+
+ c = cli_cm_find( server, share );
+
+ if ( !c )
+ c = cli_cm_connect( server, share, show_hdr );
+
+ return c;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+void cli_cm_shutdown( void )
+{
+
+ struct client_connection *p, *x;
+
+ for ( p=connections; p; ) {
+ cli_shutdown( p->cli );
+ x = p;
+ p = p->next;
+
+ SAFE_FREE( x );
+ }
+
+ connections = NULL;
+
+ return;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+void cli_cm_display(void)
+{
+ struct client_connection *p;
+ int i;
+
+ for ( p=connections,i=0; p; p=p->next,i++ ) {
+ d_printf("%d:\tserver=%s, share=%s\n",
+ i, p->cli->desthost, p->cli->share );
+ }
+}
+
+/****************************************************************************
+****************************************************************************/
+
+void cli_cm_set_credentials( struct user_auth_info *user )
+{
+ pstrcpy( username, user->username );
+
+ if ( user->got_pass ) {
+ pstrcpy( password, user->password );
+ got_pass = True;
+ }
+
+ use_kerberos = user->use_kerberos;
+ signing_state = user->signing_state;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+void cli_cm_set_port( int port_number )
+{
+ port = port_number;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+void cli_cm_set_dest_name_type( int type )
+{
+ name_type = type;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+void cli_cm_set_dest_ip(struct in_addr ip )
+{
+ dest_ip = ip;
+ have_ip = True;
+}
+
+/********************************************************************
+ split a dfs path into the server and share name components
+********************************************************************/
+
+static void split_dfs_path( const char *nodepath, fstring server, fstring share )
+{
+ char *p;
+ pstring path;
+
+ pstrcpy( path, nodepath );
+
+ if ( path[0] != '\\' )
+ return;
+
+ p = strrchr_m( path, '\\' );
+
+ if ( !p )
+ return;
+
+ *p = '\0';
+ p++;
+
+ 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
+ terminated string
+****************************************************************************/
+
+static void clean_path( pstring clean, const char *path )
+{
+ int len;
+ char *p;
+ pstring newpath;
+
+ pstrcpy( newpath, path );
+ p = newpath;
+
+ while ( p ) {
+ /* first check for '*' */
+
+ p = strrchr_m( newpath, '*' );
+ if ( p ) {
+ *p = '\0';
+ p = newpath;
+ continue;
+ }
+
+ /* first check for '?' */
+
+ p = strrchr_m( newpath, '?' );
+ if ( p ) {
+ *p = '\0';
+ p = newpath;
+ }
+ }
+
+ /* strip a trailing backslash */
+
+ len = strlen( newpath );
+ if ( newpath[len-1] == '\\' )
+ newpath[len-1] = '\0';
+
+ pstrcpy( clean, newpath );
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL make_full_path( pstring path, const char *server, const char *share,
+ const char *dir )
+{
+ 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++;
+ }
+
+ directory = dir;
+ if ( *directory == '\\' )
+ directory++;
+
+ pstr_sprintf( path, "\\%s\\%s\\%s", server, sharename, directory );
+
+ return True;
+}
+
+/********************************************************************
+ check for dfs referral
+********************************************************************/
+
+static BOOL cli_dfs_check_error( struct cli_state *cli )
+{
+ uint32 flgs2 = SVAL(cli->inbuf,smb_flg2);
+
+ /* only deal with DS when we negotiated NT_STATUS codes and UNICODE */
+
+ if ( !( (flgs2&FLAGS2_32_BIT_ERROR_CODES) && (flgs2&FLAGS2_UNICODE_STRINGS) ) )
+ return False;
+
+ if ( NT_STATUS_EQUAL( NT_STATUS_PATH_NOT_COVERED, NT_STATUS(IVAL(cli->inbuf,smb_rcls)) ) )
+ return True;
+
+ return False;
+}
+
+/********************************************************************
+ 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)
+{
+ unsigned int data_len = 0;
+ unsigned int param_len = 0;
+ uint16 setup = TRANSACT2_GET_DFS_REFERRAL;
+ char param[sizeof(pstring)+2];
+ pstring data;
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ size_t pathlen = 2*(strlen(path)+1);
+ uint16 num_referrals;
+ CLIENT_DFS_REFERRAL *referrals;
+
+ memset(param, 0, sizeof(param));
+ SSVAL(param, 0, 0x03); /* max referral level */
+ p = &param[2];
+
+ p += clistr_push(cli, p, path, MIN(pathlen, sizeof(param)-2), STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ 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;
+ }
+
+ *consumed = SVAL( rdata, 0 );
+ num_referrals = SVAL( rdata, 2 );
+
+ if ( num_referrals != 0 ) {
+ uint16 ref_version;
+ 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;
+ for ( i=0; i<num_referrals; i++ ) {
+ ref_version = SVAL( p, 0 );
+ ref_size = SVAL( p, 2 );
+ node_offset = SVAL( p, 16 );
+
+ if ( ref_version != 3 ) {
+ p += ref_size;
+ continue;
+ }
+
+ referrals[i].proximity = SVAL( p, 8 );
+ referrals[i].ttl = SVAL( p, 10 );
+
+ clistr_pull( cli, referrals[i].dfspath, p+node_offset,
+ sizeof(referrals[i].dfspath), -1, STR_TERMINATE|STR_UNICODE );
+
+ p += ref_size;
+ }
+
+ }
+
+ *num_refs = num_referrals;
+ *refs = referrals;
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ return True;
+}
+
+/********************************************************************
+********************************************************************/
+
+BOOL cli_resolve_path( 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;
+ int pathlen;
+ fstring server, share;
+ struct cli_state *newcli;
+ pstring newpath;
+
+ SMB_STRUCT_STAT sbuf;
+ uint32 attributes;
+
+ *targetcli = NULL;
+
+ if ( !rootcli || !path || !targetcli )
+ return False;
+
+ /* send a trans2_query_path_info to check for a referral */
+
+ clean_path( cleanpath, path );
+ make_full_path( fullpath, rootcli->desthost, rootcli->share, cleanpath );
+
+ /* don't bother continuing if this is not a dfs root */
+
+ if ( !rootcli->dfsroot || cli_qpathinfo_basic( rootcli, cleanpath, &sbuf, &attributes ) ) {
+ *targetcli = rootcli;
+ pstrcpy( targetpath, path );
+ return True;
+ }
+
+ /* we got an error, check for DFS referral */
+
+ if ( !cli_dfs_check_error(rootcli) )
+ return False;
+
+ /* check for the referral */
+
+ 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 )
+ {
+ return False;
+ }
+
+ /* just store the first referral for now
+ Make sure to recreate the original string including any wildcards */
+
+ make_full_path( fullpath, rootcli->desthost, rootcli->share, path );
+ pathlen = strlen( fullpath )*2;
+ consumed = MIN(pathlen, consumed );
+ pstrcpy( targetpath, &fullpath[consumed/2] );
+
+ split_dfs_path( refs[0].dfspath, server, share );
+ SAFE_FREE( refs );
+
+ /* open the connection to the target path */
+
+ if ( (*targetcli = cli_cm_open(server, share, False)) == NULL ) {
+ d_printf("Unable to follow dfs referral [//%s/%s]\n",
+ server, share );
+
+ return False;
+ }
+
+ /* check for another dfs refeerrali, note that we are not
+ checking for loops here */
+
+ if ( !strequal( targetpath, "\\" ) ) {
+ if ( cli_resolve_path( *targetcli, targetpath, &newcli, newpath ) ) {
+ *targetcli = newcli;
+ pstrcpy( targetpath, newpath );
+ }
+ }
+
+ return True;
+}
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 39fe91172d4..369fba35218 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -185,6 +185,8 @@ void cli_setup_packet(struct cli_state *cli)
flags2 = FLAGS2_LONG_PATH_COMPONENTS;
if (cli->capabilities & CAP_UNICODE)
flags2 |= FLAGS2_UNICODE_STRINGS;
+ if (cli->capabilities & CAP_DFS)
+ flags2 |= FLAGS2_DFS_PATHNAMES;
if (cli->capabilities & CAP_STATUS32)
flags2 |= FLAGS2_32_BIT_ERROR_CODES;
if (cli->use_spnego)
@@ -283,7 +285,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
cli->use_spnego = lp_client_use_spnego();
- cli->capabilities = CAP_UNICODE | CAP_STATUS32;
+ cli->capabilities = CAP_UNICODE | CAP_STATUS32 | CAP_DFS;
/* Set the CLI_FORCE_DOSERR environment variable to test
client routines using DOS errors instead of STATUS32
diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c
index 8ab5854c8fb..532fb3a772e 100644
--- a/source/libsmb/clilist.c
+++ b/source/libsmb/clilist.c
@@ -171,8 +171,14 @@ 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;
-
- pstrcpy(mask,Mask);
+
+ /* 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);
while (ff_eos == 0) {
loop_count++;
diff --git a/source/libsmb/cliprint.c b/source/libsmb/cliprint.c
index 2fb0e59acac..732241a758f 100644
--- a/source/libsmb/cliprint.c
+++ b/source/libsmb/cliprint.c
@@ -156,3 +156,108 @@ int cli_printjob_del(struct cli_state *cli, int job)
}
+/****************************************************************************
+ Open a spool file
+****************************************************************************/
+
+int cli_spl_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
+{
+ char *p;
+ unsigned openfn=0;
+ unsigned accessmode=0;
+
+ if (flags & O_CREAT)
+ openfn |= (1<<4);
+ if (!(flags & O_EXCL)) {
+ if (flags & O_TRUNC)
+ openfn |= (1<<1);
+ else
+ openfn |= (1<<0);
+ }
+
+ accessmode = (share_mode<<4);
+
+ if ((flags & O_ACCMODE) == O_RDWR) {
+ accessmode |= 2;
+ } else if ((flags & O_ACCMODE) == O_WRONLY) {
+ accessmode |= 1;
+ }
+
+#if defined(O_SYNC)
+ if ((flags & O_SYNC) == O_SYNC) {
+ accessmode |= (1<<14);
+ }
+#endif /* O_SYNC */
+
+ if (share_mode == DENY_FCB) {
+ accessmode = 0xFF;
+ }
+
+ memset(cli->outbuf,'\0',smb_size);
+ memset(cli->inbuf,'\0',smb_size);
+
+ set_message(cli->outbuf,15,0,True);
+
+ SCVAL(cli->outbuf,smb_com,SMBsplopen);
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0,0xFF);
+ SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
+ SSVAL(cli->outbuf,smb_vwv3,accessmode);
+ SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
+ SSVAL(cli->outbuf,smb_vwv5,0);
+ SSVAL(cli->outbuf,smb_vwv8,openfn);
+
+ if (cli->use_oplocks) {
+ /* if using oplocks then ask for a batch oplock via
+ core and extended methods */
+ SCVAL(cli->outbuf,smb_flg, CVAL(cli->outbuf,smb_flg)|
+ FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK);
+ SSVAL(cli->outbuf,smb_vwv2,SVAL(cli->outbuf,smb_vwv2) | 6);
+ }
+
+ p = smb_buf(cli->outbuf);
+ p += clistr_push(cli, p, fname, -1, STR_TERMINATE);
+
+ cli_setup_bcc(cli, p);
+
+ cli_send_smb(cli);
+ if (!cli_receive_smb(cli)) {
+ return -1;
+ }
+
+ if (cli_is_error(cli)) {
+ return -1;
+ }
+
+ return SVAL(cli->inbuf,smb_vwv2);
+}
+
+/****************************************************************************
+ Close a file.
+****************************************************************************/
+
+BOOL cli_spl_close(struct cli_state *cli, int fnum)
+{
+ memset(cli->outbuf,'\0',smb_size);
+ memset(cli->inbuf,'\0',smb_size);
+
+ set_message(cli->outbuf,3,0,True);
+
+ SCVAL(cli->outbuf,smb_com,SMBsplclose);
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0,fnum);
+ SIVALS(cli->outbuf,smb_vwv1,-1);
+
+ cli_send_smb(cli);
+ if (!cli_receive_smb(cli)) {
+ return False;
+ }
+
+ return !cli_is_error(cli);
+}
+
+
diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c
index 8cc5d8bf901..8e6742d4380 100644
--- a/source/libsmb/clirap.c
+++ b/source/libsmb/clirap.c
@@ -1,7 +1,8 @@
/*
Unix SMB/CIFS implementation.
client RAP calls
- Copyright (C) Andrew Tridgell 1994-1998
+ Copyright (C) Andrew Tridgell 1994-1998
+ Copyright (C) Gerald (Jerry) Carter 2004
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
@@ -641,9 +642,80 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
return True;
}
+
+/****************************************************************************
+send a qpathinfo BASIC_INFO call
+****************************************************************************/
+BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
+ SMB_STRUCT_STAT *sbuf, uint32 *attributes )
+{
+ unsigned int param_len = 0;
+ unsigned int data_len = 0;
+ uint16 setup = TRANSACT2_QPATHINFO;
+ char param[sizeof(pstring)+6];
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ 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 );
+
+ /* cleanup */
+
+ len = strlen( path );
+ if ( path[len] == '\\' )
+ path[len] = '\0';
+
+ p = param;
+ memset(p, 0, 6);
+ SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
+ p += 6;
+ p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ 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 */
+ NULL, 0, cli->max_xmit /* data, length, max */
+ )) {
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ return False;
+ }
+
+ if (data_len < 36) {
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return False;
+ }
+
+ sbuf->st_atime = interpret_long_date( rdata+8 );
+ sbuf->st_mtime = interpret_long_date( rdata+16 );
+ sbuf->st_ctime = interpret_long_date( rdata+24 );
+
+ *attributes = IVAL( rdata, 32 );
+
+ SAFE_FREE(rparam);
+ SAFE_FREE(rdata);
+
+ return True;
+}
+
/****************************************************************************
send a qfileinfo call
****************************************************************************/
+
BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
{
unsigned int data_len = 0;
diff --git a/source/libsmb/clisecdesc.c b/source/libsmb/clisecdesc.c
index b79ea9d14ba..24757434794 100644
--- a/source/libsmb/clisecdesc.c
+++ b/source/libsmb/clisecdesc.c
@@ -30,6 +30,7 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
char *rparam=NULL, *rdata=NULL;
unsigned int rparam_count=0, rdata_count=0;
prs_struct pd;
+ BOOL pd_initialized = False;
SEC_DESC *psd = NULL;
SIVAL(param, 0, fnum);
@@ -56,7 +57,10 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
if (cli_is_error(cli))
goto cleanup;
- prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL);
+ if (!prs_init(&pd, rdata_count, mem_ctx, UNMARSHALL)) {
+ goto cleanup;
+ }
+ pd_initialized = True;
prs_copy_data_in(&pd, rdata, rdata_count);
prs_set_offset(&pd,0);
@@ -70,7 +74,8 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum,
SAFE_FREE(rparam);
SAFE_FREE(rdata);
- prs_mem_free(&pd);
+ if (pd_initialized)
+ prs_mem_free(&pd);
return psd;
}
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index eb1fce54392..4d9aaf989b1 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -393,7 +393,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
&neg_flags,
&cliname,
&domname)) {
- DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n"));
+ DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP Negotiate:\n"));
dump_data(2, (const char *)request.data, request.length);
return NT_STATUS_INVALID_PARAMETER;
}
@@ -442,13 +442,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
/* This creates the 'blob' of names that appears at the end of the packet */
if (chal_flags & NTLMSSP_CHAL_TARGET_INFO)
{
- const char *target_name_dns = "";
- if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) {
- target_name_dns = dnsdomname;
- } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) {
- target_name_dns = dnsname;
- }
-
msrpc_gen(&struct_blob, "aaaaa",
NTLMSSP_NAME_TYPE_DOMAIN, target_name,
NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(),
@@ -546,8 +539,6 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
&workstation,
&encrypted_session_key,
&auth_flags)) {
- DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
- dump_data(2, (const char *)request.data, request.length);
SAFE_FREE(domain);
SAFE_FREE(user);
SAFE_FREE(workstation);
@@ -570,7 +561,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
&domain,
&user,
&workstation)) {
- DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
+ DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
dump_data(2, (const char *)request.data, request.length);
SAFE_FREE(domain);
SAFE_FREE(user);
diff --git a/source/libsmb/ntlmssp_sign.c b/source/libsmb/ntlmssp_sign.c
index ee0f9df0249..b8105970762 100644
--- a/source/libsmb/ntlmssp_sign.c
+++ b/source/libsmb/ntlmssp_sign.c
@@ -53,7 +53,7 @@ static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len)
hash[257] = index_j;
}
-static void calc_hash(unsigned char hash[258], const char *k2, int k2l)
+static void calc_hash(unsigned char hash[258], unsigned char *k2, int k2l)
{
unsigned char j = 0;
int ind;
@@ -390,7 +390,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n"));
- calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 8);
+ calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8);
dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
sizeof(ntlmssp_state->ntlmssp_hash));
} else {
@@ -402,7 +402,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n"));
- calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 16);
+ calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16);
dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
sizeof(ntlmssp_state->ntlmssp_hash));
}
diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c
index 8a111eb957a..4baf2d3d6ce 100644
--- a/source/nmbd/nmbd_packets.c
+++ b/source/nmbd/nmbd_packets.c
@@ -864,6 +864,7 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
struct res_rec answers;
struct nmb_packet *orig_nmb = &orig_packet->packet.nmb;
BOOL loopback_this_packet = False;
+ int rr_type = RR_TYPE_NB;
const char *packet_type = "unknown";
/* Check if we are sending to or from ourselves. */
@@ -885,11 +886,15 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
packet_type = "nmb_status";
nmb->header.nm_flags.recursion_desired = False;
nmb->header.nm_flags.recursion_available = False;
+ rr_type = RR_TYPE_NBSTAT;
break;
case NMB_QUERY:
packet_type = "nmb_query";
nmb->header.nm_flags.recursion_desired = True;
nmb->header.nm_flags.recursion_available = True;
+ if (rcode) {
+ rr_type = RR_TYPE_NULL;
+ }
break;
case NMB_REG:
case NMB_REG_REFRESH:
@@ -906,6 +911,7 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
packet_type = "nmb_wack";
nmb->header.nm_flags.recursion_desired = False;
nmb->header.nm_flags.recursion_available = False;
+ rr_type = RR_TYPE_NULL;
break;
case WINS_REG:
packet_type = "wins_reg";
@@ -916,6 +922,9 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
packet_type = "wins_query";
nmb->header.nm_flags.recursion_desired = True;
nmb->header.nm_flags.recursion_available = True;
+ if (rcode) {
+ rr_type = RR_TYPE_NULL;
+ }
break;
default:
DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n",
@@ -947,8 +956,8 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
nmb->answers->rr_name = orig_nmb->question.question_name;
- nmb->answers->rr_type = orig_nmb->question.question_type;
- nmb->answers->rr_class = orig_nmb->question.question_class;
+ nmb->answers->rr_type = rr_type;
+ nmb->answers->rr_class = RR_CLASS_IN;
nmb->answers->ttl = ttl;
if (data && len) {
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index 0ea5db74da6..d8d4f936769 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -62,7 +62,7 @@ static char *get_static(char **buffer, size_t *buflen, size_t len)
lib/util_str.c as I really don't want to have to link in any other
objects if I can possibly avoid it. */
-BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize)
+BOOL next_token(char **ptr,char *buff,const char *sep, size_t bufsize)
{
char *s;
BOOL quoted;
@@ -976,11 +976,11 @@ _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid);
#endif
+ ZERO_STRUCT(response);
+ ZERO_STRUCT(request);
+
/* we need to fetch the separator first time through */
if (!sep_char) {
- ZERO_STRUCT(response);
- ZERO_STRUCT(request);
-
ret = winbindd_request(WINBINDD_INFO, &request, &response);
if (ret != NSS_STATUS_SUCCESS) {
*errnop = errno = EINVAL;
diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c
index f5dcb69ce08..dc2d6cfc6f6 100644
--- a/source/nsswitch/winbindd_cm.c
+++ b/source/nsswitch/winbindd_cm.c
@@ -459,97 +459,107 @@ static BOOL add_sockaddr_to_array(TALLOC_CTX *mem_ctx,
return True;
}
-static BOOL get_dcs_1c(TALLOC_CTX *mem_ctx,
- const struct winbindd_domain *domain,
- struct dc_name_ip **dcs, int *num_dcs)
+/*******************************************************************
+ convert an ip to a name
+*******************************************************************/
+
+static void dcip_to_name( const char *domainname, const char *realm, struct in_addr ip, fstring name )
{
- struct ip_service *iplist = NULL;
- int i, num = 0;
+ /* try node status request first */
- if (!internal_resolve_name(domain->name, 0x1c, &iplist, &num,
- lp_name_resolve_order()))
- return False;
+ if ( name_status_find(domainname, 0x1c, 0x20, ip, name) )
+ return;
- /* Now try to find the server names of at least one IP address, hosts
- * not replying are cached as such */
+ /* backup in case the ads stuff fails */
- for (i=0; i<num; i++) {
+ fstrcpy( name, inet_ntoa(ip) );
- fstring dcname;
+#ifdef WITH_ADS
+ /* for active directory servers, try to get the ldap server name.
+ None of these failure should be considered critical for now */
- if (!name_status_find(domain->name, 0x1c, 0x20, iplist[i].ip,
- dcname))
- continue;
+ if ( lp_security() == SEC_ADS )
+ {
+ ADS_STRUCT *ads;
+ ADS_STATUS status;
- if (add_one_dc_unique(mem_ctx, domain->name, dcname,
- iplist[i].ip, dcs, num_dcs)) {
- /* One DC responded, so we assume that he will also
- work on 139/445 */
- break;
+ ads = ads_init( realm, domainname, NULL );
+ ads->auth.flags |= ADS_AUTH_NO_BIND;
+
+ if ( !ads_try_connect( ads, inet_ntoa(ip), LDAP_PORT ) ) {
+ ads_destroy( &ads );
+ return;
}
- }
- SAFE_FREE(iplist);
+ status = ads_server_info(ads);
+ if ( !ADS_ERR_OK(status) ) {
+ ads_destroy( &ads );
+ return;
+ }
- return True;
+ fstrcpy(name, ads->config.ldap_server_name);
+
+ ads_destroy( &ads );
+ }
+#endif
+
+ return;
}
+
+/*******************************************************************
+ Retreive a list of IP address for domain controllers. Fill in
+ the dcs[] with results.
+*******************************************************************/
+
static BOOL get_dcs(TALLOC_CTX *mem_ctx, const struct winbindd_domain *domain,
struct dc_name_ip **dcs, int *num_dcs)
{
fstring dcname;
- struct in_addr ip;
- BOOL is_our_domain;
+ struct in_addr ip;
+ struct ip_service *ip_list = NULL;
+ int iplist_size = 0;
+ int i;
+ BOOL is_our_domain;
- const char *p;
is_our_domain = strequal(domain->name, lp_workgroup());
- if (!is_our_domain && get_dc_name_via_netlogon(domain, dcname, &ip) &&
- add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs))
- return True;
-
- if (!is_our_domain) {
- /* NETLOGON to our own domain could not give us a DC name
- * (which is an error), fall back to looking up domain#1c */
- return get_dcs_1c(mem_ctx, domain, dcs, num_dcs);
+ if ( !is_our_domain
+ && get_dc_name_via_netlogon(domain, dcname, &ip)
+ && add_one_dc_unique(mem_ctx, domain->name, dcname, ip, dcs, num_dcs) )
+ {
+ return True;
}
- if (must_use_pdc(domain->name) && get_pdc_ip(domain->name, &ip)) {
-
- if (!name_status_find(domain->name, 0x1b, 0x20, ip, dcname))
- return False;
-
- if (add_one_dc_unique(mem_ctx, domain->name,
- dcname, ip, dcs, num_dcs))
+ if ( is_our_domain
+ && must_use_pdc(domain->name)
+ && get_pdc_ip(domain->name, &ip))
+ {
+ if (add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip), ip, dcs, num_dcs))
return True;
}
- p = lp_passwordserver();
-
- if (*p == 0)
- return get_dcs_1c(mem_ctx, domain, dcs, num_dcs);
+ /* try standard netbios queries first */
- while (next_token(&p, dcname, LIST_SEP, sizeof(dcname))) {
-
- if (strequal(dcname, "*")) {
- get_dcs_1c(mem_ctx, domain, dcs, num_dcs);
- continue;
- }
+ get_sorted_dc_list(domain->name, &ip_list, &iplist_size, False);
- if (!resolve_name(dcname, &ip, 0x20))
- continue;
+ /* check for security = ads and use DNS if we can */
- /* Even if we got the dcname, double check the name to use for
- * the netlogon auth2 */
+ if ( iplist_size==0 && lp_security() == SEC_ADS )
+ get_sorted_dc_list(domain->alt_name, &ip_list, &iplist_size, True);
- if (!name_status_find(domain->name, 0x1c, 0x20, ip, dcname))
- continue;
+ /* now add to the dc array. We'll wait until the last minute
+ to look up the name of the DC. But we fill in the char* for
+ the ip now in to make the failed connection cache work */
- add_one_dc_unique(mem_ctx, domain->name, dcname, ip,
- dcs, num_dcs);
+ for ( i=0; i<iplist_size; i++ ) {
+ add_one_dc_unique(mem_ctx, domain->name, inet_ntoa(ip_list[i].ip),
+ ip_list[i].ip, dcs, num_dcs);
}
+ SAFE_FREE( ip_list );
+
return True;
}
@@ -560,7 +570,7 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
struct dc_name_ip *dcs = NULL;
int num_dcs = 0;
- char **dcnames = NULL;
+ const char **dcnames = NULL;
int num_dcnames = 0;
struct sockaddr_in *addrs = NULL;
@@ -587,18 +597,25 @@ static BOOL find_new_dc(TALLOC_CTX *mem_ctx,
if ((num_dcnames == 0) || (num_dcnames != num_addrs))
return False;
- if (!open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd)) {
+ if ( !open_any_socket_out(addrs, num_addrs, 10000, &fd_index, fd) )
+ {
for (i=0; i<num_dcs; i++) {
add_failed_connection_entry(domain->name,
- dcs[i].name,
- NT_STATUS_UNSUCCESSFUL);
+ dcs[i].name, NT_STATUS_UNSUCCESSFUL);
}
return False;
}
- fstrcpy(dcname, dcnames[fd_index]);
*addr = addrs[fd_index];
+ /* if we have no name on the server or just an IP address for
+ the name, now try to get the name */
+
+ if ( is_ipaddress(dcnames[fd_index]) || *dcnames[fd_index] == '\0' )
+ dcip_to_name( domain->name, domain->alt_name, addr->sin_addr, dcname );
+ else
+ fstrcpy(dcname, dcnames[fd_index]);
+
return True;
}
@@ -883,6 +900,11 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
done:
+ DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
+ domain->active_directory ? "ADS" : "NT4",
+ domain->native_mode ? "native mode" :
+ ((domain->active_directory && !domain->native_mode) ? "mixed mode" : "")));
+
/* close the connection; no other calls use this pipe and it is called only
on reestablishing the domain list --jerry */
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index cb44ec98d76..90613911182 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -372,10 +372,22 @@ done:
afsname = realloc_string_sub(afsname, "%u", name_user);
afsname = realloc_string_sub(afsname, "%U", name_user);
+ {
+ DOM_SID user_sid;
+ fstring sidstr;
+
+ sid_copy(&user_sid, &info3.dom_sid.sid);
+ sid_append_rid(&user_sid, info3.user_rid);
+ sid_to_string(sidstr, &user_sid);
+ afsname = realloc_string_sub(afsname, "%s", sidstr);
+ }
+
if (afsname == NULL) goto no_token;
strlower_m(afsname);
+ DEBUG(10, ("Generating token for user %s\n", afsname));
+
cell = strchr(afsname, '@');
if (cell == NULL) goto no_token;
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 10d6e4f4fa9..42f451c5051 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -723,7 +723,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
/* Lookup a chunk of rids */
result = cli_samr_lookup_rids(hnd->cli, mem_ctx,
- &dom_pol, 1000, /* flags */
+ &dom_pol,
num_lookup_rids,
&rid_mem[i],
&tmp_num_names,
@@ -769,7 +769,7 @@ static int get_ldap_seq(const char *server, int port, uint32 *seq)
{
int ret = -1;
struct timeval to;
- char *attrs[] = {"highestCommittedUSN", NULL};
+ const char *attrs[] = {"highestCommittedUSN", NULL};
LDAPMessage *res = NULL;
char **values = NULL;
LDAP *ldp = NULL;
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index 1f727dd18d5..11da05ac3b4 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -167,11 +167,6 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
sid_copy(&domain->sid, sid);
}
- DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
- domain->active_directory ? "ADS" : "NT4",
- domain->native_mode ? "native mode" :
- ((domain->active_directory && !domain->native_mode) ? "mixed mode" : "")));
-
/* Link to domain list */
DLIST_ADD(_domain_list, domain);
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 01213a8fb39..80843eda829 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -128,6 +128,7 @@ typedef struct
char *szRealm;
char *szAfsUsernameMap;
int iAfsTokenLifetime;
+ char *szLogNtTokenCommand;
char *szUsernameMap;
char *szLogonScript;
char *szLogonPath;
@@ -1130,6 +1131,7 @@ static struct parm_struct parm_table[] = {
{"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED},
{"afs username map", P_STRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_ADVANCED},
{"afs token lifetime", P_INTEGER, P_GLOBAL, &Globals.iAfsTokenLifetime, NULL, NULL, FLAG_ADVANCED},
+ {"log nt token command", P_STRING, P_GLOBAL, &Globals.szLogNtTokenCommand, NULL, NULL, FLAG_ADVANCED},
{"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED},
{"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED},
{"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
@@ -1224,7 +1226,9 @@ static void init_printer_values(service *pService)
case PRINT_CUPS:
#ifdef HAVE_CUPS
- string_set(&pService->szLpqcommand, "");
+ /* set the lpq command to contain the destination printer
+ name only. This is used by cups_queue_get() */
+ string_set(&pService->szLpqcommand, "%p");
string_set(&pService->szLprmcommand, "");
string_set(&pService->szPrintcommand, "");
string_set(&pService->szLppausecommand, "");
@@ -1664,6 +1668,7 @@ FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder)
FN_GLOBAL_STRING(lp_realm, &Globals.szRealm)
FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap)
FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime)
+FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand)
FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap)
FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript)
FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath)
diff --git a/source/param/params.c b/source/param/params.c
index 2d6fe567166..9d21d25a240 100644
--- a/source/param/params.c
+++ b/source/param/params.c
@@ -107,27 +107,44 @@ typedef struct {
char *buf;
char *p;
size_t size;
+ char *end_section_p;
} myFILE;
static int mygetc(myFILE *f)
{
- if (f->p >= f->buf+f->size) return EOF;
+ if (f->p >= f->buf+f->size)
+ return EOF;
/* be sure to return chars >127 as positive values */
return (int)( *(f->p++) & 0x00FF );
}
static void myfile_close(myFILE *f)
{
- if (!f) return;
+ if (!f)
+ return;
SAFE_FREE(f->buf);
SAFE_FREE(f);
}
+/* Find the end of the section. We must use mb functions for this. */
+static int FindSectionEnd(myFILE *f)
+{
+ f->end_section_p = strchr_m(f->p, ']');
+ return f->end_section_p ? 1 : 0;
+}
+
+static int AtSectionEnd(myFILE *f)
+{
+ if (f->p == f->end_section_p + 1) {
+ f->end_section_p = NULL;
+ return 1;
+ }
+ return 0;
+}
+
/* -------------------------------------------------------------------------- **
* Functions...
*/
-
-static int EatWhitespace( myFILE *InFile )
/* ------------------------------------------------------------------------ **
* Scan past whitespace (see ctype(3C)) and return the first non-whitespace
* character, or newline, or EOF.
@@ -144,15 +161,16 @@ static int EatWhitespace( myFILE *InFile )
*
* ------------------------------------------------------------------------ **
*/
- {
- int c;
+
+static int EatWhitespace( myFILE *InFile )
+{
+ int c;
- for( c = mygetc( InFile ); isspace( c ) && ('\n' != c); c = mygetc( InFile ) )
- ;
- return( c );
- } /* EatWhitespace */
+ for( c = mygetc( InFile ); isspace( c ) && ('\n' != c); c = mygetc( InFile ) )
+ ;
+ return( c );
+}
-static int EatComment( myFILE *InFile )
/* ------------------------------------------------------------------------ **
* Scan to the end of a comment.
*
@@ -169,13 +187,15 @@ static int EatComment( myFILE *InFile )
*
* ------------------------------------------------------------------------ **
*/
- {
- int c;
- for( c = mygetc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = mygetc( InFile ) )
- ;
- return( c );
- } /* EatComment */
+static int EatComment( myFILE *InFile )
+{
+ int c;
+
+ for( c = mygetc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = mygetc( InFile ) )
+ ;
+ return( c );
+}
/*****************************************************************************
* Scan backards within a string to discover if the last non-whitespace
@@ -200,400 +220,384 @@ static int Continuation(char *line, int pos )
return (((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
}
+/* ------------------------------------------------------------------------ **
+ * Scan a section name, and pass the name to function sfunc().
+ *
+ * Input: InFile - Input source.
+ * sfunc - Pointer to the function to be called if the section
+ * name is successfully read.
+ *
+ * Output: True if the section name was read and True was returned from
+ * <sfunc>. False if <sfunc> failed or if a lexical error was
+ * encountered.
+ *
+ * ------------------------------------------------------------------------ **
+ */
static BOOL Section( myFILE *InFile, BOOL (*sfunc)(const char *) )
- /* ------------------------------------------------------------------------ **
- * Scan a section name, and pass the name to function sfunc().
- *
- * Input: InFile - Input source.
- * sfunc - Pointer to the function to be called if the section
- * name is successfully read.
- *
- * Output: True if the section name was read and True was returned from
- * <sfunc>. False if <sfunc> failed or if a lexical error was
- * encountered.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int c;
- int i;
- int end;
- const char *func = "params.c:Section() -";
-
- i = 0; /* <i> is the offset of the next free byte in bufr[] and */
- end = 0; /* <end> is the current "end of string" offset. In most */
- /* cases these will be the same, but if the last */
- /* character written to bufr[] is a space, then <end> */
- /* will be one less than <i>. */
-
- c = EatWhitespace( InFile ); /* We've already got the '['. Scan */
- /* past initial white space. */
-
- while( (EOF != c) && (c > 0) )
- {
-
- /* Check that the buffer is big enough for the next character. */
- if( i > (bSize - 2) )
- {
- char *tb;
+{
+ int c;
+ int i;
+ int end;
+ const char *func = "params.c:Section() -";
+
+ i = 0; /* <i> is the offset of the next free byte in bufr[] and */
+ end = 0; /* <end> is the current "end of string" offset. In most */
+ /* cases these will be the same, but if the last */
+ /* character written to bufr[] is a space, then <end> */
+ /* will be one less than <i>. */
+
+
+ /* Find the end of the section. We must use mb functions for this. */
+ if (!FindSectionEnd(InFile)) {
+ DEBUG(0, ("%s No terminating ']' character in section.\n", func) );
+ return False;
+ }
+
+ c = EatWhitespace( InFile ); /* We've already got the '['. Scan */
+ /* past initial white space. */
+
+ while( (EOF != c) && (c > 0) ) {
+ /* Check that the buffer is big enough for the next character. */
+ if( i > (bSize - 2) ) {
+ char *tb;
- tb = SMB_REALLOC( bufr, bSize +BUFR_INC );
- if( NULL == tb )
- {
- DEBUG(0, ("%s Memory re-allocation failure.", func) );
- return( False );
- }
- bufr = tb;
- bSize += BUFR_INC;
- }
-
- /* Handle a single character. */
- switch( c )
- {
- case ']': /* Found the closing bracket. */
- bufr[end] = '\0';
- if( 0 == end ) /* Don't allow an empty name. */
- {
- DEBUG(0, ("%s Empty section name in configuration file.\n", func ));
- return( False );
- }
- if( !sfunc(bufr) ) /* Got a valid name. Deal with it. */
- return( False );
- (void)EatComment( InFile ); /* Finish off the line. */
- return( True );
-
- case '\n': /* Got newline before closing ']'. */
- i = Continuation( bufr, i ); /* Check for line continuation. */
- if( i < 0 )
- {
- bufr[end] = '\0';
- DEBUG(0, ("%s Badly formed line in configuration file: %s\n",
- func, bufr ));
- return( False );
- }
- end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
- c = mygetc( InFile ); /* Continue with next line. */
- break;
-
- default: /* All else are a valid name chars. */
- if( isspace( c ) ) /* One space per whitespace region. */
- {
- bufr[end] = ' ';
- i = end + 1;
- c = EatWhitespace( InFile );
- }
- else /* All others copy verbatim. */
- {
- bufr[i++] = c;
- end = i;
- c = mygetc( InFile );
- }
- }
- }
-
- /* We arrive here if we've met the EOF before the closing bracket. */
- DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, bufr ));
- return( False );
- } /* Section */
+ tb = SMB_REALLOC( bufr, bSize +BUFR_INC );
+ if( NULL == tb ) {
+ DEBUG(0, ("%s Memory re-allocation failure.", func) );
+ return False;
+ }
+ bufr = tb;
+ bSize += BUFR_INC;
+ }
+
+ /* Handle a single character other than section end. */
+ switch( c ) {
+ case '\n': /* Got newline before closing ']'. */
+ i = Continuation( bufr, i ); /* Check for line continuation. */
+ if( i < 0 ) {
+ bufr[end] = '\0';
+ DEBUG(0, ("%s Badly formed line in configuration file: %s\n", func, bufr ));
+ return False;
+ }
+ end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
+ c = mygetc( InFile ); /* Continue with next line. */
+ break;
+
+ default: /* All else are a valid name chars. */
+ if(isspace( c )) {
+ /* One space per whitespace region. */
+ bufr[end] = ' ';
+ i = end + 1;
+ c = EatWhitespace( InFile );
+ } else {
+ bufr[i++] = c;
+ end = i;
+ c = mygetc( InFile );
+ }
+ }
+
+ if (AtSectionEnd(InFile)) {
+ /* Got to the closing bracket. */
+ bufr[end] = '\0';
+ if( 0 == end ) {
+ /* Don't allow an empty name. */
+ DEBUG(0, ("%s Empty section name in configuration file.\n", func ));
+ return False;
+ }
+ if( !sfunc(bufr) ) /* Got a valid name. Deal with it. */
+ return False;
+ EatComment( InFile ); /* Finish off the line. */
+ return True;
+ }
+
+ }
+
+ /* We arrive here if we've met the EOF before the closing bracket. */
+ DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, bufr ));
+ return False;
+}
+
+/* ------------------------------------------------------------------------ **
+ * Scan a parameter name and value, and pass these two fields to pfunc().
+ *
+ * Input: InFile - The input source.
+ * pfunc - A pointer to the function that will be called to
+ * process the parameter, once it has been scanned.
+ * c - The first character of the parameter name, which
+ * would have been read by Parse(). Unlike a comment
+ * line or a section header, there is no lead-in
+ * character that can be discarded.
+ *
+ * Output: True if the parameter name and value were scanned and processed
+ * successfully, else False.
+ *
+ * Notes: This function is in two parts. The first loop scans the
+ * parameter name. Internal whitespace is compressed, and an
+ * equal sign (=) terminates the token. Leading and trailing
+ * whitespace is discarded. The second loop scans the parameter
+ * value. When both have been successfully identified, they are
+ * passed to pfunc() for processing.
+ *
+ * ------------------------------------------------------------------------ **
+ */
static BOOL Parameter( myFILE *InFile, BOOL (*pfunc)(const char *, const char *), int c )
- /* ------------------------------------------------------------------------ **
- * Scan a parameter name and value, and pass these two fields to pfunc().
- *
- * Input: InFile - The input source.
- * pfunc - A pointer to the function that will be called to
- * process the parameter, once it has been scanned.
- * c - The first character of the parameter name, which
- * would have been read by Parse(). Unlike a comment
- * line or a section header, there is no lead-in
- * character that can be discarded.
- *
- * Output: True if the parameter name and value were scanned and processed
- * successfully, else False.
- *
- * Notes: This function is in two parts. The first loop scans the
- * parameter name. Internal whitespace is compressed, and an
- * equal sign (=) terminates the token. Leading and trailing
- * whitespace is discarded. The second loop scans the parameter
- * value. When both have been successfully identified, they are
- * passed to pfunc() for processing.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int i = 0; /* Position within bufr. */
- int end = 0; /* bufr[end] is current end-of-string. */
- int vstart = 0; /* Starting position of the parameter value. */
- const char *func = "params.c:Parameter() -";
-
- /* Read the parameter name. */
- while( 0 == vstart ) /* Loop until we've found the start of the value. */
- {
-
- if( i > (bSize - 2) ) /* Ensure there's space for next char. */
- {
- char *tb;
-
- tb = SMB_REALLOC( bufr, bSize + BUFR_INC );
- if( NULL == tb )
- {
- DEBUG(0, ("%s Memory re-allocation failure.", func) );
- return( False );
- }
- bufr = tb;
- bSize += BUFR_INC;
- }
-
- switch( c )
- {
- case '=': /* Equal sign marks end of param name. */
- if( 0 == end ) /* Don't allow an empty name. */
- {
- DEBUG(0, ("%s Invalid parameter name in config. file.\n", func ));
- return( False );
- }
- bufr[end++] = '\0'; /* Mark end of string & advance. */
- i = end; /* New string starts here. */
- vstart = end; /* New string is parameter value. */
- bufr[i] = '\0'; /* New string is nul, for now. */
- break;
-
- case '\n': /* Find continuation char, else error. */
- i = Continuation( bufr, i );
- if( i < 0 )
- {
- bufr[end] = '\0';
- DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n",
- func, bufr ));
- return( True );
- }
- end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
- c = mygetc( InFile ); /* Read past eoln. */
- break;
-
- case '\0': /* Shouldn't have EOF within param name. */
- case EOF:
- bufr[i] = '\0';
- DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, bufr ));
- return( True );
-
- default:
- if( isspace( c ) ) /* One ' ' per whitespace region. */
- {
- bufr[end] = ' ';
- i = end + 1;
- c = EatWhitespace( InFile );
- }
- else /* All others verbatim. */
- {
- bufr[i++] = c;
- end = i;
- c = mygetc( InFile );
- }
- }
- }
-
- /* Now parse the value. */
- c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */
- while( (EOF !=c) && (c > 0) )
- {
-
- if( i > (bSize - 2) ) /* Make sure there's enough room. */
- {
- char *tb;
-
- tb = SMB_REALLOC( bufr, bSize + BUFR_INC );
- if( NULL == tb )
- {
- DEBUG(0, ("%s Memory re-allocation failure.", func) );
- return( False );
- }
- bufr = tb;
- bSize += BUFR_INC;
- }
-
- switch( c )
- {
- case '\r': /* Explicitly remove '\r' because the older */
- c = mygetc( InFile ); /* version called fgets_slash() which also */
- break; /* removes them. */
-
- case '\n': /* Marks end of value unless there's a '\'. */
- i = Continuation( bufr, i );
- if( i < 0 )
- c = 0;
- else
- {
- for( end = i; (end >= 0) && isspace((int)bufr[end]); end-- )
- ;
- c = mygetc( InFile );
- }
- break;
-
- default: /* All others verbatim. Note that spaces do */
- bufr[i++] = c; /* not advance <end>. This allows trimming */
- if( !isspace( c ) ) /* of whitespace at the end of the line. */
- end = i;
- c = mygetc( InFile );
- break;
- }
- }
- bufr[end] = '\0'; /* End of value. */
-
- return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */
- } /* Parameter */
+{
+ int i = 0; /* Position within bufr. */
+ int end = 0; /* bufr[end] is current end-of-string. */
+ int vstart = 0; /* Starting position of the parameter value. */
+ const char *func = "params.c:Parameter() -";
+
+ /* Read the parameter name. */
+ while( 0 == vstart ) {
+ /* Loop until we've found the start of the value. */
+ if( i > (bSize - 2) ) {
+ /* Ensure there's space for next char. */
+ char *tb = SMB_REALLOC( bufr, bSize + BUFR_INC );
+ if( NULL == tb ) {
+ DEBUG(0, ("%s Memory re-allocation failure.", func) );
+ return False;
+ }
+ bufr = tb;
+ bSize += BUFR_INC;
+ }
+
+ switch(c) {
+ case '=': /* Equal sign marks end of param name. */
+ if( 0 == end ) {
+ /* Don't allow an empty name. */
+ DEBUG(0, ("%s Invalid parameter name in config. file.\n", func ));
+ return False;
+ }
+ bufr[end++] = '\0'; /* Mark end of string & advance. */
+ i = end; /* New string starts here. */
+ vstart = end; /* New string is parameter value. */
+ bufr[i] = '\0'; /* New string is nul, for now. */
+ break;
+
+ case '\n': /* Find continuation char, else error. */
+ i = Continuation( bufr, i );
+ if( i < 0 ) {
+ bufr[end] = '\0';
+ DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n", func, bufr ));
+ return True;
+ }
+ end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
+ c = mygetc( InFile ); /* Read past eoln. */
+ break;
+
+ case '\0': /* Shouldn't have EOF within param name. */
+ case EOF:
+ bufr[i] = '\0';
+ DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, bufr ));
+ return True;
+
+ default:
+ if(isspace( c )) {
+ /* One ' ' per whitespace region. */
+ bufr[end] = ' ';
+ i = end + 1;
+ c = EatWhitespace( InFile );
+ } else {
+ bufr[i++] = c;
+ end = i;
+ c = mygetc( InFile );
+ }
+ }
+ }
+
+ /* Now parse the value. */
+ c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */
+ while( (EOF !=c) && (c > 0) ) {
+ if( i > (bSize - 2) ) {
+ /* Make sure there's enough room. */
+ char *tb = SMB_REALLOC( bufr, bSize + BUFR_INC );
+ if( NULL == tb ) {
+ DEBUG(0, ("%s Memory re-allocation failure.", func));
+ return False;
+ }
+ bufr = tb;
+ bSize += BUFR_INC;
+ }
+
+ switch(c) {
+ case '\r': /* Explicitly remove '\r' because the older */
+ c = mygetc( InFile ); /* version called fgets_slash() which also */
+ break; /* removes them. */
+
+ case '\n': /* Marks end of value unless there's a '\'. */
+ i = Continuation( bufr, i );
+ if( i < 0 ) {
+ c = 0;
+ } else {
+ for( end = i; (end >= 0) && isspace((int)bufr[end]); end-- )
+ ;
+ c = mygetc( InFile );
+ }
+ break;
+
+ default: /* All others verbatim. Note that spaces do not advance <end>. This allows trimming */
+ bufr[i++] = c;
+ if( !isspace( c ) ) /* of whitespace at the end of the line. */
+ end = i;
+ c = mygetc( InFile );
+ break;
+ }
+ }
+ bufr[end] = '\0'; /* End of value. */
+
+ return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */
+}
+
+/* ------------------------------------------------------------------------ **
+ * Scan & parse the input.
+ *
+ * Input: InFile - Input source.
+ * sfunc - Function to be called when a section name is scanned.
+ * See Section().
+ * pfunc - Function to be called when a parameter is scanned.
+ * See Parameter().
+ *
+ * Output: True if the file was successfully scanned, else False.
+ *
+ * Notes: The input can be viewed in terms of 'lines'. There are four
+ * types of lines:
+ * Blank - May contain whitespace, otherwise empty.
+ * Comment - First non-whitespace character is a ';' or '#'.
+ * The remainder of the line is ignored.
+ * Section - First non-whitespace character is a '['.
+ * Parameter - The default case.
+ *
+ * ------------------------------------------------------------------------ **
+ */
static BOOL Parse( myFILE *InFile,
BOOL (*sfunc)(const char *),
BOOL (*pfunc)(const char *, const char *) )
- /* ------------------------------------------------------------------------ **
- * Scan & parse the input.
- *
- * Input: InFile - Input source.
- * sfunc - Function to be called when a section name is scanned.
- * See Section().
- * pfunc - Function to be called when a parameter is scanned.
- * See Parameter().
- *
- * Output: True if the file was successfully scanned, else False.
- *
- * Notes: The input can be viewed in terms of 'lines'. There are four
- * types of lines:
- * Blank - May contain whitespace, otherwise empty.
- * Comment - First non-whitespace character is a ';' or '#'.
- * The remainder of the line is ignored.
- * Section - First non-whitespace character is a '['.
- * Parameter - The default case.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int c;
-
- c = EatWhitespace( InFile );
- while( (EOF != c) && (c > 0) )
- {
- switch( c )
- {
- case '\n': /* Blank line. */
- c = EatWhitespace( InFile );
- break;
-
- case ';': /* Comment line. */
- case '#':
- c = EatComment( InFile );
- break;
-
- case '[': /* Section Header. */
- if( !Section( InFile, sfunc ) )
- return( False );
- c = EatWhitespace( InFile );
- break;
-
- case '\\': /* Bogus backslash. */
- c = EatWhitespace( InFile );
- break;
-
- default: /* Parameter line. */
- if( !Parameter( InFile, pfunc, c ) )
- return( False );
- c = EatWhitespace( InFile );
- break;
- }
- }
- return( True );
- } /* Parse */
+{
+ int c;
+
+ c = EatWhitespace( InFile );
+ while( (EOF != c) && (c > 0) ) {
+ switch( c ) {
+ case '\n': /* Blank line. */
+ c = EatWhitespace( InFile );
+ break;
+
+ case ';': /* Comment line. */
+ case '#':
+ c = EatComment( InFile );
+ break;
+
+ case '[': /* Section Header. */
+ if( !Section( InFile, sfunc ) )
+ return False;
+ c = EatWhitespace( InFile );
+ break;
+
+ case '\\': /* Bogus backslash. */
+ c = EatWhitespace( InFile );
+ break;
+
+ default: /* Parameter line. */
+ if( !Parameter( InFile, pfunc, c ) )
+ return False;
+ c = EatWhitespace( InFile );
+ break;
+ }
+ }
+ return True;
+}
+
+/* ------------------------------------------------------------------------ **
+ * Open a configuration file.
+ *
+ * Input: FileName - The pathname of the config file to be opened.
+ *
+ * Output: A pointer of type (char **) to the lines of the file
+ *
+ * ------------------------------------------------------------------------ **
+ */
static myFILE *OpenConfFile( const char *FileName )
- /* ------------------------------------------------------------------------ **
- * Open a configuration file.
- *
- * Input: FileName - The pathname of the config file to be opened.
- *
- * Output: A pointer of type (char **) to the lines of the file
- *
- * ------------------------------------------------------------------------ **
- */
- {
- const char *func = "params.c:OpenConfFile() -";
- extern BOOL in_client;
- int lvl = in_client?1:0;
- myFILE *ret;
-
- ret = SMB_MALLOC_P(myFILE);
- if (!ret) return NULL;
-
- ret->buf = file_load(FileName, &ret->size);
- if( NULL == ret->buf )
- {
- DEBUG( lvl,
- ("%s Unable to open configuration file \"%s\":\n\t%s\n",
- func, FileName, strerror(errno)) );
- SAFE_FREE(ret);
- return NULL;
- }
-
- ret->p = ret->buf;
- return( ret );
- } /* OpenConfFile */
+{
+ const char *func = "params.c:OpenConfFile() -";
+ extern BOOL in_client;
+ int lvl = in_client?1:0;
+ myFILE *ret;
+
+ ret = SMB_MALLOC_P(myFILE);
+ if (!ret)
+ return NULL;
+
+ ret->buf = file_load(FileName, &ret->size);
+ if( NULL == ret->buf ) {
+ DEBUG( lvl, ("%s Unable to open configuration file \"%s\":\n\t%s\n",
+ func, FileName, strerror(errno)) );
+ SAFE_FREE(ret);
+ return NULL;
+ }
+
+ ret->p = ret->buf;
+ ret->end_section_p = NULL;
+ return( ret );
+}
+
+/* ------------------------------------------------------------------------ **
+ * Process the named parameter file.
+ *
+ * Input: FileName - The pathname of the parameter file to be opened.
+ * sfunc - A pointer to a function that will be called when
+ * a section name is discovered.
+ * pfunc - A pointer to a function that will be called when
+ * a parameter name and value are discovered.
+ *
+ * Output: TRUE if the file was successfully parsed, else FALSE.
+ *
+ * ------------------------------------------------------------------------ **
+ */
BOOL pm_process( const char *FileName,
- BOOL (*sfunc)(const char *),
- BOOL (*pfunc)(const char *, const char *) )
- /* ------------------------------------------------------------------------ **
- * Process the named parameter file.
- *
- * Input: FileName - The pathname of the parameter file to be opened.
- * sfunc - A pointer to a function that will be called when
- * a section name is discovered.
- * pfunc - A pointer to a function that will be called when
- * a parameter name and value are discovered.
- *
- * Output: TRUE if the file was successfully parsed, else FALSE.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int result;
- myFILE *InFile;
- const char *func = "params.c:pm_process() -";
-
- InFile = OpenConfFile( FileName ); /* Open the config file. */
- if( NULL == InFile )
- return( False );
-
- DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) );
-
- if( NULL != bufr ) /* If we already have a buffer */
- result = Parse( InFile, sfunc, pfunc ); /* (recursive call), then just */
- /* use it. */
-
- else /* If we don't have a buffer */
- { /* allocate one, then parse, */
- bSize = BUFR_INC; /* then free. */
- bufr = (char *)SMB_MALLOC( bSize );
- if( NULL == bufr )
- {
- DEBUG(0,("%s memory allocation failure.\n", func));
- myfile_close(InFile);
- return( False );
- }
- result = Parse( InFile, sfunc, pfunc );
- SAFE_FREE( bufr );
- bufr = NULL;
- bSize = 0;
- }
-
- myfile_close(InFile);
-
- if( !result ) /* Generic failure. */
- {
- DEBUG(0,("%s Failed. Error returned from params.c:parse().\n", func));
- return( False );
- }
-
- return( True ); /* Generic success. */
- } /* pm_process */
-
-/* -------------------------------------------------------------------------- */
+ BOOL (*sfunc)(const char *),
+ BOOL (*pfunc)(const char *, const char *) )
+{
+ int result;
+ myFILE *InFile;
+ const char *func = "params.c:pm_process() -";
+
+ InFile = OpenConfFile( FileName ); /* Open the config file. */
+ if( NULL == InFile )
+ return False;
+
+ DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) );
+
+ if( NULL != bufr ) {
+ /* If we already have a buffer */
+ /* (recursive call), then just */
+ /* use it. */
+ result = Parse( InFile, sfunc, pfunc );
+ } else {
+ bSize = BUFR_INC;
+ bufr = (char *)SMB_MALLOC( bSize );
+ if( NULL == bufr ) {
+ DEBUG(0,("%s memory allocation failure.\n", func));
+ myfile_close(InFile);
+ return False;
+ }
+
+ result = Parse( InFile, sfunc, pfunc );
+ SAFE_FREE( bufr );
+ bufr = NULL;
+ bSize = 0;
+ }
+
+ myfile_close(InFile);
+
+ if( !result ) {
+ DEBUG(0,("%s Failed. Error returned from params.c:parse().\n", func));
+ return False;
+ }
+
+ return True;
+}
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 6777149a8a5..deac2bbd6e3 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -1152,9 +1152,11 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n",
unix_pw->pw_name, (unsigned long)uid));
- return algorithmic_uid_to_sid( psid, uid);
+ algorithmic_uid_to_sid( psid, uid);
}
+ pdb_free_sam(&sampw);
+
DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n",
(unsigned int)uid, sid_string_static(psid), unix_pw->pw_name));
@@ -1379,18 +1381,18 @@ BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
pass_last_set_time,
pass_can_change_time,
pass_must_change_time;
- char *username;
- char *domain;
- char *nt_username;
- char *dir_drive;
- char *unknown_str;
- char *munged_dial;
- char *fullname;
- char *homedir;
- char *logon_script;
- char *profile_path;
- char *acct_desc;
- char *workstations;
+ char *username = NULL;
+ char *domain = NULL;
+ char *nt_username = NULL;
+ char *dir_drive = NULL;
+ char *unknown_str = NULL;
+ char *munged_dial = NULL;
+ char *fullname = NULL;
+ char *homedir = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *acct_desc = NULL;
+ char *workstations = NULL;
uint32 username_len, domain_len, nt_username_len,
dir_drive_len, unknown_str_len, munged_dial_len,
fullname_len, homedir_len, logon_script_len,
@@ -1399,8 +1401,8 @@ BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
uint16 acct_ctrl, logon_divs;
uint16 bad_password_count, logon_count;
- uint8 *hours;
- uint8 *lm_pw_ptr, *nt_pw_ptr;
+ uint8 *hours = NULL;
+ uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
uint32 len = 0;
uint32 lm_pw_len, nt_pw_len, hourslen;
BOOL ret = True;
@@ -1558,18 +1560,18 @@ BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
pass_last_set_time,
pass_can_change_time,
pass_must_change_time;
- char *username;
- char *domain;
- char *nt_username;
- char *dir_drive;
- char *unknown_str;
- char *munged_dial;
- char *fullname;
- char *homedir;
- char *logon_script;
- char *profile_path;
- char *acct_desc;
- char *workstations;
+ char *username = NULL;
+ char *domain = NULL;
+ char *nt_username = NULL;
+ char *dir_drive = NULL;
+ char *unknown_str = NULL;
+ char *munged_dial = NULL;
+ char *fullname = NULL;
+ char *homedir = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *acct_desc = NULL;
+ char *workstations = NULL;
uint32 username_len, domain_len, nt_username_len,
dir_drive_len, unknown_str_len, munged_dial_len,
fullname_len, homedir_len, logon_script_len,
@@ -1578,8 +1580,8 @@ BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
uint32 user_rid, group_rid, remove_me, hours_len, unknown_6;
uint16 acct_ctrl, logon_divs;
uint16 bad_password_count, logon_count;
- uint8 *hours;
- uint8 *lm_pw_ptr, *nt_pw_ptr;
+ uint8 *hours = NULL;
+ uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL;
uint32 len = 0;
uint32 lm_pw_len, nt_pw_len, hourslen;
BOOL ret = True;
@@ -1744,18 +1746,18 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
pass_last_set_time,
pass_can_change_time,
pass_must_change_time;
- char *username;
- char *domain;
- char *nt_username;
- char *dir_drive;
- char *unknown_str;
- char *munged_dial;
- char *fullname;
- char *homedir;
- char *logon_script;
- char *profile_path;
- char *acct_desc;
- char *workstations;
+ char *username = NULL;
+ char *domain = NULL;
+ char *nt_username = NULL;
+ char *dir_drive = NULL;
+ char *unknown_str = NULL;
+ char *munged_dial = NULL;
+ char *fullname = NULL;
+ char *homedir = NULL;
+ char *logon_script = NULL;
+ char *profile_path = NULL;
+ char *acct_desc = NULL;
+ char *workstations = NULL;
uint32 username_len, domain_len, nt_username_len,
dir_drive_len, unknown_str_len, munged_dial_len,
fullname_len, homedir_len, logon_script_len,
@@ -1764,8 +1766,8 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
uint32 user_rid, group_rid, hours_len, unknown_6;
uint16 acct_ctrl, logon_divs;
uint16 bad_password_count, logon_count;
- uint8 *hours;
- uint8 *lm_pw_ptr, *nt_pw_ptr, *nt_pw_hist_ptr;
+ uint8 *hours = NULL;
+ uint8 *lm_pw_ptr = NULL, *nt_pw_ptr = NULL, *nt_pw_hist_ptr = NULL;
uint32 len = 0;
uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen;
uint32 pwHistLen = 0;
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index c8710097525..36a575214b9 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -453,6 +453,25 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context,
num_entries, unix_only);
}
+static NTSTATUS context_enum_group_members(struct pdb_context *context,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *group,
+ uint32 **member_rids,
+ int *num_members)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if ((!context) || (!context->pdb_methods)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ return context->pdb_methods->enum_group_members(context->pdb_methods,
+ mem_ctx, group,
+ member_rids,
+ num_members);
+}
+
static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
const char *username,
gid_t primary_gid,
@@ -621,7 +640,7 @@ static NTSTATUS context_enum_alias_memberships(struct pdb_context *context,
enum_alias_memberships(context->pdb_methods, members,
num_members, aliases, num);
}
-
+
/******************************************************************
Free and cleanup a pdb context, any associated data and anything
that the attached modules might have associated.
@@ -737,6 +756,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_update_group_mapping_entry = context_update_group_mapping_entry;
(*context)->pdb_delete_group_mapping_entry = context_delete_group_mapping_entry;
(*context)->pdb_enum_group_mapping = context_enum_group_mapping;
+ (*context)->pdb_enum_group_members = context_enum_group_members;
(*context)->pdb_enum_group_memberships = context_enum_group_memberships;
(*context)->pdb_find_alias = context_find_alias;
@@ -1058,6 +1078,21 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap,
rmap, num_entries, unix_only));
}
+NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ uint32 **member_rids,
+ int *num_members)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return pdb_context->pdb_enum_group_members(pdb_context, mem_ctx, sid,
+ member_rids, num_members);
+}
+
NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
DOM_SID **sids, gid_t **gids,
int *num_groups)
@@ -1259,6 +1294,116 @@ static void pdb_default_endsampwent(struct pdb_methods *methods)
return; /* NT_STATUS_NOT_IMPLEMENTED; */
}
+static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
+ uid_t uid, uid_t **uids, int *num)
+{
+ int i;
+
+ for (i=0; i<*num; i++) {
+ if ((*uids)[i] == uid)
+ return;
+ }
+
+ *uids = TALLOC_REALLOC_ARRAY(mem_ctx, *uids, uid_t, *num+1);
+
+ if (*uids == NULL)
+ return;
+
+ (*uids)[*num] = uid;
+ *num += 1;
+}
+
+static BOOL get_memberuids(TALLOC_CTX *mem_ctx, gid_t gid, uid_t **uids,
+ int *num)
+{
+ struct group *grp;
+ char **gr;
+ struct sys_pwent *userlist, *user;
+
+ *uids = NULL;
+ *num = 0;
+
+ /* We only look at our own sam, so don't care about imported stuff */
+
+ winbind_off();
+
+ if ((grp = getgrgid(gid)) == NULL) {
+ winbind_on();
+ return False;
+ }
+
+ /* Primary group members */
+
+ userlist = getpwent_list();
+
+ for (user = userlist; user != NULL; user = user->next) {
+ if (user->pw_gid != gid)
+ continue;
+ add_uid_to_array_unique(mem_ctx, user->pw_uid, uids, num);
+ }
+
+ pwent_free(userlist);
+
+ /* Secondary group members */
+
+ for (gr = grp->gr_mem; (*gr != NULL) && ((*gr)[0] != '\0'); gr += 1) {
+ struct passwd *pw = getpwnam(*gr);
+
+ if (pw == NULL)
+ continue;
+ add_uid_to_array_unique(mem_ctx, pw->pw_uid, uids, num);
+ }
+
+ winbind_on();
+
+ return True;
+}
+
+NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *group,
+ uint32 **member_rids,
+ int *num_members)
+{
+ gid_t gid;
+ uid_t *uids;
+ int i, num_uids;
+
+ *member_rids = NULL;
+ *num_members = 0;
+
+ if (!NT_STATUS_IS_OK(sid_to_gid(group, &gid)))
+ return NT_STATUS_NO_SUCH_GROUP;
+
+ if(!get_memberuids(mem_ctx, gid, &uids, &num_uids))
+ return NT_STATUS_NO_SUCH_GROUP;
+
+ if (num_uids == 0)
+ return NT_STATUS_OK;
+
+ *member_rids = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_uids);
+
+ for (i=0; i<num_uids; i++) {
+ DOM_SID sid;
+
+ if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
+ DEBUG(1, ("Could not map member uid to SID\n"));
+ continue;
+ }
+
+ if (!sid_check_is_in_our_domain(&sid)) {
+ DEBUG(1, ("Inconsistent SAM -- group member uid not "
+ "in our domain\n"));
+ continue;
+ }
+
+ sid_peek_rid(&sid, &(*member_rids)[*num_members]);
+ *num_members += 1;
+ }
+
+ return NT_STATUS_OK;
+}
+
NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
{
*methods = TALLOC_P(mem_ctx, struct pdb_methods);
@@ -1285,6 +1430,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->update_group_mapping_entry = pdb_default_update_group_mapping_entry;
(*methods)->delete_group_mapping_entry = pdb_default_delete_group_mapping_entry;
(*methods)->enum_group_mapping = pdb_default_enum_group_mapping;
+ (*methods)->enum_group_members = pdb_default_enum_group_members;
(*methods)->enum_group_memberships = pdb_default_enum_group_memberships;
(*methods)->find_alias = pdb_default_find_alias;
(*methods)->create_alias = pdb_default_create_alias;
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 8b7661d9a36..0a0426ef2ab 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -96,6 +96,8 @@ struct ldapsam_privates {
/* configuration items */
int schema_ver;
+
+ char *domain_dn;
};
/**********************************************************************
@@ -132,7 +134,7 @@ static const char* get_userattr_key2string( int schema_ver, int key )
Return the list of attribute names given a user schema version.
**********************************************************************/
-static char** get_userattr_list( int schema_ver )
+static const char** get_userattr_list( int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
@@ -152,7 +154,7 @@ static char** get_userattr_list( int schema_ver )
Return the list of attribute names to delete given a user schema version.
**************************************************************************/
-static char** get_userattr_delete_list( int schema_ver )
+static const char** get_userattr_delete_list( int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
@@ -199,7 +201,8 @@ static const char* get_objclass_filter( int schema_ver )
static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state,
const char *user,
- LDAPMessage ** result, char **attr)
+ LDAPMessage ** result,
+ const char **attr)
{
pstring filter;
char *escape_user = escape_ldap_string_alloc(user);
@@ -233,7 +236,7 @@ static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state,
static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
uint32 rid, LDAPMessage ** result,
- char **attr)
+ const char **attr)
{
pstring filter;
int rc;
@@ -252,7 +255,7 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state,
static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
const DOM_SID *sid, LDAPMessage ** result,
- char **attr)
+ const char **attr)
{
pstring filter;
int rc;
@@ -276,7 +279,7 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
LDAPMessage *result,
const char *objectclass,
- char **attrs)
+ const char **attrs)
{
int rc;
LDAPMessage *entry = NULL;
@@ -314,7 +317,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
name != NULL;
name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
- char **attrib;
+ const char **attrib;
/* We are only allowed to delete the attributes that
really exist. */
@@ -1190,7 +1193,7 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update,
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
int rc;
pstring filter, suffix;
- char **attr_list;
+ const char **attr_list;
BOOL machine_mask = False, user_mask = False;
pstr_sprintf( filter, "(&%s%s)", lp_ldap_filter(),
@@ -1272,7 +1275,7 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT
return NT_STATUS_OK;
}
-static void append_attr(char ***attr_list, const char *new_attr)
+static void append_attr(const char ***attr_list, const char *new_attr)
{
int i;
@@ -1284,7 +1287,7 @@ static void append_attr(char ***attr_list, const char *new_attr)
;
}
- (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), char *, i+2);
+ (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *, i+2);
SMB_ASSERT((*attr_list) != NULL);
(*attr_list)[i] = SMB_STRDUP(new_attr);
(*attr_list)[i+1] = NULL;
@@ -1301,7 +1304,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
int count;
- char ** attr_list;
+ const char ** attr_list;
int rc;
attr_list = get_userattr_list( ldap_state->schema_ver );
@@ -1345,7 +1348,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
const DOM_SID *sid, LDAPMessage **result)
{
int rc = -1;
- char ** attr_list;
+ const char ** attr_list;
uint32 rid;
switch ( ldap_state->schema_ver ) {
@@ -1575,7 +1578,7 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
int rc;
LDAPMessage *result = NULL;
NTSTATUS ret;
- char **attr_list;
+ const char **attr_list;
fstring objclass;
if (!sam_acct) {
@@ -1640,7 +1643,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
LDAPMod **mods = NULL;
- char **attr_list;
+ const char **attr_list;
result = pdb_get_backend_private_data(newpwd, my_methods);
if (!result) {
@@ -1728,7 +1731,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
LDAPMod **mods = NULL;
int ldap_op = LDAP_MOD_REPLACE;
uint32 num_result;
- char **attr_list;
+ const char **attr_list;
char *escape_user;
const char *username = pdb_get_username(newpwd);
const DOM_SID *sid = pdb_get_user_sid(newpwd);
@@ -1928,7 +1931,7 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
{
int scope = LDAP_SCOPE_SUBTREE;
int rc;
- char **attr_list;
+ const char **attr_list;
attr_list = get_attr_list(groupmap_attr_list);
rc = smbldap_search(ldap_state->smbldap_state,
@@ -2162,6 +2165,213 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
return ldapsam_getgroup(methods, filter, map);
}
+static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx,
+ uint32 rid, uint32 **rids, int *num)
+{
+ int i;
+
+ for (i=0; i<*num; i++) {
+ if ((*rids)[i] == rid)
+ return;
+ }
+
+ *rids = TALLOC_REALLOC_ARRAY(mem_ctx, *rids, uint32, *num+1);
+
+ if (*rids == NULL)
+ return;
+
+ (*rids)[*num] = rid;
+ *num += 1;
+}
+
+static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *group,
+ uint32 **member_rids,
+ int *num_members)
+{
+ struct ldapsam_privates *ldap_state =
+ (struct ldapsam_privates *)methods->private_data;
+ struct smbldap_state *conn = ldap_state->smbldap_state;
+ pstring filter;
+ int rc, count;
+ LDAPMessage *msg = NULL;
+ LDAPMessage *entry;
+ char **values = NULL;
+ char **memberuid;
+ char *sid_filter = NULL;
+ char *tmp;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
+ return pdb_default_enum_group_members(methods, mem_ctx, group,
+ member_rids,
+ num_members);
+
+ *member_rids = NULL;
+ *num_members = 0;
+
+ pstr_sprintf(filter,
+ "(&(objectClass=sambaSamAccount)"
+ "(sambaPrimaryGroupSid=%s))",
+ sid_string_static(group));
+
+ {
+ const char *attrs[] = { "sambaSID", NULL };
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0,
+ &msg);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(conn->ldap_struct, entry))
+ {
+ fstring str;
+ DOM_SID sid;
+ uint32 rid;
+
+ if (!smbldap_get_single_attribute(conn->ldap_struct,
+ entry, "sambaSID",
+ str, sizeof(str)-1))
+ continue;
+
+ if (!string_to_sid(&sid, str))
+ goto done;
+
+ if (!sid_check_is_in_our_domain(&sid)) {
+ DEBUG(1, ("Inconsistent SAM -- group member uid not "
+ "in our domain\n"));
+ continue;
+ }
+
+ sid_peek_rid(&sid, &rid);
+
+ add_rid_to_array_unique(mem_ctx, rid, member_rids,
+ num_members);
+ }
+
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ pstr_sprintf(filter,
+ "(&(objectClass=sambaGroupMapping)"
+ "(objectClass=posixGroup)"
+ "(sambaSID=%s))",
+ sid_string_static(group));
+
+ {
+ const char *attrs[] = { "memberUid", NULL };
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, filter, attrs, 0,
+ &msg);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ count = ldap_count_entries(conn->ldap_struct, msg);
+
+ if (count > 1) {
+ DEBUG(1, ("Found more than one groupmap entry for %s\n",
+ sid_string_static(group)));
+ goto done;
+ }
+
+ if (count == 0) {
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ entry = ldap_first_entry(conn->ldap_struct, msg);
+ if (entry == NULL)
+ goto done;
+
+ values = ldap_get_values(conn->ldap_struct, msg, "memberUid");
+ if (values == NULL) {
+ result = NT_STATUS_OK;
+ goto done;
+ }
+
+ sid_filter = strdup("(&(objectClass=sambaSamAccount)(|");
+ if (sid_filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ for (memberuid = values; *memberuid != NULL; memberuid += 1) {
+ tmp = sid_filter;
+ asprintf(&sid_filter, "%s(uid=%s)", tmp, *memberuid);
+ free(tmp);
+ if (sid_filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+
+ tmp = sid_filter;
+ asprintf(&sid_filter, "%s))", sid_filter);
+ free(tmp);
+ if (sid_filter == NULL) {
+ result = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ {
+ const char *attrs[] = { "sambaSID", NULL };
+ rc = smbldap_search(conn, lp_ldap_user_suffix(),
+ LDAP_SCOPE_SUBTREE, sid_filter, attrs, 0,
+ &msg);
+ }
+
+ if (rc != LDAP_SUCCESS)
+ goto done;
+
+ for (entry = ldap_first_entry(conn->ldap_struct, msg);
+ entry != NULL;
+ entry = ldap_next_entry(conn->ldap_struct, entry))
+ {
+ fstring str;
+ DOM_SID sid;
+ uint32 rid;
+
+ if (!smbldap_get_single_attribute(conn->ldap_struct,
+ entry, "sambaSID",
+ str, sizeof(str)-1))
+ continue;
+
+ if (!string_to_sid(&sid, str))
+ goto done;
+
+ if (!sid_check_is_in_our_domain(&sid)) {
+ DEBUG(1, ("Inconsistent SAM -- group member uid not "
+ "in our domain\n"));
+ continue;
+ }
+
+ sid_peek_rid(&sid, &rid);
+
+ add_rid_to_array_unique(mem_ctx, rid, member_rids,
+ num_members);
+ }
+
+ result = NT_STATUS_OK;
+
+ done:
+ SAFE_FREE(sid_filter);
+
+ if (values != NULL)
+ ldap_value_free(values);
+
+ if (msg != NULL)
+ ldap_msgfree(msg);
+
+ return result;
+}
+
static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
const char *username,
gid_t primary_gid,
@@ -2172,7 +2382,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
(struct ldapsam_privates *)methods->private_data;
struct smbldap_state *conn = ldap_state->smbldap_state;
pstring filter;
- char *attrs[] = { "gidNumber", "sambaSID", NULL };
+ const char *attrs[] = { "gidNumber", "sambaSID", NULL };
char *escape_name;
int rc;
LDAPMessage *msg = NULL;
@@ -2328,7 +2538,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
pstring suffix;
pstring filter;
- char **attr_list;
+ const char **attr_list;
ldap_msgfree(result);
@@ -2487,7 +2697,7 @@ static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
LDAPMessage *result = NULL;
int rc;
NTSTATUS ret;
- char **attr_list;
+ const char **attr_list;
sid_to_string(sidstring, &sid);
@@ -2517,7 +2727,7 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
fstring filter;
int rc;
- char **attr_list;
+ const char **attr_list;
pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
attr_list = get_attr_list( groupmap_attr_list );
@@ -2813,7 +3023,7 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
(struct ldapsam_privates *)methods->private_data;
LDAP *ldap_struct;
- char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
+ const char *attrs[] = { LDAP_ATTRIBUTE_SID, NULL };
LDAPMessage *result = NULL;
LDAPMessage *entry = NULL;
@@ -2892,6 +3102,9 @@ static void free_private_data(void **vp)
ldap_msgfree((*ldap_state)->result);
(*ldap_state)->result = NULL;
}
+ if ((*ldap_state)->domain_dn != NULL) {
+ SAFE_FREE((*ldap_state)->domain_dn);
+ }
*ldap_state = NULL;
@@ -2930,6 +3143,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
(*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
(*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
(*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
+ (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
(*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
/* TODO: Setup private data and free */
@@ -3010,6 +3224,7 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met
DOM_SID ldap_domain_sid;
DOM_SID secrets_domain_sid;
pstring domain_sid_string;
+ char *dn;
if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
return nt_status;
@@ -3047,6 +3262,14 @@ and will risk BDCs having inconsistant SIDs\n"));
return NT_STATUS_UNSUCCESSFUL;
}
+ dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ if (!dn) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ldap_state->domain_dn = smb_xstrdup(dn);
+ ldap_memfree(dn);
+
if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID),
domain_sid_string)) {
diff --git a/source/printing/print_cups.c b/source/printing/print_cups.c
index 59ab41b9f67..e6064564dc8 100644
--- a/source/printing/print_cups.c
+++ b/source/printing/print_cups.c
@@ -670,12 +670,13 @@ static int cups_job_submit(int snum, struct printjob *pjob)
* 'cups_queue_get()' - Get all the jobs in the print queue.
*/
-static int cups_queue_get(const char *printer_name,
+static int cups_queue_get(const char *sharename,
enum printing_types printing_type,
char *lpq_command,
print_queue_struct **q,
print_status_struct *status)
{
+ fstring printername;
http_t *http = NULL; /* HTTP connection to server */
ipp_t *request = NULL, /* IPP Request */
*response = NULL; /* IPP Response */
@@ -711,7 +712,15 @@ static int cups_queue_get(const char *printer_name,
*q = NULL;
- DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printer_name, q, status));
+ /* HACK ALERT!!! The porblem with support the 'printer name'
+ option is that we key the tdb off the sharename. So we will
+ overload the lpq_command string to pass in the printername
+ (which is basically what we do for non-cups printers ... using
+ the lpq_command to get the queue listing). */
+
+ fstrcpy( printername, lpq_command );
+
+ DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printername, q, status));
/*
* Make sure we don't ask for passwords...
@@ -733,7 +742,7 @@ static int cups_queue_get(const char *printer_name,
* Generate the printer URI...
*/
- slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printer_name);
+ slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername);
/*
* Build an IPP_GET_JOBS request, which requires the following
@@ -936,14 +945,14 @@ static int cups_queue_get(const char *printer_name,
*/
if ((response = cupsDoRequest(http, request, "/")) == NULL) {
- DEBUG(0,("Unable to get printer status for %s - %s\n", printer_name,
+ DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
ippErrorString(cupsLastError())));
*q = queue;
goto out;
}
if (response->request.status.status_code >= IPP_OK_CONFLICT) {
- DEBUG(0,("Unable to get printer status for %s - %s\n", printer_name,
+ DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
ippErrorString(response->request.status.status_code)));
*q = queue;
goto out;
diff --git a/source/python/py_smb.c b/source/python/py_smb.c
index 1347f79a9b3..c3d59d4fb8c 100644
--- a/source/python/py_smb.c
+++ b/source/python/py_smb.c
@@ -179,6 +179,83 @@ static PyObject *py_smb_nt_create_andx(PyObject *self, PyObject *args,
return PyInt_FromLong(result);
}
+static PyObject *py_smb_open(PyObject *self, PyObject *args, PyObject *kw)
+{
+ cli_state_object *cli = (cli_state_object *)self;
+ static char *kwlist[] = { "filename", "flags",
+ "share_mode", NULL };
+ char *filename;
+ uint32 flags, share_mode = DENY_NONE;
+ int result;
+
+ /* Parse parameters */
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "si|i", kwlist, &filename, &flags, &share_mode))
+ return NULL;
+
+ result = cli_open(cli->cli, filename, flags, share_mode);
+
+ if (cli_is_error(cli->cli)) {
+ PyErr_SetString(PyExc_RuntimeError, "open failed");
+ return NULL;
+ }
+
+ /* Return FID */
+
+ return PyInt_FromLong(result);
+}
+
+static PyObject *py_smb_read(PyObject *self, PyObject *args, PyObject *kw)
+{
+ cli_state_object *cli = (cli_state_object *)self;
+ static char *kwlist[] = { "fnum", "offset", "size", NULL };
+ int fnum, offset=0, size=0;
+ ssize_t result;
+ size_t fsize;
+ char *data;
+ PyObject *ret;
+
+ /* Parse parameters */
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kw, "i|ii", kwlist, &fnum, &offset, &size))
+ return NULL;
+
+ if (!cli_qfileinfo(cli->cli, fnum, NULL, &fsize, NULL, NULL,
+ NULL, NULL, NULL) &&
+ !cli_getattrE(cli->cli, fnum, NULL, &fsize, NULL, NULL, NULL)) {
+ PyErr_SetString(PyExc_RuntimeError, "getattrib failed");
+ return NULL;
+ }
+
+ if (offset < 0)
+ offset = 0;
+
+ if (size < 1 || size > fsize - offset)
+ size = fsize - offset;
+
+ if (!(data = (char *) malloc((size_t) size))) {
+ PyErr_SetString(PyExc_RuntimeError, "malloc failed");
+ return NULL;
+ }
+
+ result = cli_read(cli->cli, fnum, data, (off_t) offset, (size_t) size);
+
+ if (result==-1 || cli_is_error(cli->cli)) {
+ SAFE_FREE(data);
+ PyErr_SetString(PyExc_RuntimeError, "read failed");
+ return NULL;
+ }
+
+ /* Return a python string */
+
+ ret = Py_BuildValue("s#", data, result);
+ SAFE_FREE(data);
+
+ return ret;
+}
+
static PyObject *py_smb_close(PyObject *self, PyObject *args,
PyObject *kw)
{
@@ -323,6 +400,33 @@ static PyMethodDef smb_hnd_methods[] = {
{ "nt_create_andx", (PyCFunction)py_smb_nt_create_andx,
METH_VARARGS | METH_KEYWORDS, "NT Create&X" },
+ { "open", (PyCFunction)py_smb_open,
+ METH_VARARGS | METH_KEYWORDS,
+ "Open a file\n"
+"\n"
+"This function returns a fnum handle to an open file. The file is\n"
+"opened with flags and optional share mode. If unspecified, the\n"
+"default share mode is DENY_NONE\n"
+"\n"
+"Example:\n"
+"\n"
+">>> fnum=conn.open(filename, os.O_RDONLY)" },
+
+ { "read", (PyCFunction)py_smb_read,
+ METH_VARARGS | METH_KEYWORDS,
+ "Read from an open file\n"
+"\n"
+"This function returns a string read from an open file starting at\n"
+"offset for size bytes (until EOF is reached). If unspecified, the\n"
+"default offset is 0, and default size is the remainder of the file.\n"
+"\n"
+"Example:\n"
+"\n"
+">>> conn.read(fnum) # read entire file\n"
+">>> conn.read(fnum,5) # read entire file from offset 5\n"
+">>> conn.read(fnum,size=64) # read 64 bytes from start of file\n"
+">>> conn.read(fnum,4096,1024) # read 1024 bytes from offset 4096\n" },
+
{ "close", (PyCFunction)py_smb_close,
METH_VARARGS | METH_KEYWORDS, "Close" },
diff --git a/source/python/py_spoolss.h b/source/python/py_spoolss.h
index 34b48190cd1..ec94de8fe4f 100644
--- a/source/python/py_spoolss.h
+++ b/source/python/py_spoolss.h
@@ -67,7 +67,8 @@ BOOL py_to_DRIVER_INFO_1(DRIVER_INFO_1 *info, PyObject *dict);
BOOL py_from_DRIVER_INFO_2(PyObject **dict, DRIVER_INFO_2 *info);
BOOL py_to_DRIVER_INFO_2(DRIVER_INFO_2 *info, PyObject *dict);
BOOL py_from_DRIVER_INFO_3(PyObject **dict, DRIVER_INFO_3 *info);
-BOOL py_to_DRIVER_INFO_3(DRIVER_INFO_3 *info, PyObject *dict);
+BOOL py_to_DRIVER_INFO_3(DRIVER_INFO_3 *info, PyObject *dict,
+ TALLOC_CTX *mem_ctx);
BOOL py_from_DRIVER_INFO_6(PyObject **dict, DRIVER_INFO_6 *info);
BOOL py_to_DRIVER_INFO_6(DRIVER_INFO_6 *info, PyObject *dict);
BOOL py_from_DRIVER_DIRECTORY_1(PyObject **dict, DRIVER_DIRECTORY_1 *info);
diff --git a/source/python/py_spoolss_drivers.c b/source/python/py_spoolss_drivers.c
index 9424fe1527d..310f978188c 100644
--- a/source/python/py_spoolss_drivers.c
+++ b/source/python/py_spoolss_drivers.c
@@ -365,7 +365,7 @@ PyObject *spoolss_addprinterdriver(PyObject *self, PyObject *args,
case 3:
ctr.info3 = &dinfo.driver_3;
- if (!py_to_DRIVER_INFO_3(&dinfo.driver_3, info)) {
+ if (!py_to_DRIVER_INFO_3(&dinfo.driver_3, info, mem_ctx)) {
PyErr_SetString(spoolss_error,
"error converting to driver info 3");
goto done;
diff --git a/source/python/py_spoolss_drivers_conv.c b/source/python/py_spoolss_drivers_conv.c
index 9bc84080529..ae196c19037 100644
--- a/source/python/py_spoolss_drivers_conv.c
+++ b/source/python/py_spoolss_drivers_conv.c
@@ -78,9 +78,49 @@ struct pyconv py_DRIVER_DIRECTORY_1[] = {
{ NULL }
};
-static uint16 *to_dependentfiles(PyObject *dict)
+static uint16 *to_dependentfiles(PyObject *list, TALLOC_CTX *mem_ctx)
{
- return (uint16 *)"abcd\0";
+ uint32 elements, size=0, pos=0, i;
+ char *str;
+ uint16 *ret = NULL;
+ PyObject *borrowedRef;
+
+ if (!PyList_Check(list)) {
+ goto done;
+ }
+
+ /* calculate size for dependentfiles */
+ elements=PyList_Size(list);
+ for (i = 0; i < elements; i++) {
+ borrowedRef=PyList_GetItem(list, i);
+ if (!PyString_Check(borrowedRef))
+ /* non string found, return error */
+ goto done;
+ size+=PyString_Size(borrowedRef)+1;
+ }
+
+ if (!(ret = (uint16*) talloc(mem_ctx,(size+1)*sizeof(uint16))))
+ goto done;
+
+ /* create null terminated sequence of null terminated strings */
+ for (i = 0; i < elements; i++) {
+ borrowedRef=PyList_GetItem(list, i);
+ str=PyString_AsString(borrowedRef);
+ do {
+ if (pos >= size) {
+ /* dependentfiles too small. miscalculated? */
+ ret = NULL;
+ goto done;
+ }
+ SSVAL(&ret[pos], 0, str[0]);
+ pos++;
+ } while (*(str++));
+ }
+ /* final null */
+ ret[pos]='\0';
+
+done:
+ return ret;
}
BOOL py_from_DRIVER_INFO_1(PyObject **dict, DRIVER_INFO_1 *info)
@@ -122,16 +162,17 @@ BOOL py_from_DRIVER_INFO_3(PyObject **dict, DRIVER_INFO_3 *info)
return True;
}
-BOOL py_to_DRIVER_INFO_3(DRIVER_INFO_3 *info, PyObject *dict)
+BOOL py_to_DRIVER_INFO_3(DRIVER_INFO_3 *info, PyObject *dict,
+ TALLOC_CTX *mem_ctx)
{
PyObject *obj, *dict_copy = PyDict_Copy(dict);
BOOL result = False;
- if (!(obj = PyDict_GetItemString(dict_copy, "dependent_files")) ||
- !PyList_Check(obj))
+ if (!(obj = PyDict_GetItemString(dict_copy, "dependent_files")))
goto done;
- info->dependentfiles = to_dependentfiles(obj);
+ if (!(info->dependentfiles = to_dependentfiles(obj, mem_ctx)))
+ goto done;
PyDict_DelItemString(dict_copy, "dependent_files");
diff --git a/source/registry/reg_cachehook.c b/source/registry/reg_cachehook.c
index 3b75cae1a59..dc7136a1d53 100644
--- a/source/registry/reg_cachehook.c
+++ b/source/registry/reg_cachehook.c
@@ -21,6 +21,7 @@
/* Implementation of registry hook cache tree */
#include "includes.h"
+#include "adt_tree.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
@@ -35,7 +36,7 @@ static REGISTRY_HOOK default_hook = { KEY_TREE_ROOT, &regdb_ops };
BOOL reghook_cache_init( void )
{
- cache_tree = sorted_tree_init( &default_hook, NULL, NULL );
+ cache_tree = pathtree_init( &default_hook, NULL, NULL );
return ( cache_tree == NULL );
}
@@ -59,7 +60,7 @@ BOOL reghook_cache_add( REGISTRY_HOOK *hook )
DEBUG(10,("reghook_cache_add: Adding key [%s]\n", key));
- return sorted_tree_add( cache_tree, key, hook );
+ return pathtree_add( cache_tree, key, hook );
}
/**********************************************************************
@@ -93,7 +94,7 @@ REGISTRY_HOOK* reghook_cache_find( char *keyname )
DEBUG(10,("reghook_cache_find: Searching for keyname [%s]\n", key));
- hook = sorted_tree_find( cache_tree, key ) ;
+ hook = pathtree_find( cache_tree, key ) ;
SAFE_FREE( key );
@@ -108,5 +109,5 @@ void reghook_dump_cache( int debuglevel )
{
DEBUG(debuglevel,("reghook_dump_cache: Starting cache dump now...\n"));
- sorted_tree_print_keys( cache_tree, debuglevel );
+ pathtree_print_keys( cache_tree, debuglevel );
}
diff --git a/source/registry/reg_objects.c b/source/registry/reg_objects.c
index 16fb7dd18d7..c8dc6330873 100644
--- a/source/registry/reg_objects.c
+++ b/source/registry/reg_objects.c
@@ -113,7 +113,7 @@ void regsubkey_ctr_destroy( REGSUBKEY_CTR *ctr )
void regval_ctr_init( REGVAL_CTR *ctr )
{
- if ( !ctr->ctx )
+ if ( ctr && !ctr->ctx )
ctr->ctx = talloc_init("regval_ctr_init for ctr %p", ctr);
}
diff --git a/source/rpc_client/cli_dfs.c b/source/rpc_client/cli_dfs.c
index 0975242b7d6..79335191183 100644
--- a/source/rpc_client/cli_dfs.c
+++ b/source/rpc_client/cli_dfs.c
@@ -43,7 +43,7 @@ NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_dfs_q_dfs_exist(&q);
if (!dfs_io_q_dfs_exist("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, PI_NETLOGON, DFS_EXIST, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, PI_NETDFS, DFS_EXIST, &qbuf, &rbuf)) {
goto done;
}
@@ -89,7 +89,7 @@ NTSTATUS cli_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
flags);
if (!dfs_io_q_dfs_add("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, PI_NETLOGON, DFS_ADD, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, PI_NETDFS, DFS_ADD, &qbuf, &rbuf)) {
goto done;
}
@@ -132,7 +132,7 @@ NTSTATUS cli_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_dfs_q_dfs_remove(&q, entrypath, servername, sharename);
if (!dfs_io_q_dfs_remove("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, PI_NETLOGON, DFS_REMOVE, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, PI_NETDFS, DFS_REMOVE, &qbuf, &rbuf)) {
goto done;
}
@@ -178,7 +178,7 @@ NTSTATUS cli_dfs_get_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
info_level);
if (!dfs_io_q_dfs_get_info("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, PI_NETLOGON, DFS_GET_INFO, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, PI_NETDFS, DFS_GET_INFO, &qbuf, &rbuf)) {
goto done;
}
@@ -223,7 +223,7 @@ NTSTATUS cli_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
init_dfs_q_dfs_enum(&q, info_level, ctr);
if (!dfs_io_q_dfs_enum("", &q, &qbuf, 0) ||
- !rpc_api_pipe_req(cli, PI_NETLOGON, DFS_ENUM, &qbuf, &rbuf)) {
+ !rpc_api_pipe_req(cli, PI_NETDFS, DFS_ENUM, &qbuf, &rbuf)) {
goto done;
}
diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c
index 03b3c2134b9..5473168c0f8 100644
--- a/source/rpc_client/cli_samr.c
+++ b/source/rpc_client/cli_samr.c
@@ -1605,7 +1605,7 @@ NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
looked up in one packet. */
NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *domain_pol, uint32 flags,
+ POLICY_HND *domain_pol,
uint32 num_rids, uint32 *rids,
uint32 *num_names, char ***names,
uint32 **name_types)
@@ -1633,8 +1633,7 @@ NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Marshall data and send request */
- init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags,
- num_rids, rids);
+ init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, 1000, num_rids, rids);
if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, PI_SAMR, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
@@ -1649,9 +1648,11 @@ NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Return output parameters */
- if (!NT_STATUS_IS_OK(result = r.status)) {
+ result = r.status;
+
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
goto done;
- }
if (r.num_names1 == 0) {
*num_names = 0;
diff --git a/source/rpc_client/cli_wkssvc.c b/source/rpc_client/cli_wkssvc.c
index 636e0fa0188..aea47443988 100644
--- a/source/rpc_client/cli_wkssvc.c
+++ b/source/rpc_client/cli_wkssvc.c
@@ -61,7 +61,7 @@ NTSTATUS cli_wks_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
}
/* actual rpc call over \PIPE\wkssvc */
- if (!rpc_api_pipe_req(cli, PI_SRVSVC, WKS_QUERY_INFO, &buf, &rbuf)) {
+ if (!rpc_api_pipe_req(cli, PI_WKSSVC, WKS_QUERY_INFO, &buf, &rbuf)) {
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return NT_STATUS_UNSUCCESSFUL;
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index b26083b89e9..d7bdca4df99 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -1174,28 +1174,14 @@ void init_id_info2(NET_ID_INFO_2 * id, const char *domain_name,
const uchar * lm_chal_resp, size_t lm_chal_resp_len,
const uchar * nt_chal_resp, size_t nt_chal_resp_len)
{
- unsigned char lm_owf[24];
- unsigned char nt_owf[128];
DEBUG(5,("init_id_info2: %d\n", __LINE__));
id->ptr_id_info2 = 1;
-
id->param_ctrl = param_ctrl;
init_logon_id(&id->logon_id, log_id_low, log_id_high);
- if (nt_chal_resp) {
- /* oops. can only send what-ever-it-is direct */
- memcpy(nt_owf, nt_chal_resp, MIN(sizeof(nt_owf), nt_chal_resp_len));
- nt_chal_resp = nt_owf;
- }
- if (lm_chal_resp) {
- /* oops. can only send what-ever-it-is direct */
- memcpy(lm_owf, lm_chal_resp, MIN(sizeof(lm_owf), lm_chal_resp_len));
- lm_chal_resp = lm_owf;
- }
-
memcpy(id->lm_chal, lm_challenge, sizeof(id->lm_chal));
init_str_hdr(&id->hdr_nt_chal_resp, nt_chal_resp_len, nt_chal_resp_len, (nt_chal_resp != NULL) ? 1 : 0);
init_str_hdr(&id->hdr_lm_chal_resp, lm_chal_resp_len, lm_chal_resp_len, (lm_chal_resp != NULL) ? 1 : 0);
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 748ee1fb7c8..27570ae8213 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -564,9 +564,9 @@ static BOOL sam_io_unk_info6(const char *desc, SAM_UNK_INFO_6 * u_6,
inits a structure.
********************************************************************/
-void init_unk_info7(SAM_UNK_INFO_7 * u_7)
+void init_unk_info7(SAM_UNK_INFO_7 * u_7, uint32 server_role)
{
- u_7->unknown_0 = 0x0003;
+ u_7->server_role = server_role;
}
/*******************************************************************
@@ -582,7 +582,7 @@ static BOOL sam_io_unk_info7(const char *desc, SAM_UNK_INFO_7 * u_7,
prs_debug(ps, depth, desc, "sam_io_unk_info7");
depth++;
- if(!prs_uint16("unknown_0", ps, depth, &u_7->unknown_0)) /* 0x0003 */
+ if(!prs_uint16("server_role", ps, depth, &u_7->server_role))
return False;
return True;
@@ -697,7 +697,7 @@ inits a structure.
void init_unk_info2(SAM_UNK_INFO_2 * u_2,
const char *comment, const char *domain, const char *server,
- uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias, NTTIME nt_logout)
+ uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias, NTTIME nt_logout, uint32 server_role)
{
u_2->logout.low = nt_logout.low;
u_2->logout.high = nt_logout.high;
@@ -707,7 +707,7 @@ void init_unk_info2(SAM_UNK_INFO_2 * u_2,
u_2->unknown_4 = 0x00000001;
- u_2->unknown_5 = 0x00000003;
+ u_2->server_role = server_role;
u_2->unknown_6 = 0x00000001;
u_2->num_domain_usrs = num_users;
u_2->num_domain_grps = num_groups;
@@ -754,7 +754,7 @@ static BOOL sam_io_unk_info2(const char *desc, SAM_UNK_INFO_2 * u_2,
if(!prs_uint32("unknown_4 ", ps, depth, &u_2->unknown_4)) /* 0x0000 0001 */
return False;
- if(!prs_uint32("unknown_5 ", ps, depth, &u_2->unknown_5)) /* 0x0000 0003 */
+ if(!prs_uint32("server_role ", ps, depth, &u_2->server_role))
return False;
if(!prs_uint32("unknown_6 ", ps, depth, &u_2->unknown_6)) /* 0x0000 0001 */
return False;
diff --git a/source/rpc_server/srv_lsa_hnd.c b/source/rpc_server/srv_lsa_hnd.c
index 0f9f239a029..68072b528aa 100644
--- a/source/rpc_server/srv_lsa_hnd.c
+++ b/source/rpc_server/srv_lsa_hnd.c
@@ -252,6 +252,10 @@ BOOL pipe_access_check(pipes_struct *p)
if (lp_restrict_anonymous() > 0) {
user_struct *user = get_valid_user_struct(p->vuid);
+ /* schannel, so we must be ok */
+ if (p->netsec_auth_validated)
+ return True;
+
if (!user) {
DEBUG(3, ("invalid vuid %d\n", p->vuid));
return False;
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index da00d2d6c43..225e5efd54c 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -647,8 +647,9 @@ NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_
uint32 mapped_count = 0;
if (num_entries > MAX_LOOKUP_SIDS) {
- num_entries = MAX_LOOKUP_SIDS;
- DEBUG(5,("_lsa_lookup_sids: truncating SID lookup list to %d\n", num_entries));
+ num_entries = 0;
+ DEBUG(5,("_lsa_lookup_sids: limit of %d exceeded, truncating SID lookup list to %d\n", MAX_LOOKUP_SIDS, num_entries));
+ r_u->status = NT_STATUS_NONE_MAPPED;
}
ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
@@ -968,7 +969,7 @@ NTSTATUS _lsa_create_account(pipes_struct *p, LSA_Q_CREATEACCOUNT *q_u, LSA_R_CR
if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED;
- if ( is_privileged_sid( &info->sid ) )
+ if ( is_privileged_sid( &q_u->sid.sid ) )
return NT_STATUS_OBJECT_NAME_COLLISION;
/* associate the user/group SID with the (unique) handle. */
@@ -1333,6 +1334,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R
DOM_SID sid;
fstring privname;
UNISTR2_ARRAY *uni_privnames = &q_u->rights;
+ struct current_user user;
/* find the connection policy handle. */
@@ -1342,8 +1344,12 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R
/* check to see if the pipe_user is a Domain Admin since
account_pol.tdb was already opened as root, this is all we have */
- if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ get_current_user( &user, p );
+ if ( user.uid != sec_initial_uid()
+ && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ {
return NT_STATUS_ACCESS_DENIED;
+ }
/* according to an NT4 PDC, you can add privileges to SIDs even without
call_lsa_create_account() first. And you can use any arbitrary SID. */
@@ -1381,6 +1387,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u,
DOM_SID sid;
fstring privname;
UNISTR2_ARRAY *uni_privnames = &q_u->rights;
+ struct current_user user;
/* find the connection policy handle. */
@@ -1390,8 +1397,12 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u,
/* check to see if the pipe_user is a Domain Admin since
account_pol.tdb was already opened as root, this is all we have */
- if ( !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ get_current_user( &user, p );
+ if ( user.uid != sec_initial_uid()
+ && !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
+ {
return NT_STATUS_ACCESS_DENIED;
+ }
sid_copy( &sid, &q_u->sid.sid );
diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c
index 971f5ed40ce..ffb7882e110 100644
--- a/source/rpc_server/srv_samr.c
+++ b/source/rpc_server/srv_samr.c
@@ -785,6 +785,7 @@ static BOOL api_samr_set_userinfo(pipes_struct *p)
if (!samr_io_q_set_userinfo("", &q_u, data, 0)) {
DEBUG(0,("api_samr_set_userinfo: Unable to unmarshall SAMR_Q_SET_USERINFO.\n"));
/* Fix for W2K SP2 */
+ /* what is that status-code ? - gd */
if (q_u.switch_value == 0x1a) {
setup_fault_pdu(p, NT_STATUS(0x1c000006));
return True;
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index 12c9c36c365..8a10fa6d2da 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -34,6 +34,11 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
+#define SAMR_USR_RIGHTS_WRITE_PW \
+ ( READ_CONTROL_ACCESS | \
+ SA_RIGHT_USER_CHANGE_PASSWORD | \
+ SA_RIGHT_USER_SET_LOC_COM )
+
extern DOM_SID global_sid_Builtin;
extern rid_name domain_group_rids[];
@@ -69,86 +74,39 @@ struct generic_mapping grp_generic_mapping = {GENERIC_RIGHTS_GROUP_READ, GENERIC
struct generic_mapping ali_generic_mapping = {GENERIC_RIGHTS_ALIAS_READ, GENERIC_RIGHTS_ALIAS_WRITE, GENERIC_RIGHTS_ALIAS_EXECUTE, GENERIC_RIGHTS_ALIAS_ALL_ACCESS};
/*******************************************************************
- samr_make_dom_obj_sd
- ********************************************************************/
+*******************************************************************/
-static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size,
+ struct generic_mapping *map,
+ DOM_SID *sid, uint32 sid_access )
{
extern DOM_SID global_sid_World;
DOM_SID adm_sid, act_sid, domadmin_sid;
- SEC_ACE ace[4];
+ SEC_ACE ace[5]; /* at most 5 entries */
SEC_ACCESS mask;
size_t i = 0;
SEC_ACL *psa = NULL;
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_EXECUTE | GENERIC_RIGHTS_DOMAIN_READ);
- init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
-
- init_sec_access(&mask, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS);
+ /* basic access for Everyone */
- init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ init_sec_access(&mask, map->generic_execute | map->generic_read );
+ init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- /* add domain admins if we are a DC */
+ /* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */
- if ( IS_DC ) {
- sid_copy( &domadmin_sid, get_global_sam_sid() );
- sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS );
- init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- }
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
- samr_make_usr_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size, DOM_SID *usr_sid)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid, act_sid, domadmin_sid;
- size_t i = 0;
-
- SEC_ACE ace[5];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
sid_copy(&adm_sid, &global_sid_Builtin);
sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
sid_copy(&act_sid, &global_sid_Builtin);
sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_USER_EXECUTE | GENERIC_RIGHTS_USER_READ);
- init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
+ init_sec_access(&mask, map->generic_all);
- init_sec_access(&mask, GENERIC_RIGHTS_USER_ALL_ACCESS);
init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
init_sec_ace(&ace[i++], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /* add domain admins if we are a DC */
+
+ /* Add Full Access for Domain Admins if we are a DC */
if ( IS_DC ) {
sid_copy( &domadmin_sid, get_global_sam_sid() );
@@ -156,90 +114,16 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd
init_sec_ace(&ace[i++], &domadmin_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
}
- /*extended access for the user*/
+ /* if we have a sid, give it some special access */
- init_sec_access(&mask,READ_CONTROL_ACCESS | SA_RIGHT_USER_CHANGE_PASSWORD | SA_RIGHT_USER_SET_LOC_COM);
- init_sec_ace(&ace[i++], usr_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
- samr_make_grp_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid;
- DOM_SID act_sid;
-
- SEC_ACE ace[3];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_GROUP_EXECUTE | GENERIC_RIGHTS_GROUP_READ);
- init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
- init_sec_access(&mask, GENERIC_RIGHTS_GROUP_ALL_ACCESS);
- init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
- return NT_STATUS_NO_MEMORY;
-
- return NT_STATUS_OK;
-}
-
-/*******************************************************************
- samr_make_ali_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
- extern DOM_SID global_sid_World;
- DOM_SID adm_sid;
- DOM_SID act_sid;
-
- SEC_ACE ace[3];
- SEC_ACCESS mask;
-
- SEC_ACL *psa = NULL;
-
- sid_copy(&adm_sid, &global_sid_Builtin);
- sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
- sid_copy(&act_sid, &global_sid_Builtin);
- sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
- /*basic access for every one*/
- init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_EXECUTE | GENERIC_RIGHTS_ALIAS_READ);
- init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- /*full access for builtin aliases Administrators and Account Operators*/
- init_sec_access(&mask, GENERIC_RIGHTS_ALIAS_ALL_ACCESS);
- init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
- if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+ if ( sid ) {
+ init_sec_access( &mask, sid_access );
+ init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+ }
+
+ /* create the security descriptor */
+
+ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)
return NT_STATUS_NO_MEMORY;
if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL)
@@ -603,8 +487,8 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN
SEC_DESC *psd = NULL;
uint32 acc_granted;
uint32 des_access = q_u->flags;
- size_t sd_size;
NTSTATUS status;
+ size_t sd_size;
SE_PRIV se_rights;
r_u->status = NT_STATUS_OK;
@@ -622,7 +506,7 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN
/*check if access can be granted as requested by client. */
- samr_make_dom_obj_sd( p->mem_ctx, &psd, &sd_size );
+ make_samr_object_sd( p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0 );
se_map_generic( &des_access, &dom_generic_mapping );
se_priv_copy( &se_rights, &se_machine_account );
@@ -719,8 +603,8 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
DOM_SID pol_sid;
fstring str_sid;
SEC_DESC * psd = NULL;
- size_t sd_size;
uint32 acc_granted;
+ size_t sd_size;
r_u->status = NT_STATUS_OK;
@@ -738,19 +622,19 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
if (pol_sid.sid_rev_num == 0)
{
DEBUG(5,("_samr_query_sec_obj: querying security on SAM\n"));
- r_u->status = samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+ r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0);
}
else if (sid_equal(&pol_sid,get_global_sam_sid())) /* check if it is our domain SID */
{
DEBUG(5,("_samr_query_sec_obj: querying security on Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
- r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+ r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0);
}
else if (sid_equal(&pol_sid,&global_sid_Builtin)) /* check if it is the Builtin Domain */
{
/* TODO: Builtin probably needs a different SD with restricted write access*/
DEBUG(5,("_samr_query_sec_obj: querying security on Builtin Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
- r_u->status = samr_make_dom_obj_sd(p->mem_ctx, &psd, &sd_size);
+ r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0);
}
else if (sid_check_is_in_our_domain(&pol_sid) ||
sid_check_is_in_builtin(&pol_sid))
@@ -758,7 +642,7 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
/* TODO: different SDs have to be generated for aliases groups and users.
Currently all three get a default user SD */
DEBUG(10,("_samr_query_sec_obj: querying security on Object with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
- r_u->status = samr_make_usr_obj_sd(p->mem_ctx, &psd,&sd_size, &pol_sid);
+ r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &pol_sid, SAMR_USR_RIGHTS_WRITE_PW);
}
else return NT_STATUS_OBJECT_TYPE_MISMATCH;
@@ -1626,7 +1510,9 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
int num_rids = q_u->num_rids1;
int i;
uint32 acc_granted;
-
+ BOOL have_mapped = False;
+ BOOL have_unmapped = False;
+
r_u->status = NT_STATUS_OK;
DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
@@ -1635,9 +1521,10 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
- if (num_rids > MAX_SAM_ENTRIES) {
- num_rids = MAX_SAM_ENTRIES;
- DEBUG(5,("_samr_lookup_rids: truncating entries to %d\n", num_rids));
+ if (num_rids > 1000) {
+ DEBUG(0, ("Got asked for %d rids (more than 1000) -- according "
+ "to samba4 idl this is not possible\n", num_rids));
+ return NT_STATUS_UNSUCCESSFUL;
}
if (num_rids) {
@@ -1645,7 +1532,11 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
return NT_STATUS_NO_MEMORY;
}
- r_u->status = NT_STATUS_NONE_MAPPED;
+ if (!sid_equal(&pol_sid, get_global_sam_sid())) {
+ /* TODO: Sooner or later we need to look up BUILTIN rids as
+ * well. -- vl */
+ goto done;
+ }
become_root(); /* lookup_sid can require root privs */
@@ -1658,21 +1549,30 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
group_attrs[i] = SID_NAME_UNKNOWN;
*group_names[i] = '\0';
- if (sid_equal(&pol_sid, get_global_sam_sid())) {
- sid_copy(&sid, &pol_sid);
- sid_append_rid(&sid, q_u->rid[i]);
+ sid_copy(&sid, &pol_sid);
+ sid_append_rid(&sid, q_u->rid[i]);
- if (lookup_sid(&sid, domname, tmpname, &type)) {
- r_u->status = NT_STATUS_OK;
- group_attrs[i] = (uint32)type;
- fstrcpy(group_names[i],tmpname);
- DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i], group_attrs[i]));
- }
+ if (lookup_sid(&sid, domname, tmpname, &type)) {
+ group_attrs[i] = (uint32)type;
+ fstrcpy(group_names[i],tmpname);
+ DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i],
+ group_attrs[i]));
+ have_mapped = True;
+ } else {
+ have_unmapped = True;
}
}
unbecome_root();
+ done:
+
+ r_u->status = NT_STATUS_NONE_MAPPED;
+
+ if (have_mapped)
+ r_u->status =
+ have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK;
+
if(!make_samr_lookup_rids(p->mem_ctx, num_rids, group_names, &hdr_name, &uni_name))
return NT_STATUS_NO_MEMORY;
@@ -1727,7 +1627,7 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
/* check if access can be granted as requested by client. */
- samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW);
se_map_generic(&des_access, &usr_generic_mapping);
se_priv_copy( &se_rights, &se_machine_account );
@@ -1764,6 +1664,40 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
}
/*************************************************************************
+ get_user_info_7. Safe. Only gives out account_name.
+ *************************************************************************/
+
+static NTSTATUS get_user_info_7(TALLOC_CTX *mem_ctx, SAM_USER_INFO_7 *id7, DOM_SID *user_sid)
+{
+ SAM_ACCOUNT *smbpass=NULL;
+ BOOL ret;
+ NTSTATUS nt_status;
+
+ nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ become_root();
+ ret = pdb_getsampwsid(smbpass, user_sid);
+ unbecome_root();
+
+ if (ret==False) {
+ DEBUG(4,("User %s not found\n", sid_string_static(user_sid)));
+ return NT_STATUS_NO_SUCH_USER;
+ }
+
+ DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) ));
+
+ ZERO_STRUCTP(id7);
+ init_sam_user_info7(id7, pdb_get_username(smbpass) );
+
+ pdb_free_sam(&smbpass);
+
+ return NT_STATUS_OK;
+}
+/*************************************************************************
get_user_info_10. Safe. Only gives out acb bits.
*************************************************************************/
@@ -1954,6 +1888,14 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
ctr->switch_value = q_u->switch_value;
switch (q_u->switch_value) {
+ case 0x07:
+ ctr->info.id7 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_7);
+ if (ctr->info.id7 == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ if (!NT_STATUS_IS_OK(r_u->status = get_user_info_7(p->mem_ctx, ctr->info.id7, &info->sid)))
+ return r_u->status;
+ break;
case 0x10:
ctr->info.id10 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_10);
if (ctr->info.id10 == NULL)
@@ -2146,6 +2088,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
NTTIME nt_logout;
uint32 account_policy_temp;
+ uint32 server_role;
uint32 num_users=0, num_groups=0, num_aliases=0;
@@ -2210,9 +2153,13 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
unix_to_nt_time_abs(&nt_logout, u_logout);
+ server_role = ROLE_DOMAIN_PDC;
+ if (lp_server_role() == ROLE_DOMAIN_BDC)
+ server_role = ROLE_DOMAIN_BDC;
+
/* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
- init_unk_info2(&ctr->info.inf2, "", lp_workgroup(), global_myname(), (uint32) time(NULL),
- num_users, num_groups, num_aliases, nt_logout);
+ init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), time(NULL),
+ num_users, num_groups, num_aliases, nt_logout, server_role);
break;
case 0x03:
account_policy_get(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout);
@@ -2227,7 +2174,11 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
init_unk_info6(&ctr->info.inf6);
break;
case 0x07:
- init_unk_info7(&ctr->info.inf7);
+ server_role = ROLE_DOMAIN_PDC;
+ if (lp_server_role() == ROLE_DOMAIN_BDC)
+ server_role = ROLE_DOMAIN_BDC;
+
+ init_unk_info7(&ctr->info.inf7, server_role);
break;
case 0x08:
init_unk_info8(&ctr->info.inf8, (uint32) time(NULL));
@@ -2286,7 +2237,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
uint32 new_rid = 0;
/* check this, when giving away 'add computer to domain' privs */
uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS;
- BOOL can_add_account;
+ BOOL can_add_account = False;
SE_PRIV se_rights;
/* Get the domain SID stored in the domain policy */
@@ -2370,7 +2321,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
all_string_sub(add_script, "%u", account, sizeof(add_script));
add_ret = smbrun(add_script,NULL);
- DEBUG(3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
+ DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
}
else /* no add user script -- ask winbindd to do it */
{
@@ -2414,7 +2365,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
sid_copy(&sid, pdb_get_user_sid(sam_pass));
- samr_make_usr_obj_sd(p->mem_ctx, &psd, &sd_size, &sid);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW);
se_map_generic(&des_access, &usr_generic_mapping);
nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
@@ -2501,8 +2452,8 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
SEC_DESC *psd = NULL;
uint32 acc_granted;
uint32 des_access = q_u->access_mask;
- size_t sd_size;
NTSTATUS nt_status;
+ size_t sd_size;
DEBUG(5,("_samr_connect: %d\n", __LINE__));
@@ -2515,7 +2466,7 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
return r_u->status;
}
- samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0);
se_map_generic(&des_access, &sam_generic_mapping);
nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
@@ -2552,8 +2503,8 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *
SEC_DESC *psd = NULL;
uint32 acc_granted;
uint32 des_access = q_u->access_mask;
- size_t sd_size;
NTSTATUS nt_status;
+ size_t sd_size;
DEBUG(5,("_samr_connect4: %d\n", __LINE__));
@@ -2566,7 +2517,7 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *
return r_u->status;
}
- samr_make_sam_obj_sd(p->mem_ctx, &psd, &sd_size);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0);
se_map_generic(&des_access, &sam_generic_mapping);
nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token,
@@ -2740,7 +2691,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
/*check if access can be granted as requested by client. */
- samr_make_ali_obj_sd(p->mem_ctx, &psd, &sd_size);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &ali_generic_mapping, NULL, 0);
se_map_generic(&des_access,&ali_generic_mapping);
se_priv_add( &se_rights, &se_add_users );
@@ -3071,7 +3022,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
uint32 acc_granted;
uint32 acc_required;
BOOL ret;
- BOOL has_enough_rights;
+ BOOL has_enough_rights = False;
uint32 acb_info;
DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
@@ -3212,7 +3163,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
uint32 acc_granted;
uint32 acc_required;
BOOL ret;
- BOOL has_enough_rights;
+ BOOL has_enough_rights = False;
uint32 acb_info;
DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
@@ -3499,18 +3450,17 @@ static BOOL get_memberuids(gid_t gid, uid_t **uids, int *num)
NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_R_QUERY_GROUPMEM *r_u)
{
- int final_num_rids, i;
DOM_SID group_sid;
fstring group_sid_str;
- uid_t *uids;
- int num;
- gid_t gid;
+ int i, num_members;
uint32 *rid=NULL;
uint32 *attr=NULL;
uint32 acc_granted;
+ NTSTATUS result;
+
/* find the policy handle. open a policy on it. */
if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted))
return NT_STATUS_INVALID_HANDLE;
@@ -3529,46 +3479,23 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
DEBUG(10, ("lookup on Domain SID\n"));
- if (!NT_STATUS_IS_OK(sid_to_gid(&group_sid, &gid)))
- return NT_STATUS_NO_SUCH_GROUP;
+ become_root();
+ result = pdb_enum_group_members(p->mem_ctx, &group_sid,
+ &rid, &num_members);
+ unbecome_root();
- if(!get_memberuids(gid, &uids, &num))
- return NT_STATUS_NO_SUCH_GROUP;
+ if (!NT_STATUS_IS_OK(result))
+ return result;
- rid=TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num);
- attr=TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num);
+ attr=TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_members);
- if (num!=0 && (rid==NULL || attr==NULL))
+ if ((num_members!=0) && (rid==NULL))
return NT_STATUS_NO_MEMORY;
- final_num_rids = 0;
-
- for (i=0; i<num; i++) {
- DOM_SID sid;
+ for (i=0; i<num_members; i++)
+ attr[i] = SID_NAME_USER;
- if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
- DEBUG(1, ("Could not map member uid to SID\n"));
- continue;
- }
-
- if (!sid_check_is_in_our_domain(&sid)) {
- DEBUG(1, ("Inconsistent SAM -- group member uid not "
- "in our domain\n"));
- continue;
- }
-
- sid_peek_rid(&sid, &rid[final_num_rids]);
-
- /* Hmm. In a trace I got the constant 7 here from NT. */
- attr[final_num_rids] = SID_NAME_USER;
-
- final_num_rids += 1;
- }
-
- SAFE_FREE(uids);
-
- init_samr_r_query_groupmem(r_u, final_num_rids, rid, attr,
- NT_STATUS_OK);
+ init_samr_r_query_groupmem(r_u, num_members, rid, attr, NT_STATUS_OK);
return NT_STATUS_OK;
}
@@ -3878,7 +3805,7 @@ static int smb_delete_user(const char *unix_user)
return -1;
all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
ret = smbrun(del_script,NULL);
- DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
+ DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
return ret;
}
@@ -4445,7 +4372,7 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
return status;
/*check if access can be granted as requested by client. */
- samr_make_grp_obj_sd(p->mem_ctx, &psd, &sd_size);
+ make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &grp_generic_mapping, NULL, 0);
se_map_generic(&des_access,&grp_generic_mapping);
se_priv_copy( &se_rights, &se_add_users );
@@ -4620,6 +4547,7 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
uint32 num_users=0, num_groups=0, num_aliases=0;
uint32 account_policy_temp;
+ uint32 server_role;
if ((ctr = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_CTR)) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -4681,9 +4609,13 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
unix_to_nt_time_abs(&nt_logout, u_logout);
+ server_role = ROLE_DOMAIN_PDC;
+ if (lp_server_role() == ROLE_DOMAIN_BDC)
+ server_role = ROLE_DOMAIN_BDC;
+
/* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
- init_unk_info2(&ctr->info.inf2, "", lp_workgroup(), global_myname(), (uint32) time(NULL),
- num_users, num_groups, num_aliases, nt_logout);
+ init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), time(NULL),
+ num_users, num_groups, num_aliases, nt_logout, server_role);
break;
case 0x03:
account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
@@ -4700,7 +4632,10 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
init_unk_info6(&ctr->info.inf6);
break;
case 0x07:
- init_unk_info7(&ctr->info.inf7);
+ server_role = ROLE_DOMAIN_PDC;
+ if (lp_server_role() == ROLE_DOMAIN_BDC)
+ server_role = ROLE_DOMAIN_BDC;
+ init_unk_info7(&ctr->info.inf7, server_role);
break;
case 0x08:
init_unk_info8(&ctr->info.inf8, (uint32) time(NULL));
@@ -4780,6 +4715,7 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R
u_lock_duration=nt_time_to_unix_abs(&q_u->ctr->info.inf12.duration);
if (u_lock_duration != -1)
u_lock_duration /= 60;
+
u_reset_time=nt_time_to_unix_abs(&q_u->ctr->info.inf12.reset_count)/60;
account_policy_set(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration);
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index a69a0cb73a7..d3f89540502 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -141,6 +141,27 @@ static const char *display_time(NTTIME nttime)
return (string);
}
+static const char* server_role_str(uint32 server_role)
+{
+ switch(server_role) {
+ case ROLE_STANDALONE:
+ return strdup("ROLE_STANDALONE");
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ return strdup("ROLE_DOMAIN_MEMBER");
+ break;
+ case ROLE_DOMAIN_BDC:
+ return strdup("ROLE_DOMAIN_BDC");
+ break;
+ case ROLE_DOMAIN_PDC:
+ return strdup("ROLE_DOMAIN_PDC");
+ break;
+ default:
+ return strdup("Unknown -- internal error?");
+ break;
+ }
+}
+
static void display_sam_unk_info_1(SAM_UNK_INFO_1 *info1)
{
@@ -159,10 +180,10 @@ static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
fstring name;
unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1);
- printf("Domain:\t%s\n", name);
+ printf("Domain:\t\t%s\n", name);
unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1);
- printf("Server:\t%s\n", name);
+ printf("Server:\t\t%s\n", name);
unistr2_to_ascii(name, &info2->uni_comment, sizeof(name) - 1);
printf("Comment:\t%s\n", name);
@@ -176,10 +197,15 @@ static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2)
printf("Force Logoff:\t%d\n", (int)nt_time_to_unix_abs(&info2->logout));
printf("Unknown 4:\t0x%x\n", info2->unknown_4);
- printf("Unknown 5:\t0x%x\n", info2->unknown_5);
+ printf("Server Role:\t%s\n", server_role_str(info2->server_role));
printf("Unknown 6:\t0x%x\n", info2->unknown_6);
}
+static void display_sam_unk_info_7(SAM_UNK_INFO_7 *info7)
+{
+ printf("Server Role:\t%s\n", server_role_str(info7->server_role));
+}
+
static void display_sam_unk_info_8(SAM_UNK_INFO_8 *info8)
{
printf("Sequence No:\t%d\n", info8->seq_num.low);
@@ -688,7 +714,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli,
sscanf(argv[1], "%x", &access_mask);
if (argc > 2)
- sscanf(argv[2], "%x", &acb_mask);
+ sscanf(argv[2], "%hx", &acb_mask);
/* Get sam policy handle */
@@ -1161,6 +1187,9 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli,
case 2:
display_sam_unk_info_2(&ctr.info.inf2);
break;
+ case 7:
+ display_sam_unk_info_7(&ctr.info.inf7);
+ break;
case 8:
display_sam_unk_info_8(&ctr.info.inf8);
break;
@@ -1365,7 +1394,6 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli,
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
POLICY_HND connect_pol, domain_pol;
- uint32 flags = 0x000003e8; /* Unknown */
uint32 num_rids, num_names, *rids, *name_types;
char **names;
int i;
@@ -1398,11 +1426,11 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli,
for (i = 0; i < argc - 1; i++)
sscanf(argv[i + 1], "%i", &rids[i]);
- result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
- flags, num_rids, rids,
+ result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
&num_names, &names, &name_types);
- if (!NT_STATUS_IS_OK(result))
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
goto done;
/* Display results */
diff --git a/source/sam/idmap_ldap.c b/source/sam/idmap_ldap.c
index 28fdbab77e5..b4a8c8a7528 100644
--- a/source/sam/idmap_ldap.c
+++ b/source/sam/idmap_ldap.c
@@ -124,9 +124,8 @@ static BOOL sid_in_use(struct ldap_idmap_state *state,
fstring filter;
fstring sid_string;
LDAPMessage *result = NULL;
- int count;
int rc;
- char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
+ const char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
@@ -144,7 +143,7 @@ static BOOL sid_in_use(struct ldap_idmap_state *state,
return True;
}
- if ((count = ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) {
+ if ((ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) {
DEBUG(3, ("Sid %s already in use - trying next RID\n",
sid_string));
ldap_msgfree(result);
@@ -168,7 +167,6 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
int rid_type)
{
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- int rc;
LDAPMessage *domain_result = NULL;
LDAPMessage *entry = NULL;
char *dn;
@@ -291,7 +289,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid,
}
}
- if ((rc = smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) {
+ if ((smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) {
DOM_SID dom_sid;
DOM_SID sid;
pstring domain_sid_string;
@@ -384,7 +382,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
LDAPMod **mods = NULL;
const char *type;
char *dn = NULL;
- char **attr_list;
+ const char **attr_list;
pstring filter;
uid_t luid, huid;
gid_t lgid, hgid;
@@ -495,7 +493,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
int rc;
int count;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- char **attr_list;
+ const char **attr_list;
if ( id_type & ID_USERID )
type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER );
@@ -559,7 +557,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
const char *type;
int rc;
int count;
- char **attr_list;
+ const char **attr_list;
char *dn = NULL;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
@@ -669,7 +667,7 @@ static NTSTATUS verify_idpool( void )
{
fstring filter;
int rc;
- char **attr_list;
+ const char **attr_list;
LDAPMessage *result = NULL;
LDAPMod **mods = NULL;
int count;
diff --git a/source/sam/idmap_rid.c b/source/sam/idmap_rid.c
index d0cbcd71862..f16dbfb5e81 100644
--- a/source/sam/idmap_rid.c
+++ b/source/sam/idmap_rid.c
@@ -49,12 +49,13 @@ static NTSTATUS rid_idmap_parse(const char *init_param,
{
const char *p;
int i;
- trust.number = 0;
fstring sid_str;
BOOL known_domain = False;
p = init_param;
fstring tok;
+ trust.number = 0;
+
/* falling back to automatic mapping when there were no options given */
if (!*init_param) {
diff --git a/source/smbd/dfree.c b/source/smbd/dfree.c
index f93cdf3791e..c556c8c8ab2 100644
--- a/source/smbd/dfree.c
+++ b/source/smbd/dfree.c
@@ -36,11 +36,11 @@ static void disk_norm(BOOL small_query, SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,
errors */
}
- while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) {
- *dfree /= 2;
- *dsize /= 2;
- *bsize *= 2;
- if(small_query) {
+ if(small_query) {
+ while (*dfree > WORDMAX || *dsize > WORDMAX || *bsize < 512) {
+ *dfree /= 2;
+ *dsize /= 2;
+ *bsize *= 2;
/*
* Force max to fit in 16 bit fields.
*/
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index f721bf3ba8a..7dde18f4306 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -24,22 +24,40 @@
This module implements directory related functions for Samba.
*/
-typedef struct _dptr_struct {
- struct _dptr_struct *next, *prev;
+/* Make directory handle internals available. */
+
+#define NAME_CACHE_SIZE 100
+
+struct name_cache_entry {
+ char *name;
+ long offset;
+};
+
+struct smb_Dir {
+ connection_struct *conn;
+ DIR *dir;
+ long offset;
+ char *dir_path;
+ struct name_cache_entry *name_cache;
+ unsigned int name_cache_index;
+};
+
+struct dptr_struct {
+ struct dptr_struct *next, *prev;
int dnum;
uint16 spid;
- connection_struct *conn;
- void *ptr;
+ struct connection_struct *conn;
+ struct smb_Dir *dir_hnd;
BOOL expect_close;
- char *wcard; /* Field only used for trans2_ searches */
- uint16 attr; /* Field only used for trans2_ searches */
+ char *wcard;
+ uint16 attr;
char *path;
-} dptr_struct;
+ BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
+};
static struct bitmap *dptr_bmap;
-static dptr_struct *dirptrs;
-
-static int dptrs_open = 0;
+static struct dptr_struct *dirptrs;
+static int dirhandles_open = 0;
#define INVALID_DPTR_KEY (-3)
@@ -66,13 +84,12 @@ void init_dptrs(void)
Idle a dptr - the directory is closed but the control info is kept.
****************************************************************************/
-static void dptr_idle(dptr_struct *dptr)
+static void dptr_idle(struct dptr_struct *dptr)
{
- if (dptr->ptr) {
+ if (dptr->dir_hnd) {
DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
- dptrs_open--;
- CloseDir(dptr->ptr);
- dptr->ptr = NULL;
+ CloseDir(dptr->dir_hnd);
+ dptr->dir_hnd = NULL;
}
}
@@ -82,7 +99,7 @@ static void dptr_idle(dptr_struct *dptr)
static void dptr_idleoldest(void)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
/*
* Go to the end of the list.
@@ -100,7 +117,7 @@ static void dptr_idleoldest(void)
*/
for(; dptr; dptr = dptr->prev) {
- if (dptr->ptr) {
+ if (dptr->dir_hnd) {
dptr_idle(dptr);
return;
}
@@ -108,21 +125,24 @@ static void dptr_idleoldest(void)
}
/****************************************************************************
- Get the dptr_struct for a dir index.
+ Get the struct dptr_struct for a dir index.
****************************************************************************/
-static dptr_struct *dptr_get(int key, BOOL forclose)
+static struct dptr_struct *dptr_get(int key, BOOL forclose)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
for(dptr = dirptrs; dptr; dptr = dptr->next) {
if(dptr->dnum == key) {
- if (!forclose && !dptr->ptr) {
- if (dptrs_open >= MAX_OPEN_DIRECTORIES)
+ if (!forclose && !dptr->dir_hnd) {
+ if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
dptr_idleoldest();
- DEBUG(4,("Reopening dptr key %d\n",key));
- if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True)))
- dptrs_open++;
+ DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
+ if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path))) {
+ DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
+ strerror(errno)));
+ return False;
+ }
}
DLIST_PROMOTE(dirptrs,dptr);
return dptr;
@@ -132,94 +152,70 @@ static dptr_struct *dptr_get(int key, BOOL forclose)
}
/****************************************************************************
- Get the dptr ptr for a dir index.
-****************************************************************************/
-
-static void *dptr_ptr(int key)
-{
- dptr_struct *dptr = dptr_get(key, False);
-
- if (dptr)
- return(dptr->ptr);
- return(NULL);
-}
-
-/****************************************************************************
Get the dir path for a dir index.
****************************************************************************/
char *dptr_path(int key)
{
- dptr_struct *dptr = dptr_get(key, False);
-
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->path);
return(NULL);
}
/****************************************************************************
- Get the dir wcard for a dir index (lanman2 specific).
+ Get the dir wcard for a dir index.
****************************************************************************/
char *dptr_wcard(int key)
{
- dptr_struct *dptr = dptr_get(key, False);
-
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->wcard);
return(NULL);
}
/****************************************************************************
- Set the dir wcard for a dir index (lanman2 specific).
- Returns 0 on ok, 1 on fail.
+ Get the dir attrib for a dir index.
****************************************************************************/
-BOOL dptr_set_wcard(int key, char *wcard)
+uint16 dptr_attr(int key)
{
- dptr_struct *dptr = dptr_get(key, False);
-
- if (dptr) {
- dptr->wcard = wcard;
- return True;
- }
- return False;
+ struct dptr_struct *dptr = dptr_get(key, False);
+ if (dptr)
+ return(dptr->attr);
+ return(0);
}
/****************************************************************************
- Set the dir attrib for a dir index (lanman2 specific).
+ Set the dir wcard for a dir index.
Returns 0 on ok, 1 on fail.
****************************************************************************/
-BOOL dptr_set_attr(int key, uint16 attr)
+BOOL dptr_set_wcard_and_attributes(int key, const char *wcard, uint16 attr)
{
- dptr_struct *dptr = dptr_get(key, False);
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr) {
dptr->attr = attr;
+ dptr->wcard = SMB_STRDUP(wcard);
+ if (!dptr->wcard)
+ return False;
+ if (wcard[0] == '.' && wcard[1] == 0) {
+ dptr->has_wild = True;
+ } else {
+ dptr->has_wild = ms_has_wild(wcard);
+ }
return True;
}
return False;
}
/****************************************************************************
- Get the dir attrib for a dir index (lanman2 specific)
-****************************************************************************/
-
-uint16 dptr_attr(int key)
-{
- dptr_struct *dptr = dptr_get(key, False);
-
- if (dptr)
- return(dptr->attr);
- return(0);
-}
-
-/****************************************************************************
Close a dptr (internal func).
****************************************************************************/
-static void dptr_close_internal(dptr_struct *dptr)
+static void dptr_close_internal(struct dptr_struct *dptr)
{
DEBUG(4,("closing dptr key %d\n",dptr->dnum));
@@ -237,9 +233,8 @@ static void dptr_close_internal(dptr_struct *dptr)
bitmap_clear(dptr_bmap, dptr->dnum - 1);
- if (dptr->ptr) {
- CloseDir(dptr->ptr);
- dptrs_open--;
+ if (dptr->dir_hnd) {
+ CloseDir(dptr->dir_hnd);
}
/* Lanman 2 specific code */
@@ -254,14 +249,14 @@ static void dptr_close_internal(dptr_struct *dptr)
void dptr_close(int *key)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
if(*key == INVALID_DPTR_KEY)
return;
/* OS/2 seems to use -1 to indicate "close all directories" */
if (*key == -1) {
- dptr_struct *next;
+ struct dptr_struct *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
dptr_close_internal(dptr);
@@ -288,7 +283,7 @@ void dptr_close(int *key)
void dptr_closecnum(connection_struct *conn)
{
- dptr_struct *dptr, *next;
+ struct dptr_struct *dptr, *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
if (dptr->conn == conn)
@@ -302,9 +297,9 @@ void dptr_closecnum(connection_struct *conn)
void dptr_idlecnum(connection_struct *conn)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
for(dptr = dirptrs; dptr; dptr = dptr->next) {
- if (dptr->conn == conn && dptr->ptr)
+ if (dptr->conn == conn && dptr->dir_hnd)
dptr_idle(dptr);
}
}
@@ -315,7 +310,7 @@ void dptr_idlecnum(connection_struct *conn)
void dptr_closepath(char *path,uint16 spid)
{
- dptr_struct *dptr, *next;
+ struct dptr_struct *dptr, *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
if (spid == dptr->spid && strequal(dptr->path,path))
@@ -324,35 +319,6 @@ void dptr_closepath(char *path,uint16 spid)
}
/****************************************************************************
- Start a directory listing.
-****************************************************************************/
-
-static BOOL start_dir(connection_struct *conn, pstring directory)
-{
- const char *dir2;
-
- DEBUG(5,("start_dir dir=%s\n",directory));
-
- if (!check_name(directory,conn))
- return(False);
-
- /* use a const pointer from here on */
- dir2 = directory;
-
- if (! *dir2)
- dir2 = ".";
-
- conn->dirptr = OpenDir(conn, directory, True);
- if (conn->dirptr) {
- dptrs_open++;
- string_set(&conn->dirpath,directory);
- return(True);
- }
-
- return(False);
-}
-
-/****************************************************************************
Try and close the oldest handle not marked for
expect close in the hope that the client has
finished with that one.
@@ -360,7 +326,7 @@ static BOOL start_dir(connection_struct *conn, pstring directory)
static void dptr_close_oldest(BOOL old)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
/*
* Go to the end of the list.
@@ -393,23 +359,39 @@ static void dptr_close_oldest(BOOL old)
from the bitmap range 0 - 255 as old SMBsearch directory handles are only
one byte long. If old_handle is false we allocate from the range
256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
- a directory handle is never zero. All the above is folklore taught to
- me at Andrew's knee.... :-) :-). JRA.
+ a directory handle is never zero.
****************************************************************************/
int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr = NULL;
+ struct smb_Dir *dir_hnd;
+ const char *dir2;
- if (!start_dir(conn,path))
+ DEBUG(5,("dptr_create dir=%s\n", path));
+
+ if (!check_name(path,conn))
return(-2); /* Code to say use a unix error return code. */
- if (dptrs_open >= MAX_OPEN_DIRECTORIES)
+ /* use a const pointer from here on */
+ dir2 = path;
+ if (!*dir2)
+ dir2 = ".";
+
+ dir_hnd = OpenDir(conn, dir2);
+ if (!dir_hnd) {
+ return (-2);
+ }
+
+ string_set(&conn->dirpath,dir2);
+
+ if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
dptr_idleoldest();
- dptr = SMB_MALLOC_P(dptr_struct);
+ dptr = SMB_MALLOC_P(struct dptr_struct);
if(!dptr) {
DEBUG(0,("malloc fail in dptr_create.\n"));
+ CloseDir(dir_hnd);
return -1;
}
@@ -439,6 +421,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
if(dptr->dnum == -1 || dptr->dnum > 254) {
DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
+ CloseDir(dir_hnd);
return -1;
}
}
@@ -468,6 +451,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
if(dptr->dnum == -1 || dptr->dnum < 255) {
DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
+ CloseDir(dir_hnd);
return -1;
}
}
@@ -477,22 +461,131 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
- dptr->ptr = conn->dirptr;
- string_set(&dptr->path,path);
+ string_set(&dptr->path,dir2);
dptr->conn = conn;
+ dptr->dir_hnd = dir_hnd;
dptr->spid = spid;
dptr->expect_close = expect_close;
dptr->wcard = NULL; /* Only used in lanman2 searches */
dptr->attr = 0; /* Only used in lanman2 searches */
+ dptr->has_wild = True; /* Only used in lanman2 searches */
DLIST_ADD(dirptrs, dptr);
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
dptr->dnum,path,expect_close));
+ conn->dirptr = dptr;
+
return(dptr->dnum);
}
+
+/****************************************************************************
+ Wrapper functions to access the lower level directory handles.
+****************************************************************************/
+
+int dptr_CloseDir(struct dptr_struct *dptr)
+{
+ return CloseDir(dptr->dir_hnd);
+}
+
+void dptr_SeekDir(struct dptr_struct *dptr, long offset)
+{
+ SeekDir(dptr->dir_hnd, offset);
+}
+
+long dptr_TellDir(struct dptr_struct *dptr)
+{
+ return TellDir(dptr->dir_hnd);
+}
+
+/****************************************************************************
+ Return the next visible file name, skipping veto'd and invisible files.
+****************************************************************************/
+
+static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
+{
+ /* Normal search for the next file. */
+ const char *name;
+ while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
+ if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
+ return name;
+ }
+ }
+ return NULL;
+}
+
+/****************************************************************************
+ Return the next visible file name, skipping veto'd and invisible files.
+****************************************************************************/
+
+const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
+{
+ pstring pathreal;
+
+ ZERO_STRUCTP(pst);
+ if (dptr->has_wild) {
+ return dptr_normal_ReadDirName(dptr, poffset, pst);
+ }
+
+ /* We know the stored wcard contains no wildcard characters. See if we can match
+ with a stat call. If we can't, then set has_wild to true to
+ prevent us from doing this on every call. */
+
+ /* First check if it should be visible. */
+ if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
+ dptr->has_wild = True;
+ return dptr_normal_ReadDirName(dptr, poffset, pst);
+ }
+
+ if (VALID_STAT(*pst)) {
+ return dptr->wcard;
+ }
+
+ pstrcpy(pathreal,dptr->path);
+ pstrcat(pathreal,"/");
+ pstrcat(pathreal,dptr->wcard);
+
+ if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
+ return dptr->wcard;
+ } else {
+ /* If we get any other error than ENOENT or ENOTDIR
+ then the file exists we just can't stat it. */
+ if (errno != ENOENT && errno != ENOTDIR) {
+ return dptr->wcard;
+ }
+ }
+
+ dptr->has_wild = True;
+
+ /* In case sensitive mode we don't search - we know if it doesn't exist
+ with a stat we will fail. */
+
+ if (dptr->conn->case_sensitive) {
+ return NULL;
+ } else {
+ return dptr_normal_ReadDirName(dptr, poffset, pst);
+ }
+}
+
+/****************************************************************************
+ Search for a file by name, skipping veto'ed and not visible files.
+****************************************************************************/
+
+BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
+{
+ BOOL ret;
+
+ ZERO_STRUCTP(pst);
+ while ((ret = SearchDir(dptr->dir_hnd, name, poffset)) == True) {
+ if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
+ return True;
+ }
+ }
+ return False;
+}
+
/****************************************************************************
Fill the 5 byte server reserved dptr field.
****************************************************************************/
@@ -500,15 +593,15 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
BOOL dptr_fill(char *buf1,unsigned int key)
{
unsigned char *buf = (unsigned char *)buf1;
- void *p = dptr_ptr(key);
+ struct dptr_struct *dptr = dptr_get(key, False);
uint32 offset;
- if (!p) {
+ if (!dptr) {
DEBUG(1,("filling null dirptr %d\n",key));
return(False);
}
- offset = TellDir(p);
+ offset = TellDir(dptr->dir_hnd);
DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
- (long)p,(int)offset));
+ (long)dptr->dir_hnd,(int)offset));
buf[0] = key;
SIVAL(buf,1,offset | DPTR_MASK);
return(True);
@@ -518,45 +611,45 @@ BOOL dptr_fill(char *buf1,unsigned int key)
Fetch the dir ptr and seek it given the 5 byte server field.
****************************************************************************/
-void *dptr_fetch(char *buf,int *num)
+struct dptr_struct *dptr_fetch(char *buf,int *num)
{
unsigned int key = *(unsigned char *)buf;
- void *p = dptr_ptr(key);
+ struct dptr_struct *dptr = dptr_get(key, False);
uint32 offset;
- if (!p) {
+ if (!dptr) {
DEBUG(3,("fetched null dirptr %d\n",key));
return(NULL);
}
*num = key;
offset = IVAL(buf,1)&~DPTR_MASK;
- SeekDir(p,offset);
+ SeekDir(dptr->dir_hnd,(long)offset);
DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
key,dptr_path(key),offset));
- return(p);
+ return(dptr);
}
/****************************************************************************
Fetch the dir ptr.
****************************************************************************/
-void *dptr_fetch_lanman2(int dptr_num)
+struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
{
- void *p = dptr_ptr(dptr_num);
+ struct dptr_struct *dptr = dptr_get(dptr_num, False);
- if (!p) {
+ if (!dptr) {
DEBUG(3,("fetched null dirptr %d\n",dptr_num));
return(NULL);
}
DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
- return(p);
+ return(dptr);
}
/****************************************************************************
Check a filetype for being valid.
****************************************************************************/
-BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
+BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype)
{
int mask;
@@ -612,10 +705,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname
return(False);
while (!found) {
- dname = ReadDirName(conn->dirptr);
+ long curoff = dptr_TellDir(conn->dirptr);
+ dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
- DEBUG(6,("readdir on dirptr 0x%lx now at offset %d\n",
- (long)conn->dirptr,TellDir(conn->dirptr)));
+ DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
+ (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
if (dname == NULL)
return(False);
@@ -643,14 +737,14 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname
pstrcpy(pathreal,path);
pstrcat(path,fname);
pstrcat(pathreal,dname);
- if (SMB_VFS_STAT(conn, pathreal, &sbuf) != 0) {
+ if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
continue;
}
*mode = dos_mode(conn,pathreal,&sbuf);
- if (!dir_check_ftype(conn,*mode,&sbuf,dirtype)) {
+ if (!dir_check_ftype(conn,*mode,dirtype)) {
DEBUG(5,("[%s] attribs didn't match %x\n",filename,dirtype));
continue;
}
@@ -667,14 +761,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname
return(found);
}
-typedef struct {
- int pos;
- int numentries;
- int mallocsize;
- char *data;
- char *current;
-} Dir;
-
/*******************************************************************
Check to see if a user can read a file. This is only approximate,
it is used as part of the "hide unreadable" option. Don't
@@ -807,116 +893,95 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT
}
/*******************************************************************
- Open a directory.
+ Should the file be seen by the client ?
********************************************************************/
-void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
+BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
{
- Dir *dirp;
- const char *n;
- DIR *p = SMB_VFS_OPENDIR(conn,name);
- int used=0;
+ BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
+ BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
+ BOOL hide_special = lp_hide_special_files(SNUM(conn));
- if (!p)
- return(NULL);
- dirp = SMB_MALLOC_P(Dir);
- if (!dirp) {
- DEBUG(0,("Out of memory in OpenDir\n"));
- SMB_VFS_CLOSEDIR(conn,p);
- return(NULL);
- }
- dirp->pos = dirp->numentries = dirp->mallocsize = 0;
- dirp->data = dirp->current = NULL;
+ ZERO_STRUCTP(pst);
- while (True) {
- int l;
- BOOL normal_entry = True;
- SMB_STRUCT_STAT st;
- char *entry = NULL;
-
- if (used == 0) {
- n = ".";
- normal_entry = False;
- } else if (used == 2) {
- n = "..";
- normal_entry = False;
- } else {
- n = vfs_readdirname(conn, p);
- if (n == NULL)
- break;
- if ((strcmp(".",n) == 0) ||(strcmp("..",n) == 0))
- continue;
- normal_entry = True;
- }
+ if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
+ return True; /* . and .. are always visible. */
+ }
- ZERO_STRUCT(st);
- l = strlen(n)+1;
+ /* If it's a vetoed file, pretend it doesn't even exist */
+ if (use_veto && IS_VETO_PATH(conn, name)) {
+ return False;
+ }
- /* If it's a vetoed file, pretend it doesn't even exist */
- if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n))
- continue;
+ if (hide_unreadable || hide_unwriteable || hide_special) {
+ char *entry = NULL;
+ if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
+ return False;
+ }
/* Honour _hide unreadable_ option */
- if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) {
- int ret=0;
-
- if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = user_can_read_file(conn, entry, &st);
- }
- if (!ret) {
- SAFE_FREE(entry);
- continue;
- }
+ if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
+ SAFE_FREE(entry);
+ return False;
}
-
/* Honour _hide unwriteable_ option */
- if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) {
- int ret=0;
-
- if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = user_can_write_file(conn, entry, &st);
- }
- if (!ret) {
- SAFE_FREE(entry);
- continue;
- }
+ if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
+ SAFE_FREE(entry);
+ return False;
}
-
/* Honour _hide_special_ option */
- if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) {
- int ret=0;
-
- if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = file_is_special(conn, entry, &st);
- }
- if (ret) {
- SAFE_FREE(entry);
- continue;
- }
+ if (hide_special && !file_is_special(conn, entry, pst)) {
+ SAFE_FREE(entry);
+ return False;
}
-
SAFE_FREE(entry);
+ }
+ return True;
+}
- if (used + l > dirp->mallocsize) {
- int s = MAX(used+l,used+2000);
- char *r;
- r = (char *)SMB_REALLOC(dirp->data,s);
- if (!r) {
- DEBUG(0,("Out of memory in OpenDir\n"));
- break;
- }
- dirp->data = r;
- dirp->mallocsize = s;
- dirp->current = dirp->data;
- }
+/*******************************************************************
+ Open a directory.
+********************************************************************/
+
+struct smb_Dir *OpenDir(connection_struct *conn, const char *name)
+{
+ struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
+ if (!dirp) {
+ return NULL;
+ }
+ ZERO_STRUCTP(dirp);
- safe_strcpy_base(dirp->data+used,n, dirp->data, dirp->mallocsize);
- used += l;
- dirp->numentries++;
+ dirp->conn = conn;
+
+ dirp->dir_path = SMB_STRDUP(name);
+ if (!dirp->dir_path) {
+ goto fail;
+ }
+ dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path);
+ if (!dirp->dir) {
+ DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
+ goto fail;
+ }
+
+ dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
+ if (!dirp->name_cache) {
+ goto fail;
}
- SMB_VFS_CLOSEDIR(conn,p);
- return((void *)dirp);
+ dirhandles_open++;
+ return dirp;
+
+ fail:
+
+ if (dirp) {
+ if (dirp->dir) {
+ SMB_VFS_CLOSEDIR(conn,dirp->dir);
+ }
+ SAFE_FREE(dirp->dir_path);
+ SAFE_FREE(dirp->name_cache);
+ SAFE_FREE(dirp);
+ }
+ return NULL;
}
@@ -924,65 +989,110 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
Close a directory.
********************************************************************/
-void CloseDir(void *p)
+int CloseDir(struct smb_Dir *dirp)
{
- if (!p)
- return;
- SAFE_FREE(((Dir *)p)->data);
- SAFE_FREE(p);
+ int i, ret = 0;
+
+ if (dirp->dir) {
+ ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
+ }
+ SAFE_FREE(dirp->dir_path);
+ if (dirp->name_cache) {
+ for (i = 0; i < NAME_CACHE_SIZE; i++) {
+ SAFE_FREE(dirp->name_cache[i].name);
+ }
+ }
+ SAFE_FREE(dirp->name_cache);
+ SAFE_FREE(dirp);
+ dirhandles_open--;
+ return ret;
}
/*******************************************************************
- Read from a directory.
+ Read from a directory. Also return current offset.
+ Don't check for veto or invisible files.
********************************************************************/
-const char *ReadDirName(void *p)
+const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
{
- char *ret;
- Dir *dirp = (Dir *)p;
-
- if (!dirp || !dirp->current || dirp->pos >= dirp->numentries)
- return(NULL);
-
- ret = dirp->current;
- dirp->current = skip_string(dirp->current,1);
- dirp->pos++;
+ const char *n;
+ connection_struct *conn = dirp->conn;
+
+ SeekDir(dirp, *poffset);
+ while ((n = vfs_readdirname(conn, dirp->dir))) {
+ struct name_cache_entry *e;
+ dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
+ if (dirp->offset == -1) {
+ return NULL;
+ }
+ dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
- return(ret);
+ e = &dirp->name_cache[dirp->name_cache_index];
+ SAFE_FREE(e->name);
+ e->name = SMB_STRDUP(n);
+ *poffset = e->offset= dirp->offset;
+ return e->name;
+ }
+ return NULL;
}
/*******************************************************************
Seek a dir.
********************************************************************/
-BOOL SeekDir(void *p,int pos)
+void SeekDir(struct smb_Dir *dirp, long offset)
{
- Dir *dirp = (Dir *)p;
-
- if (!dirp)
- return(False);
-
- if (pos < dirp->pos) {
- dirp->current = dirp->data;
- dirp->pos = 0;
+ if (offset != dirp->offset) {
+ SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
+ dirp->offset = offset;
}
+}
- while (dirp->pos < pos && ReadDirName(p))
- ;
+/*******************************************************************
+ Tell a dir position.
+********************************************************************/
- return (dirp->pos == pos);
+long TellDir(struct smb_Dir *dirp)
+{
+ return(dirp->offset);
}
/*******************************************************************
- Tell a dir position.
+ Find an entry by name. Leave us at the offset after it.
+ Don't check for veto or invisible files.
********************************************************************/
-int TellDir(void *p)
+BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
{
- Dir *dirp = (Dir *)p;
+ int i;
+ const char *entry;
+ connection_struct *conn = dirp->conn;
+
+ /* Search back in the name cache. */
+ for (i = dirp->name_cache_index; i >= 0; i--) {
+ struct name_cache_entry *e = &dirp->name_cache[i];
+ if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
+ *poffset = e->offset;
+ SeekDir(dirp, e->offset);
+ return True;
+ }
+ }
+ for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
+ struct name_cache_entry *e = &dirp->name_cache[i];
+ if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
+ *poffset = e->offset;
+ SeekDir(dirp, e->offset);
+ return True;
+ }
+ }
- if (!dirp)
- return(-1);
-
- return(dirp->pos);
+ /* Not found in the name cache. Rewind directory and start from scratch. */
+ SMB_VFS_REWINDDIR(conn, dirp->dir);
+ *poffset = 0;
+ while ((entry = ReadDirName(dirp, poffset))) {
+ if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
+ return True;
+ }
+ }
+ return False;
}
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index 279c9dd3c45..8c484dd232a 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -150,11 +150,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
pstrcpy(saved_last_component, name);
}
-#if 1
if (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve))
-#else
- if (!conn->case_sensitive && (!conn->case_preserve || (mangle_is_8_3(name, False) && !conn->short_case_preserve)))
-#endif
strnorm(name, lp_defaultcase(SNUM(conn)));
start = name;
@@ -432,9 +428,10 @@ BOOL check_name(pstring name,connection_struct *conn)
static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength)
{
- void *cur_dir;
+ struct smb_Dir *cur_dir;
const char *dname;
BOOL mangled;
+ long curpos;
mangled = mangle_is_mangled(name);
@@ -453,13 +450,14 @@ static BOOL scan_directory(connection_struct *conn, const char *path, char *name
mangled = !mangle_check_cache( name, maxlength );
/* open the directory */
- if (!(cur_dir = OpenDir(conn, path, True))) {
+ if (!(cur_dir = OpenDir(conn, path))) {
DEBUG(3,("scan dir didn't open dir [%s]\n",path));
return(False);
}
/* now scan for matching names */
- while ((dname = ReadDirName(cur_dir))) {
+ curpos = 0;
+ while ((dname = ReadDirName(cur_dir, &curpos))) {
/* Is it dot or dot dot. */
if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) {
diff --git a/source/smbd/notify_hash.c b/source/smbd/notify_hash.c
index 843580f6edf..b16b7677833 100644
--- a/source/smbd/notify_hash.c
+++ b/source/smbd/notify_hash.c
@@ -44,7 +44,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
const char *fname;
size_t remaining_len;
size_t fullname_len;
- void *dp;
+ struct smb_Dir *dp;
+ long offset;
ZERO_STRUCTP(data);
@@ -75,7 +76,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
* larger than the max time_t value).
*/
- dp = OpenDir(conn, path, True);
+ dp = OpenDir(conn, path);
if (dp == NULL)
return False;
@@ -88,19 +89,24 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
remaining_len = sizeof(full_name) - fullname_len - 1;
p = &full_name[fullname_len];
- while ((fname = ReadDirName(dp))) {
+ offset = 0;
+ while ((fname = ReadDirName(dp, &offset))) {
+ ZERO_STRUCT(st);
if(strequal(fname, ".") || strequal(fname, ".."))
continue;
+ if (!is_visible_file(conn, path, fname, &st, True))
+ continue;
+
data->num_entries++;
safe_strcpy(p, fname, remaining_len);
- ZERO_STRUCT(st);
-
/*
* Do the stat - but ignore errors.
*/
- SMB_VFS_STAT(conn,full_name, &st);
+ if (!VALID_STAT(st)) {
+ SMB_VFS_STAT(conn,full_name, &st);
+ }
/*
* Always sum the times.
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 2395d0d8db5..675da4c7478 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -780,6 +780,27 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
}
}
+#if 0
+ /* 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
+ is really going to delete this file. */
+ if (desired_access & DELETE_ACCESS) {
+#else
+ /* Setting FILE_SHARE_DELETE is the hint. */
+ if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+#endif
+ status = can_delete(conn, fname, file_attributes, bad_path, True);
+ /* We're only going to fail here if it's access denied, as that's the
+ only error we care about for "can we delete this ?" questions. */
+ if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(status);
+ }
+ }
+
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -908,7 +929,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
#endif
if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
- fsp->initial_allocation_size = smb_roundup(allocation_size);
+ fsp->initial_allocation_size = allocation_size;
if (fsp->is_directory) {
close_file(fsp,False);
END_PROFILE(SMBntcreateX);
@@ -921,7 +942,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
- fsp->initial_allocation_size = smb_roundup((SMB_BIG_UINT)file_len);
+ fsp->initial_allocation_size = (SMB_BIG_UINT)file_len;
}
/*
@@ -1319,6 +1340,27 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
+#if 0
+ /* 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
+ is really going to delete this file. */
+ if (desired_access & DELETE_ACCESS) {
+#else
+ /* Setting FILE_SHARE_DELETE is the hint. */
+ if ((share_access & FILE_SHARE_DELETE) && (desired_access & DELETE_ACCESS)) {
+#endif
+ status = can_delete(conn, fname, file_attributes, bad_path, True);
+ /* We're only going to fail here if it's access denied, as that's the
+ only error we care about for "can we delete this ?" questions. */
+ if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) ||
+ NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(status);
+ }
+ }
+
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -1430,7 +1472,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
#endif
if (allocation_size && (allocation_size > file_len)) {
- fsp->initial_allocation_size = smb_roundup(allocation_size);
+ fsp->initial_allocation_size = allocation_size;
if (fsp->is_directory) {
close_file(fsp,False);
END_PROFILE(SMBntcreateX);
@@ -1442,7 +1484,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
- fsp->initial_allocation_size = smb_roundup((SMB_BIG_UINT)file_len);
+ fsp->initial_allocation_size = (SMB_BIG_UINT)file_len;
}
/* Realloc the size of parameters and data we will return */
@@ -2143,6 +2185,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA);
if (shadow_data == NULL) {
DEBUG(0,("talloc_zero() failed!\n"));
+ talloc_destroy(shadow_mem_ctx);
return ERROR_NT(NT_STATUS_NO_MEMORY);
}
@@ -2310,7 +2353,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
/* access check */
if (current_user.uid != 0) {
- DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
+ DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
lp_servicename(SNUM(conn)),conn->user));
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 903b9435225..d02edc5ea06 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -3753,3 +3753,160 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
return True;
}
+
+/****************************************************************************
+ Check for POSIX group ACLs. If none use stat entry.
+****************************************************************************/
+
+static int check_posix_acl_group_write(connection_struct *conn, const char *dname, SMB_STRUCT_STAT *psbuf)
+{
+ extern struct current_user current_user;
+ SMB_ACL_T posix_acl = NULL;
+ int entry_id = SMB_ACL_FIRST_ENTRY;
+ SMB_ACL_ENTRY_T entry;
+ int i;
+ int ret = -1;
+
+ if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, dname, SMB_ACL_TYPE_ACCESS)) == NULL) {
+ goto check_stat;
+ }
+
+ /* First ensure the group mask allows group read. */
+ while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
+ SMB_ACL_TAG_T tagtype;
+ SMB_ACL_PERMSET_T permset;
+
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
+
+ if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
+ goto check_stat;
+ }
+
+ if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+ goto check_stat;
+ }
+
+ switch(tagtype) {
+ case SMB_ACL_MASK:
+ if (!SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE)) {
+ /* We don't have group write permission. */
+ ret = -1; /* Allow caller to check "other" permissions. */
+ goto done;
+ }
+ break;
+ default:
+ continue;
+ }
+ }
+
+ /* Now check all group entries. */
+ entry_id = SMB_ACL_FIRST_ENTRY;
+ while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
+ SMB_ACL_TAG_T tagtype;
+ SMB_ACL_PERMSET_T permset;
+ int have_write = -1;
+
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY)
+ entry_id = SMB_ACL_NEXT_ENTRY;
+
+ if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
+ goto check_stat;
+ }
+
+ if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+ goto check_stat;
+ }
+
+ have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
+ if (have_write == -1) {
+ goto check_stat;
+ }
+
+ switch(tagtype) {
+ case SMB_ACL_USER:
+ {
+ /* Check against current_user.uid. */
+ uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ if (puid == NULL) {
+ goto check_stat;
+ }
+ if (current_user.uid == *puid) {
+ /* We're done now we have a uid match. */
+ ret = have_write;
+ goto done;
+ }
+ }
+ break;
+ case SMB_ACL_MASK:
+ {
+ gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ if (pgid == NULL) {
+ goto check_stat;
+ }
+ for (i = 0; i < current_user.ngroups; i++) {
+ if (current_user.groups[i] == *pgid) {
+ /* We're done now we have a gid match. */
+ ret = have_write;
+ goto done;
+ }
+ }
+ }
+ break;
+ default:
+ continue;
+ }
+ }
+
+
+ check_stat:
+
+ for (i = 0; i < current_user.ngroups; i++) {
+ if (current_user.groups[i] == psbuf->st_gid) {
+ ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0;
+ break;
+ }
+ }
+
+ done:
+
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
+ return ret;
+}
+
+/****************************************************************************
+ Actually emulate the in-kernel access checking for write access. We need
+ this to successfully return ACCESS_DENIED on a file open for delete access.
+****************************************************************************/
+
+BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
+{
+ extern struct current_user current_user;
+ SMB_STRUCT_STAT sbuf;
+ pstring dname;
+ int ret;
+
+ pstrcpy(dname, parent_dirname(fname));
+ if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
+ return False;
+ }
+ if (!S_ISDIR(sbuf.st_mode)) {
+ return False;
+ }
+ if (current_user.uid == 0) {
+ /* I'm sorry sir, I didn't know you were root... */
+ return True;
+ }
+
+ if (current_user.uid == sbuf.st_uid) {
+ return (sbuf.st_mode & S_IWUSR) ? True : False;
+ }
+ /* Check group ownership. */
+ ret = check_posix_acl_group_write(conn, dname, &sbuf);
+ if (ret == 0 || ret == 1) {
+ return ret ? True : False;
+ }
+ return (sbuf.st_mode & S_IWOTH) ? True : False;
+}
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 26a0c9e7a9b..89183aed347 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -899,8 +899,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
END_PROFILE(SMBsearch);
return ERROR_DOS(ERRDOS,ERRnofids);
}
- dptr_set_wcard(dptr_num, SMB_STRDUP(mask));
- dptr_set_attr(dptr_num, dirtype);
+ if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
+ END_PROFILE(SMBsearch);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
} else {
dirtype = dptr_attr(dptr_num);
}
@@ -910,7 +912,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
if (ok) {
if ((dirtype&0x1F) == aVOLID) {
memcpy(p,status,21);
- make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0,conn->case_sensitive);
+ make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
dptr_fill(p+12,dptr_num);
if (dptr_zero(p+12) && (status_len==0))
numentries = 1;
@@ -930,7 +932,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
if (!finished) {
memcpy(p,status,21);
- make_dir_struct(p,mask,fname,size,mode,date,conn->case_sensitive);
+ make_dir_struct(p,mask,fname,size,mode,date);
dptr_fill(p+12,dptr_num);
numentries++;
p += DIR_STRUCT_SIZE;
@@ -947,18 +949,21 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
and no entries were found then return error and close dirptr
(X/Open spec) */
- if(ok && expect_close && numentries == 0 && status_len == 0) {
- /* Close the dptr - we know it's gone */
+ if (numentries == 0 || !ok) {
dptr_close(&dptr_num);
- return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
- } else if (numentries == 0 || !ok) {
+ } else if(ok && expect_close && status_len == 0) {
+ /* Close the dptr - we know it's gone */
dptr_close(&dptr_num);
- return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
- if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
+ if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
dptr_close(&dptr_num);
+ }
+
+ if ((numentries == 0) && !ms_has_wild(mask)) {
+ return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
+ }
SSVAL(outbuf,smb_vwv0,numentries);
SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
@@ -1433,7 +1438,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
Check if a user is allowed to rename a file.
********************************************************************/
-static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
{
int smb_action;
int access_mode;
@@ -1474,7 +1479,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, uint16 dirtype,
Check if a user is allowed to delete a file.
********************************************************************/
-static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
+NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_path, BOOL check_is_at_open)
{
SMB_STRUCT_STAT sbuf;
int fmode;
@@ -1515,25 +1520,34 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO
if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
return NT_STATUS_NO_SUCH_FILE;
- /* We need a better way to return NT status codes from open... */
- unix_ERR_class = 0;
- unix_ERR_code = 0;
-
- fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+ if (check_is_at_open) {
+ if (!can_delete_file_in_directory(conn, fname)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ } else {
+ /* On open checks the open itself will check the share mode, so
+ don't do it here as we'll get it wrong. */
- if (!fsp) {
- NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
- if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
- ret = unix_ERR_ntstatus;
- else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- ret = NT_STATUS_SHARING_VIOLATION;
+ /* We need a better way to return NT status codes from open... */
unix_ERR_class = 0;
unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
- return ret;
+
+ fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+
+ if (!fsp) {
+ NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
+ if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
+ ret = unix_ERR_ntstatus;
+ else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ ret = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ unix_ERR_ntstatus = NT_STATUS_OK;
+ return ret;
+ }
+ close_file(fsp,False);
}
- close_file(fsp,False);
return NT_STATUS_OK;
}
@@ -1593,7 +1607,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- error = can_delete(directory,conn,dirtype,bad_path);
+ error = can_delete(conn,directory,dirtype,bad_path,False);
if (!NT_STATUS_IS_OK(error))
return error;
@@ -1601,28 +1615,34 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
count++;
}
} else {
- void *dirptr = NULL;
+ struct smb_Dir *dir_hnd = NULL;
const char *dname;
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dir_hnd = OpenDir(conn, directory);
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name, otherwise the short name
We don't implement this yet XXXX
*/
- if (dirptr) {
+ if (dir_hnd) {
+ long offset = 0;
error = NT_STATUS_NO_SUCH_FILE;
-
+
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
- while ((dname = ReadDirName(dirptr))) {
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ SMB_STRUCT_STAT st;
pstring fname;
BOOL sys_direntry = False;
pstrcpy(fname,dname);
+ if (!is_visible_file(conn, directory, dname, &st, True)) {
+ continue;
+ }
+
/* Quick check for "." and ".." */
if (fname[0] == '.') {
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
@@ -1645,7 +1665,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
}
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- error = can_delete(fname,conn,dirtype,bad_path);
+ error = can_delete(conn,fname,dirtype,bad_path,False);
if (!NT_STATUS_IS_OK(error)) {
continue;
}
@@ -1653,7 +1673,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
count++;
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
}
@@ -3361,18 +3381,22 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
{
const char *dname = NULL;
BOOL ret = False;
- void *dirptr = OpenDir(conn, directory, False);
+ long offset = 0;
+ struct smb_Dir *dir_hnd = OpenDir(conn, directory);
- if(dirptr == NULL)
+ if(dir_hnd == NULL)
return True;
- while((dname = ReadDirName(dirptr))) {
+ while((dname = ReadDirName(dir_hnd, &offset))) {
pstring fullname;
SMB_STRUCT_STAT st;
if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
+
/* Construct the full name. */
if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
errno = ENOMEM;
@@ -3403,7 +3427,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
break;
}
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
return ret;
}
@@ -3414,6 +3438,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
BOOL rmdir_internals(connection_struct *conn, char *directory)
{
BOOL ok;
+ SMB_STRUCT_STAT st;
ok = (SMB_VFS_RMDIR(conn,directory) == 0);
if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
@@ -3425,13 +3450,15 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
*/
BOOL all_veto_files = True;
const char *dname;
- void *dirptr = OpenDir(conn, directory, False);
+ struct smb_Dir *dir_hnd = OpenDir(conn, directory);
- if(dirptr != NULL) {
- int dirpos = TellDir(dirptr);
- while ((dname = ReadDirName(dirptr))) {
+ if(dir_hnd != NULL) {
+ long dirpos = TellDir(dir_hnd);
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
if(!IS_VETO_PATH(conn, dname)) {
all_veto_files = False;
break;
@@ -3439,13 +3466,14 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
}
if(all_veto_files) {
- SeekDir(dirptr,dirpos);
- while ((dname = ReadDirName(dirptr))) {
+ SeekDir(dir_hnd,dirpos);
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
pstring fullname;
- SMB_STRUCT_STAT st;
if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
/* Construct the full name. */
if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
@@ -3469,11 +3497,11 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
} else if(SMB_VFS_UNLINK(conn,fullname) != 0)
break;
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
/* Retry the rmdir */
ok = (SMB_VFS_RMDIR(conn,directory) == 0);
} else {
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
} else {
errno = ENOTEMPTY;
@@ -3725,7 +3753,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- error = can_rename(newname,conn,attrs,&sbuf);
+ error = can_rename(conn,newname,attrs,&sbuf);
if (dest_exists && !NT_STATUS_IS_OK(error)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3931,7 +3959,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- error = can_rename(directory,conn,attrs,&sbuf1);
+ error = can_rename(conn,directory,attrs,&sbuf1);
if (!NT_STATUS_IS_OK(error)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
@@ -3976,21 +4004,22 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
/*
* Wildcards - process each file that matches.
*/
- void *dirptr = NULL;
+ struct smb_Dir *dir_hnd = NULL;
const char *dname;
pstring destname;
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dir_hnd = OpenDir(conn, directory);
- if (dirptr) {
+ if (dir_hnd) {
+ long offset = 0;
error = NT_STATUS_NO_SUCH_FILE;
/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
- while ((dname = ReadDirName(dirptr))) {
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
pstring fname;
BOOL sysdir_entry = False;
@@ -4007,6 +4036,9 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
}
}
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False))
+ continue;
+
if(!mask_match(fname, mask, conn->case_sensitive))
continue;
@@ -4022,7 +4054,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
continue;
}
- error = can_rename(fname,conn,attrs,&sbuf1);
+ error = can_rename(conn,fname,attrs,&sbuf1);
if (!NT_STATUS_IS_OK(error)) {
DEBUG(6,("rename %s refused\n", fname));
continue;
@@ -4057,7 +4089,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
}
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
@@ -4329,23 +4361,27 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
exists = vfs_file_exist(conn,directory,NULL);
}
} else {
- void *dirptr = NULL;
+ struct smb_Dir *dir_hnd = NULL;
const char *dname;
pstring destname;
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dir_hnd = OpenDir(conn, directory);
- if (dirptr) {
+ if (dir_hnd) {
+ long offset = 0;
error = ERRbadfile;
if (strequal(mask,"????????.???"))
pstrcpy(mask,"*");
- while ((dname = ReadDirName(dirptr))) {
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
pstring fname;
pstrcpy(fname,dname);
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False))
+ continue;
+
if(!mask_match(fname, mask, conn->case_sensitive))
continue;
@@ -4358,7 +4394,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
count++;
DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
}
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 2e60adc6366..f199fe3ade6 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -60,17 +60,26 @@ BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
last_flags = flags;
/* Obey the client case sensitivity requests - only for clients that support it. */
- if (lp_casesensitive(snum) == Auto) {
- /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
- enum remote_arch_types ra_type = get_remote_arch();
- if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
- /* Client can't support per-packet case sensitive pathnames. */
+ switch (lp_casesensitive(snum)) {
+ case Auto:
+ {
+ /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
+ enum remote_arch_types ra_type = get_remote_arch();
+ if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
+ /* Client can't support per-packet case sensitive pathnames. */
+ conn->case_sensitive = False;
+ } else {
+ conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
+ }
+ }
+ break;
+ case True:
+ conn->case_sensitive = True;
+ break;
+ default:
conn->case_sensitive = False;
- } else {
- conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
- }
+ break;
}
-
magic_char = lp_magicchar(snum);
return(True);
}
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index cff7d7371c6..40ea28a86d5 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -755,10 +755,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
pstring pass;
BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
+#if 0
+ /* This was the previous fix. Not sure if it's still valid. JRA. */
if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
/* NT4.0 stuffs up plaintext unicode password lengths... */
srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
sizeof(pass), passlen1, STR_TERMINATE);
+#endif
+
+ if (unic && (passlen2 == 0) && passlen1) {
+ /* Only a ascii plaintext password was sent. */
+ srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
+ passlen1, STR_TERMINATE|STR_ASCII);
} else {
srvstr_pull(inbuf, pass, smb_buf(inbuf),
sizeof(pass), unic ? passlen2 : passlen1,
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index a15a89bb766..d22705214e4 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -33,21 +33,6 @@ extern struct current_user current_user;
#define DIR_ENTRY_SAFETY_MARGIN 4096
/********************************************************************
- Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
- Only do this for Windows clients.
-********************************************************************/
-
-SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
-{
- /* Only roundup for Windows clients. */
- enum remote_arch_types ra_type = get_remote_arch();
- if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
- val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
- }
- return val;
-}
-
-/********************************************************************
Given a stat buffer return the allocated size on disk, taking into
account sparse files.
********************************************************************/
@@ -65,8 +50,6 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
if (!ret && fsp && fsp->initial_allocation_size)
ret = fsp->initial_allocation_size;
- ret = smb_roundup(ret);
-
return ret;
}
@@ -801,21 +784,6 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps
}
/****************************************************************************
- Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date.
-****************************************************************************/
-
-time_t interpret_long_unix_date(char *p)
-{
- DEBUG(10,("interpret_long_unix_date\n"));
- if(IVAL(p,0) == SMB_TIME_NO_CHANGE_LO &&
- IVAL(p,4) == SMB_TIME_NO_CHANGE_HI) {
- return -1;
- } else {
- return interpret_long_date(p);
- }
-}
-
-/****************************************************************************
Get a level dependent lanman2 dir entry.
****************************************************************************/
@@ -836,7 +804,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
pstring fname;
char *p, *q, *pdata = *ppdata;
uint32 reskey=0;
- int prev_dirpos=0;
+ long prev_dirpos=0;
int mode=0;
SMB_OFF_T file_size = 0;
SMB_BIG_UINT allocation_size = 0;
@@ -863,12 +831,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
} else
pstrcpy(mask, path_mask);
+
while (!found) {
BOOL got_match;
-
/* Needed if we run out of space */
- prev_dirpos = TellDir(conn->dirptr);
- dname = ReadDirName(conn->dirptr);
+ long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
+ dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
/*
* Due to bugs in NT client redirectors we are not using
@@ -879,8 +847,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
reskey = 0;
- DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
- (long)conn->dirptr,TellDir(conn->dirptr)));
+ DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
+ (long)conn->dirptr,curr_dirpos));
if (!dname)
return(False);
@@ -922,7 +890,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
pathreal,strerror(errno)));
continue;
}
- } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+ } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
/* Needed to show the msdfs symlinks as
* directories */
@@ -945,7 +913,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
mode = dos_mode(conn,pathreal,&sbuf);
- if (!dir_check_ftype(conn,mode,&sbuf,dirtype)) {
+ if (!dir_check_ftype(conn,mode,dirtype)) {
DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
continue;
}
@@ -1303,7 +1271,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
if (PTR_DIFF(p,pdata) > space_remaining) {
/* Move the dirptr back to prev_dirpos */
- SeekDir(conn->dirptr, prev_dirpos);
+ dptr_SeekDir(conn->dirptr, prev_dirpos);
*out_of_space = True;
DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
return False; /* Not finished - just out of space */
@@ -1341,7 +1309,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
int info_level = SVAL(params,6);
pstring directory;
pstring mask;
- char *p, *wcard;
+ char *p;
int last_name_off=0;
int dptr_num = -1;
int numentries = 0;
@@ -1437,15 +1405,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
/* Save the wildcard match and attribs we are using on this directory -
needed as lanman2 assumes these are being saved between calls */
- if(!(wcard = SMB_STRDUP(mask))) {
+ if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
dptr_close(&dptr_num);
return ERROR_DOS(ERRDOS,ERRnomem);
}
- dptr_set_wcard(dptr_num, wcard);
- dptr_set_attr(dptr_num, dirtype);
-
- DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, wcard, dirtype));
+ DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
@@ -1648,10 +1613,10 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
/* Get the attr mask from the dptr */
dirtype = dptr_attr(dptr_num);
- DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%d)\n",
+ DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
dptr_num, mask, dirtype,
(long)conn->dirptr,
- TellDir(conn->dirptr)));
+ dptr_TellDir(conn->dirptr)));
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
@@ -1670,84 +1635,29 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
*/
if(*resume_name && !continue_bit) {
+ SMB_STRUCT_STAT st;
+ long current_pos = 0;
/*
- * Fix for NT redirector problem triggered by resume key indexes
- * changing between directory scans. We now return a resume key of 0
- * and instead look for the filename to continue from (also given
- * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
- * findfirst/findnext (as is usual) then the directory pointer
- * should already be at the correct place. Check this by scanning
- * backwards looking for an exact (ie. case sensitive) filename match.
- * If we get to the beginning of the directory and haven't found it then scan
- * forwards again looking for a match. JRA.
+ * Remember, mangle_map is called by
+ * get_lanman2_dir_entry(), so the resume name
+ * could be mangled. Ensure we check the unmangled name.
*/
- int current_pos, start_pos;
- const char *dname = NULL;
- pstring dname_pstring;
- void *dirptr = conn->dirptr;
- start_pos = TellDir(dirptr);
- for(current_pos = start_pos; current_pos >= 0; current_pos--) {
- DEBUG(7,("call_trans2findnext: seeking to pos %d\n", current_pos));
-
- SeekDir(dirptr, current_pos);
- dname = ReadDirName(dirptr);
- if (dname) {
- /*
- * Remember, mangle_map is called by
- * get_lanman2_dir_entry(), so the resume name
- * could be mangled. Ensure we do the same
- * here.
- */
-
- /* make sure we get a copy that mangle_map can modify */
-
- pstrcpy(dname_pstring, dname);
- mangle_map( dname_pstring, False, True, SNUM(conn));
-
- if(strcsequal( resume_name, dname_pstring)) {
- SeekDir(dirptr, current_pos+1);
- DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
- break;
- }
- }
+ if (mangle_is_mangled(resume_name)) {
+ mangle_check_cache(resume_name, sizeof(resume_name)-1);
}
/*
- * Scan forward from start if not found going backwards.
+ * Fix for NT redirector problem triggered by resume key indexes
+ * changing between directory scans. We now return a resume key of 0
+ * and instead look for the filename to continue from (also given
+ * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
+ * findfirst/findnext (as is usual) then the directory pointer
+ * should already be at the correct place.
*/
- if(current_pos < 0) {
- DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
- SeekDir(dirptr, start_pos);
- for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) {
-
- /*
- * Remember, mangle_map is called by
- * get_lanman2_dir_entry(), so the resume name
- * could be mangled. Ensure we do the same
- * here.
- */
-
- if(dname) {
- /* make sure we get a copy that mangle_map can modify */
-
- pstrcpy(dname_pstring, dname);
- mangle_map(dname_pstring, False, True, SNUM(conn));
-
- if(strcsequal( resume_name, dname_pstring)) {
- SeekDir(dirptr, current_pos+1);
- DEBUG(7,("call_trans2findnext: got match at pos %d\n", current_pos+1 ));
- break;
- }
- }
- } /* end for */
- } /* end if current_pos */
- /* Can't find the name. Just resume from where we were... */
- if (dname == 0) {
- SeekDir(dirptr, start_pos);
- }
+ finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
} /* end if resume_name && !continue_bit */
for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
@@ -2249,6 +2159,7 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint
return UNIXERROR(def_class,def_code);
}
+#if defined(HAVE_POSIX_ACLS)
/****************************************************************************
Utility function to count the number of entries in a POSIX acl.
****************************************************************************/
@@ -2363,6 +2274,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
return True;
}
+#endif
/****************************************************************************
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
@@ -2928,6 +2840,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
break;
}
+#if defined(HAVE_POSIX_ACLS)
case SMB_QUERY_POSIX_ACL:
{
SMB_ACL_T file_acl = NULL;
@@ -3004,6 +2917,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
break;
}
+#endif
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
@@ -3027,10 +2941,12 @@ NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, u
* Only allow delete on close for writable files.
*/
- if (dosmode & aRONLY) {
- DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
- fsp->fsp_name ));
- return NT_STATUS_CANNOT_DELETE;
+ if (!lp_delete_readonly(SNUM(fsp->conn))) {
+ if (dosmode & aRONLY) {
+ DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
+ fsp->fsp_name ));
+ return NT_STATUS_CANNOT_DELETE;
+ }
}
/*
@@ -3385,7 +3301,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
tvs.modtime = MIN(write_time, changed_time);
- if (write_time > tvs.modtime && write_time != 0xffffffff) {
+ if (write_time > tvs.modtime && write_time != (time_t)-1) {
tvs.modtime = write_time;
}
/* Prefer a defined time to an undefined one. */
@@ -3417,9 +3333,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
fname, (double)allocation_size ));
- if (allocation_size)
- allocation_size = smb_roundup(allocation_size);
-
if(allocation_size != get_file_size(sbuf)) {
SMB_STRUCT_STAT new_sbuf;
@@ -3564,8 +3477,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
#endif /* LARGE_SMB_OFF_T */
}
pdata+=24; /* ctime & st_blocks are not changed */
- tvs.actime = interpret_long_unix_date(pdata); /* access_time */
- tvs.modtime = interpret_long_unix_date(pdata+8); /* modification_time */
+ tvs.actime = interpret_long_date(pdata); /* access_time */
+ tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
pdata+=16;
set_owner = (uid_t)IVAL(pdata,0);
pdata += 8;
@@ -3813,6 +3726,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
return(-1);
}
+#if defined(HAVE_POSIX_ACLS)
case SMB_SET_POSIX_ACL:
{
uint16 posix_acl_version;
@@ -3862,6 +3776,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
return(-1);
}
+#endif
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
index 45895d2ec71..b3d596f4428 100644
--- a/source/tdb/tdb.c
+++ b/source/tdb/tdb.c
@@ -1272,6 +1272,13 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
goto fail;
return tlock->off;
}
+
+ /* Detect infinite loops. From "Shlomi Yaakobovich" <Shlomi@exanet.com>. */
+ if (tlock->off == rec->next) {
+ TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n"));
+ goto fail;
+ }
+
/* Try to clean dead ones from old traverses */
current = tlock->off;
tlock->off = rec->next;
diff --git a/source/torture/torture.c b/source/torture/torture.c
index 72a391dbdbb..ec13abc1c1f 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -3128,7 +3128,7 @@ static BOOL run_deletetest(int dummy)
FILE_OVERWRITE_IF, 0, 0);
if (fnum1 == -1) {
- printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1));
+ printf("[8] open 1 of %s failed (%s)\n", fname, cli_errstr(cli1));
correct = False;
goto fail;
}
@@ -3138,7 +3138,7 @@ static BOOL run_deletetest(int dummy)
FILE_OPEN, 0, 0);
if (fnum2 == -1) {
- printf("[8] open of %s failed (%s)\n", fname, cli_errstr(cli1));
+ printf("[8] open 2 of %s failed (%s)\n", fname, cli_errstr(cli2));
correct = False;
goto fail;
}
@@ -3205,6 +3205,49 @@ static BOOL run_deletetest(int dummy)
correct = False;
} else
printf("tenth delete on close test succeeded.\n");
+
+ cli_setatr(cli1, fname, 0, 0);
+ cli_unlink(cli1, fname);
+
+ /* What error do we get when attempting to open a read-only file with
+ delete access ? */
+
+ /* Create a readonly file. */
+ fnum1 = cli_nt_create_full(cli1, fname, 0, FILE_READ_DATA|FILE_WRITE_DATA,
+ FILE_ATTRIBUTE_READONLY, FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0, 0);
+ if (fnum1 == -1) {
+ printf("[11] open of %s failed (%s)\n", fname, cli_errstr(cli1));
+ correct = False;
+ goto fail;
+ }
+
+ if (!cli_close(cli1, fnum1)) {
+ printf("[11] close failed (%s)\n", cli_errstr(cli1));
+ correct = False;
+ goto fail;
+ }
+
+ /* Now try open for delete access. */
+ fnum1 = cli_nt_create_full(cli1, fname, 0, FILE_READ_ATTRIBUTES|DELETE_ACCESS,
+ 0, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
+ FILE_OVERWRITE_IF, 0, 0);
+
+ if (fnum1 != -1) {
+ printf("[11] open of %s succeeded should have been denied with ACCESS_DENIED!\n", fname);
+ cli_close(cli1, fnum1);
+ goto fail;
+ correct = False;
+ } else {
+ NTSTATUS nterr = cli_nt_error(cli1);
+ if (!NT_STATUS_EQUAL(nterr,NT_STATUS_ACCESS_DENIED)) {
+ printf("[11] open of %s should have been denied with ACCESS_DENIED! Got error %s\n", fname, nt_errstr(nterr));
+ goto fail;
+ correct = False;
+ } else {
+ printf("eleventh delete on close test succeeded.\n");
+ }
+ }
+
printf("finished delete test\n");
fail:
diff --git a/source/utils/net.c b/source/utils/net.c
index cfbc8aca512..9c05828357c 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -552,14 +552,16 @@ static int net_getdomainsid(int argc, const char **argv)
#ifdef WITH_FAKE_KASERVER
-int net_afskey_usage(int argc, const char **argv)
+int net_help_afs(int argc, const char **argv)
{
- d_printf(" net afskey filename\n"
+ d_printf(" net afs key filename\n"
"\tImports a OpenAFS KeyFile into our secrets.tdb\n\n");
+ d_printf(" net afs impersonate <user> <cell>\n"
+ "\tCreates a token for user@cell\n\n");
return -1;
}
-static int net_afskey(int argc, const char **argv)
+static int net_afs_key(int argc, const char **argv)
{
int fd;
struct afs_keyfile keyfile;
@@ -592,6 +594,42 @@ static int net_afskey(int argc, const char **argv)
return 0;
}
+static int net_afs_impersonate(int argc, const char **argv)
+{
+ char *token;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: net afs impersonate <user> <cell>\n");
+ exit(1);
+ }
+
+ token = afs_createtoken_str(argv[0], argv[1]);
+
+ if (token == NULL) {
+ fprintf(stderr, "Could not create token\n");
+ exit(1);
+ }
+
+ if (!afs_settoken_str(token)) {
+ fprintf(stderr, "Could not set token into kernel\n");
+ exit(1);
+ }
+
+ printf("Success: %s@%s\n", argv[0], argv[1]);
+ return 0;
+}
+
+static int net_afs(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"key", net_afs_key},
+ {"impersonate", net_afs_impersonate},
+ {"help", net_help_afs},
+ {NULL, NULL}
+ };
+ return net_run_function(argc, argv, func, net_help_afs);
+}
+
#endif /* WITH_FAKE_KASERVER */
static uint32 get_maxrid(void)
@@ -707,7 +745,7 @@ static struct functable net_func[] = {
{"STATUS", net_status},
{"USERSIDLIST", net_usersidlist},
#ifdef WITH_FAKE_KASERVER
- {"AFSKEY", net_afskey},
+ {"AFS", net_afs},
#endif
{"HELP", net_help},
diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c
index c6391a65feb..158c006d1c0 100644
--- a/source/utils/net_groupmap.c
+++ b/source/utils/net_groupmap.c
@@ -277,8 +277,22 @@ static int net_groupmap_add(int argc, const char **argv)
sid_to_string(string_sid, &sid);
}
- if (!ntcomment[0])
- fstrcpy(ntcomment, "Local Unix group");
+ if (!ntcomment[0]) {
+ switch (sid_type) {
+ case SID_NAME_WKN_GRP:
+ fstrcpy(ntcomment, "Wellknown Unix group");
+ break;
+ case SID_NAME_DOM_GRP:
+ fstrcpy(ntcomment, "Domain Unix group");
+ break;
+ case SID_NAME_ALIAS:
+ fstrcpy(ntcomment, "Local Unix group");
+ break;
+ default:
+ fstrcpy(ntcomment, "Unix group");
+ break;
+ }
+ }
if (!ntgroup[0] )
fstrcpy( ntgroup, unixgrp );
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index 60206429b7e..26d59beda2b 100644
--- a/source/utils/net_help.c
+++ b/source/utils/net_help.c
@@ -269,7 +269,7 @@ int net_help(int argc, const char **argv)
{"LOOKUP", net_lookup_usage},
{"USERSIDLIST", net_usersidlist_usage},
#ifdef WITH_FAKE_KASERVER
- {"AFSKEY", net_afskey_usage},
+ {"AFS", net_help_afs},
#endif
{"HELP", help_usage},
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 76b53d61136..b18d4b0ba5e 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -1005,26 +1005,32 @@ rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name,
result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
&num_rids, &user_gids);
- /* Look up rids */
+ if (!NT_STATUS_IS_OK(result)) goto done;
- rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
+ /* Look up rids */
- for (i = 0; i < num_rids; i++)
- rids[i] = user_gids[i].g_rid;
+ if (rids) {
+ rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
- result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
- flags, num_rids, rids,
- &num_names, &names, &name_types);
+ for (i = 0; i < num_rids; i++)
+ rids[i] = user_gids[i].g_rid;
- if (!NT_STATUS_IS_OK(result)) {
- goto done;
- }
+ result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
+ num_rids, rids,
+ &num_names, &names, &name_types);
- /* Display results */
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
- for (i = 0; i < num_names; i++)
- printf("%s\n", names[i]);
+ /* Display results */
+ for (i = 0; i < num_names; i++)
+ printf("%s\n", names[i]);
+ }
+ else {
+ printf("no groups\n");
+ }
done:
return result;
}
@@ -2142,7 +2148,7 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
if (num_members < this_time)
this_time = num_members;
- result = cli_samr_lookup_rids(cli, mem_ctx, domain_pol, 1000,
+ result = cli_samr_lookup_rids(cli, mem_ctx, domain_pol,
this_time, group_rids,
&num_names, &names, &name_types);
diff --git a/source/utils/net_rpc_printer.c b/source/utils/net_rpc_printer.c
index 456a29287fd..4b53dec36e9 100644
--- a/source/utils/net_rpc_printer.c
+++ b/source/utils/net_rpc_printer.c
@@ -234,7 +234,7 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
}
-static void display_reg_value(pstring subkey, REGISTRY_VALUE value)
+static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
{
pstring text;
@@ -980,7 +980,7 @@ net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* enumprinterdataex call */
result = cli_spoolss_enumprinterdataex(
- cli, mem_ctx, 0, &needed, hnd, keyname, NULL);
+ cli, mem_ctx, 0, &needed, hnd, keyname, ctr);
if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
result = cli_spoolss_enumprinterdataex(
@@ -2205,7 +2205,6 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
char *devicename = NULL, *unc_name = NULL, *url = NULL;
fstring longname;
- const char *keyname = NULL;
uint16 *keylist = NULL, *curkey;
ZERO_STRUCT(ctr_enum);
@@ -2242,7 +2241,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
sizeof(printername), -1, STR_TERMINATE);
rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
sizeof(sharename), -1, STR_TERMINATE);
- keyname = "";
+
/* we can reset NT_STATUS here because we do not
get any real NT_STATUS-codes anymore from now on */
nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -2305,14 +2304,6 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
/* do not copy security descriptor (we have another command for that) */
ctr_dst.printers_2->secdesc = NULL;
-
- /* devmode->devicename is possibly broken at the moment for all
- strlen(longprinternames) > MAXDEVICENAME (that is 32 chars)
- this fires up thousands of safe_strncpy-debug0-messages
- on my test-servers
- TODO: tell jerry, jra, etc. again.
- */
-
#if 0
if (asprintf(&devicename, "\\\\%s\\%s", longname, printername) < 0) {
nt_status = NT_STATUS_NO_MEMORY;
@@ -2333,7 +2324,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
/* please keep in mind that samba parse_spools gives horribly
crippled results when used to cli_spoolss_enumprinterdataex
- a win2k3-server.
+ a win2k3-server. (Bugzilla #1851)
FIXME: IIRC I've seen it too on a win2k-server
*/
@@ -2341,7 +2332,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0,
&val_needed, &data_needed, NULL);
- /* loop for all printerdata */
+ /* loop for all printerdata of "PrinterDriverData" */
while (W_ERROR_IS_OK(result)) {
REGISTRY_VALUE value;
@@ -2355,7 +2346,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
/* display_value */
if (opt_verbose)
- display_reg_value(NULL, value);
+ display_reg_value(SPOOL_PRINTERDATA_KEY, value);
/* set_value */
if (!net_spoolss_setprinterdata(cli_dst, mem_ctx,
@@ -2374,7 +2365,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
respond to enumprinterkey, win2k does, so continue
in case of an error */
- if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, keyname, &keylist)) {
+ if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, "", &keylist)) {
printf("got no key-data\n");
continue;
}
diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c
index 320341ec050..49aef2a23cd 100644
--- a/source/utils/net_rpc_samsync.c
+++ b/source/utils/net_rpc_samsync.c
@@ -523,7 +523,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
all_string_sub(add_script, "%u", account,
sizeof(account));
add_ret = smbrun(add_script,NULL);
- DEBUG(1,("fetch_account: Running the command `%s' "
+ DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
"gave %d\n", add_script, add_ret));
} else {
DEBUG(8,("fetch_account_info: no add user/machine script. Asking winbindd\n"));
diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c
index ea2faebdff4..3584ef0367a 100644
--- a/source/utils/pdbedit.c
+++ b/source/utils/pdbedit.c
@@ -694,8 +694,8 @@ int main (int argc, char **argv)
{"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL},
{"bad-password-count-reset", 'z', POPT_ARG_NONE, &badpw_reset, 0, "reset bad password count", NULL},
{"logon-hours-reset", 'Z', POPT_ARG_NONE, &hours_reset, 0, "reset logon hours", NULL},
- {"pwd-can-change-time", 0, POPT_ARG_STRING, &pwd_can_change_time, 0, "Set password can change time (unix time if time format no provided)", NULL },
- {"pwd-must-change-time", 0, POPT_ARG_STRING, &pwd_must_change_time, 0, "Set password can change time (unix time if time format no provided)", NULL },
+ {"pwd-can-change-time", 0, POPT_ARG_STRING, &pwd_can_change_time, 0, "Set password can change time (unix time in seconds since 1970 if time format not provided)", NULL },
+ {"pwd-must-change-time", 0, POPT_ARG_STRING, &pwd_must_change_time, 0, "Set password can change time (unix time in seconds since 1970 if time format not provided)", NULL },
{"time-format", 0, POPT_ARG_STRING, &pwd_time_format, 0, "The time format for time parameters", NULL },
POPT_COMMON_SAMBA
POPT_TABLEEND
diff --git a/source/utils/profiles.c b/source/utils/profiles.c
index a31674dfb2e..5b5cb7f07b2 100644
--- a/source/utils/profiles.c
+++ b/source/utils/profiles.c
@@ -521,7 +521,7 @@ static void process_acl(ACL *acl, const char *prefix)
int main(int argc, char *argv[])
{
int opt;
- int fd, start = 0;
+ int fd;
char *base;
struct stat sbuf;
REGF_HDR *regf_hdr;
@@ -577,6 +577,8 @@ int main(int argc, char *argv[])
}
}
+ poptGetArg(pc); /* To get argv[0] */
+
if (!poptPeekArg(pc)) {
poptPrintUsage(pc, stderr, 0);
exit(1);
@@ -588,8 +590,6 @@ int main(int argc, char *argv[])
exit(252);
}
- poptGetArg(pc); /* To get argv[0] */
-
fd = open(poptPeekArg(pc), O_RDWR, 0000);
if (fd < 0) {
@@ -608,10 +608,9 @@ int main(int argc, char *argv[])
* Now, mmap the file into memory, check the header and start
* dealing with the records. We are interested in the sk record
*/
- start = 0;
#ifdef HAVE_MMAP
- base = mmap(&start, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ base = mmap(NULL, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
#else
base = (char *)-1;
errno = ENOSYS;
diff --git a/source/utils/status.c b/source/utils/status.c
index cae4e07975a..75e7cb3de71 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -541,7 +541,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
return 0;
}
- d_printf("%-10.10s %5d %-12s %s",
+ d_printf("%-10s %5d %-12s %s",
crec.name,(int)crec.pid,
crec.machine,
asctime(LocalTime(&crec.start)));