summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2004-09-23 12:21:10 +0000
committerGerald Carter <jerry@samba.org>2004-09-23 12:21:10 +0000
commit3cf617a8c779ef153080bd00d20bfaa349603096 (patch)
tree8950e518321f034d21006ebe087a8cd4a80d1ca8
parentf36cd948f0006d177ff67ab5bb2636d32493ce28 (diff)
downloadsamba-3cf617a8c779ef153080bd00d20bfaa349603096.tar.gz
samba-3cf617a8c779ef153080bd00d20bfaa349603096.tar.xz
samba-3cf617a8c779ef153080bd00d20bfaa349603096.zip
r2565: syncing up for 3.0.8pre1
-rw-r--r--README12
-rw-r--r--Roadmap4
-rw-r--r--examples/auth/crackcheck/Makefile25
-rw-r--r--examples/auth/crackcheck/crackcheck.c62
-rw-r--r--packaging/SuSE/samba3-vscan.diff6
-rw-r--r--source/Makefile.in68
-rw-r--r--source/VERSION4
-rw-r--r--source/client/client.c2
-rw-r--r--source/client/clitar.c8
-rw-r--r--source/configure.in19
-rw-r--r--source/include/charset.h9
-rw-r--r--source/include/fake_file.h4
-rw-r--r--source/include/hash.h74
-rw-r--r--source/include/includes.h51
-rwxr-xr-xsource/include/rpc_spoolss.h1
-rw-r--r--source/include/smb.h6
-rw-r--r--source/include/smb_macros.h1
-rw-r--r--source/include/smbldap.h2
-rw-r--r--source/lib/charcnv.c30
-rw-r--r--source/lib/hash.c316
-rw-r--r--source/lib/iconv.c347
-rw-r--r--source/lib/ms_fnmatch.c3
-rw-r--r--source/lib/smbldap.c55
-rw-r--r--source/lib/smbrun.c123
-rw-r--r--source/lib/util.c5
-rw-r--r--source/lib/util_file.c492
-rw-r--r--source/lib/util_str.c13
-rw-r--r--source/lib/util_uuid.c66
-rw-r--r--source/libads/kerberos.c10
-rw-r--r--source/libsmb/cliconnect.c8
-rw-r--r--source/libsmb/clifile.c41
-rw-r--r--source/libsmb/clikrb5.c18
-rw-r--r--source/libsmb/cliquota.c4
-rw-r--r--source/libsmb/clireadwrite.c8
-rw-r--r--source/locking/locking.c13
-rw-r--r--source/modules/weird.c4
-rw-r--r--source/nmbd/nmbd.c8
-rw-r--r--source/nmbd/nmbd_workgroupdb.c43
-rw-r--r--source/nsswitch/pam_winbind.c64
-rw-r--r--source/nsswitch/pam_winbind.h1
-rw-r--r--source/nsswitch/wbinfo.c41
-rw-r--r--source/nsswitch/winbind_nss_linux.c41
-rw-r--r--source/nsswitch/winbindd.c25
-rw-r--r--source/nsswitch/winbindd_cache.c4
-rw-r--r--source/nsswitch/winbindd_dual.c2
-rw-r--r--source/nsswitch/winbindd_group.c7
-rw-r--r--source/nsswitch/winbindd_sid.c78
-rw-r--r--source/nsswitch/winbindd_user.c2
-rw-r--r--source/nsswitch/winbindd_util.c8
-rw-r--r--source/param/loadparm.c4
-rw-r--r--source/passdb/pdb_ldap.c45
-rw-r--r--source/passdb/pdb_smbpasswd.c1823
-rw-r--r--source/passdb/pdb_xml.c73
-rw-r--r--source/printing/nt_printing.c2
-rw-r--r--source/rpc_client/cli_spoolss.c24
-rw-r--r--source/rpc_client/cli_srvsvc.c6
-rw-r--r--source/rpc_parse/parse_net.c8
-rw-r--r--source/rpc_parse/parse_spoolss.c68
-rw-r--r--source/rpc_parse/parse_srv.c45
-rw-r--r--source/rpc_server/srv_netlog_nt.c48
-rw-r--r--source/rpc_server/srv_samr_nt.c33
-rw-r--r--source/rpc_server/srv_spoolss_nt.c21
-rw-r--r--source/rpcclient/cmd_spoolss.c23
-rw-r--r--source/script/mkproto.awk2
-rw-r--r--source/smbd/blocking.c74
-rw-r--r--source/smbd/chgpasswd.c13
-rw-r--r--source/smbd/dir.c109
-rw-r--r--source/smbd/fake_file.c6
-rw-r--r--source/smbd/filename.c18
-rw-r--r--source/smbd/mangle_hash.c218
-rw-r--r--source/smbd/negprot.c4
-rw-r--r--source/smbd/nttrans.c30
-rw-r--r--source/smbd/process.c7
-rw-r--r--source/smbd/service.c5
-rw-r--r--source/smbd/statcache.c150
-rw-r--r--source/tdb/tdb.c59
-rw-r--r--source/tdb/tdb.h18
-rw-r--r--source/tdb/tdbutil.c2
-rw-r--r--source/ubiqx/ubi_BinTree.c68
-rw-r--r--source/ubiqx/ubi_BinTree.h31
-rw-r--r--source/utils/net.c68
-rw-r--r--source/utils/net.h5
-rw-r--r--source/utils/net_ads.c5
-rw-r--r--source/utils/net_ads_cldap.c3
-rw-r--r--source/utils/net_help.c51
-rw-r--r--source/utils/net_rpc.c735
-rw-r--r--source/utils/net_rpc_printer.c2339
-rw-r--r--source/utils/smbcacls.c8
-rw-r--r--source/utils/smbcquotas.c16
89 files changed, 5995 insertions, 2510 deletions
diff --git a/README b/README
index f529610ef43..d6c5e15bdf7 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is a development version of Samba, the free SMB and CIFS client and
+This is a development version of Samba, the free SMB and CIFS client and
server for UNIX and other operating systems. Samba is maintained by
the Samba Team, who support the original author, Andrew Tridgell.
@@ -6,7 +6,7 @@ the Samba Team, who support the original author, Andrew Tridgell.
>>>> about the configuration and use of Samba.
NOTE: Installation instructions may be found in
- docs/htmldocs/install.html
+ docs/htmldocs/Samba-HOWTO-Collection/install.html
This software is freely distributable under the GNU public license, a
copy of which you should have received with this software (in a file
@@ -102,16 +102,16 @@ for more details) and are always glad to receive feedback or
suggestions to the address samba@lists.samba.org. More information
on the various Samba mailing lists can be found at http://lists.samba.org/.
-You can also get the Samba sourcecode straight from the CVS tree - see
-http://samba.org/cvs.html.
+You can also get the Samba sourcecode straight from the Subversion tree - see
+http://samba.org/samba/subversion.html.
You could also send hardware/software/money/jewelry or pre-paid pizza
vouchers directly to Andrew. The pizza vouchers would be especially
welcome, in fact there is a special field in the survey for people who
have paid up their pizza :-)
-If you like a particular feature then look through the CVS change-log
-(on the web at http://samba.org/cgi-bin/cvsweb/samba) and see
+If you like a particular feature then look through the Subversion change-log
+(on the web at http://websvn.samba.org/cgi-bin/viewcvs.cgi) and see
who added it, then send them an email.
Remember that free software of this kind lives or dies by the response
diff --git a/Roadmap b/Roadmap
index 42c63f78098..6d678783f57 100644
--- a/Roadmap
+++ b/Roadmap
@@ -3,7 +3,7 @@ Copyright (C) 1997-2003 Samba-Team
The Samba-Team are committed to an aggressive program to deliver quality
controlled software to a well defined roadmap.
-The current Samba Beta series of Samba 3.0.0 is called the "Domain Integration"
+The current Samba series of Samba 3.0.0 is called the "Domain Integration"
release.
The following development objectives for future releases
@@ -27,4 +27,4 @@ well with whatever "Beta" releases Redmond throws our way :-).
You may also note that the release numbers get fuzzier the
further into the future the objectives get. This is intentional
-as we cannot yet commit to exact timeframes.
+as we cannot commit to exact timeframes.
diff --git a/examples/auth/crackcheck/Makefile b/examples/auth/crackcheck/Makefile
new file mode 100644
index 00000000000..84377aafefe
--- /dev/null
+++ b/examples/auth/crackcheck/Makefile
@@ -0,0 +1,25 @@
+# C compiler
+#CC=cc
+CC=gcc
+
+# Uncomment the following to add symbols to the code for debugging
+#DEBUG=-g -Wall
+
+# Optimization for the compiler
+#OPTIMIZE=
+OPTIMIZE=-O2
+
+CFLAGS= $(DEBUG) $(OPTIMIZE)
+
+OBJS = crackcheck.o
+LIBS = -lcrack
+
+crackcheck: $(OBJS)
+ $(CC) $(CFLAGS) $(LIBS) -o crackcheck $(OBJS)
+
+clean:
+ rm -f core *.o crackcheck
+
+install: crackcheck
+ install -m 555 crackcheck $(PREFIX)/sbin/crackcheck
+
diff --git a/examples/auth/crackcheck/crackcheck.c b/examples/auth/crackcheck/crackcheck.c
new file mode 100644
index 00000000000..338433779b0
--- /dev/null
+++ b/examples/auth/crackcheck/crackcheck.c
@@ -0,0 +1,62 @@
+#include <memory.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <crack.h>
+
+void usage(char *command) {
+ char *c, *comm;
+
+ comm = command;
+ while ((c = strrchr(comm, '/')) != NULL) {
+ comm = c + 1;
+ }
+
+ fprintf(stderr, "Usage: %s -d dictionary\n\n", comm);
+ fprintf(stderr, " -d dictionary file for cracklib\n\n");
+ fprintf(stderr, " The password is expected to be given via stdin.\n\n");
+ exit(-1);
+}
+
+int main(int argc, char **argv) {
+ extern char *optarg;
+ int c;
+
+ char f[256];
+ char *dictionary = NULL;
+ char *password;
+ char *reply;
+
+ while ( (c = getopt(argc, argv, "d:")) != EOF){
+ switch(c) {
+ case 'd':
+ dictionary = strdup(optarg);
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if (dictionary == NULL) {
+ fprintf(stderr, "ERR - Wrong Command Line\n\n");
+ usage(argv[0]);
+ }
+
+ password = fgets(f, sizeof(f), stdin);
+
+ if (password == NULL) {
+ fprintf(stderr, "ERR - Failed to read password\n\n");
+ exit(-2);
+ }
+
+ reply = FascistCheck(password, dictionary);
+ if (reply != NULL) {
+ fprintf(stderr, "ERR - %s\n\n", reply);
+ exit(-3);
+ }
+
+ exit(0);
+
+}
+
diff --git a/packaging/SuSE/samba3-vscan.diff b/packaging/SuSE/samba3-vscan.diff
index 330b470af2c..cf474c97d00 100644
--- a/packaging/SuSE/samba3-vscan.diff
+++ b/packaging/SuSE/samba3-vscan.diff
@@ -18,7 +18,7 @@
- lrufiles_add(filepath, stat_buf.st_mtime, TRUE);
+ lrufiles_add(filepath, stat_buf.st_mtime, True);
- /* virus found, deny acces */
+ /* virus found, deny access */
errno = EACCES;
return -1;
} else if ( retval == 0 ) {
@@ -68,7 +68,7 @@
- lrufiles_add(filepath, stat_buf.st_mtime, TRUE);
+ lrufiles_add(filepath, stat_buf.st_mtime, True);
- /* virus found, deny acces */
+ /* virus found, deny access */
errno = EACCES;
return -1;
} else if ( retval == 0 ) {
@@ -197,7 +197,7 @@
- lrufiles_add(filepath, stat_buf.st_mtime, TRUE);
+ lrufiles_add(filepath, stat_buf.st_mtime, True);
- /* virus found, deny acces */
+ /* virus found, deny access */
errno = EACCES;
return -1;
} else if ( retval == 0 ) {
diff --git a/source/Makefile.in b/source/Makefile.in
index 5d3462913c1..b6fe22b5934 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -35,8 +35,6 @@ IDMAP_LIBS=@IDMAP_LIBS@
KRB5LIBS=@KRB5_LIBS@
LDAP_LIBS=@LDAP_LIBS@
-LINK=$(CC) $(FLAGS) $(LDFLAGS)
-
INSTALLCMD=@INSTALL@
INSTALLCLIENTCMD_SH=@INSTALLCLIENTCMD_SH@
INSTALLCLIENTCMD_A=@INSTALLCLIENTCMD_A@
@@ -199,7 +197,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \
lib/util_unistr.o lib/util_file.o lib/data_blob.o \
lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \
- lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \
+ lib/talloc.o lib/substitute.o lib/fsusage.o \
lib/ms_fnmatch.o lib/select.o lib/messages.o \
lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \
lib/md5.o lib/hmacmd5.o lib/iconv.o \
@@ -397,7 +395,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
$(LIBMSRPC_OBJ) \
$(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
$(LIB_SMBD_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
- $(UBIQX_OBJ) $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
+ $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
PRINTING_OBJ = printing/pcap.o printing/print_svid.o \
printing/print_cups.o printing/print_generic.o \
@@ -533,7 +531,7 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
- utils/net_status.o
+ utils/net_status.o utils/net_rpc_printer.o
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -847,27 +845,27 @@ bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy
bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
bin/editreg@EXEEXT@: $(EDITREG_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(EDITREG_OBJ) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(EDITREG_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
bin/smbspool@EXEEXT@: $(CUPS_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbmount@EXEEXT@: $(MOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbmnt@EXEEXT@: $(MNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MNT_OBJ) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(MNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/smbumount@EXEEXT@: $(UMOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(UMOUNT_OBJ) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/testparm@EXEEXT@: $(TESTPARM_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -919,15 +917,15 @@ bin/smbtorture@EXEEXT@: $(SMBTORTURE_OBJ) bin/.dummy
bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
bin/masktest@EXEEXT@: $(MASKTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(SECRETS_OBJ)
+ @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(SECRETS_OBJ)
bin/msgtest@EXEEXT@: $(MSGTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbcacls@EXEEXT@: $(SMBCACLS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -939,11 +937,11 @@ bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy
bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -955,11 +953,11 @@ bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy
bin/log2pcap@EXEEXT@: $(LOG2PCAP_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) @POPTLIBS@ $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS)
bin/locktest2@EXEEXT@: $(LOCKTEST2_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy
@echo Linking $@
@@ -967,15 +965,15 @@ bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy
bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy
@echo Linking $@
@@ -989,7 +987,7 @@ bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy
bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS)
@echo Linking libsmbclient shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \
$(KRB5LIBS) $(LDAP_LIBS) \
@SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR)
@@ -1064,7 +1062,8 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ)
bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
@echo "Linking $@"
- @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
# libraries. Add to the appropriate PICOBJ variable instead.
@@ -1225,13 +1224,14 @@ bin/afsacl.@SHLIBEXT@: $(VFS_AFSACL_OBJ:.o=.po)
bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@
bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(LINK) -o $@ $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
- $(UBIQX_OBJ) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \
+ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(LIBS) \
+ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ)
@echo "Linking shared library $@"
@@ -1242,28 +1242,28 @@ bin/libmsrpc.a: $(LIBMSRPC_PICOBJ)
bin/tdbbackup@EXEEXT@: $(TDBBACKUP_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(TDBBACKUP_OBJ)
+ @$(CC) $(FLAGS) -o $@ $(DYNEXP) $(TDBBACKUP_OBJ)
bin/tdbdump@EXEEXT@: $(TDBDUMP_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(TDBDUMP_OBJ)
+ @$(CC) $(FLAGS) -o $@ $(DYNEXP) $(TDBDUMP_OBJ)
bin/t_strcmp@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud
bin/t_strstr@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o
- $(CC) $(FLAGS) -o $@ torture/t_stringoverflow.o -L./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud
bin/t_doschar@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_doschar.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud
bin/t_push_ucs2@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_push_ucs2.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud
bin/t_snprintf@EXEEXT@: lib/snprintf.c
- $(CC) $(FLAGS) -o $@ -DTEST_SNPRINTF lib/snprintf.c -lm
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) -DTEST_SNPRINTF lib/snprintf.c -lm
install: installbin installman installscripts installdat installswat installmodules @INSTALLCLIENT@
install-everything: install installmodules
diff --git a/source/VERSION b/source/VERSION
index ab14d54bdd0..f33e71fb577 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -19,7 +19,7 @@
########################################################
SAMBA_VERSION_MAJOR=3
SAMBA_VERSION_MINOR=0
-SAMBA_VERSION_RELEASE=7
+SAMBA_VERSION_RELEASE=8
########################################################
# For 'pre' releases the version will be #
@@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=7
# 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/client/client.c b/source/client/client.c
index 1fccfaa581c..e14bcaa2616 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -592,7 +592,7 @@ static int cmd_dir(void)
else
pstrcat(mask,p);
} else {
- pstrcat(mask,"*");
+ pstrcat(mask,"\\*");
}
do_list(mask, attribute, display_finfo, recurse, True);
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 64c194b54da..4cadef558d6 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -1345,8 +1345,9 @@ Principal command for creating / extracting
int cmd_tar(void)
{
fstring buf;
- char **argl;
- int argcl;
+ char **argl = NULL;
+ int argcl = 0;
+ int ret;
if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
@@ -1357,8 +1358,9 @@ int cmd_tar(void)
if (!tar_parseargs(argcl, argl, buf, 0))
return 1;
+ ret = process_tar();
SAFE_FREE(argl);
- return process_tar();
+ return ret;
}
/****************************************************************************
diff --git a/source/configure.in b/source/configure.in
index 53267f0cd95..69152d8fc8f 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -414,7 +414,6 @@ case "$host_os" in
AC_DEFINE(_MAX_ALIGNMENT, 4, [Maximum alignment])
;;
esac
- DYNEXP="-Wl,-E"
;;
#
@@ -1215,9 +1214,9 @@ if test "$enable_shared" = "yes"; then
# Use special PIC flags for the native HP-UX compiler.
if test $ac_cv_prog_cc_Ae = yes; then
BLDSHARED="true"
- SHLD="/usr/bin/ld"
- LDSHFLAGS="-B symbolic -b -z"
- SONAMEFLAG="+h "
+ SHLD="cc"
+ LDSHFLAGS="-b -Wl,-B,symbolic,-b,-z"
+ SONAMEFLAG="-Wl,+h "
PICFLAGS="+z"
elif test "${GCC}" = "yes"; then
PICFLAGS="-fPIC"
@@ -1302,13 +1301,14 @@ fi
if test $BLDSHARED = true; then
AC_CACHE_CHECK([whether building shared libraries actually works],
[ac_cv_shlib_works],[
- ac_cv_shlib_works=no
# try building a trivial shared library
+ ac_cv_shlib_works=no
+ # The $SHLD and $LDSHFLAGS variables may contain references to other
+ # variables so they need to be eval'ed.
$CC $CPPFLAGS $CFLAGS $PICFLAGS -c -o \
shlib.$PICSUFFIX ${srcdir-.}/tests/shlib.c && \
- $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" \
- shlib.$PICSUFFIX && \
- ac_cv_shlib_works=yes
+ `eval echo $SHLD` `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" \
+ shlib.$PICSUFFIX && ac_cv_shlib_works=yes
rm -f "shlib.$SHLIBEXT" shlib.$PICSUFFIX
])
if test $ac_cv_shlib_works = no; then
@@ -2761,6 +2761,7 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_free_unparsed_name, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_keytab_entry_contents, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_kt_free_entry, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_krbhst_get_addrinfo, $KRB5_LIBS)
LIBS="$LIBS $KRB5_LIBS"
@@ -4235,7 +4236,7 @@ AC_SUBST(WINBIND_NSS_LDSHFLAGS)
AC_SUBST(WINBIND_NSS_EXTRA_OBJS)
AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
-# Check the setting of --with-winbindd
+# Check the setting of --with-winbind
AC_ARG_WITH(winbind,
[ --with-winbind Build winbind (default, if supported by OS)],
diff --git a/source/include/charset.h b/source/include/charset.h
index 7a9b12ef55d..c5d03a62e89 100644
--- a/source/include/charset.h
+++ b/source/include/charset.h
@@ -31,9 +31,9 @@ typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t
struct charset_functions {
const char *name;
- size_t (*pull)(void *, char **inbuf, size_t *inbytesleft,
+ size_t (*pull)(void *, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
- size_t (*push)(void *, char **inbuf, size_t *inbytesleft,
+ size_t (*push)(void *, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
struct charset_functions *prev, *next;
};
@@ -57,7 +57,7 @@ struct charset_gap_table {
*
* */
#define SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CHARSETNAME) \
-static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft, \
+static size_t CHARSETNAME ## _push(void *cd, const char **inbuf, size_t *inbytesleft, \
char **outbuf, size_t *outbytesleft) \
{ \
while (*inbytesleft >= 2 && *outbytesleft >= 1) { \
@@ -97,7 +97,7 @@ static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft,
return 0; \
} \
\
-static size_t CHARSETNAME ## _pull(void *cd, char **inbuf, size_t *inbytesleft, \
+static size_t CHARSETNAME ## _pull(void *cd, const char **inbuf, size_t *inbytesleft, \
char **outbuf, size_t *outbytesleft) \
{ \
while (*inbytesleft >= 1 && *outbytesleft >= 2) { \
@@ -124,4 +124,3 @@ NTSTATUS charset_ ## CHARSETNAME ## _init(void) \
return smb_register_charset(& CHARSETNAME ## _functions); \
} \
-
diff --git a/source/include/fake_file.h b/source/include/fake_file.h
index cfcd16f6830..63ba41d7860 100644
--- a/source/include/fake_file.h
+++ b/source/include/fake_file.h
@@ -28,9 +28,9 @@ enum FAKE_FILE_TYPE {
/*
we now get the unix name --metze
-#define FAKE_FILE_NAME_QUOTA "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"
*/
-#define FAKE_FILE_NAME_QUOTA "$Extend/$Quota:$Q:$INDEX_ALLOCATION"
+#define FAKE_FILE_NAME_QUOTA_WIN32 "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"
+#define FAKE_FILE_NAME_QUOTA_UNIX "$Extend/$Quota:$Q:$INDEX_ALLOCATION"
typedef struct _FAKE_FILE_HANDLE {
enum FAKE_FILE_TYPE type;
diff --git a/source/include/hash.h b/source/include/hash.h
deleted file mode 100644
index 40cc8b7cab3..00000000000
--- a/source/include/hash.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Ying Chen 2000.
-
- 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.
-*/
-
-#ifndef _HASH_H_
-#define _HASH_H_
-
-#define MAX_HASH_TABLE_SIZE 16384
-#define HASH_TABLE_INCREMENT 2
-
-typedef int (*compare_function)(char *, char *);
-typedef int (*hash_function)(int, char *);
-
-/*
- * lru_link: links the node to the LRU list.
- * hash_elem: the pointer to the element that is tied onto the link.
- */
-typedef struct lru_node {
- ubi_dlNode lru_link;
- void *hash_elem;
-} lru_node;
-
-/*
- * bucket_link: link the hash element to the bucket chain that it belongs to.
- * lru_link: this element ties the hash element to the lru list.
- * bucket: a pointer to the hash bucket that this element belongs to.
- * value: a pointer to the hash element content. It can be anything.
- * key: stores the string key. The hash_element is always allocated with
- * more memory space than the structure shown below to accomodate the space
- * used for the whole string. But the memory is always appended at the
- * end of the structure, so keep "key" at the end of the structure.
- * Don't move it.
- */
-typedef struct hash_element {
- ubi_dlNode bucket_link;
- lru_node lru_link;
- ubi_dlList *bucket;
- void *value;
- char key[1];
-} hash_element;
-
-/*
- * buckets: a list of buckets, implemented as a dLinkList.
- * lru_chain: the lru list of all the hash elements.
- * num_elements: the # of elements in the hash table.
- * size: the hash table size.
- * comp_func: the compare function used during hash key comparisons.
- */
-
-typedef struct hash_table {
- ubi_dlList *buckets;
- ubi_dlList lru_chain;
- unsigned num_elements;
- unsigned size;
- compare_function comp_func;
-} hash_table;
-
-#endif /* _HASH_H_ */
diff --git a/source/include/includes.h b/source/include/includes.h
index 1d913d3f32a..3ea4eaa35a9 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -45,10 +45,11 @@
#undef HAVE_TERMIOS_H
#endif
-#ifdef __GNUC__
+#if (__GNUC__ >= 3)
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
- * argument. **/
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
@@ -309,6 +310,19 @@
#endif
#ifdef HAVE_SHADOW_H
+/*
+ * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
+ * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
+ * them again without checking if they already exsist. This generates
+ * two "Redefinition of macro" warnings for every single .c file that is
+ * compiled.
+ */
+#if defined(HPUX) && defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(HPUX) && defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
#include <shadow.h>
#endif
@@ -361,6 +375,19 @@
#if defined(HAVE_SYS_SECURITY_H) && defined(HAVE_RPC_AUTH_ERROR_CONFLICT)
#undef AUTH_ERROR
#endif
+/*
+ * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
+ * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
+ * them again without checking if they already exsist. This generates
+ * two "Redefinition of macro" warnings for every single .c file that is
+ * compiled.
+ */
+#if defined(HPUX) && defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(HPUX) && defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
#include <rpc/rpc.h>
#endif
@@ -369,12 +396,25 @@
#endif
#if defined (HAVE_NETGROUP)
-#if defined(HAVE_RPCSVC_YPCLNT_H)
-#include <rpcsvc/ypclnt.h>
-#endif
#if defined(HAVE_RPCSVC_YP_PROT_H)
+/*
+ * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
+ * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
+ * them again without checking if they already exsist. This generates
+ * two "Redefinition of macro" warnings for every single .c file that is
+ * compiled.
+ */
+#if defined(HPUX) && defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(HPUX) && defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
#include <rpcsvc/yp_prot.h>
#endif
+#if defined(HAVE_RPCSVC_YPCLNT_H)
+#include <rpcsvc/ypclnt.h>
+#endif
#endif /* HAVE_NETGROUP */
#if defined(HAVE_SYS_IPC_H)
@@ -760,7 +800,6 @@ extern int errno;
#include "nt_status.h"
#include "ads.h"
#include "interfaces.h"
-#include "hash.h"
#include "trans2.h"
#include "nterr.h"
#include "ntioctl.h"
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index cf7d1ba3412..f2b78f91bc0 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -1026,6 +1026,7 @@ typedef struct printer_info_ctr_info
PRINTER_INFO_3 *printers_3;
PRINTER_INFO_4 *printers_4;
PRINTER_INFO_5 *printers_5;
+ PRINTER_INFO_7 *printers_7;
}
PRINTER_INFO_CTR;
diff --git a/source/include/smb.h b/source/include/smb.h
index 32dba0cf78f..7317fd16b0f 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1658,11 +1658,11 @@ struct unix_error_map {
/* generic iconv conversion structure */
typedef struct {
- size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
+ size_t (*direct)(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
- size_t (*pull)(void *cd, char **inbuf, size_t *inbytesleft,
+ size_t (*pull)(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
- size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft,
+ size_t (*push)(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
void *cd_direct, *cd_pull, *cd_push;
char *from_name, *to_name;
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index bcbaa64f863..a9e911c066a 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -26,7 +26,6 @@
/* Misc bit macros */
#define BOOLSTR(b) ((b) ? "Yes" : "No")
-#define BITSETB(ptr,bit) ((((char *)ptr)[0] & (1<<(bit)))!=0)
#define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0)
/* for readability... */
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index 953937fb75d..58502ec34e7 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -107,7 +107,9 @@ typedef struct _attrib_map_entry {
/* structures */
extern ATTRIB_MAP_ENTRY attrib_map_v22[];
+extern ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[];
extern ATTRIB_MAP_ENTRY attrib_map_v30[];
+extern ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[];
extern ATTRIB_MAP_ENTRY dominfo_attr_list[];
extern ATTRIB_MAP_ENTRY groupmap_attr_list[];
extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[];
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 6cbf7562b06..40004826b4a 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -56,7 +56,7 @@ static const char *charset_name(charset_t ch)
{
const char *ret = NULL;
- if (ch == CH_UCS2) ret = "UCS-2LE";
+ if (ch == CH_UCS2) ret = "UTF-16LE";
else if (ch == CH_UNIX) ret = lp_unix_charset();
else if (ch == CH_DOS) ret = lp_dos_charset();
else if (ch == CH_DISPLAY) ret = lp_display_charset();
@@ -116,10 +116,10 @@ void init_iconv(void)
/* so that charset_name() works we need to get the UNIX<->UCS2 going
first */
if (!conv_handles[CH_UNIX][CH_UCS2])
- conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
+ conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII");
if (!conv_handles[CH_UCS2][CH_UNIX])
- conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
+ conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2));
for (c1=0;c1<NUM_CHARSETS;c1++) {
for (c2=0;c2<NUM_CHARSETS;c2++) {
@@ -216,7 +216,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
again:
- retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len);
+ retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
if(retval==(size_t)-1) {
const char *reason="unknown error";
switch(errno) {
@@ -229,14 +229,18 @@ static size_t convert_string_internal(charset_t from, charset_t to,
break;
case E2BIG:
reason="No more room";
- if (!conv_silent)
- DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n",
- (unsigned long)srclen, (unsigned long)destlen));
- /* we are not sure we need srclen bytes,
- may be more, may be less.
- We only know we need more than destlen
- bytes ---simo */
- break;
+ if (!conv_silent) {
+ if (from == CH_UNIX) {
+ DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
+ charset_name(from), charset_name(to),
+ (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
+ } else {
+ DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
+ charset_name(from), charset_name(to),
+ (unsigned int)srclen, (unsigned int)destlen));
+ }
+ }
+ break;
case EILSEQ:
reason="Illegal multibyte sequence";
if (!conv_silent)
@@ -531,7 +535,7 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
again:
retval = smb_iconv(descriptor,
- (char **)&inbuf, &i_len,
+ &inbuf, &i_len,
&outbuf, &o_len);
if(retval == (size_t)-1) {
const char *reason="unknown error";
diff --git a/source/lib/hash.c b/source/lib/hash.c
deleted file mode 100644
index 18b6534dec2..00000000000
--- a/source/lib/hash.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Ying Chen 2000.
- Copyright (C) Jeremy Allison 2000.
- - added some defensive programming.
-
- 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.
-*/
-
-/*
- * NB. We may end up replacing this functionality in a future 2.x
- * release to reduce the number of hashing/lookup methods we support. JRA.
- */
-
-#include "includes.h"
-
-static BOOL enlarge_hash_table(hash_table *table);
-static unsigned primes[] =
- {17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411};
-
-/****************************************************************************
- * This function initializes the hash table.
- * This hash function hashes on string keys.
- * This number of hash buckets is always rounded up to a power of
- * 2 first, then to a prime number that is large than the power of two.
- * Input:
- * table -- the hash table pointer.
- * num_buckets -- the number of buckets to be allocated. This
- * hash function can dynamically increase its size when the
- * the hash table size becomes small. There is a MAX hash table
- * size defined in hash.h.
- * compare_func -- the function pointer to a comparison function
- * used by the hash key comparison.
- ****************************************************************************
- */
-
-BOOL hash_table_init(hash_table *table, unsigned num_buckets, compare_function compare_func)
-{
- unsigned i;
- ubi_dlList *bucket;
-
- table->num_elements = 0;
- table->size = 2;
- table->comp_func = compare_func;
- while (table->size < num_buckets)
- table->size <<= 1;
- for (i = 0; i < ARRAY_SIZE(primes); i++) {
- if (primes[i] > table->size) {
- table->size = primes[i];
- break;
- }
- }
-
- DEBUG(5, ("Hash size = %d.\n", table->size));
-
- if(!(table->buckets = (ubi_dlList *) malloc(sizeof(ubi_dlList) * table->size))) {
- DEBUG(0,("hash_table_init: malloc fail !\n"));
- return False;
- }
- ubi_dlInitList(&(table->lru_chain));
- for (i=0, bucket = table->buckets; i < table->size; i++, bucket++)
- ubi_dlInitList(bucket);
-
- return True;
-}
-
-/*
- **************************************************************
- * Compute a hash value based on a string key value.
- * Make the string key into an array of int's if possible.
- * For the last few chars that cannot be int'ed, use char instead.
- * The function returns the bucket index number for the hashed
- * key.
- * JRA. Use a djb-algorithm hash for speed.
- **************************************************************
- */
-
-static int string_hash(int hash_size, const char *key)
-{
- u32 n = 0;
- const char *p;
- for (p = key; *p != '\0'; p++) {
- n = ((n << 5) + n) ^ (u32)(*p);
- }
- return (n % hash_size);
-}
-
-/* *************************************************************************
- * Search the hash table for the entry in the hash chain.
- * The function returns the pointer to the
- * element found in the chain or NULL if none is found.
- * If the element is found, the element is also moved to
- * the head of the LRU list.
- *
- * Input:
- * table -- The hash table where the element is stored in.
- * hash_chain -- The pointer to the bucket that stores the
- * element to be found.
- * key -- The hash key to be found.
- ***************************************************************************
- */
-
-static hash_element *hash_chain_find(hash_table *table, ubi_dlList *hash_chain, char *key)
-{
- hash_element *hash_elem;
- ubi_dlNodePtr lru_item;
- unsigned int i = 0;
-
- for (hash_elem = (hash_element *)(ubi_dlFirst(hash_chain)); i < hash_chain->count;
- i++, hash_elem = (hash_element *)(ubi_dlNext(hash_elem))) {
- if ((table->comp_func)(hash_elem->key, key) == 0) {
- /* Move to the head of the lru List. */
- lru_item = ubi_dlRemove(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- ubi_dlAddHead(&(table->lru_chain), lru_item);
- return(hash_elem);
- }
- }
- return ((hash_element *) NULL);
-}
-
-/* ***************************************************************************
- *
- * Lookup a hash table for an element with key.
- * The function returns a pointer to the hash element.
- * If no element is found, the function returns NULL.
- *
- * Input:
- * table -- The hash table to be searched on.
- * key -- The key to be found.
- *****************************************************************************
- */
-
-hash_element *hash_lookup(hash_table *table, char *key)
-{
- return (hash_chain_find(table, &table->buckets[string_hash(table->size, key)], key));
-}
-
-/* ***************************************************************
- *
- * This function first checks if an element with key "key"
- * exists in the hash table. If so, the function moves the
- * element to the front of the LRU list. Otherwise, a new
- * hash element corresponding to "value" and "key" is allocated
- * and inserted into the hash table. The new elements are
- * always inserted in the LRU order to the LRU list as well.
- *
- * Input:
- * table -- The hash table to be inserted in.
- * value -- The content of the element to be inserted.
- * key -- The key of the new element to be inserted.
- *
- ****************************************************************
- */
-
-hash_element *hash_insert(hash_table *table, char *value, char *key)
-{
- hash_element *hash_elem;
- ubi_dlNodePtr lru_item;
- ubi_dlList *bucket;
- size_t string_length;
-
- /*
- * If the hash table size has not reached the MAX_HASH_TABLE_SIZE,
- * the hash table may be enlarged if the current hash table is full.
- * If the hash table size has reached the MAX_HASH_TABLE_SIZE,
- * use LRU to remove the oldest element from the hash table.
- */
-
- if ((table->num_elements >= table->size) &&
- (table->num_elements < MAX_HASH_TABLE_SIZE)) {
- if(!enlarge_hash_table(table))
- return (hash_element *)NULL;
- table->num_elements += 1;
- } else if (table->num_elements >= MAX_HASH_TABLE_SIZE) {
- /* Do an LRU replacement. */
- lru_item = ubi_dlLast(&(table->lru_chain));
- hash_elem = (hash_element *)(((lru_node *)lru_item)->hash_elem);
- bucket = hash_elem->bucket;
- ubi_dlRemThis(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- ubi_dlRemThis(bucket, (ubi_dlNodePtr)hash_elem);
- SAFE_FREE(hash_elem->value);
- SAFE_FREE(hash_elem);
- } else {
- table->num_elements += 1;
- }
-
- bucket = &table->buckets[string_hash(table->size, key)];
-
- /* Since we only have 1-byte for the key string, we need to
- * allocate extra space in the hash_element to store the entire key
- * string.
- */
-
- string_length = strlen(key);
- if(!(hash_elem = (hash_element *) malloc(sizeof(hash_element) + string_length))) {
- DEBUG(0,("hash_insert: malloc fail !\n"));
- return (hash_element *)NULL;
- }
-
- safe_strcpy((char *) hash_elem->key, key, string_length);
-
- hash_elem->value = (char *)value;
- hash_elem->bucket = bucket;
- /* Insert in front of the lru list and the bucket list. */
- ubi_dlAddHead(bucket, hash_elem);
- hash_elem->lru_link.hash_elem = hash_elem;
- ubi_dlAddHead(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
-
- return(hash_elem);
-}
-
-/* **************************************************************************
- *
- * Remove a hash element from the hash table. The hash element is
- * removed from both the LRU list and the hash bucket chain.
- *
- * Input:
- * table -- the hash table to be manipulated on.
- * hash_elem -- the element to be removed.
- **************************************************************************
- */
-
-void hash_remove(hash_table *table, hash_element *hash_elem)
-{
- if (hash_elem) {
- ubi_dlRemove(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- ubi_dlRemove(hash_elem->bucket, (ubi_dlNodePtr) hash_elem);
- SAFE_FREE(hash_elem->value);
- SAFE_FREE(hash_elem);
- table->num_elements--;
- }
-}
-
-/* ******************************************************************
- * Increase the hash table size if it is too small.
- * The hash table size is increased by the HASH_TABLE_INCREMENT
- * ratio.
- * Input:
- * table -- the hash table to be enlarged.
- ******************************************************************
- */
-
-static BOOL enlarge_hash_table(hash_table *table)
-{
- hash_element *hash_elem;
- int size, hash_value;
- ubi_dlList *buckets;
- ubi_dlList *old_bucket;
- ubi_dlList *bucket;
- ubi_dlList lru_chain;
-
- buckets = table->buckets;
- lru_chain = table->lru_chain;
- size = table->size;
-
- /* Reinitialize the hash table. */
- if(!hash_table_init(table, table->size * HASH_TABLE_INCREMENT, table->comp_func))
- return False;
-
- for (old_bucket = buckets; size > 0; size--, old_bucket++) {
- while (old_bucket->count != 0) {
- hash_elem = (hash_element *) ubi_dlRemHead(old_bucket);
- ubi_dlRemove(&lru_chain, &(hash_elem->lru_link.lru_link));
- hash_value = string_hash(table->size, (char *) hash_elem->key);
- bucket = &(table->buckets[hash_value]);
- ubi_dlAddHead(bucket, hash_elem);
- ubi_dlAddHead(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- hash_elem->bucket = bucket;
- hash_elem->lru_link.hash_elem = hash_elem;
- table->num_elements++;
- }
- }
- SAFE_FREE(buckets);
-
- return True;
-}
-
-/* **********************************************************************
- *
- * Remove everything from a hash table and free up the memory it
- * occupies.
- * Input:
- * table -- the hash table to be cleared.
- *
- *************************************************************************
- */
-
-void hash_clear(hash_table *table)
-{
- unsigned int i;
- ubi_dlList *bucket = table->buckets;
- hash_element *hash_elem;
- for (i = 0; i < table->size; bucket++, i++) {
- while (bucket->count != 0) {
- hash_elem = (hash_element *) ubi_dlRemHead(bucket);
- SAFE_FREE(hash_elem->value);
- SAFE_FREE(hash_elem);
- }
- }
- table->size = 0;
- SAFE_FREE(table->buckets);
- table->buckets = NULL;
-}
diff --git a/source/lib/iconv.c b/source/lib/iconv.c
index 4c9ecf992e6..66a6e6cd8bc 100644
--- a/source/lib/iconv.c
+++ b/source/lib/iconv.c
@@ -51,18 +51,26 @@
* @sa Samba Developers Guide
**/
-static size_t ascii_pull(void *,char **, size_t *, char **, size_t *);
-static size_t ascii_push(void *,char **, size_t *, char **, size_t *);
-static size_t latin1_push(void *,char **, size_t *, char **, size_t *);
-static size_t utf8_pull(void *,char **, size_t *, char **, size_t *);
-static size_t utf8_push(void *,char **, size_t *, char **, size_t *);
-static size_t ucs2hex_pull(void *,char **, size_t *, char **, size_t *);
-static size_t ucs2hex_push(void *,char **, size_t *, char **, size_t *);
-static size_t iconv_copy(void *,char **, size_t *, char **, size_t *);
+static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *);
+static size_t ascii_push(void *,const char **, size_t *, char **, size_t *);
+static size_t latin1_push(void *,const char **, size_t *, char **, size_t *);
+static size_t utf8_pull(void *,const char **, size_t *, char **, size_t *);
+static size_t utf8_push(void *,const char **, size_t *, char **, size_t *);
+static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *);
+static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *);
+static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *);
+static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *);
static struct charset_functions builtin_functions[] = {
+ /* windows is really neither UCS-2 not UTF-16 */
{"UCS-2LE", iconv_copy, iconv_copy},
+ {"UTF-16LE", iconv_copy, iconv_copy},
+ {"UCS-2BE", iconv_swab, iconv_swab},
+ {"UTF-16BE", iconv_swab, iconv_swab},
+
+ /* we include the UTF-8 alias to cope with differing locale settings */
{"UTF8", utf8_pull, utf8_push},
+ {"UTF-8", utf8_pull, utf8_push},
{"ASCII", ascii_pull, ascii_push},
{"646", ascii_pull, ascii_push},
{"ISO-8859-1", ascii_pull, latin1_push},
@@ -122,12 +130,12 @@ static void lazy_initialize_iconv(void)
this ensures that we don't have a shift state remaining for
character sets like SJIS */
static size_t sys_iconv(void *cd,
- char **inbuf, size_t *inbytesleft,
+ const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
#ifdef HAVE_NATIVE_ICONV
size_t ret = iconv((iconv_t)cd,
- inbuf, inbytesleft,
+ (char **)inbuf, inbytesleft,
outbuf, outbytesleft);
if (ret == (size_t)-1) {
int saved_errno = errno;
@@ -148,7 +156,7 @@ static size_t sys_iconv(void *cd,
* enough that Samba works on systems that don't have iconv.
**/
size_t smb_iconv(smb_iconv_t cd,
- char **inbuf, size_t *inbytesleft,
+ const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
char cvtbuf[2048];
@@ -158,7 +166,7 @@ size_t smb_iconv(smb_iconv_t cd,
/* in many cases we can go direct */
if (cd->direct) {
return cd->direct(cd->cd_direct,
- (char **)inbuf, inbytesleft, outbuf, outbytesleft);
+ inbuf, inbytesleft, outbuf, outbytesleft);
}
@@ -168,20 +176,27 @@ size_t smb_iconv(smb_iconv_t cd,
bufsize = sizeof(cvtbuf);
if (cd->pull(cd->cd_pull,
- (char **)inbuf, inbytesleft, &bufp, &bufsize) == -1
+ inbuf, inbytesleft, &bufp, &bufsize) == -1
&& errno != E2BIG) return -1;
bufp = cvtbuf;
bufsize = sizeof(cvtbuf) - bufsize;
if (cd->push(cd->cd_push,
- &bufp, &bufsize,
+ (const char **)&bufp, &bufsize,
outbuf, outbytesleft) == -1) return -1;
}
return 0;
}
+
+static BOOL is_utf16(const char *name)
+{
+ return strcasecmp(name, "UCS-2LE") == 0 ||
+ strcasecmp(name, "UTF-16LE") == 0;
+}
+
/*
simple iconv_open() wrapper
*/
@@ -220,13 +235,17 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
/* check if we can use iconv for this conversion */
#ifdef HAVE_NATIVE_ICONV
if (!ret->pull) {
- ret->cd_pull = iconv_open("UCS-2LE", fromcode);
+ ret->cd_pull = iconv_open("UTF-16LE", fromcode);
+ if (ret->cd_pull == (iconv_t)-1)
+ ret->cd_pull = iconv_open("UCS-2LE", fromcode);
if (ret->cd_pull != (iconv_t)-1)
ret->pull = sys_iconv;
}
if (!ret->push) {
- ret->cd_push = iconv_open(tocode, "UCS-2LE");
+ ret->cd_push = iconv_open(tocode, "UTF-16LE");
+ if (ret->cd_push == (iconv_t)-1)
+ ret->cd_push = iconv_open(tocode, "UCS-2LE");
if (ret->cd_push != (iconv_t)-1)
ret->push = sys_iconv;
}
@@ -256,13 +275,13 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
}
/* check for conversion to/from ucs2 */
- if (strcasecmp(fromcode, "UCS-2LE") == 0 && to) {
+ if (is_utf16(fromcode) && to) {
ret->direct = to->push;
ret->push = ret->pull = NULL;
return ret;
}
- if (strcasecmp(tocode, "UCS-2LE") == 0 && from) {
+ if (is_utf16(tocode) && from) {
ret->direct = from->pull;
ret->push = ret->pull = NULL;
return ret;
@@ -270,13 +289,13 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
/* Check if we can do the conversion direct */
#ifdef HAVE_NATIVE_ICONV
- if (strcasecmp(fromcode, "UCS-2LE") == 0) {
+ if (is_utf16(fromcode)) {
ret->direct = sys_iconv;
ret->cd_direct = ret->cd_push;
ret->cd_push = NULL;
return ret;
}
- if (strcasecmp(tocode, "UCS-2LE") == 0) {
+ if (is_utf16(tocode)) {
ret->direct = sys_iconv;
ret->cd_direct = ret->cd_pull;
ret->cd_pull = NULL;
@@ -313,7 +332,7 @@ int smb_iconv_close (smb_iconv_t cd)
multi-byte character set support for english users
***********************************************************************/
-static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 1 && *outbytesleft >= 2) {
@@ -333,7 +352,7 @@ static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int ir_count=0;
@@ -360,7 +379,7 @@ static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft,
return ir_count;
}
-static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int ir_count=0;
@@ -387,7 +406,7 @@ static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft,
return ir_count;
}
-static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 1 && *outbytesleft >= 2) {
@@ -430,7 +449,7 @@ static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 2 && *outbytesleft >= 1) {
@@ -471,8 +490,32 @@ static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
+static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft,
+ char **outbuf, size_t *outbytesleft)
+{
+ int n;
+
+ n = MIN(*inbytesleft, *outbytesleft);
+
+ swab(*inbuf, *outbuf, (n&~1));
+ if (n&1) {
+ (*outbuf)[n-1] = 0;
+ }
+
+ (*inbytesleft) -= n;
+ (*outbytesleft) -= n;
+ (*inbuf) += n;
+ (*outbuf) += n;
+
+ if (*inbytesleft > 0) {
+ errno = E2BIG;
+ return -1;
+ }
-static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft,
+ return 0;
+}
+
+static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int n;
@@ -494,102 +537,234 @@ static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t utf8_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
- while (*inbytesleft >= 1 && *outbytesleft >= 2) {
- unsigned char *c = (unsigned char *)*inbuf;
- unsigned char *uc = (unsigned char *)*outbuf;
- int len = 1;
+ size_t in_left=*inbytesleft, out_left=*outbytesleft;
+ const uint8 *c = (const uint8 *)*inbuf;
+ uint8 *uc = (uint8 *)*outbuf;
+ while (in_left >= 1 && out_left >= 2) {
if ((c[0] & 0x80) == 0) {
uc[0] = c[0];
uc[1] = 0;
- } else if ((c[0] & 0xf0) == 0xe0) {
- if (*inbytesleft < 3) {
- DEBUG(0,("short utf8 char\n"));
- goto badseq;
+ c += 1;
+ in_left -= 1;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ if ((c[0] & 0xe0) == 0xc0) {
+ if (in_left < 2 ||
+ (c[1] & 0xc0) != 0x80) {
+ errno = EILSEQ;
+ goto error;
+ }
+ uc[1] = (c[0]>>2) & 0x7;
+ uc[0] = (c[0]<<6) | (c[1]&0x3f);
+ c += 2;
+ in_left -= 2;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ if ((c[0] & 0xf0) == 0xe0) {
+ if (in_left < 3 ||
+ (c[1] & 0xc0) != 0x80 ||
+ (c[2] & 0xc0) != 0x80) {
+ errno = EILSEQ;
+ goto error;
}
uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF);
uc[0] = (c[1]<<6) | (c[2]&0x3f);
- len = 3;
- } else if ((c[0] & 0xe0) == 0xc0) {
- if (*inbytesleft < 2) {
- DEBUG(0,("short utf8 char\n"));
- goto badseq;
+ c += 3;
+ in_left -= 3;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ if ((c[0] & 0xf8) == 0xf0) {
+ unsigned int codepoint;
+ if (in_left < 4 ||
+ (c[1] & 0xc0) != 0x80 ||
+ (c[2] & 0xc0) != 0x80 ||
+ (c[3] & 0xc0) != 0x80) {
+ errno = EILSEQ;
+ goto error;
}
- uc[1] = (c[0]>>2) & 0x7;
- uc[0] = (c[0]<<6) | (c[1]&0x3f);
- len = 2;
+ codepoint =
+ (c[3]&0x3f) |
+ ((c[2]&0x3f)<<6) |
+ ((c[1]&0x3f)<<12) |
+ ((c[0]&0x7)<<18);
+ if (codepoint < 0x10000) {
+ /* accept UTF-8 characters that are not
+ minimally packed, but pack the result */
+ uc[0] = (codepoint & 0xFF);
+ uc[1] = (codepoint >> 8);
+ c += 4;
+ in_left -= 4;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ codepoint -= 0x10000;
+
+ if (out_left < 4) {
+ errno = E2BIG;
+ goto error;
+ }
+
+ uc[0] = (codepoint>>10) & 0xFF;
+ uc[1] = (codepoint>>18) | 0xd8;
+ uc[2] = codepoint & 0xFF;
+ uc[3] = ((codepoint>>8) & 0x3) | 0xdc;
+ c += 4;
+ in_left -= 4;
+ out_left -= 4;
+ uc += 4;
+ continue;
}
- (*inbuf) += len;
- (*inbytesleft) -= len;
- (*outbytesleft) -= 2;
- (*outbuf) += 2;
+ /* we don't handle 5 byte sequences */
+ errno = EINVAL;
+ goto error;
}
- if (*inbytesleft > 0) {
+ if (in_left > 0) {
errno = E2BIG;
- return -1;
+ goto error;
}
-
+
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = c;
+ *outbuf = uc;
return 0;
-badseq:
- errno = EINVAL;
+error:
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = c;
+ *outbuf = uc;
return -1;
}
-static size_t utf8_push(void *cd, char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft)
+static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft,
+ char **outbuf, size_t *outbytesleft)
{
- while (*inbytesleft >= 2 && *outbytesleft >= 1) {
- unsigned char *c = (unsigned char *)*outbuf;
- unsigned char *uc = (unsigned char *)*inbuf;
- int len=1;
-
- if (uc[1] & 0xf8) {
- if (*outbytesleft < 3) {
- DEBUG(0,("short utf8 write\n"));
- goto toobig;
+ size_t in_left=*inbytesleft, out_left=*outbytesleft;
+ uint8 *c = (uint8 *)*outbuf;
+ const uint8 *uc = (const uint8 *)*inbuf;
+
+ while (in_left >= 2 && out_left >= 1) {
+ unsigned int codepoint;
+
+ if (uc[1] == 0 && !(uc[0] & 0x80)) {
+ /* simplest case */
+ c[0] = uc[0];
+ in_left -= 2;
+ out_left -= 1;
+ uc += 2;
+ c += 1;
+ continue;
+ }
+
+ if ((uc[1]&0xf8) == 0) {
+ /* next simplest case */
+ if (out_left < 2) {
+ errno = E2BIG;
+ goto error;
}
- c[0] = 0xe0 | (uc[1]>>4);
- c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6);
- c[2] = 0x80 | (uc[0]&0x3f);
- len = 3;
- } else if (uc[1] | (uc[0] & 0x80)) {
- if (*outbytesleft < 2) {
- DEBUG(0,("short utf8 write\n"));
- goto toobig;
+ c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2);
+ c[1] = 0x80 | (uc[0] & 0x3f);
+ in_left -= 2;
+ out_left -= 2;
+ uc += 2;
+ c += 2;
+ continue;
+ }
+
+ if ((uc[1] & 0xfc) == 0xdc) {
+ /* its the second part of a 4 byte sequence. Illegal */
+ if (in_left < 4) {
+ errno = EINVAL;
+ } else {
+ errno = EILSEQ;
}
- c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6);
- c[1] = 0x80 | (uc[0]&0x3f);
- len = 2;
- } else {
- c[0] = uc[0];
+ goto error;
}
+ if ((uc[1] & 0xfc) != 0xd8) {
+ codepoint = uc[0] | (uc[1]<<8);
+ if (out_left < 3) {
+ errno = E2BIG;
+ goto error;
+ }
+ c[0] = 0xe0 | (codepoint >> 12);
+ c[1] = 0x80 | ((codepoint >> 6) & 0x3f);
+ c[2] = 0x80 | (codepoint & 0x3f);
+
+ in_left -= 2;
+ out_left -= 3;
+ uc += 2;
+ c += 3;
+ continue;
+ }
- (*inbytesleft) -= 2;
- (*outbytesleft) -= len;
- (*inbuf) += 2;
- (*outbuf) += len;
+ /* its the first part of a 4 byte sequence */
+ if (in_left < 4) {
+ errno = EINVAL;
+ goto error;
+ }
+ if ((uc[3] & 0xfc) != 0xdc) {
+ errno = EILSEQ;
+ goto error;
+ }
+ codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) |
+ (uc[0]<<10) | ((uc[1] & 0x3)<<18));
+
+ if (out_left < 4) {
+ errno = E2BIG;
+ goto error;
+ }
+ c[0] = 0xf0 | (codepoint >> 18);
+ c[1] = 0x80 | ((codepoint >> 12) & 0x3f);
+ c[2] = 0x80 | ((codepoint >> 6) & 0x3f);
+ c[3] = 0x80 | (codepoint & 0x3f);
+
+ in_left -= 4;
+ out_left -= 4;
+ uc += 4;
+ c += 4;
}
- if (*inbytesleft == 1) {
+ if (in_left == 1) {
errno = EINVAL;
- return -1;
+ goto error;
}
- if (*inbytesleft > 1) {
+ if (in_left > 1) {
errno = E2BIG;
- return -1;
+ goto error;
}
+
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = uc;
+ *outbuf = c;
return 0;
-toobig:
- errno = E2BIG;
+error:
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = uc;
+ *outbuf = c;
return -1;
}
+
diff --git a/source/lib/ms_fnmatch.c b/source/lib/ms_fnmatch.c
index 24232c3b523..42c91bd18df 100644
--- a/source/lib/ms_fnmatch.c
+++ b/source/lib/ms_fnmatch.c
@@ -179,6 +179,9 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string,
break;
case UCS2_CHAR('*'):
+ while (*p == UCS2_CHAR('*')) {
+ p++;
+ }
for (; *n; n++) {
if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
}
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index e66fb3640cf..57aab70a5ba 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -66,6 +66,29 @@ ATTRIB_MAP_ENTRY attrib_map_v22[] = {
{ LDAP_ATTR_DOMAIN, "domain" },
{ LDAP_ATTR_OBJCLASS, "objectClass" },
{ LDAP_ATTR_ACB_INFO, "acctFlags" },
+ { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" },
+ { LDAP_ATTR_LIST_END, NULL }
+};
+
+ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[] = {
+ { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" },
+ { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" },
+ { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" },
+ { LDAP_ATTR_LOGON_TIME, "logonTime" },
+ { LDAP_ATTR_LOGOFF_TIME, "logoffTime" },
+ { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" },
+ { LDAP_ATTR_DISPLAY_NAME, "displayName" },
+ { LDAP_ATTR_HOME_PATH, "smbHome" },
+ { LDAP_ATTR_HOME_DRIVE, "homeDrives" },
+ { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" },
+ { LDAP_ATTR_PROFILE_PATH, "profilePath" },
+ { LDAP_ATTR_USER_WKS, "userWorkstations"},
+ { LDAP_ATTR_USER_RID, "rid" },
+ { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"},
+ { LDAP_ATTR_LMPW, "lmPassword" },
+ { LDAP_ATTR_NTPW, "ntPassword" },
+ { LDAP_ATTR_DOMAIN, "domain" },
+ { LDAP_ATTR_ACB_INFO, "acctFlags" },
{ LDAP_ATTR_LIST_END, NULL }
};
@@ -106,6 +129,32 @@ ATTRIB_MAP_ENTRY attrib_map_v30[] = {
{ LDAP_ATTR_LIST_END, NULL }
};
+ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[] = {
+ { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" },
+ { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" },
+ { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" },
+ { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" },
+ { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" },
+ { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" },
+ { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" },
+ { LDAP_ATTR_HOME_PATH, "sambaHomePath" },
+ { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" },
+ { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" },
+ { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" },
+ { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID },
+ { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" },
+ { LDAP_ATTR_LMPW, "sambaLMPassword" },
+ { LDAP_ATTR_NTPW, "sambaNTPassword" },
+ { LDAP_ATTR_DOMAIN, "sambaDomainName" },
+ { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" },
+ { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" },
+ { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
+ { LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" },
+ { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" },
+ { LDAP_ATTR_LOGON_HOURS, "sambaLogonHours" },
+ { LDAP_ATTR_LIST_END, NULL }
+};
+
/* attributes used for allocating RIDs */
ATTRIB_MAP_ENTRY dominfo_attr_list[] = {
@@ -428,6 +477,12 @@ static BOOL fetch_ldap_pw(char **dn, char** pw)
char oldval[2048]; /* current largest allowed value is mungeddial */
BOOL existed;
+ if (attribute == NULL) {
+ /* This can actually happen for ldapsam_compat where we for
+ * example don't have a password history */
+ return;
+ }
+
if (existing != NULL) {
existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
} else {
diff --git a/source/lib/smbrun.c b/source/lib/smbrun.c
index 592543bc43b..43cb209174e 100644
--- a/source/lib/smbrun.c
+++ b/source/lib/smbrun.c
@@ -90,7 +90,7 @@ int smbrun(char *cmd, int *outfd)
*outfd = -1;
}
return errno;
- }
+ }
if (pid) {
/*
@@ -178,3 +178,124 @@ int smbrun(char *cmd, int *outfd)
exit(82);
return 1;
}
+
+
+/****************************************************************************
+run a command being careful about uid/gid handling and putting the output in
+outfd (or discard it if outfd is NULL).
+sends the provided secret to the child stdin.
+****************************************************************************/
+
+int smbrunsecret(char *cmd, char *secret)
+{
+ pid_t pid;
+ uid_t uid = current_user.uid;
+ gid_t gid = current_user.gid;
+ int ifd[2];
+
+ /*
+ * Lose any kernel oplock capabilities we may have.
+ */
+ oplock_set_capability(False, False);
+
+ /* build up an input pipe */
+ if(pipe(ifd)) {
+ return -1;
+ }
+
+ /* in this method we will exec /bin/sh with the correct
+ arguments, after first setting stdout to point at the file */
+
+ /*
+ * We need to temporarily stop CatchChild from eating
+ * SIGCLD signals as it also eats the exit status code. JRA.
+ */
+
+ CatchChildLeaveStatus();
+
+ if ((pid=sys_fork()) < 0) {
+ DEBUG(0, ("smbrunsecret: fork failed with error %s\n", strerror(errno)));
+ CatchChild();
+ return errno;
+ }
+
+ if (pid) {
+ /*
+ * Parent.
+ */
+ int status = 0;
+ pid_t wpid;
+
+ close(ifd[0]);
+ /* send the secret */
+ write(ifd[1], secret, strlen(secret));
+ fsync(ifd[1]);
+ close(ifd[1]);
+
+ /* the parent just waits for the child to exit */
+ while((wpid = sys_waitpid(pid, &status, 0)) < 0) {
+ if(errno == EINTR) {
+ errno = 0;
+ continue;
+ }
+ break;
+ }
+
+ CatchChild();
+
+ if (wpid != pid) {
+ DEBUG(2, ("waitpid(%d) : %s\n", (int)pid, strerror(errno)));
+ return -1;
+ }
+
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+ if (WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ }
+#endif
+
+ return status;
+ }
+
+ CatchChild();
+
+ /* we are in the child. we exec /bin/sh to do the work for us. we
+ don't directly exec the command we want because it may be a
+ pipeline or anything else the config file specifies */
+
+ close(ifd[1]);
+ close(0);
+ if (sys_dup2(ifd[0], 0) != 0) {
+ DEBUG(2,("Failed to create stdin file descriptor\n"));
+ close(ifd[0]);
+ exit(80);
+ }
+
+ /* now completely lose our privileges. This is a fairly paranoid
+ way of doing it, but it does work on all systems that I know of */
+
+ become_user_permanently(uid, gid);
+
+ if (getuid() != uid || geteuid() != uid ||
+ getgid() != gid || getegid() != gid) {
+ /* we failed to lose our privileges - do not execute
+ the command */
+ exit(81); /* we can't print stuff at this stage,
+ instead use exit codes for debugging */
+ }
+
+#ifndef __INSURE__
+ /* close all other file descriptors, leaving only 0, 1 and 2. 0 and
+ 2 point to /dev/null from the startup code */
+ {
+ int fd;
+ for (fd = 3; fd < 256; fd++) close(fd);
+ }
+#endif
+
+ execl("/bin/sh", "sh", "-c", cmd, NULL);
+
+ /* not reached */
+ exit(82);
+ return 1;
+}
diff --git a/source/lib/util.c b/source/lib/util.c
index 8d01d9e7c9c..a456395cad1 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -1491,14 +1491,13 @@ BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensit
pstring last_component;
char *p;
- DEBUG(8, ("is_in_path: %s\n", name));
-
/* if we have no list it's obviously not in the path */
if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
- DEBUG(8,("is_in_path: no name list.\n"));
return False;
}
+ DEBUG(8, ("is_in_path: %s\n", name));
+
/* Get the last component of the unix name. */
p = strrchr_m(name, '/');
strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
diff --git a/source/lib/util_file.c b/source/lib/util_file.c
index bd505ac921c..303d961df57 100644
--- a/source/lib/util_file.c
+++ b/source/lib/util_file.c
@@ -24,7 +24,6 @@
#define MAP_FAILED ((void *)-1)
#endif
-
static int gotalarm;
/***************************************************************
@@ -33,7 +32,7 @@ static int gotalarm;
static void gotalarm_sig(void)
{
- gotalarm = 1;
+ gotalarm = 1;
}
/***************************************************************
@@ -43,34 +42,33 @@ static void gotalarm_sig(void)
BOOL do_file_lock(int fd, int waitsecs, int type)
{
- SMB_STRUCT_FLOCK lock;
- int ret;
- void (*oldsig_handler)(int);
-
- gotalarm = 0;
- oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
-
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 1;
- lock.l_pid = 0;
-
- alarm(waitsecs);
- /* Note we must *NOT* use sys_fcntl here ! JRA */
- ret = fcntl(fd, SMB_F_SETLKW, &lock);
- alarm(0);
- CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
-
- if (gotalarm) {
- DEBUG(0, ("do_file_lock: failed to %s file.\n",
- type == F_UNLCK ? "unlock" : "lock"));
- return False;
- }
-
- return (ret == 0);
-}
+ SMB_STRUCT_FLOCK lock;
+ int ret;
+ void (*oldsig_handler)(int);
+
+ gotalarm = 0;
+ oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+
+ lock.l_type = type;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ lock.l_pid = 0;
+
+ alarm(waitsecs);
+ /* Note we must *NOT* use sys_fcntl here ! JRA */
+ ret = fcntl(fd, SMB_F_SETLKW, &lock);
+ alarm(0);
+ CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
+
+ if (gotalarm) {
+ DEBUG(0, ("do_file_lock: failed to %s file.\n",
+ type == F_UNLCK ? "unlock" : "lock"));
+ return False;
+ }
+ return (ret == 0);
+}
/***************************************************************
Lock an fd. Abandon after waitsecs seconds.
@@ -78,21 +76,19 @@ BOOL do_file_lock(int fd, int waitsecs, int type)
BOOL file_lock(int fd, int type, int secs, int *plock_depth)
{
- if (fd < 0)
- return False;
+ if (fd < 0)
+ return False;
- (*plock_depth)++;
+ (*plock_depth)++;
- if ((*plock_depth) == 0)
- {
- if (!do_file_lock(fd, secs, type)) {
- DEBUG(10,("file_lock: locking file failed, error = %s.\n",
- strerror(errno)));
- return False;
- }
- }
+ if ((*plock_depth) == 0) {
+ if (!do_file_lock(fd, secs, type)) {
+ DEBUG(10,("file_lock: locking file failed, error = %s.\n", strerror(errno)));
+ return False;
+ }
+ }
- return True;
+ return True;
}
/***************************************************************
@@ -101,105 +97,107 @@ BOOL file_lock(int fd, int type, int secs, int *plock_depth)
BOOL file_unlock(int fd, int *plock_depth)
{
- BOOL ret=True;
+ BOOL ret=True;
- if(*plock_depth == 1)
- ret = do_file_lock(fd, 5, F_UNLCK);
+ if(*plock_depth == 1) {
+ ret = do_file_lock(fd, 5, F_UNLCK);
+ }
- (*plock_depth)--;
+ (*plock_depth)--;
- if(!ret)
- DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n",
- strerror(errno)));
- return ret;
+ if(!ret) {
+ DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", strerror(errno)));
+ }
+ return ret;
}
/***************************************************************
- locks a file for enumeration / modification.
+ Locks a file for enumeration / modification.
update to be set = True if modification is required.
****************************************************************/
void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
int *file_lock_depth, BOOL update)
{
- FILE *fp = NULL;
+ FILE *fp = NULL;
- if (!*pfile)
- {
- DEBUG(0, ("startfilepwent: No file set\n"));
- return (NULL);
- }
- DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
+ if (!*pfile) {
+ DEBUG(0, ("startfilepwent: No file set\n"));
+ return (NULL);
+ }
+ DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
- fp = sys_fopen(pfile, update ? "r+b" : "rb");
+ fp = sys_fopen(pfile, update ? "r+b" : "rb");
- if (fp == NULL) {
- DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
- return NULL;
- }
+ if (fp == NULL) {
+ DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
+ return NULL;
+ }
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, s_readbuf, _IOFBF, bufsize);
+ /* Set a buffer to do more efficient reads */
+ setvbuf(fp, s_readbuf, _IOFBF, bufsize);
- if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
- {
- DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
- fclose(fp);
- return NULL;
- }
+ if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth)) {
+ DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
+ fclose(fp);
+ return NULL;
+ }
- /* Make sure it is only rw by the owner */
- chmod(pfile, 0600);
+ /* Make sure it is only rw by the owner */
+ chmod(pfile, 0600);
- /* We have a lock on the file. */
- return (void *)fp;
+ /* We have a lock on the file. */
+ return (void *)fp;
}
/***************************************************************
End enumeration of the file.
****************************************************************/
+
void endfilepwent(void *vp, int *file_lock_depth)
{
- FILE *fp = (FILE *)vp;
+ FILE *fp = (FILE *)vp;
- file_unlock(fileno(fp), file_lock_depth);
- fclose(fp);
- DEBUG(7, ("endfilepwent: closed file.\n"));
+ file_unlock(fileno(fp), file_lock_depth);
+ fclose(fp);
+ DEBUG(7, ("endfilepwent: closed file.\n"));
}
/*************************************************************************
Return the current position in the file list as an SMB_BIG_UINT.
This must be treated as an opaque token.
*************************************************************************/
+
SMB_BIG_UINT getfilepwpos(void *vp)
{
- return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
+ return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
}
/*************************************************************************
Set the current position in the file list from an SMB_BIG_UINT.
This must be treated as an opaque token.
*************************************************************************/
+
BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
{
- return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
+ return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
}
/*************************************************************************
- gets a line out of a file.
+ Gets a line out of a file.
line is of format "xxxx:xxxxxx:xxxxx:".
lines with "#" at the front are ignored.
*************************************************************************/
+
int getfileline(void *vp, char *linebuf, int linebuf_size)
{
/* Static buffers we will return. */
FILE *fp = (FILE *)vp;
unsigned char c;
unsigned char *p;
- size_t linebuf_len;
+ size_t linebuf_len;
- if (fp == NULL)
- {
+ if (fp == NULL) {
DEBUG(0,("getfileline: Bad file pointer.\n"));
return -1;
}
@@ -207,13 +205,11 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
/*
* Scan the file, a line at a time.
*/
- while (!feof(fp))
- {
+ while (!feof(fp)) {
linebuf[0] = '\0';
fgets(linebuf, linebuf_size, fp);
- if (ferror(fp))
- {
+ if (ferror(fp)) {
return -1;
}
@@ -223,47 +219,38 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
*/
linebuf_len = strlen(linebuf);
- if (linebuf_len == 0)
- {
+ if (linebuf_len == 0) {
linebuf[0] = '\0';
return 0;
}
- if (linebuf[linebuf_len - 1] != '\n')
- {
+ if (linebuf[linebuf_len - 1] != '\n') {
c = '\0';
- while (!ferror(fp) && !feof(fp))
- {
+ while (!ferror(fp) && !feof(fp)) {
c = fgetc(fp);
- if (c == '\n')
- {
+ if (c == '\n') {
break;
}
}
- }
- else
- {
+ } else {
linebuf[linebuf_len - 1] = '\0';
}
#ifdef DEBUG_PASSWORD
DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
#endif
- if ((linebuf[0] == 0) && feof(fp))
- {
+ if ((linebuf[0] == 0) && feof(fp)) {
DEBUG(4, ("getfileline: end of file reached\n"));
return 0;
}
- if (linebuf[0] == '#' || linebuf[0] == '\0')
- {
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
DEBUG(6, ("getfileline: skipping comment or blank line\n"));
continue;
}
p = (unsigned char *) strchr_m(linebuf, ':');
- if (p == NULL)
- {
+ if (p == NULL) {
DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
continue;
}
@@ -272,85 +259,89 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
return -1;
}
-
/****************************************************************************
-read a line from a file with possible \ continuation chars.
-Blanks at the start or end of a line are stripped.
-The string will be allocated if s2 is NULL
+ Read a line from a file with possible \ continuation chars.
+ Blanks at the start or end of a line are stripped.
+ The string will be allocated if s2 is NULL.
****************************************************************************/
+
char *fgets_slash(char *s2,int maxlen,XFILE *f)
{
- char *s=s2;
- int len = 0;
- int c;
- BOOL start_of_line = True;
-
- if (x_feof(f))
- return(NULL);
-
- if (maxlen <2) return(NULL);
-
- if (!s2)
- {
- maxlen = MIN(maxlen,8);
- s = (char *)malloc(maxlen);
- }
-
- if (!s) return(NULL);
-
- *s = 0;
-
- while (len < maxlen-1)
- {
- c = x_getc(f);
- switch (c)
- {
- case '\r':
- break;
- case '\n':
- while (len > 0 && s[len-1] == ' ')
- {
- s[--len] = 0;
- }
- if (len > 0 && s[len-1] == '\\')
- {
- s[--len] = 0;
- start_of_line = True;
- break;
- }
- return(s);
- case EOF:
- if (len <= 0 && !s2)
- SAFE_FREE(s);
- return(len>0?s:NULL);
- case ' ':
- if (start_of_line)
- break;
- default:
- start_of_line = False;
- s[len++] = c;
- s[len] = 0;
- }
- if (!s2 && len > maxlen-3)
- {
- char *t;
+ char *s=s2;
+ int len = 0;
+ int c;
+ BOOL start_of_line = True;
+
+ if (x_feof(f)) {
+ return(NULL);
+ }
+
+ if (maxlen <2) {
+ return(NULL);
+ }
+
+ if (!s2) {
+ maxlen = MIN(maxlen,8);
+ s = (char *)malloc(maxlen);
+ }
+
+ if (!s) {
+ return(NULL);
+ }
+
+ *s = 0;
+
+ while (len < maxlen-1) {
+ c = x_getc(f);
+ switch (c) {
+ case '\r':
+ break;
+ case '\n':
+ while (len > 0 && s[len-1] == ' ') {
+ s[--len] = 0;
+ }
+ if (len > 0 && s[len-1] == '\\') {
+ s[--len] = 0;
+ start_of_line = True;
+ break;
+ }
+ return(s);
+ case EOF:
+ if (len <= 0 && !s2) {
+ SAFE_FREE(s);
+ }
+ return(len>0?s:NULL);
+ case ' ':
+ if (start_of_line) {
+ break;
+ }
+ default:
+ start_of_line = False;
+ s[len++] = c;
+ s[len] = 0;
+ }
+
+ if (!s2 && len > maxlen-3) {
+ char *t;
- maxlen *= 2;
- t = (char *)Realloc(s,maxlen);
- if (!t) {
- DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
- SAFE_FREE(s);
- return(NULL);
- } else s = t;
- }
- }
- return(s);
+ maxlen *= 2;
+ t = (char *)Realloc(s,maxlen);
+ if (!t) {
+ DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
+ SAFE_FREE(s);
+ return(NULL);
+ } else {
+ s = t;
+ }
+ }
+ }
+ return(s);
}
-
/****************************************************************************
-load from a pipe into memory
+ Load from a pipe into memory.
****************************************************************************/
+
char *file_pload(char *syscmd, size_t *size)
{
int fd, n;
@@ -359,7 +350,9 @@ char *file_pload(char *syscmd, size_t *size)
size_t total;
fd = sys_popen(syscmd);
- if (fd == -1) return NULL;
+ if (fd == -1) {
+ return NULL;
+ }
p = NULL;
total = 0;
@@ -371,7 +364,9 @@ char *file_pload(char *syscmd, size_t *size)
close(fd);
SAFE_FREE(p);
return NULL;
- } else p = tp;
+ } else {
+ p = tp;
+ }
memcpy(p+total, buf, n);
total += n;
}
@@ -382,13 +377,15 @@ char *file_pload(char *syscmd, size_t *size)
* truncated. */
sys_pclose(fd);
- if (size) *size = total;
+ if (size) {
+ *size = total;
+ }
return p;
}
/****************************************************************************
-load a file into memory from a fd.
+ Load a file into memory from a fd.
****************************************************************************/
char *fd_load(int fd, size_t *size)
@@ -396,10 +393,14 @@ char *fd_load(int fd, size_t *size)
SMB_STRUCT_STAT sbuf;
char *p;
- if (sys_fstat(fd, &sbuf) != 0) return NULL;
+ if (sys_fstat(fd, &sbuf) != 0) {
+ return NULL;
+ }
p = (char *)malloc(sbuf.st_size+1);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
SAFE_FREE(p);
@@ -407,79 +408,85 @@ char *fd_load(int fd, size_t *size)
}
p[sbuf.st_size] = 0;
- if (size) *size = sbuf.st_size;
+ if (size) {
+ *size = sbuf.st_size;
+ }
return p;
}
/****************************************************************************
-load a file into memory
+ Load a file into memory.
****************************************************************************/
+
char *file_load(const char *fname, size_t *size)
{
int fd;
char *p;
- if (!fname || !*fname) return NULL;
+ if (!fname || !*fname) {
+ return NULL;
+ }
fd = open(fname,O_RDONLY);
- if (fd == -1) return NULL;
+ if (fd == -1) {
+ return NULL;
+ }
p = fd_load(fd, size);
-
close(fd);
-
return p;
}
-
/*******************************************************************
-mmap (if possible) or read a file
+ mmap (if possible) or read a file.
********************************************************************/
+
void *map_file(char *fname, size_t size)
{
size_t s2 = 0;
void *p = NULL;
#ifdef HAVE_MMAP
- if (lp_use_mmap()) {
- int fd;
- fd = open(fname, O_RDONLY, 0);
- if (fd == -1) {
- DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno)));
- return NULL;
- }
- p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
- close(fd);
- if (p == MAP_FAILED) {
- DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno)));
- return NULL;
- }
+ int fd;
+ fd = open(fname, O_RDONLY, 0);
+ if (fd == -1) {
+ DEBUG(2,("map_file: Failed to load %s - %s\n", fname, strerror(errno)));
+ return NULL;
+ }
+ p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
+ close(fd);
+ if (p == MAP_FAILED) {
+ DEBUG(1,("map_file: Failed to mmap %s - %s\n", fname, strerror(errno)));
+ return NULL;
}
#endif
if (!p) {
p = file_load(fname, &s2);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
if (s2 != size) {
- DEBUG(1,("incorrect size for %s - got %lu expected %lu\n",
+ DEBUG(1,("map_file: incorrect size for %s - got %lu expected %lu\n",
fname, (unsigned long)s2, (unsigned long)size));
- if (p) free(p);
+ SAFE_FREE(p);
return NULL;
}
}
-
return p;
}
-
/****************************************************************************
-parse a buffer into lines
+ Parse a buffer into lines.
****************************************************************************/
+
static char **file_lines_parse(char *p, size_t size, int *numlines)
{
int i;
char *s, **ret;
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
for (s = p, i=0; s < p+size; s++) {
if (s[0] == '\n') i++;
@@ -491,7 +498,9 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
return NULL;
}
memset(ret, 0, sizeof(ret[0])*(i+2));
- if (numlines) *numlines = i;
+ if (numlines) {
+ *numlines = i;
+ }
ret[0] = p;
for (s = p, i=0; s < p+size; s++) {
@@ -500,75 +509,87 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
i++;
ret[i] = s+1;
}
- if (s[0] == '\r') s[0] = 0;
+ if (s[0] == '\r') {
+ s[0] = 0;
+ }
}
return ret;
}
-
/****************************************************************************
-load a file into memory and return an array of pointers to lines in the file
-must be freed with file_lines_free().
+ Load a file into memory and return an array of pointers to lines in the file
+ must be freed with file_lines_free().
****************************************************************************/
+
char **file_lines_load(const char *fname, int *numlines)
{
char *p;
size_t size;
p = file_load(fname, &size);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
return file_lines_parse(p, size, numlines);
}
/****************************************************************************
-load a fd into memory and return an array of pointers to lines in the file
-must be freed with file_lines_free(). If convert is true calls unix_to_dos on
-the list.
+ Load a fd into memory and return an array of pointers to lines in the file
+ must be freed with file_lines_free(). If convert is true calls unix_to_dos on
+ the list.
****************************************************************************/
+
char **fd_lines_load(int fd, int *numlines)
{
char *p;
size_t size;
p = fd_load(fd, &size);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
return file_lines_parse(p, size, numlines);
}
-
/****************************************************************************
-load a pipe into memory and return an array of pointers to lines in the data
-must be freed with file_lines_free().
+ Load a pipe into memory and return an array of pointers to lines in the data
+ must be freed with file_lines_free().
****************************************************************************/
+
char **file_lines_pload(char *syscmd, int *numlines)
{
char *p;
size_t size;
p = file_pload(syscmd, &size);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
return file_lines_parse(p, size, numlines);
}
/****************************************************************************
-free lines loaded with file_lines_load
+ Free lines loaded with file_lines_load.
****************************************************************************/
+
void file_lines_free(char **lines)
{
- if (!lines) return;
+ if (!lines) {
+ return;
+ }
SAFE_FREE(lines[0]);
SAFE_FREE(lines);
}
-
/****************************************************************************
-take a lislist of lines and modify them to produce a list where \ continues
-a line
+ Take a list of lines and modify them to produce a list where \ continues
+ a line.
****************************************************************************/
+
void file_lines_slashcont(char **lines)
{
int i, j;
@@ -579,8 +600,12 @@ void file_lines_slashcont(char **lines)
lines[i][len-1] = ' ';
if (lines[i+1]) {
char *p = &lines[i][len];
- while (p < lines[i+1]) *p++ = ' ';
- for (j = i+1; lines[j]; j++) lines[j] = lines[j+1];
+ while (p < lines[i+1]) {
+ *p++ = ' ';
+ }
+ for (j = i+1; lines[j]; j++) {
+ lines[j] = lines[j+1];
+ }
}
} else {
i++;
@@ -588,9 +613,10 @@ void file_lines_slashcont(char **lines)
}
}
-/*
- save a lump of data into a file. Mostly used for debugging
-*/
+/****************************************************************************
+ Save a lump of data into a file. Mostly used for debugging.
+****************************************************************************/
+
BOOL file_save(const char *fname, void *packet, size_t length)
{
int fd;
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 6eee62c14aa..65a616ad419 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -134,17 +134,20 @@ char **toktocliplist(int *ctok, const char *sep)
*ctok=ictok;
s=(char *)last_ptr;
- if (!(ret=iret=malloc(ictok*sizeof(char *))))
+ if (!(ret=iret=malloc((ictok+1)*sizeof(char *))))
return NULL;
while(ictok--) {
*iret++=s;
- while(*s++)
- ;
- while(!*s)
- s++;
+ if (ictok > 0) {
+ while(*s++)
+ ;
+ while(!*s)
+ s++;
+ }
}
+ ret[*ctok] = NULL;
return ret;
}
diff --git a/source/lib/util_uuid.c b/source/lib/util_uuid.c
index 8f86c2109ea..df70740b33c 100644
--- a/source/lib/util_uuid.c
+++ b/source/lib/util_uuid.c
@@ -29,11 +29,11 @@
void smb_uuid_pack(const struct uuid uu, UUID_FLAT *ptr)
{
- SIVAL(ptr, 0, uu.time_low);
- SSVAL(ptr, 4, uu.time_mid);
- SSVAL(ptr, 6, uu.time_hi_and_version);
- memcpy(ptr+8, uu.clock_seq, 2);
- memcpy(ptr+10, uu.node, 6);
+ SIVAL(ptr->info, 0, uu.time_low);
+ SSVAL(ptr->info, 4, uu.time_mid);
+ SSVAL(ptr->info, 6, uu.time_hi_and_version);
+ memcpy(ptr->info+8, uu.clock_seq, 2);
+ memcpy(ptr->info+10, uu.node, 6);
}
void smb_uuid_unpack(const UUID_FLAT in, struct uuid *uu)
@@ -96,6 +96,7 @@ BOOL smb_string_to_uuid(const char *in, struct uuid* uu)
const char *ptr = in;
char *end = (char *)in;
int i;
+ unsigned v1, v2;
if (!in || !uu) goto out;
@@ -111,61 +112,22 @@ BOOL smb_string_to_uuid(const char *in, struct uuid* uu)
if ((end - ptr) != 4 || *end != '-') goto out;
ptr = (end + 1);
- for (i = 0; i < 2; i++) {
- int adj = 0;
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
- goto out;
- }
- uu->clock_seq[i] = (*ptr - adj) << 4;
- ptr++;
-
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
- goto out;
- }
- uu->clock_seq[i] |= (*ptr - adj);
- ptr++;
+ if (sscanf(ptr, "%02x%02x", &v1, &v2) != 2) {
+ goto out;
}
+ uu->clock_seq[0] = v1;
+ uu->clock_seq[1] = v2;
+ ptr += 4;
if (*ptr != '-') goto out;
ptr++;
for (i = 0; i < 6; i++) {
- int adj = 0;
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
- goto out;
- }
- uu->node[i] = (*ptr - adj) << 4;
- ptr++;
-
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
+ if (sscanf(ptr, "%02x", &v1) != 1) {
goto out;
}
- uu->node[i] |= (*ptr - adj);
- ptr++;
+ uu->node[i] = v1;
+ ptr += 2;
}
ret = True;
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index 97b895a2418..327a76826ef 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -146,7 +146,8 @@ int ads_kdestroy(const char *cc_name)
krb5_ccache cc = NULL;
if ((code = krb5_init_context (&ctx))) {
- DEBUG(3, ("ads_kdestroy: kdb5_init_context rc=%d\n", code));
+ DEBUG(3, ("ads_kdestroy: kdb5_init_context failed: %s\n",
+ error_message(code)));
return code;
}
@@ -157,15 +158,16 @@ int ads_kdestroy(const char *cc_name)
}
} else {
if ((code = krb5_cc_resolve(ctx, cc_name, &cc))) {
- DEBUG(3, ("ads_kdestroy: krb5_cc_resolve rc=%d\n",
- code));
+ DEBUG(3, ("ads_kdestroy: krb5_cc_resolve failed: %s\n",
+ error_message(code)));
krb5_free_context(ctx);
return code;
}
}
if ((code = krb5_cc_destroy (ctx, cc))) {
- DEBUG(3, ("ads_kdestroy: krb5_cc_destroy rc=%d\n", code));
+ DEBUG(3, ("ads_kdestroy: krb5_cc_destroy failed: %s\n",
+ error_message(code)));
}
krb5_free_context (ctx);
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 559538aac9b..4ff60c1b1ca 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -668,11 +668,16 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
ntlmssp_state->session_key.length);
DATA_BLOB null_blob = data_blob(NULL, 0);
+ BOOL res;
fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
cli_set_session_key(cli, ntlmssp_state->session_key);
- if (cli_simple_set_signing(cli, key, null_blob)) {
+ res = cli_simple_set_signing(cli, key, null_blob);
+
+ data_blob_free(&key);
+
+ if (res) {
/* 'resign' the last message, so we get the right sequence numbers
for checking the first reply from the server */
@@ -1133,6 +1138,7 @@ BOOL cli_negprot(struct cli_state *cli)
cli->use_spnego = False;
cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
+ cli->max_mux = SVAL(cli->inbuf, smb_vwv3);
cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
cli->serverzone *= 60;
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index 398c7cc4f0a..ff0edc6bb4e 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -983,6 +983,47 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
}
/****************************************************************************
+ Do a SMBsetattrE call.
+****************************************************************************/
+
+BOOL cli_setattrE(struct cli_state *cli, int fd,
+ time_t c_time, time_t a_time, time_t m_time)
+
+{
+ char *p;
+
+ memset(cli->outbuf,'\0',smb_size);
+ memset(cli->inbuf,'\0',smb_size);
+
+ set_message(cli->outbuf,7,0,True);
+
+ SCVAL(cli->outbuf,smb_com,SMBsetattrE);
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0, fd);
+ put_dos_date3(cli->outbuf,smb_vwv1, c_time);
+ put_dos_date3(cli->outbuf,smb_vwv3, a_time);
+ put_dos_date3(cli->outbuf,smb_vwv5, m_time);
+
+ p = smb_buf(cli->outbuf);
+ *p++ = 4;
+
+ cli_setup_bcc(cli, p);
+
+ cli_send_smb(cli);
+ if (!cli_receive_smb(cli)) {
+ return False;
+ }
+
+ if (cli_is_error(cli)) {
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
Do a SMBsetatr call.
****************************************************************************/
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index 5fcde4654ad..f7f84f1e297 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -190,6 +190,7 @@
krb5_error_code rc;
int num_kdcs, i;
struct sockaddr *sa;
+ struct addrinfo *ai;
*addr_pp = NULL;
*naddrs = 0;
@@ -219,10 +220,19 @@
return -1;
}
+ *addr_pp = malloc(sizeof(struct sockaddr) * num_kdcs);
memset(*addr_pp, '\0', sizeof(struct sockaddr) * num_kdcs );
for (i = 0; i < num_kdcs && (rc = krb5_krbhst_next(ctx, hnd, &hinfo) == 0); i++) {
- if (hinfo->ai->ai_family == AF_INET)
+
+#if defined(HAVE_KRB5_KRBHST_GET_ADDRINFO)
+ rc = krb5_krbhst_get_addrinfo(ctx, hinfo, &ai);
+ if (rc) {
+ DEBUG(0,("krb5_krbhst_get_addrinfo failed: %s\n", error_message(rc)));
+ continue;
+ }
+#endif
+ if (hinfo->ai && hinfo->ai->ai_family == AF_INET)
memcpy(&sa[i], hinfo->ai->ai_addr, sizeof(struct sockaddr));
}
@@ -420,14 +430,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
failed:
if ( context ) {
-/* Removed by jra. They really need to fix their kerberos so we don't leak memory.
- JERRY -- disabled since it causes heimdal 0.6.1rc3 to die
- SuSE 9.1 Pro
-*/
if (ccdef)
-#if 0 /* redisabled by gd :) at least until any official heimdal version has it fixed. */
krb5_cc_close(context, ccdef);
-#endif
if (auth_context)
krb5_auth_con_free(context, auth_context);
krb5_free_context(context);
diff --git a/source/libsmb/cliquota.c b/source/libsmb/cliquota.c
index ed808aa1f5c..af8b4422b78 100644
--- a/source/libsmb/cliquota.c
+++ b/source/libsmb/cliquota.c
@@ -22,13 +22,13 @@
BOOL cli_get_quota_handle(struct cli_state *cli, int *quota_fnum)
{
- *quota_fnum = cli_nt_create_full(cli, FAKE_FILE_NAME_QUOTA,
+ *quota_fnum = cli_nt_create_full(cli, FAKE_FILE_NAME_QUOTA_WIN32,
0x00000016, DESIRED_ACCESS_PIPE,
0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, 0x00000000, 0x03);
if (*quota_fnum == (-1)) {
- return False;
+ return False;
}
return True;
diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c
index 8eac7d07d8b..3f14e530943 100644
--- a/source/libsmb/clireadwrite.c
+++ b/source/libsmb/clireadwrite.c
@@ -325,10 +325,16 @@ ssize_t cli_write(struct cli_state *cli,
int bwritten = 0;
int issued = 0;
int received = 0;
- int mpx = MAX(cli->max_mux-1, 1);
+ int mpx = 1;
int block = cli->max_xmit - (smb_size+32);
int blocks = (size + (block-1)) / block;
+ if(cli->max_mux > 1) {
+ mpx = cli->max_mux-1;
+ } else {
+ mpx = 1;
+ }
+
while (received < blocks) {
while ((issued - received < mpx) && (issued < blocks)) {
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 8f53b55fc54..d4e8c493d50 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -1043,18 +1043,6 @@ int get_deferred_opens(connection_struct *conn,
static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2)
{
-#if 1 /* JRA PARANOIA TEST - REMOVE LATER */
- if (e1->pid == e2->pid &&
- e1->port == e2->port &&
- e1->dev == e2->dev &&
- e1->inode == e2->inode &&
- ((e1->time.tv_sec != e2->time.tv_sec) ||
- (e1->time.tv_usec != e2->time.tv_usec) ||
- (e1->mid != e2->mid))) {
- smb_panic("PANIC: deferred_open_entries_identical: logic error.\n");
- }
-#endif
-
return (e1->pid == e2->pid &&
e1->mid == e2->mid &&
e1->port == e2->port &&
@@ -1064,7 +1052,6 @@ static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_o
e1->time.tv_usec == e2->time.tv_usec);
}
-
/*******************************************************************
Delete a specific deferred open entry.
Ignore if no entry deleted.
diff --git a/source/modules/weird.c b/source/modules/weird.c
index 444853f3831..3c59fd9d61f 100644
--- a/source/modules/weird.c
+++ b/source/modules/weird.c
@@ -31,7 +31,7 @@ static struct {
{0, NULL}
};
-static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t weird_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 1 && *outbytesleft >= 2) {
@@ -74,7 +74,7 @@ static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t weird_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t weird_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int ir_count=0;
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 880de7f91bf..f8006a22a9e 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -29,6 +29,8 @@ int global_nmb_port = -1;
extern BOOL global_in_nmbd;
+extern BOOL override_logfile;
+
/* are we running as a daemon ? */
static BOOL is_daemon;
@@ -623,8 +625,10 @@ static BOOL open_sockets(BOOL isdaemon, int port)
sys_srandom(time(NULL) ^ sys_getpid());
- slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
+ if (!override_logfile) {
+ slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
+ }
fault_setup((void (*)(void *))fault_continue );
diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c
index 8880cb58bb4..8f3ae36b65d 100644
--- a/source/nmbd/nmbd_workgroupdb.c
+++ b/source/nmbd/nmbd_workgroupdb.c
@@ -41,6 +41,27 @@ static void add_workgroup(struct subnet_record *subrec, struct work_record *work
}
/****************************************************************************
+ Copy name to unstring. Used by create_workgroup() and find_workgroup_on_subnet().
+**************************************************************************/
+
+static void name_to_unstring(unstring unname, const char *name)
+{
+ nstring nname;
+
+ errno = 0;
+ push_ascii_nstring(nname, name);
+ if (errno == E2BIG) {
+ unstring tname;
+ pull_ascii_nstring(tname, sizeof(tname), nname);
+ unstrcpy(unname, tname);
+ DEBUG(0,("name_to_nstring: workgroup name %s is too long. Truncating to %s\n",
+ name, tname));
+ } else {
+ unstrcpy(unname, name);
+ }
+}
+
+/****************************************************************************
Create an empty workgroup.
**************************************************************************/
@@ -48,8 +69,6 @@ static struct work_record *create_workgroup(const char *name, int ttl)
{
struct work_record *work;
struct subnet_record *subrec;
- nstring nname;
-
int t = -1;
if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) {
@@ -58,17 +77,8 @@ static struct work_record *create_workgroup(const char *name, int ttl)
}
memset((char *)work, '\0', sizeof(*work));
- errno = 0;
- push_ascii_nstring(nname, name);
- if (errno == E2BIG) {
- unstring tname;
- pull_ascii_nstring(tname, sizeof(tname), nname);
- unstrcpy(work->work_group,tname);
- DEBUG(0,("create_workgroup: workgroup name %s is too long. Truncating to %s\n",
- name, tname));
- } else {
- unstrcpy(work->work_group,name);
- }
+ name_to_unstring(work->work_group, name);
+
work->serverlist = NULL;
work->RunningElection = False;
@@ -157,12 +167,15 @@ struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec,
const char *name)
{
struct work_record *ret;
-
+ unstring un_name;
+
DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ",
name, subrec->subnet_name));
+ name_to_unstring(un_name, name);
+
for (ret = subrec->workgrouplist; ret; ret = ret->next) {
- if (strequal(ret->work_group,name)) {
+ if (strequal(ret->work_group,un_name)) {
DEBUGADD(4, ("found.\n"));
return(ret);
}
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 123f6703665..64e21738221 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -45,6 +45,8 @@ static int _pam_parse(int argc, const char **argv)
ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
else if (!strcasecmp(*argv, "unknown_ok"))
ctrl |= WINBIND_UNKNOWN_OK_ARG;
+ else if (!strncasecmp(*argv, "required_membership", strlen("required_membership")))
+ ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
else {
_pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
}
@@ -148,7 +150,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
switch (retval) {
case PAM_AUTH_ERR:
/* incorrect password */
- _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user);
+ _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user);
return retval;
case PAM_ACCT_EXPIRED:
/* account expired */
@@ -174,7 +176,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
case PAM_SUCCESS:
if (req_type == WINBINDD_PAM_AUTH) {
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted acces", user);
+ _pam_log(LOG_NOTICE, "user '%s' granted access", user);
} else if (req_type == WINBINDD_PAM_CHAUTHTOK) {
/* Otherwise, the authentication looked good */
_pam_log(LOG_NOTICE, "user '%s' password changed", user);
@@ -192,7 +194,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
}
/* talk to winbindd */
-static int winbind_auth_request(const char *user, const char *pass, int ctrl)
+static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -204,7 +206,35 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
strncpy(request.data.auth.pass, pass,
sizeof(request.data.auth.pass)-1);
-
+
+ if (member == NULL )
+ return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+
+ /* lookup name? */
+ if (!strncmp("S-", member, 2) == 0) {
+
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (ctrl & WINBIND_DEBUG_ARG)
+ _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member);
+
+ /* fortunatly winbindd can handle non-separated names */
+ strcpy(request.data.name.name, member);
+
+ if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) {
+ _pam_log(LOG_INFO, "could not lookup name: %s\n", member);
+ return PAM_AUTH_ERR;
+ }
+
+ member = strdup(response.data.sid.sid);
+ }
+
+ strncpy(request.data.auth.required_membership_sid, member,
+ sizeof(request.data.auth.required_membership_sid)-1);
return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
}
@@ -419,7 +449,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
{
const char *username;
const char *password;
+ const char *member = NULL;
int retval = PAM_AUTH_ERR;
+ int i;
/* parse arguments */
int ctrl = _pam_parse(argc, argv);
@@ -453,8 +485,25 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
#endif
}
+ /* Retrieve membership-string here */
+ for ( i=0; i<argc; i++ ) {
+
+ if (!strncmp(argv[i], "required_membership", strlen("required_membership"))) {
+
+ char *p;
+ char *parm = strdup(argv[i]);
+
+ if ( (p = strchr( parm, '=' )) == NULL) {
+ _pam_log(LOG_INFO, "no \"=\" delimiter for \"required_membership\" found\n");
+ break;
+ }
+
+ member = strdup(p+1);
+ }
+ }
+
/* Now use the username to look up password */
- return winbind_auth_request(username, password, ctrl);
+ return winbind_auth_request(username, password, member, ctrl);
}
PAM_EXTERN
@@ -502,7 +551,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
return PAM_USER_UNKNOWN;
case 0:
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted acces", username);
+ _pam_log(LOG_NOTICE, "user '%s' granted access", username);
return PAM_SUCCESS;
default:
/* we don't know anything about this return value */
@@ -546,6 +595,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/* <DO NOT free() THESE> */
const char *user;
+ const char *member = NULL;
char *pass_old, *pass_new;
/* </DO NOT free() THESE> */
@@ -606,7 +656,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
}
/* verify that this is the password for this user */
- retval = winbind_auth_request(user, pass_old, ctrl);
+ retval = winbind_auth_request(user, pass_old, member, ctrl);
if (retval != PAM_ACCT_EXPIRED
&& retval != PAM_AUTHTOK_EXPIRED
diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
index 0afcceb6aa2..7cae477714b 100644
--- a/source/nsswitch/pam_winbind.h
+++ b/source/nsswitch/pam_winbind.h
@@ -82,6 +82,7 @@ do { \
#define WINBIND_TRY_FIRST_PASS_ARG (1<<3)
#define WINBIND_USE_FIRST_PASS_ARG (1<<4)
#define WINBIND__OLD_PASSWORD (1<<5)
+#define WINBIND_REQUIRED_MEMBERSHIP (1<<6)
/*
* here is the string to inform the user that the new passwords they
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 0028982d201..b6a09bf2a1f 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -398,27 +398,6 @@ static BOOL wbinfo_sid_to_uid(char *sid)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* First see whether the SID is actually a user -- otherwise
- * winbind might end up a uid number for a group SID and this
- * is asking for trouble later. */
-
- fstrcpy(request.data.sid, sid);
-
- if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("Could not lookup sid %s\n", sid);
- return False;
- }
-
- if (response.data.name.type != SID_NAME_USER) {
- d_printf("SID is of type %s\n",
- sid_type_lookup(response.data.name.type));
- return False;
- }
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
/* Send request */
fstrcpy(request.data.sid, sid);
@@ -442,26 +421,6 @@ static BOOL wbinfo_sid_to_gid(char *sid)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* First see whether the SID is actually a group -- otherwise
- * winbind might end up a gid number for a user SID and this
- * is asking for trouble later. */
-
- fstrcpy(request.data.sid, sid);
-
- if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("Could not lookup sid %s\n", sid);
- return False;
- }
-
- if ((response.data.name.type != SID_NAME_DOM_GRP) &&
- (response.data.name.type != SID_NAME_ALIAS) &&
- (response.data.name.type != SID_NAME_WKN_GRP)) {
- d_printf("SID is of type %s\n",
- sid_type_lookup(response.data.name.type));
- return False;
- }
-
/* Send request */
fstrcpy(request.data.sid, sid);
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index ae2bcc7ade9..0ea5db74da6 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -833,25 +833,40 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
/* Skip primary group */
- if (gid_list[i] == group) continue;
-
- /* Add to buffer */
+ if (gid_list[i] == group) {
+ continue;
+ }
- if (*start == *size && limit <= 0) {
- (*groups) = realloc(
- (*groups), (2 * (*size) + 1) * sizeof(**groups));
- if (! *groups) goto done;
- *size = 2 * (*size) + 1;
+ /* Filled buffer ? If so, resize. */
+
+ if (*start == *size) {
+ long int newsize;
+ gid_t *newgroups;
+
+ newsize = 2 * (*size);
+ if (limit > 0) {
+ if (*size == limit) {
+ goto done;
+ }
+ if (newsize > limit) {
+ newsize = limit;
+ }
+ }
+
+ newgroups = realloc((*groups), newsize * sizeof(**groups));
+ if (!newgroups) {
+ *errnop = ENOMEM;
+ ret = NSS_STATUS_NOTFOUND;
+ goto done;
+ }
+ *groups = newgroups;
+ *size = newsize;
}
- if (*start == *size) goto done;
+ /* Add to buffer */
(*groups)[*start] = gid_list[i];
*start += 1;
-
- /* Filled buffer? */
-
- if (*start == limit) goto done;
}
}
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index d08aa84face..455fb74f171 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -28,6 +28,8 @@
BOOL opt_nocache = False;
BOOL opt_dual_daemon = True;
+extern BOOL override_logfile;
+
/* Reload configuration */
static BOOL reload_services_file(void)
@@ -587,6 +589,7 @@ static void process_loop(void)
int maxfd, listen_sock, listen_priv_sock, selret;
struct timeval timeout;
+ again:
/* Handle messages */
message_dispatch();
@@ -715,6 +718,15 @@ static void process_loop(void)
for (state = winbindd_client_list(); state;
state = state->next) {
+ /* Data available for writing */
+
+ if (FD_ISSET(state->sock, &w_fds))
+ client_write(state);
+ }
+
+ for (state = winbindd_client_list(); state;
+ state = state->next) {
+
/* Data available for reading */
if (FD_ISSET(state->sock, &r_fds)) {
@@ -747,13 +759,10 @@ static void process_loop(void)
if (state->read_buf_len ==
sizeof(state->request)) {
winbind_process_packet(state);
+ winbindd_demote_client(state);
+ goto again;
}
}
-
- /* Data available for writing */
-
- if (FD_ISSET(state->sock, &w_fds))
- client_write(state);
}
}
@@ -846,8 +855,10 @@ int main(int argc, char **argv)
exit(1);
}
- pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
+ if (!override_logfile) {
+ pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
+ }
setup_logging("winbindd", log_stdout);
reopen_logs();
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index b81f8ecd45a..493255a5a65 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -609,7 +609,6 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
{
struct cache_entry *centry;
fstring uname;
- fstring sid_string;
centry = centry_start(domain, status);
if (!centry)
@@ -619,7 +618,8 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
fstrcpy(uname, name);
strupper_m(uname);
centry_end(centry, "NS/%s/%s", domain_name, uname);
- DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string));
+ DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname,
+ sid_string_static(sid)));
centry_free(centry);
}
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index a9796afa367..d4ec6e586db 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -155,7 +155,7 @@ void do_dual_daemon(void)
dual_daemon_pipe = fdpair[1];
state.sock = fdpair[0];
- if (fork() != 0) {
+ if (sys_fork() != 0) {
close(fdpair[0]);
return;
}
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index ca7f72d0178..a3b826278b5 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -495,8 +495,6 @@ enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
The dispinfo_ndx field is incremented to the index of the next group to
fetch. Return True if some groups were returned, False otherwise. */
-#define MAX_FETCH_SAM_ENTRIES 100
-
static BOOL get_sam_group_entries(struct getent_state *ent)
{
NTSTATUS status;
@@ -925,14 +923,11 @@ static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num)
{
int i;
- if ((*num) >= groups_max())
- return;
-
for (i=0; i<*num; i++) {
if ((*gids)[i] == gid)
return;
}
-
+
*gids = Realloc(*gids, (*num+1) * sizeof(gid_t));
if (*gids == NULL)
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 61da9b3d92f..c6e503bef39 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -119,7 +119,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 flags = 0x0;
+ NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -166,8 +166,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
/* But first check and see if we don't already have a mapping */
- flags = ID_QUERY_ONLY;
- if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) )
+ if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), ID_QUERY_ONLY)) )
return WINBINDD_OK;
/* now fall back to the hard way */
@@ -191,17 +190,37 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
}
- if ( state->request.flags & WBFLAG_QUERY_ONLY )
- flags = ID_QUERY_ONLY;
-
/* Find uid for this sid and return it */
-
- if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) {
- DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
+ ID_QUERY_ONLY);
+
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ if (state->request.flags & WBFLAG_QUERY_ONLY)
return WINBINDD_ERROR;
+
+ /* The query-only did not work, allocate a new uid *if* it's a user */
+
+ {
+ fstring dom_name, name;
+ enum SID_NAME_USE type;
+
+ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type))
+ return WINBINDD_ERROR;
+
+ if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))
+ return WINBINDD_ERROR;
}
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid), 0);
- return WINBINDD_OK;
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
+ return WINBINDD_ERROR;
}
/* Convert a sid to a gid. We assume we only have one rid attached to the
@@ -210,7 +229,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 flags = 0x0;
+ NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -256,8 +275,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
/* But first check and see if we don't already have a mapping */
- flags = ID_QUERY_ONLY;
- if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) )
+ if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), ID_QUERY_ONLY)) )
return WINBINDD_OK;
/* now fall back to the hard way */
@@ -281,16 +299,38 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
}
- if ( state->request.flags & WBFLAG_QUERY_ONLY )
- flags = ID_QUERY_ONLY;
-
/* Find gid for this sid and return it */
- if ( !NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) {
- DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
+
+ result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
+ ID_QUERY_ONLY);
+
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ if (state->request.flags & WBFLAG_QUERY_ONLY)
return WINBINDD_ERROR;
+
+ /* The query-only did not work, allocate a new gid *if* it's a group */
+
+ {
+ fstring dom_name, name;
+ enum SID_NAME_USE type;
+
+ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type))
+ return WINBINDD_ERROR;
+
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP))
+ return WINBINDD_ERROR;
}
+
+ result = idmap_sid_to_gid(&sid, &(state->response.data.gid), 0);
- return WINBINDD_OK;
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
+ return WINBINDD_ERROR;
}
/* Convert a uid to a sid */
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 795d657aae7..6f5a86f43ae 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -385,8 +385,6 @@ enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state)
field is incremented to the index of the next user to fetch. Return True if
some users were returned, False otherwise. */
-#define MAX_FETCH_SAM_ENTRIES 100
-
static BOOL get_sam_user_entries(struct getent_state *ent)
{
NTSTATUS status;
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index faa6e8d8da4..a9197d35616 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -736,6 +736,14 @@ void winbindd_remove_client(struct winbindd_cli_state *cli)
_num_clients--;
}
+/* Demote a client to be the last in the list */
+
+void winbindd_demote_client(struct winbindd_cli_state *cli)
+{
+ struct winbindd_cli_state *tmp;
+ DLIST_DEMOTE(_client_list, cli, tmp);
+}
+
/* Close all open clients */
void winbindd_kill_all_clients(void)
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 14981b97c42..24811af37dd 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -156,6 +156,7 @@ typedef struct
char *szAddMachineScript;
char *szShutdownScript;
char *szAbortShutdownScript;
+ char *szCheckPasswordScript;
char *szWINSHook;
char *szWINSPartners;
char *szUtmpDir;
@@ -811,6 +812,7 @@ static struct parm_struct parm_table[] = {
{"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED},
{"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED},
{"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED},
+ {"check password script", P_STRING, P_GLOBAL, &Globals.szCheckPasswordScript, NULL, NULL, FLAG_ADVANCED},
{"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED},
{"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED},
{"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED},
@@ -1678,6 +1680,8 @@ FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
+FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
+
FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup)
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 9af34705df5..454aa8d8702 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -148,6 +148,27 @@ static char** get_userattr_list( int schema_ver )
return NULL;
}
+/**************************************************************************
+ Return the list of attribute names to delete given a user schema version.
+**************************************************************************/
+
+static char** get_userattr_delete_list( int schema_ver )
+{
+ switch ( schema_ver ) {
+ case SCHEMAVER_SAMBAACCOUNT:
+ return get_attr_list( attrib_map_to_delete_v22 );
+
+ case SCHEMAVER_SAMBASAMACCOUNT:
+ return get_attr_list( attrib_map_to_delete_v30 );
+ default:
+ DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
+ break;
+ }
+
+ return NULL;
+}
+
+
/*******************************************************************
Generate the LDAP search filter for the objectclass based on the
version of the schema we are using.
@@ -299,11 +320,16 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
really exist. */
for (attrib = attrs; *attrib != NULL; attrib++) {
- if ((StrCaseCmp(*attrib, name) == 0) &&
- !(StrCaseCmp(*attrib,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MOD_TIMESTAMP)))) {
- DEBUG(10, ("ldapsam_delete_entry: deleting attribute %s\n", name));
- smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL);
+ /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
+ if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP))) {
+ continue;
+ }
+ if (strequal(*attrib, name)) {
+ DEBUG(10, ("ldapsam_delete_entry: deleting "
+ "attribute %s\n", name));
+ smbldap_set_mod(&mods, LDAP_MOD_DELETE, name,
+ NULL);
}
}
@@ -1229,8 +1255,13 @@ static void append_attr(char ***attr_list, const char *new_attr)
{
int i;
- for (i=0; (*attr_list)[i] != NULL; i++)
+ if (new_attr == NULL) {
+ return;
+ }
+
+ for (i=0; (*attr_list)[i] != NULL; i++) {
;
+ }
(*attr_list) = Realloc((*attr_list), sizeof(**attr_list) * (i+2));
SMB_ASSERT((*attr_list) != NULL);
@@ -1515,7 +1546,7 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
- attr_list= get_userattr_list( ldap_state->schema_ver );
+ attr_list= get_userattr_delete_list( ldap_state->schema_ver );
rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
if (rc != LDAP_SUCCESS) {
diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c
index 6ebac1c01a5..805201615ce 100644
--- a/source/passdb/pdb_smbpasswd.c
+++ b/source/passdb/pdb_smbpasswd.c
@@ -70,20 +70,21 @@ enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
{
- if (fd < 0)
- return False;
+ if (fd < 0) {
+ return False;
+ }
- if(*plock_depth == 0) {
- if (!do_file_lock(fd, secs, type)) {
- DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
- strerror(errno)));
- return False;
- }
- }
+ if(*plock_depth == 0) {
+ if (!do_file_lock(fd, secs, type)) {
+ DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
+ strerror(errno)));
+ return False;
+ }
+ }
- (*plock_depth)++;
+ (*plock_depth)++;
- return True;
+ return True;
}
/***************************************************************
@@ -92,25 +93,27 @@ static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
static BOOL pw_file_unlock(int fd, int *plock_depth)
{
- BOOL ret=True;
+ BOOL ret=True;
- if (fd == 0 || *plock_depth == 0) {
- return True;
- }
+ if (fd == 0 || *plock_depth == 0) {
+ return True;
+ }
- if(*plock_depth == 1)
- ret = do_file_lock(fd, 5, F_UNLCK);
+ if(*plock_depth == 1) {
+ ret = do_file_lock(fd, 5, F_UNLCK);
+ }
- if (*plock_depth > 0)
- (*plock_depth)--;
+ if (*plock_depth > 0) {
+ (*plock_depth)--;
+ }
- if(!ret)
- DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
- strerror(errno)));
- return ret;
+ if(!ret) {
+ DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
+ strerror(errno)));
+ }
+ return ret;
}
-
/**************************************************************
Intialize a smb_passwd struct
*************************************************************/
@@ -133,153 +136,160 @@ static void pdb_init_smb(struct smb_passwd *user)
static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
{
- FILE *fp = NULL;
- const char *open_mode = NULL;
- int race_loop = 0;
- int lock_type = F_RDLCK;
-
- if (!*pfile) {
- DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
- return (NULL);
- }
-
- switch(type) {
- case PWF_READ:
- open_mode = "rb";
- lock_type = F_RDLCK;
- break;
- case PWF_UPDATE:
- open_mode = "r+b";
- lock_type = F_WRLCK;
- break;
- case PWF_CREATE:
- /*
- * Ensure atomic file creation.
- */
- {
- int i, fd = -1;
-
- for(i = 0; i < 5; i++) {
- if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1)
- break;
- sys_usleep(200); /* Spin, spin... */
- }
- if(fd == -1) {
- DEBUG(0,("startsmbfilepwent_internal: too many race conditions creating file %s\n", pfile));
- return NULL;
- }
- close(fd);
- open_mode = "r+b";
- lock_type = F_WRLCK;
- break;
- }
- }
+ FILE *fp = NULL;
+ const char *open_mode = NULL;
+ int race_loop = 0;
+ int lock_type = F_RDLCK;
+
+ if (!*pfile) {
+ DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
+ return (NULL);
+ }
+
+ switch(type) {
+ case PWF_READ:
+ open_mode = "rb";
+ lock_type = F_RDLCK;
+ break;
+ case PWF_UPDATE:
+ open_mode = "r+b";
+ lock_type = F_WRLCK;
+ break;
+ case PWF_CREATE:
+ /*
+ * Ensure atomic file creation.
+ */
+ {
+ int i, fd = -1;
+
+ for(i = 0; i < 5; i++) {
+ if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1) {
+ break;
+ }
+ sys_usleep(200); /* Spin, spin... */
+ }
+ if(fd == -1) {
+ DEBUG(0,("startsmbfilepwent_internal: too many race conditions \
+creating file %s\n", pfile));
+ return NULL;
+ }
+ close(fd);
+ open_mode = "r+b";
+ lock_type = F_WRLCK;
+ break;
+ }
+ }
- for(race_loop = 0; race_loop < 5; race_loop++) {
- DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
+ for(race_loop = 0; race_loop < 5; race_loop++) {
+ DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
+
+ if((fp = sys_fopen(pfile, open_mode)) == NULL) {
+
+ /*
+ * If smbpasswd file doesn't exist, then create new one. This helps to avoid
+ * confusing error msg when adding user account first time.
+ */
+ if (errno == ENOENT) {
+ if ((fp = sys_fopen(pfile, "a+")) != NULL) {
+ DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
+exist. File successfully created.\n", pfile));
+ } else {
+ DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
+exist. Couldn't create new one. Error was: %s",
+ pfile, strerror(errno)));
+ return NULL;
+ }
+ } else {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. \
+Error was: %s\n", pfile, strerror(errno)));
+ return NULL;
+ }
+ }
- if((fp = sys_fopen(pfile, open_mode)) == NULL) {
-
- /*
- * If smbpasswd file doesn't exist, then create new one. This helps to avoid
- * confusing error msg when adding user account first time.
- */
- if (errno == ENOENT) {
- if ((fp = sys_fopen(pfile, "a+")) != NULL) {
- DEBUG(0, ("startsmbfilepwent_internal: file %s did not exist. File successfully created.\n", pfile));
-
- } else {
- DEBUG(0, ("startsmbfilepwent_internal: file %s did not exist. Couldn't create new one. Error was: %s",
- pfile, strerror(errno)));
- return NULL;
- }
-
- } else {
- DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. Error was: %s\n", pfile, strerror(errno)));
- return NULL;
- }
- }
-
- if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
- DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. Error was %s\n", pfile, strerror(errno) ));
- fclose(fp);
- return NULL;
- }
-
- /*
- * Only check for replacement races on update or create.
- * For read we don't mind if the data is one record out of date.
- */
-
- if(type == PWF_READ) {
- break;
- } else {
- SMB_STRUCT_STAT sbuf1, sbuf2;
-
- /*
- * Avoid the potential race condition between the open and the lock
- * by doing a stat on the filename and an fstat on the fd. If the
- * two inodes differ then someone did a rename between the open and
- * the lock. Back off and try the open again. Only do this 5 times to
- * prevent infinate loops. JRA.
- */
-
- if (sys_stat(pfile,&sbuf1) != 0) {
- DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. Error was %s\n", pfile, strerror(errno)));
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- return NULL;
- }
-
- if (sys_fstat(fileno(fp),&sbuf2) != 0) {
- DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. Error was %s\n", pfile, strerror(errno)));
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- return NULL;
- }
-
- if( sbuf1.st_ino == sbuf2.st_ino) {
- /* No race. */
- break;
- }
-
- /*
- * Race occurred - back off and try again...
- */
-
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- }
- }
-
- if(race_loop == 5) {
- DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
- return NULL;
- }
-
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, (char *)NULL, _IOFBF, 1024);
-
- /* Make sure it is only rw by the owner */
+ if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. \
+Error was %s\n", pfile, strerror(errno) ));
+ fclose(fp);
+ return NULL;
+ }
+
+ /*
+ * Only check for replacement races on update or create.
+ * For read we don't mind if the data is one record out of date.
+ */
+
+ if(type == PWF_READ) {
+ break;
+ } else {
+ SMB_STRUCT_STAT sbuf1, sbuf2;
+
+ /*
+ * Avoid the potential race condition between the open and the lock
+ * by doing a stat on the filename and an fstat on the fd. If the
+ * two inodes differ then someone did a rename between the open and
+ * the lock. Back off and try the open again. Only do this 5 times to
+ * prevent infinate loops. JRA.
+ */
+
+ if (sys_stat(pfile,&sbuf1) != 0) {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. \
+Error was %s\n", pfile, strerror(errno)));
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ return NULL;
+ }
+
+ if (sys_fstat(fileno(fp),&sbuf2) != 0) {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. \
+Error was %s\n", pfile, strerror(errno)));
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ return NULL;
+ }
+
+ if( sbuf1.st_ino == sbuf2.st_ino) {
+ /* No race. */
+ break;
+ }
+
+ /*
+ * Race occurred - back off and try again...
+ */
+
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ }
+ }
+
+ if(race_loop == 5) {
+ DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
+ return NULL;
+ }
+
+ /* Set a buffer to do more efficient reads */
+ setvbuf(fp, (char *)NULL, _IOFBF, 1024);
+
+ /* Make sure it is only rw by the owner */
#ifdef HAVE_FCHMOD
- if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) {
+ if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) {
#else
- if(chmod(pfile, S_IRUSR|S_IWUSR) == -1) {
+ if(chmod(pfile, S_IRUSR|S_IWUSR) == -1) {
#endif
- DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
+ DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
Error was %s\n.", pfile, strerror(errno) ));
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- return NULL;
- }
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ return NULL;
+ }
- /* We have a lock on the file. */
- return fp;
+ /* We have a lock on the file. */
+ return fp;
}
/***************************************************************
End enumeration of the smbpasswd list.
****************************************************************/
+
static void endsmbfilepwent(FILE *fp, int *lock_depth)
{
if (!fp) {
@@ -297,225 +307,235 @@ static void endsmbfilepwent(FILE *fp, int *lock_depth)
static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp)
{
- /* Static buffers we will return. */
- struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
- char *user_name = smbpasswd_state->user_name;
- unsigned char *smbpwd = smbpasswd_state->smbpwd;
- unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
- char linebuf[256];
- unsigned char c;
- unsigned char *p;
- long uidval;
- size_t linebuf_len;
-
- if(fp == NULL) {
- DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
- return NULL;
- }
-
- pdb_init_smb(pw_buf);
-
- pw_buf->acct_ctrl = ACB_NORMAL;
-
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
- while (!feof(fp)) {
- linebuf[0] = '\0';
-
- fgets(linebuf, 256, fp);
- if (ferror(fp)) {
- return NULL;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- if ((linebuf_len = strlen(linebuf)) == 0)
- continue;
-
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n')
- break;
- }
- } else
- linebuf[linebuf_len - 1] = '\0';
+ /* Static buffers we will return. */
+ struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
+ char *user_name = smbpasswd_state->user_name;
+ unsigned char *smbpwd = smbpasswd_state->smbpwd;
+ unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
+ char linebuf[256];
+ unsigned char c;
+ unsigned char *p;
+ long uidval;
+ size_t linebuf_len;
+
+ if(fp == NULL) {
+ DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
+ return NULL;
+ }
+
+ pdb_init_smb(pw_buf);
+ pw_buf->acct_ctrl = ACB_NORMAL;
+
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+ while (!feof(fp)) {
+ linebuf[0] = '\0';
+
+ fgets(linebuf, 256, fp);
+ if (ferror(fp)) {
+ return NULL;
+ }
+
+ /*
+ * Check if the string is terminated with a newline - if not
+ * then we must keep reading and discard until we get one.
+ */
+ if ((linebuf_len = strlen(linebuf)) == 0) {
+ continue;
+ }
+
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n') {
+ break;
+ }
+ }
+ } else {
+ linebuf[linebuf_len - 1] = '\0';
+ }
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf));
+ DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf));
#endif
- if ((linebuf[0] == 0) && feof(fp)) {
- DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
- break;
- }
- /*
- * The line we have should be of the form :-
- *
- * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
- *
- * if Windows NT compatible passwords are also present.
- * [Account type] is an ascii encoding of the type of account.
- * LCT-(8 hex digits) is the time_t value of the last change time.
- */
-
- if (linebuf[0] == '#' || linebuf[0] == '\0') {
- DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
- continue;
- }
- p = (unsigned char *) strchr_m(linebuf, ':');
- if (p == NULL) {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
- continue;
- }
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
- SMB_ASSERT(sizeof(pstring) > sizeof(linebuf));
-
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
-
- /* Get smb uid. */
-
- p++; /* Go past ':' */
-
- if(*p == '-') {
- DEBUG(0, ("getsmbfilepwent: uids in the smbpasswd file must not be negative.\n"));
- continue;
- }
-
- if (!isdigit(*p)) {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (uid not number)\n"));
- continue;
- }
-
- uidval = atoi((char *) p);
-
- while (*p && isdigit(*p))
- p++;
-
- if (*p != ':') {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (no : after uid)\n"));
- continue;
- }
-
- pw_buf->smb_name = user_name;
- pw_buf->smb_userid = uidval;
-
- /*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
- */
-
- /* Skip the ':' */
- p++;
-
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (passwd too short)\n"));
- continue;
- }
-
- if (p[32] != ':') {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (no terminating :)\n"));
- continue;
- }
-
- if (strnequal((char *) p, "NO PASSWORD", 11)) {
- pw_buf->smb_passwd = NULL;
- pw_buf->acct_ctrl |= ACB_PWNOTREQ;
- } else {
- if (*p == '*' || *p == 'X') {
- /* NULL LM password */
- pw_buf->smb_passwd = NULL;
- DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name));
- } else if (pdb_gethexpwd((char *)p, smbpwd)) {
- pw_buf->smb_passwd = smbpwd;
- } else {
- pw_buf->smb_passwd = NULL;
- DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
- }
- }
-
- /*
- * Now check if the NT compatible password is
- * available.
- */
- pw_buf->smb_nt_passwd = NULL;
-
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
- if (*p != '*' && *p != 'X') {
- if(pdb_gethexpwd((char *)p,smbntpwd))
- pw_buf->smb_nt_passwd = smbntpwd;
- }
- p += 33; /* Move to the first character of the line after
- the NT password. */
- }
-
- DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
- user_name, uidval));
-
- if (*p == '[')
- {
- unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
- pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
-
- /* Must have some account type set. */
- if(pw_buf->acct_ctrl == 0)
- pw_buf->acct_ctrl = ACB_NORMAL;
-
- /* Now try and get the last change time. */
- if(end_p)
- p = end_p + 1;
- if(*p == ':') {
- p++;
- if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
- int i;
- p += 4;
- for(i = 0; i < 8; i++) {
- if(p[i] == '\0' || !isxdigit(p[i]))
- break;
- }
- if(i == 8) {
- /*
- * p points at 8 characters of hex digits -
- * read into a time_t as the seconds since
- * 1970 that the password was last changed.
- */
- pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
- }
- }
- }
- } else {
- /* 'Old' style file. Fake up based on user name. */
- /*
- * Currently trust accounts are kept in the same
- * password file as 'normal accounts'. If this changes
- * we will have to fix this code. JRA.
- */
- if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
- pw_buf->acct_ctrl &= ~ACB_NORMAL;
- pw_buf->acct_ctrl |= ACB_WSTRUST;
- }
- }
-
- return pw_buf;
- }
-
- DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
- return NULL;
+ if ((linebuf[0] == 0) && feof(fp)) {
+ DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
+ break;
+ }
+
+ /*
+ * The line we have should be of the form :-
+ *
+ * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
+ * ignored....
+ *
+ * or,
+ *
+ * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
+ *
+ * if Windows NT compatible passwords are also present.
+ * [Account type] is an ascii encoding of the type of account.
+ * LCT-(8 hex digits) is the time_t value of the last change time.
+ */
+
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
+ DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
+ continue;
+ }
+ p = (unsigned char *) strchr_m(linebuf, ':');
+ if (p == NULL) {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
+ continue;
+ }
+
+ /*
+ * As 256 is shorter than a pstring we don't need to check
+ * length here - if this ever changes....
+ */
+ SMB_ASSERT(sizeof(pstring) > sizeof(linebuf));
+
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+
+ /* Get smb uid. */
+
+ p++; /* Go past ':' */
+
+ if(*p == '-') {
+ DEBUG(0, ("getsmbfilepwent: user name %s has a negative uid.\n", user_name));
+ continue;
+ }
+
+ if (!isdigit(*p)) {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (uid not number)\n",
+ user_name));
+ continue;
+ }
+
+ uidval = atoi((char *) p);
+
+ while (*p && isdigit(*p)) {
+ p++;
+ }
+
+ if (*p != ':') {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no : after uid)\n",
+ user_name));
+ continue;
+ }
+
+ pw_buf->smb_name = user_name;
+ pw_buf->smb_userid = uidval;
+
+ /*
+ * Now get the password value - this should be 32 hex digits
+ * which are the ascii representations of a 16 byte string.
+ * Get two at a time and put them into the password.
+ */
+
+ /* Skip the ':' */
+ p++;
+
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (passwd too short)\n",
+ user_name ));
+ continue;
+ }
+
+ if (p[32] != ':') {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no terminating :)\n",
+ user_name));
+ continue;
+ }
+
+ if (strnequal((char *) p, "NO PASSWORD", 11)) {
+ pw_buf->smb_passwd = NULL;
+ pw_buf->acct_ctrl |= ACB_PWNOTREQ;
+ } else {
+ if (*p == '*' || *p == 'X') {
+ /* NULL LM password */
+ pw_buf->smb_passwd = NULL;
+ DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name));
+ } else if (pdb_gethexpwd((char *)p, smbpwd)) {
+ pw_buf->smb_passwd = smbpwd;
+ } else {
+ pw_buf->smb_passwd = NULL;
+ DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry for user %s \
+(non hex chars)\n", user_name));
+ }
+ }
+
+ /*
+ * Now check if the NT compatible password is
+ * available.
+ */
+ pw_buf->smb_nt_passwd = NULL;
+ p += 33; /* Move to the first character of the line after the lanman password. */
+ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
+ if (*p != '*' && *p != 'X') {
+ if(pdb_gethexpwd((char *)p,smbntpwd)) {
+ pw_buf->smb_nt_passwd = smbntpwd;
+ }
+ }
+ p += 33; /* Move to the first character of the line after the NT password. */
+ }
+
+ DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
+ user_name, uidval));
+
+ if (*p == '[') {
+ unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
+ pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
+
+ /* Must have some account type set. */
+ if(pw_buf->acct_ctrl == 0) {
+ pw_buf->acct_ctrl = ACB_NORMAL;
+ }
+
+ /* Now try and get the last change time. */
+ if(end_p) {
+ p = end_p + 1;
+ }
+ if(*p == ':') {
+ p++;
+ if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
+ int i;
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i])) {
+ break;
+ }
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
+ }
+ }
+ }
+ } else {
+ /* 'Old' style file. Fake up based on user name. */
+ /*
+ * Currently trust accounts are kept in the same
+ * password file as 'normal accounts'. If this changes
+ * we will have to fix this code. JRA.
+ */
+ if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
+ pw_buf->acct_ctrl &= ~ACB_NORMAL;
+ pw_buf->acct_ctrl |= ACB_WSTRUST;
+ }
+ }
+
+ return pw_buf;
+ }
+
+ DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
+ return NULL;
}
/************************************************************************
@@ -524,35 +544,38 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
{
- int new_entry_length;
- char *new_entry;
- char *p;
-
- new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
+ int new_entry_length;
+ char *new_entry;
+ char *p;
- if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
- DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n", newpwd->smb_name ));
- return NULL;
- }
+ new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 +
+ NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
- slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
-
- p = new_entry+strlen(new_entry);
-
- pdb_sethexpwd(p, newpwd->smb_passwd, newpwd->acct_ctrl);
+ if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
+ DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n",
+ newpwd->smb_name ));
+ return NULL;
+ }
- p+=strlen(p); *p = ':'; p++;
+ slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
- pdb_sethexpwd(p, newpwd->smb_nt_passwd, newpwd->acct_ctrl);
+ p = new_entry+strlen(new_entry);
+ pdb_sethexpwd(p, newpwd->smb_passwd, newpwd->acct_ctrl);
+ p+=strlen(p);
+ *p = ':';
+ p++;
- p+=strlen(p); *p = ':'; p++;
+ pdb_sethexpwd(p, newpwd->smb_nt_passwd, newpwd->acct_ctrl);
+ p+=strlen(p);
+ *p = ':';
+ p++;
- /* Add the account encoding and the last change time. */
- slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
- pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
- (uint32)newpwd->pass_last_set_time);
+ /* Add the account encoding and the last change time. */
+ slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
+ pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
+ (uint32)newpwd->pass_last_set_time);
- return new_entry;
+ return new_entry;
}
/************************************************************************
@@ -561,101 +584,95 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd)
{
- const char *pfile = smbpasswd_state->smbpasswd_file;
- struct smb_passwd *pwd = NULL;
- FILE *fp = NULL;
- int wr_len;
- int fd;
- size_t new_entry_length;
- char *new_entry;
- SMB_OFF_T offpos;
- uint32 max_found_uid = 0;
+ const char *pfile = smbpasswd_state->smbpasswd_file;
+ struct smb_passwd *pwd = NULL;
+ FILE *fp = NULL;
+ int wr_len;
+ int fd;
+ size_t new_entry_length;
+ char *new_entry;
+ SMB_OFF_T offpos;
+ uint32 max_found_uid = 0;
- /* Open the smbpassword file - for update. */
- fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth));
-
- if (fp == NULL && errno == ENOENT) {
- /* Try again - create. */
- fp = startsmbfilepwent(pfile, PWF_CREATE, &(smbpasswd_state->pw_file_lock_depth));
- }
-
- if (fp == NULL) {
- DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
- return False;
- }
-
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
-
- while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL)
- {
- if (strequal(newpwd->smb_name, pwd->smb_name))
- {
- DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
+ /* Open the smbpassword file - for update. */
+ fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth);
+
+ if (fp == NULL && errno == ENOENT) {
+ /* Try again - create. */
+ fp = startsmbfilepwent(pfile, PWF_CREATE, &smbpasswd_state->pw_file_lock_depth);
+ }
+
+ if (fp == NULL) {
+ DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
+ return False;
+ }
+
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
+ if (strequal(newpwd->smb_name, pwd->smb_name)) {
+ DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
- /* Look for a free uid for use in non-unix accounts */
- if (pwd->smb_userid > max_found_uid) {
- max_found_uid = pwd->smb_userid;
- }
- }
-
- /* Ok - entry doesn't exist. We can add it */
-
- /* Create a new smb passwd entry and set it to the given password. */
- /*
- * The add user write needs to be atomic - so get the fd from
- * the fp and do a raw write() call.
- */
- fd = fileno(fp);
-
- if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1)
- {
- DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
+ /* Look for a free uid for use in non-unix accounts */
+ if (pwd->smb_userid > max_found_uid) {
+ max_found_uid = pwd->smb_userid;
+ }
+ }
+
+ /* Ok - entry doesn't exist. We can add it */
+
+ /* Create a new smb passwd entry and set it to the given password. */
+ /*
+ * The add user write needs to be atomic - so get the fd from
+ * the fp and do a raw write() call.
+ */
+ fd = fileno(fp);
+
+ if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) {
+ DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
- if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL)
- {
- DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
+ if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) {
+ DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
- new_entry_length = strlen(new_entry);
+ new_entry_length = strlen(new_entry);
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|",
- fd, new_entry_length, new_entry));
+ DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|",
+ fd, new_entry_length, new_entry));
#endif
- if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length)
- {
- DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
+ if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
+ DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
- /* Remove the entry we just wrote. */
- if(sys_ftruncate(fd, offpos) == -1)
- {
- DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
+ /* Remove the entry we just wrote. */
+ if(sys_ftruncate(fd, offpos) == -1) {
+ DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
Error was %s. Password file may be corrupt ! Please examine by hand !\n",
- newpwd->smb_name, strerror(errno)));
- }
+ newpwd->smb_name, strerror(errno)));
+ }
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- free(new_entry);
- return False;
- }
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ free(new_entry);
+ return False;
+ }
- free(new_entry);
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return True;
+ free(new_entry);
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return True;
}
/************************************************************************
@@ -669,350 +686,356 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
{
- /* Static buffers we will return. */
+ /* Static buffers we will return. */
pstring user_name;
- char linebuf[256];
- char readbuf[1024];
- unsigned char c;
- fstring ascii_p16;
- fstring encode_bits;
- unsigned char *p = NULL;
- size_t linebuf_len = 0;
- FILE *fp;
- int lockfd;
- const char *pfile = smbpasswd_state->smbpasswd_file;
- BOOL found_entry = False;
- BOOL got_pass_last_set_time = False;
-
- SMB_OFF_T pwd_seekpos = 0;
-
- int i;
- int wr_len;
- int fd;
-
- if (!*pfile) {
- DEBUG(0, ("No SMB password file set\n"));
- return False;
- }
- DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
-
- fp = sys_fopen(pfile, "r+");
-
- if (fp == NULL) {
- DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
- return False;
- }
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- lockfd = fileno(fp);
-
- if (!pw_file_lock(lockfd, F_WRLCK, 5, &(smbpasswd_state->pw_file_lock_depth))) {
- DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
- fclose(fp);
- return False;
- }
-
- /* Make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* We have a write lock on the file. */
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
- while (!feof(fp)) {
- pwd_seekpos = sys_ftell(fp);
-
- linebuf[0] = '\0';
-
- fgets(linebuf, sizeof(linebuf), fp);
- if (ferror(fp)) {
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- linebuf_len = strlen(linebuf);
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n') {
- break;
- }
- }
- } else {
- linebuf[linebuf_len - 1] = '\0';
- }
+ char linebuf[256];
+ char readbuf[1024];
+ unsigned char c;
+ fstring ascii_p16;
+ fstring encode_bits;
+ unsigned char *p = NULL;
+ size_t linebuf_len = 0;
+ FILE *fp;
+ int lockfd;
+ const char *pfile = smbpasswd_state->smbpasswd_file;
+ BOOL found_entry = False;
+ BOOL got_pass_last_set_time = False;
+
+ SMB_OFF_T pwd_seekpos = 0;
+
+ int i;
+ int wr_len;
+ int fd;
+
+ if (!*pfile) {
+ DEBUG(0, ("No SMB password file set\n"));
+ return False;
+ }
+ DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
+
+ fp = sys_fopen(pfile, "r+");
+
+ if (fp == NULL) {
+ DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
+ return False;
+ }
+ /* Set a buffer to do more efficient reads */
+ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
+
+ lockfd = fileno(fp);
+
+ if (!pw_file_lock(lockfd, F_WRLCK, 5, &smbpasswd_state->pw_file_lock_depth)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
+ fclose(fp);
+ return False;
+ }
+
+ /* Make sure it is only rw by the owner */
+ chmod(pfile, 0600);
+
+ /* We have a write lock on the file. */
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+ while (!feof(fp)) {
+ pwd_seekpos = sys_ftell(fp);
+
+ linebuf[0] = '\0';
+
+ fgets(linebuf, sizeof(linebuf), fp);
+ if (ferror(fp)) {
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /*
+ * Check if the string is terminated with a newline - if not
+ * then we must keep reading and discard until we get one.
+ */
+ linebuf_len = strlen(linebuf);
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n') {
+ break;
+ }
+ }
+ } else {
+ linebuf[linebuf_len - 1] = '\0';
+ }
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf));
+ DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf));
#endif
- if ((linebuf[0] == 0) && feof(fp)) {
- DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
- break;
- }
-
- /*
- * The line we have should be of the form :-
- *
- * username:uid:[32hex bytes]:....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
- *
- * if Windows NT compatible passwords are also present.
- */
-
- if (linebuf[0] == '#' || linebuf[0] == '\0') {
- DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
- continue;
- }
-
- p = (unsigned char *) strchr_m(linebuf, ':');
-
- if (p == NULL) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
- continue;
- }
-
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
-
- SMB_ASSERT(sizeof(user_name) > sizeof(linebuf));
-
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
- if (strequal(user_name, pwd->smb_name)) {
- found_entry = True;
- break;
- }
- }
-
- if (!found_entry) {
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
-
- DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n",
- pwd->smb_name));
- return False;
- }
-
- DEBUG(6, ("mod_smbfilepwd_entry: entry exists\n"));
-
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
-
- if (!isdigit(*p)) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n"));
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- while (*p && isdigit(*p))
- p++;
- if (*p != ':') {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n"));
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
- */
- p++;
-
- /* Record exact password position */
- pwd_seekpos += PTR_DIFF(p, linebuf);
-
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return (False);
- }
-
- if (p[32] != ':') {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return (False);
- }
-
- if (p[32] != ':') {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /*
- * Now check if the account info and the password last
- * change time is available.
- */
- p += 33; /* Move to the first character of the line after
- the NT password. */
-
- if (*p == '[') {
-
- i = 0;
- encode_bits[i++] = *p++;
- while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']'))
- encode_bits[i++] = *p++;
-
- encode_bits[i++] = ']';
- encode_bits[i++] = '\0';
-
- if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) {
- /*
- * We are using a new format, space padded
- * acct ctrl field. Encode the given acct ctrl
- * bits into it.
- */
- fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
- } else {
- DEBUG(0,("mod_smbfilepwd_entry: Using old smbpasswd format. This is no longer supported.!\n"));
- DEBUG(0,("mod_smbfilepwd_entry: No changes made, failing.!\n"));
- return False;
- }
-
- /* Go past the ']' */
- if(linebuf_len > PTR_DIFF(p, linebuf))
- p++;
-
- if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
- p++;
-
- /* We should be pointing at the LCT entry. */
- if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
-
- p += 4;
- for(i = 0; i < 8; i++) {
- if(p[i] == '\0' || !isxdigit(p[i]))
- break;
- }
- if(i == 8) {
- /*
- * p points at 8 characters of hex digits -
- * read into a time_t as the seconds since
- * 1970 that the password was last changed.
- */
- got_pass_last_set_time = True;
- } /* i == 8 */
- } /* *p && StrnCaseCmp() */
- } /* p == ':' */
- } /* p == '[' */
-
- /* Entry is correctly formed. */
-
- /* Create the 32 byte representation of the new p16 */
- pdb_sethexpwd(ascii_p16, pwd->smb_passwd, pwd->acct_ctrl);
-
- /* Add on the NT md4 hash */
- ascii_p16[32] = ':';
- wr_len = 66;
- pdb_sethexpwd(ascii_p16+33, pwd->smb_nt_passwd, pwd->acct_ctrl);
- ascii_p16[65] = ':';
- ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */
-
- /* Add on the account info bits and the time of last
- password change. */
-
- if(got_pass_last_set_time) {
- slprintf(&ascii_p16[strlen(ascii_p16)],
- sizeof(ascii_p16)-(strlen(ascii_p16)+1),
- "%s:LCT-%08X:",
- encode_bits, (uint32)pwd->pass_last_set_time );
- wr_len = strlen(ascii_p16);
- }
+ if ((linebuf[0] == 0) && feof(fp)) {
+ DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
+ break;
+ }
+
+ /*
+ * The line we have should be of the form :-
+ *
+ * username:uid:[32hex bytes]:....other flags presently
+ * ignored....
+ *
+ * or,
+ *
+ * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
+ *
+ * if Windows NT compatible passwords are also present.
+ */
+
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
+ DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
+ continue;
+ }
+
+ p = (unsigned char *) strchr_m(linebuf, ':');
+
+ if (p == NULL) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
+ continue;
+ }
+
+ /*
+ * As 256 is shorter than a pstring we don't need to check
+ * length here - if this ever changes....
+ */
+
+ SMB_ASSERT(sizeof(user_name) > sizeof(linebuf));
+
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+ if (strequal(user_name, pwd->smb_name)) {
+ found_entry = True;
+ break;
+ }
+ }
+
+ if (!found_entry) {
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+
+ DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n",
+ pwd->smb_name));
+ return False;
+ }
+
+ DEBUG(6, ("mod_smbfilepwd_entry: entry exists for user %s\n", pwd->smb_name));
+
+ /* User name matches - get uid and password */
+ p++; /* Go past ':' */
+
+ if (!isdigit(*p)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (uid not number)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ while (*p && isdigit(*p)) {
+ p++;
+ }
+ if (*p != ':') {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no : after uid)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /*
+ * Now get the password value - this should be 32 hex digits
+ * which are the ascii representations of a 16 byte string.
+ * Get two at a time and put them into the password.
+ */
+ p++;
+
+ /* Record exact password position */
+ pwd_seekpos += PTR_DIFF(p, linebuf);
+
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return (False);
+ }
+
+ if (p[32] != ':') {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /* Now check if the NT compatible password is available. */
+ p += 33; /* Move to the first character of the line after the lanman password. */
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return (False);
+ }
+
+ if (p[32] != ':') {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /*
+ * Now check if the account info and the password last
+ * change time is available.
+ */
+ p += 33; /* Move to the first character of the line after the NT password. */
+
+ if (*p == '[') {
+ i = 0;
+ encode_bits[i++] = *p++;
+ while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']')) {
+ encode_bits[i++] = *p++;
+ }
+
+ encode_bits[i++] = ']';
+ encode_bits[i++] = '\0';
+
+ if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) {
+ /*
+ * We are using a new format, space padded
+ * acct ctrl field. Encode the given acct ctrl
+ * bits into it.
+ */
+ fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
+ } else {
+ DEBUG(0,("mod_smbfilepwd_entry: Using old smbpasswd format for user %s. \
+This is no longer supported.!\n", pwd->smb_name));
+ DEBUG(0,("mod_smbfilepwd_entry: No changes made, failing.!\n"));
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /* Go past the ']' */
+ if(linebuf_len > PTR_DIFF(p, linebuf)) {
+ p++;
+ }
+
+ if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
+ p++;
+
+ /* We should be pointing at the LCT entry. */
+ if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i])) {
+ break;
+ }
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ got_pass_last_set_time = True;
+ } /* i == 8 */
+ } /* *p && StrnCaseCmp() */
+ } /* p == ':' */
+ } /* p == '[' */
+
+ /* Entry is correctly formed. */
+
+ /* Create the 32 byte representation of the new p16 */
+ pdb_sethexpwd(ascii_p16, pwd->smb_passwd, pwd->acct_ctrl);
+
+ /* Add on the NT md4 hash */
+ ascii_p16[32] = ':';
+ wr_len = 66;
+ pdb_sethexpwd(ascii_p16+33, pwd->smb_nt_passwd, pwd->acct_ctrl);
+ ascii_p16[65] = ':';
+ ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */
+
+ /* Add on the account info bits and the time of last password change. */
+ if(got_pass_last_set_time) {
+ slprintf(&ascii_p16[strlen(ascii_p16)],
+ sizeof(ascii_p16)-(strlen(ascii_p16)+1),
+ "%s:LCT-%08X:",
+ encode_bits, (uint32)pwd->pass_last_set_time );
+ wr_len = strlen(ascii_p16);
+ }
#ifdef DEBUG_PASSWORD
- DEBUG(100,("mod_smbfilepwd_entry: "));
- dump_data(100, ascii_p16, wr_len);
+ DEBUG(100,("mod_smbfilepwd_entry: "));
+ dump_data(100, ascii_p16, wr_len);
#endif
- if(wr_len > sizeof(linebuf)) {
- DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return (False);
- }
-
- /*
- * Do an atomic write into the file at the position defined by
- * seekpos.
- */
-
- /* The mod user write needs to be atomic - so get the fd from
- the fp and do a raw write() call.
- */
-
- fd = fileno(fp);
-
- if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
- DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /* Sanity check - ensure the areas we are writing are framed by ':' */
- if (read(fd, linebuf, wr_len+1) != wr_len+1) {
- DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) {
- DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
+ if(wr_len > sizeof(linebuf)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return (False);
+ }
+
+ /*
+ * Do an atomic write into the file at the position defined by
+ * seekpos.
+ */
+
+ /* The mod user write needs to be atomic - so get the fd from
+ the fp and do a raw write() call.
+ */
+
+ fd = fileno(fp);
+
+ if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
+ DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /* Sanity check - ensure the areas we are writing are framed by ':' */
+ if (read(fd, linebuf, wr_len+1) != wr_len+1) {
+ DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) {
+ DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
- if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
- DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- if (write(fd, ascii_p16, wr_len) != wr_len) {
- DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return True;
+ if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
+ DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ if (write(fd, ascii_p16, wr_len) != wr_len) {
+ DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return True;
}
/************************************************************************
@@ -1022,100 +1045,97 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
{
const char *pfile = smbpasswd_state->smbpasswd_file;
- pstring pfile2;
- struct smb_passwd *pwd = NULL;
- FILE *fp = NULL;
- FILE *fp_write = NULL;
- int pfile2_lockdepth = 0;
-
- slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)sys_getpid() );
-
- /*
- * Open the smbpassword file - for update. It needs to be update
- * as we need any other processes to wait until we have replaced
- * it.
- */
-
- if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth))) == NULL) {
- DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
- return False;
- }
-
- /*
- * Create the replacement password file.
- */
- if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
- DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
-
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
-
- while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
- char *new_entry;
- size_t new_entry_length;
-
- if (strequal(name, pwd->smb_name)) {
- DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
- continue;
- }
-
- /*
- * We need to copy the entry out into the second file.
- */
-
- if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL)
- {
- DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
+ pstring pfile2;
+ struct smb_passwd *pwd = NULL;
+ FILE *fp = NULL;
+ FILE *fp_write = NULL;
+ int pfile2_lockdepth = 0;
+
+ slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)sys_getpid() );
+
+ /*
+ * Open the smbpassword file - for update. It needs to be update
+ * as we need any other processes to wait until we have replaced
+ * it.
+ */
+
+ if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth)) == NULL) {
+ DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
+ return False;
+ }
+
+ /*
+ * Create the replacement password file.
+ */
+ if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
+ DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
+
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
+ char *new_entry;
+ size_t new_entry_length;
+
+ if (strequal(name, pwd->smb_name)) {
+ DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
+ continue;
+ }
+
+ /*
+ * We need to copy the entry out into the second file.
+ */
+
+ if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL) {
+ DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
- unlink(pfile2);
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write, &pfile2_lockdepth);
- return False;
- }
+ unlink(pfile2);
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write, &pfile2_lockdepth);
+ return False;
+ }
- new_entry_length = strlen(new_entry);
+ new_entry_length = strlen(new_entry);
- if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length)
- {
- DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
+ if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length) {
+ DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
- unlink(pfile2);
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write, &pfile2_lockdepth);
- free(new_entry);
- return False;
- }
+ unlink(pfile2);
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write, &pfile2_lockdepth);
+ free(new_entry);
+ return False;
+ }
- free(new_entry);
- }
+ free(new_entry);
+ }
- /*
- * Ensure pfile2 is flushed before rename.
- */
+ /*
+ * Ensure pfile2 is flushed before rename.
+ */
- if(fflush(fp_write) != 0)
- {
- DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write,&pfile2_lockdepth);
- return False;
- }
+ if(fflush(fp_write) != 0) {
+ DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write,&pfile2_lockdepth);
+ return False;
+ }
- /*
- * Do an atomic rename - then release the locks.
- */
+ /*
+ * Do an atomic rename - then release the locks.
+ */
- if(rename(pfile2,pfile) != 0) {
- unlink(pfile2);
- }
+ if(rename(pfile2,pfile) != 0) {
+ unlink(pfile2);
+ }
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write,&pfile2_lockdepth);
- return True;
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write,&pfile2_lockdepth);
+ return True;
}
/*********************************************************************
@@ -1123,6 +1143,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
We will not allocate any new memory. The smb_passwd struct
should only stay around as long as the SAM_ACCOUNT does.
********************************************************************/
+
static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass)
{
uint32 rid;
@@ -1166,6 +1187,7 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
/*********************************************************************
Create a SAM_ACCOUNT from a smb_passwd struct
********************************************************************/
+
static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf)
{
@@ -1203,6 +1225,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
/*****************************************************************
Functions to be implemented by the new passdb API
****************************************************************/
+
static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update)
{
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
@@ -1212,15 +1235,13 @@ static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL upda
&(smbpasswd_state->pw_file_lock_depth));
/* did we fail? Should we try to create it? */
- if (!smbpasswd_state->pw_file && update && errno == ENOENT)
- {
+ if (!smbpasswd_state->pw_file && update && errno == ENOENT) {
FILE *fp;
/* slprintf(msg_str,msg_str_len-1,
"smbpasswd file did not exist - attempting to create it.\n"); */
DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w");
- if (fp)
- {
+ if (fp) {
fprintf(fp, "# Samba SMB password file\n");
fclose(fp);
}
@@ -1244,6 +1265,7 @@ static void smbpasswd_endsampwent (struct pdb_methods *my_methods)
/*****************************************************************
****************************************************************/
+
static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -1260,8 +1282,7 @@ static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUN
return nt_status;
}
- while (!done)
- {
+ while (!done) {
/* do we have an entry? */
pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
if (pw_buf == NULL)
@@ -1280,12 +1301,12 @@ static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUN
return NT_STATUS_OK;
}
-
/****************************************************************
Search smbpasswd file by iterating over the entries. Do not
call getpwnam() for unix account information until we have found
the correct entry
***************************************************************/
+
static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
SAM_ACCOUNT *sam_acct, const char *username)
{
diff --git a/source/passdb/pdb_xml.c b/source/passdb/pdb_xml.c
index 64cb73ba5a4..6eff57d365e 100644
--- a/source/passdb/pdb_xml.c
+++ b/source/passdb/pdb_xml.c
@@ -40,6 +40,27 @@ static int xmlsam_debug_level = DBGC_ALL;
#undef DBGC_CLASS
#define DBGC_CLASS xmlsam_debug_level
+
+/* Helper utilities for charset conversion */
+static xmlNodePtr smbXmlNewChild(xmlNodePtr prnt, xmlNsPtr ns, const xmlChar *name, const char *content)
+{
+ char *string_utf8;
+ xmlNodePtr ret;
+
+ if(!content) return xmlNewChild(prnt, ns, name, NULL);
+
+
+ if(push_utf8_allocate(&string_utf8,content) == (size_t)-1)
+ return NULL;
+
+ ret = xmlNewTextChild(prnt, ns, name, string_utf8);
+
+ SAFE_FREE(string_utf8);
+
+ return ret;
+}
+
+
static char * iota(int a) {
static char tmp[10];
@@ -394,72 +415,72 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT
root = xmlNewDocNode(data->doc, NULL, "samba", NULL);
cur = xmlDocSetRootElement(data->doc, root);
data->ns = xmlNewNs(root, XML_URL, "samba");
- data->users = xmlNewChild(root, data->ns, "users", NULL);
+ data->users = smbXmlNewChild(root, data->ns, "users", NULL);
}
- user = xmlNewChild(data->users, data->ns, "user", NULL);
+ user = smbXmlNewChild(data->users, data->ns, "user", NULL);
xmlNewProp(user, "sid",
sid_to_string(sid_str, pdb_get_user_sid(u)));
if (pdb_get_username(u) && strcmp(pdb_get_username(u), ""))
xmlNewProp(user, "name", pdb_get_username(u));
- cur = xmlNewChild(user, data->ns, "group", NULL);
+ cur = smbXmlNewChild(user, data->ns, "group", NULL);
xmlNewProp(cur, "sid",
sid_to_string(sid_str, pdb_get_group_sid(u)));
if (pdb_get_init_flags(u, PDB_LOGONTIME) != PDB_DEFAULT)
- xmlNewChild(user, data->ns, "logon_time",
+ smbXmlNewChild(user, data->ns, "logon_time",
iota(pdb_get_logon_time(u)));
if (pdb_get_init_flags(u, PDB_LOGOFFTIME) != PDB_DEFAULT)
- xmlNewChild(user, data->ns, "logoff_time",
+ smbXmlNewChild(user, data->ns, "logoff_time",
iota(pdb_get_logoff_time(u)));
if (pdb_get_init_flags(u, PDB_KICKOFFTIME) != PDB_DEFAULT)
- xmlNewChild(user, data->ns, "kickoff_time",
+ smbXmlNewChild(user, data->ns, "kickoff_time",
iota(pdb_get_kickoff_time(u)));
if (pdb_get_domain(u) && strcmp(pdb_get_domain(u), ""))
- xmlNewChild(user, data->ns, "domain", pdb_get_domain(u));
+ smbXmlNewChild(user, data->ns, "domain", pdb_get_domain(u));
if (pdb_get_nt_username(u) && strcmp(pdb_get_nt_username(u), ""))
- xmlNewChild(user, data->ns, "nt_username", pdb_get_nt_username(u));
+ smbXmlNewChild(user, data->ns, "nt_username", pdb_get_nt_username(u));
if (pdb_get_fullname(u) && strcmp(pdb_get_fullname(u), ""))
- xmlNewChild(user, data->ns, "fullname", pdb_get_fullname(u));
+ smbXmlNewChild(user, data->ns, "fullname", pdb_get_fullname(u));
if (pdb_get_homedir(u) && strcmp(pdb_get_homedir(u), ""))
- xmlNewChild(user, data->ns, "homedir", pdb_get_homedir(u));
+ smbXmlNewChild(user, data->ns, "homedir", pdb_get_homedir(u));
if (pdb_get_dir_drive(u) && strcmp(pdb_get_dir_drive(u), ""))
- xmlNewChild(user, data->ns, "dir_drive", pdb_get_dir_drive(u));
+ smbXmlNewChild(user, data->ns, "dir_drive", pdb_get_dir_drive(u));
if (pdb_get_logon_script(u) && strcmp(pdb_get_logon_script(u), ""))
- xmlNewChild(user, data->ns, "logon_script",
+ smbXmlNewChild(user, data->ns, "logon_script",
pdb_get_logon_script(u));
if (pdb_get_profile_path(u) && strcmp(pdb_get_profile_path(u), ""))
- xmlNewChild(user, data->ns, "profile_path",
+ smbXmlNewChild(user, data->ns, "profile_path",
pdb_get_profile_path(u));
if (pdb_get_acct_desc(u) && strcmp(pdb_get_acct_desc(u), ""))
- xmlNewChild(user, data->ns, "acct_desc", pdb_get_acct_desc(u));
+ smbXmlNewChild(user, data->ns, "acct_desc", pdb_get_acct_desc(u));
if (pdb_get_workstations(u) && strcmp(pdb_get_workstations(u), ""))
- xmlNewChild(user, data->ns, "workstations",
+ smbXmlNewChild(user, data->ns, "workstations",
pdb_get_workstations(u));
if (pdb_get_unknown_str(u) && strcmp(pdb_get_unknown_str(u), ""))
- xmlNewChild(user, data->ns, "unknown_str", pdb_get_unknown_str(u));
+ smbXmlNewChild(user, data->ns, "unknown_str", pdb_get_unknown_str(u));
if (pdb_get_munged_dial(u) && strcmp(pdb_get_munged_dial(u), ""))
- xmlNewChild(user, data->ns, "munged_dial", pdb_get_munged_dial(u));
+ smbXmlNewChild(user, data->ns, "munged_dial", pdb_get_munged_dial(u));
/* Password stuff */
- pass = xmlNewChild(user, data->ns, "password", NULL);
+ pass = smbXmlNewChild(user, data->ns, "password", NULL);
if (pdb_get_pass_last_set_time(u))
xmlNewProp(pass, "last_set", iota(pdb_get_pass_last_set_time(u)));
if (pdb_get_init_flags(u, PDB_CANCHANGETIME) != PDB_DEFAULT)
@@ -474,29 +495,29 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT
if (pdb_get_lanman_passwd(u)) {
pdb_sethexpwd(temp, pdb_get_lanman_passwd(u),
pdb_get_acct_ctrl(u));
- cur = xmlNewChild(pass, data->ns, "crypt", temp);
+ cur = smbXmlNewChild(pass, data->ns, "crypt", temp);
xmlNewProp(cur, "type", "lanman");
}
if (pdb_get_nt_passwd(u)) {
pdb_sethexpwd(temp, pdb_get_nt_passwd(u), pdb_get_acct_ctrl(u));
- cur = xmlNewChild(pass, data->ns, "crypt", temp);
+ cur = smbXmlNewChild(pass, data->ns, "crypt", temp);
xmlNewProp(cur, "type", "nt");
}
- xmlNewChild(user, data->ns, "acct_ctrl", iota(pdb_get_acct_ctrl(u)));
+ smbXmlNewChild(user, data->ns, "acct_ctrl", iota(pdb_get_acct_ctrl(u)));
if (pdb_get_logon_divs(u))
- xmlNewChild(user, data->ns, "logon_divs",
+ smbXmlNewChild(user, data->ns, "logon_divs",
iota(pdb_get_logon_divs(u)));
if (pdb_get_hours_len(u))
- xmlNewChild(user, data->ns, "hours_len",
+ smbXmlNewChild(user, data->ns, "hours_len",
iota(pdb_get_hours_len(u)));
- xmlNewChild(user, data->ns, "bad_password_count", iota(pdb_get_bad_password_count(u)));
- xmlNewChild(user, data->ns, "logon_count", iota(pdb_get_logon_count(u)));
- xmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u)));
+ smbXmlNewChild(user, data->ns, "bad_password_count", iota(pdb_get_bad_password_count(u)));
+ smbXmlNewChild(user, data->ns, "logon_count", iota(pdb_get_logon_count(u)));
+ smbXmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u)));
xmlSaveFile(data->location, data->doc);
return NT_STATUS_OK;
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 7850924aacb..c3551c9d90a 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -209,6 +209,7 @@ struct table_node {
#define SPL_ARCH_W32MIPS "W32MIPS"
#define SPL_ARCH_W32ALPHA "W32ALPHA"
#define SPL_ARCH_W32PPC "W32PPC"
+#define SPL_ARCH_IA64 "IA64"
static const struct table_node archi_table[]= {
@@ -217,6 +218,7 @@ static const struct table_node archi_table[]= {
{"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
{"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
+ {"Windows IA64", SPL_ARCH_IA64, 3 },
{NULL, "", -1 }
};
diff --git a/source/rpc_client/cli_spoolss.c b/source/rpc_client/cli_spoolss.c
index 8f5f2413dee..5303f83bf9c 100644
--- a/source/rpc_client/cli_spoolss.c
+++ b/source/rpc_client/cli_spoolss.c
@@ -132,6 +132,27 @@ static void decode_printer_info_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
/**********************************************************************
**********************************************************************/
+static void decode_printer_info_7(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
+ uint32 returned, PRINTER_INFO_7 **info)
+{
+ uint32 i;
+ PRINTER_INFO_7 *inf;
+
+ inf=(PRINTER_INFO_7 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_7));
+ memset(inf, 0, returned*sizeof(PRINTER_INFO_7));
+
+ prs_set_offset(&buffer->prs,0);
+
+ for (i=0; i<returned; i++) {
+ smb_io_printer_info_7("", buffer, &inf[i], 0);
+ }
+
+ *info=inf;
+}
+
+
+/**********************************************************************
+**********************************************************************/
static void decode_port_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
uint32 returned, PORT_INFO_1 **info)
{
@@ -626,6 +647,9 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
case 3:
decode_printer_info_3(mem_ctx, r.buffer, 1, &ctr->printers_3);
break;
+ case 7:
+ decode_printer_info_7(mem_ctx, r.buffer, 1, &ctr->printers_7);
+ break;
}
}
diff --git a/source/rpc_client/cli_srvsvc.c b/source/rpc_client/cli_srvsvc.c
index 68eb17074f6..f8580d0fe2e 100644
--- a/source/rpc_client/cli_srvsvc.c
+++ b/source/rpc_client/cli_srvsvc.c
@@ -269,7 +269,8 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
const char *netname, uint32 type,
const char *remark, uint32 perms,
uint32 max_uses, uint32 num_uses,
- const char *path, const char *passwd)
+ const char *path, const char *passwd,
+ int level, SEC_DESC *sd)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_SHARE_ADD q;
@@ -285,7 +286,8 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
- perms, max_uses, num_uses, path, passwd);
+ perms, max_uses, num_uses, path, passwd,
+ level, sd);
/* Marshall data and send request */
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index b42b9b2a8b4..813316177ac 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -2399,11 +2399,9 @@ static BOOL net_io_sam_alias_info(const char *desc, SAM_ALIAS_INFO * info,
info->hdr_sec_desc.buffer, ps, depth))
return False;
- if (info->hdr_als_desc.buffer != 0) {
- if (!smb_io_unistr2("uni_als_desc", &info->uni_als_desc,
- info->hdr_als_name.buffer, ps, depth))
- return False;
- }
+ if (!smb_io_unistr2("uni_als_desc", &info->uni_als_desc,
+ info->hdr_als_desc.buffer, ps, depth))
+ return False;
return True;
}
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index ae087c7f774..2b2038d16ac 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -1053,6 +1053,54 @@ BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2
return True;
}
+/*******************************************************************
+create a SPOOL_PRINTER_INFO_3 struct from a PRINTER_INFO_3 struct
+*******************************************************************/
+
+BOOL make_spoolss_printer_info_3(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3 **spool_info3,
+ PRINTER_INFO_3 *info)
+{
+
+ SPOOL_PRINTER_INFO_LEVEL_3 *inf;
+
+ /* allocate the necessary memory */
+ if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_3*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_3)))) {
+ DEBUG(0,("make_spoolss_printer_info_3: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_3 sruct!\n"));
+ return False;
+ }
+
+ inf->secdesc_ptr = (info->secdesc!=NULL)?1:0;
+
+ *spool_info3 = inf;
+
+ return True;
+}
+
+/*******************************************************************
+create a SPOOL_PRINTER_INFO_7 struct from a PRINTER_INFO_7 struct
+*******************************************************************/
+
+BOOL make_spoolss_printer_info_7(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7 **spool_info7,
+ PRINTER_INFO_7 *info)
+{
+
+ SPOOL_PRINTER_INFO_LEVEL_7 *inf;
+
+ /* allocate the necessary memory */
+ if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_7*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_7)))) {
+ DEBUG(0,("make_spoolss_printer_info_7: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_7 struct!\n"));
+ return False;
+ }
+
+ inf->guid_ptr = (info->guid.buffer!=NULL)?1:0;
+ inf->action = info->action;
+ init_unistr2_from_unistr(&inf->guid, &info->guid);
+
+ *spool_info7 = inf;
+
+ return True;
+}
+
/*******************************************************************
* read a structure.
@@ -4113,6 +4161,24 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
q_u->devmode_ctr.devmode = NULL;
#endif
break;
+ case 3:
+ secdesc = info->printers_3->secdesc;
+
+ make_spoolss_printer_info_3 (mem_ctx, &q_u->info.info_3, info->printers_3);
+
+ q_u->secdesc_ctr = (SEC_DESC_BUF*)malloc(sizeof(SEC_DESC_BUF));
+ if (!q_u->secdesc_ctr)
+ return False;
+ q_u->secdesc_ctr->ptr = (secdesc != NULL) ? 1: 0;
+ q_u->secdesc_ctr->max_len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
+ q_u->secdesc_ctr->len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
+ q_u->secdesc_ctr->sec = secdesc;
+
+ break;
+ case 7:
+ make_spoolss_printer_info_7 (mem_ctx, &q_u->info.info_7, info->printers_7);
+ break;
+
default:
DEBUG(0,("make_spoolss_q_setprinter: Unknown info level [%d]\n", level));
break;
@@ -7358,7 +7424,7 @@ BOOL spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX
if (!prs_set_offset(ps, end_offset))
return False;
- return True;
+ return True;
}
/*******************************************************************
diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c
index 6349fc16325..8313c82c93d 100644
--- a/source/rpc_parse/parse_srv.c
+++ b/source/rpc_parse/parse_srv.c
@@ -1456,19 +1456,38 @@ BOOL srv_io_q_net_share_add(const char *desc, SRV_Q_NET_SHARE_ADD *q_n, prs_stru
void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, const char *srvname,
const char *netname, uint32 type, const char *remark,
uint32 perms, uint32 max_uses, uint32 num_uses,
- const char *path, const char *passwd)
-{
- q->ptr_srv_name = 1;
- init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
- q->info.switch_value = q->info_level = 2;
-
- q->info.ptr_share_ctr = 1;
- init_srv_share_info2(&q->info.share.info2.info_2, netname, type,
- remark, perms, max_uses, num_uses, path, passwd);
- init_srv_share_info2_str(&q->info.share.info2.info_2_str, netname,
- remark, path, passwd);
- q->ptr_err_index = 1;
- q->err_index = 0;
+ const char *path, const char *passwd,
+ int level, SEC_DESC *sd)
+{
+ switch(level) {
+ case 502: {
+ size_t sd_size = sec_desc_size(sd);
+ q->ptr_srv_name = 1;
+ init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
+ q->info.switch_value = q->info_level = level;
+ q->info.ptr_share_ctr = 1;
+ init_srv_share_info502(&q->info.share.info502.info_502, netname, type,
+ remark, perms, max_uses, num_uses, path, passwd, sd, sd_size);
+ init_srv_share_info502_str(&q->info.share.info502.info_502_str, netname,
+ remark, path, passwd, sd, sd_size);
+ q->ptr_err_index = 1;
+ q->err_index = 0;
+ }
+ break;
+ case 2:
+ default:
+ q->ptr_srv_name = 1;
+ init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
+ q->info.switch_value = q->info_level = level;
+ q->info.ptr_share_ctr = 1;
+ init_srv_share_info2(&q->info.share.info2.info_2, netname, type,
+ remark, perms, max_uses, num_uses, path, passwd);
+ init_srv_share_info2_str(&q->info.share.info2.info_2_str, netname,
+ remark, path, passwd);
+ q->ptr_err_index = 1;
+ q->err_index = 0;
+ break;
+ }
}
diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c
index b5871a7e56d..3e0762fa43b 100644
--- a/source/rpc_server/srv_netlog_nt.c
+++ b/source/rpc_server/srv_netlog_nt.c
@@ -445,6 +445,7 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
unsigned char pwd[16];
int i;
uint32 acct_ctrl;
+ const uchar *old_pw;
/* checks and updates credentials. creates reply credentials */
if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)))
@@ -482,34 +483,43 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
return NT_STATUS_ACCOUNT_DISABLED;
}
+ cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
+
DEBUG(100,("Server password set : new given value was :\n"));
for(i = 0; i < 16; i++)
DEBUG(100,("%02X ", q_u->pwd[i]));
DEBUG(100,("\n"));
- cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
+ old_pw = pdb_get_nt_passwd(sampass);
- /* lies! nt and lm passwords are _not_ the same: don't care */
- if (!pdb_set_lanman_passwd (sampass, pwd, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
- return NT_STATUS_NO_MEMORY;
- }
+ if (old_pw && memcmp(pwd, old_pw, 16) == 0) {
+ /* Avoid backend modificiations and other fun if the
+ client changed the password to the *same thing* */
- if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
- return NT_STATUS_NO_MEMORY;
- }
+ ret = True;
+ } else {
- if (!pdb_set_pass_changed_now (sampass)) {
- pdb_free_sam(&sampass);
- /* Not quite sure what this one qualifies as, but this will do */
- return NT_STATUS_UNSUCCESSFUL;
+ /* LM password should be NULL for machines */
+ if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) {
+ pdb_free_sam(&sampass);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) {
+ pdb_free_sam(&sampass);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_pass_changed_now (sampass)) {
+ pdb_free_sam(&sampass);
+ /* Not quite sure what this one qualifies as, but this will do */
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ become_root();
+ ret = pdb_update_sam_account (sampass);
+ unbecome_root();
}
-
- become_root();
- ret = pdb_update_sam_account (sampass);
- unbecome_root();
-
if (ret)
status = NT_STATUS_OK;
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index ce6d9dd37ec..37617db5e8f 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -728,7 +728,17 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN
for (i = 0; i < num_entries; i++) {
pwd = &disp_user_info[i+start_idx];
temp_name = pdb_get_username(pwd);
- init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE);
+
+ /*
+ * usrmgr expects a non-NULL terminated string with
+ * trust relationships
+ */
+ if (pdb_get_acct_ctrl(pwd) & ACB_DOMTRUST) {
+ init_unistr2(&uni_temp_name, temp_name, UNI_FLAGS_NONE);
+ } else {
+ init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE);
+ }
+
user_sid = pdb_get_user_sid(pwd);
if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
@@ -2240,7 +2250,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
if (*add_script) {
int add_ret;
- all_string_sub(add_script, "%u", account, sizeof(account));
+ 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));
}
@@ -3626,7 +3636,7 @@ static int smb_delete_user(const char *unix_user)
pstrcpy(del_script, lp_deluser_script());
if (! *del_script)
return -1;
- all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
+ 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));
@@ -3665,7 +3675,14 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
return NT_STATUS_NO_SUCH_USER;
}
- /* delete the unix side */
+ /* First delete the samba side */
+ if (!pdb_delete_sam_account(sam_pass)) {
+ DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
+ pdb_free_sam(&sam_pass);
+ return NT_STATUS_CANNOT_DELETE;
+ }
+
+ /* Now delete the unix side */
/*
* note: we don't check if the delete really happened
* as the script is not necessary present
@@ -3673,13 +3690,7 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
*/
smb_delete_user(pdb_get_username(sam_pass));
- /* and delete the samba side */
- if (!pdb_delete_sam_account(sam_pass)) {
- DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
- pdb_free_sam(&sam_pass);
- return NT_STATUS_CANNOT_DELETE;
- }
-
+
pdb_free_sam(&sam_pass);
if (!close_policy_hnd(p, &q_u->user_pol))
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index 812939ddf50..d50237905ae 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -64,14 +64,14 @@ struct table_node {
static Printer_entry *printers_list;
typedef struct _counter_printer_0 {
- ubi_dlNode Next;
- ubi_dlNode Prev;
+ struct _counter_printer_0 *next;
+ struct _counter_printer_0 *prev;
int snum;
uint32 counter;
} counter_printer_0;
-static ubi_dlList counter_list;
+static counter_printer_0 *counter_list;
static struct cli_state notify_cli; /* print notify back-channel */
static uint32 smb_connections=0;
@@ -1982,6 +1982,7 @@ static int get_version_id (char * arch)
{"Windows NT R4000", "W32MIPS", 2 },
{"Windows NT Alpha_AXP", "W32ALPHA", 2 },
{"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
{NULL, "", -1 }
};
@@ -3948,9 +3949,7 @@ static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *p
count = print_queue_length(snum, &status);
/* check if we already have a counter for this printer */
- session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
-
- for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
+ for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
if (session_counter->snum == snum)
break;
}
@@ -3964,7 +3963,7 @@ static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *p
ZERO_STRUCTP(session_counter);
session_counter->snum=snum;
session_counter->counter=0;
- ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
+ DLIST_ADD(counter_list, session_counter);
}
/* increment it */
@@ -6238,6 +6237,7 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET
DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
uint32 command = q_u->command;
+ WERROR result;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
@@ -6251,7 +6251,12 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET
case 0:
return control_printer(handle, command, p);
case 2:
- return update_printer(p, handle, level, info, devmode_ctr.devmode);
+ result = update_printer(p, handle, level, info, devmode_ctr.devmode);
+ if (!W_ERROR_IS_OK(result))
+ return result;
+ if (secdesc_ctr)
+ result = update_printer_sec(handle, level, info, p, secdesc_ctr);
+ return result;
case 3:
return update_printer_sec(handle, level, info, p,
secdesc_ctr);
diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c
index 5fa59e1903b..e99cd9f9056 100644
--- a/source/rpcclient/cmd_spoolss.c
+++ b/source/rpcclient/cmd_spoolss.c
@@ -39,6 +39,7 @@ static const struct table_node archi_table[]= {
{"Windows NT R4000", "W32MIPS", 2 },
{"Windows NT Alpha_AXP", "W32ALPHA", 2 },
{"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
{NULL, "", -1 }
};
@@ -296,6 +297,18 @@ static void display_print_info_3(PRINTER_INFO_3 *i3)
printf("\n");
}
+/****************************************************************************
+printer info level 7 display function
+****************************************************************************/
+static void display_print_info_7(PRINTER_INFO_7 *i7)
+{
+ fstring guid = "";
+ rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
+ printf("\tguid:[%s]\n", guid);
+ printf("\taction:[0x%x]\n", i7->action);
+}
+
+
/* Enumerate printers */
static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
@@ -686,6 +699,9 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
case 3:
display_print_info_3(ctr.printers_3);
break;
+ case 7:
+ display_print_info_7(ctr.printers_7);
+ break;
default:
printf("unknown info level %d\n", info_level);
break;
@@ -1126,6 +1142,13 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
cli, mem_ctx, needed, NULL, info_level,
archi_table[i].long_archi, &returned, &ctr);
+ if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
+ printf ("Server does not support environment [%s]\n",
+ archi_table[i].long_archi);
+ werror = WERR_OK;
+ continue;
+ }
+
if (returned == 0)
continue;
diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk
index 4c9507dcf9b..4edc7abc63a 100644
--- a/source/script/mkproto.awk
+++ b/source/script/mkproto.awk
@@ -132,7 +132,7 @@ END {
gotstart = 1;
}
- if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP/ ) {
+ if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP|^u32/ ) {
gotstart = 1;
}
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index 3983a4cbdfb..e143999a785 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -27,8 +27,9 @@ extern char *OutBuffer;
notify. It consists of the requesting SMB and the expiry time.
*****************************************************************************/
-typedef struct {
- ubi_slNode msg_next;
+typedef struct _blocking_lock_record {
+ struct _blocking_lock_record *next;
+ struct _blocking_lock_record *prev;
int com_type;
files_struct *fsp;
time_t expire_time;
@@ -40,7 +41,7 @@ typedef struct {
int length;
} blocking_lock_record;
-static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0};
+static blocking_lock_record *blocking_lock_queue;
/****************************************************************************
Destructor for the above structure.
@@ -48,6 +49,7 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu
static void free_blocking_lock_record(blocking_lock_record *blr)
{
+ DLIST_REMOVE(blocking_lock_queue, blr);
SAFE_FREE(blr->inbuf);
SAFE_FREE(blr);
}
@@ -90,7 +92,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count)
{
static BOOL set_lock_msg;
- blocking_lock_record *blr;
+ blocking_lock_record *blr, *tmp;
BOOL my_lock_ctx = False;
NTSTATUS status;
@@ -136,7 +138,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
return False;
}
- ubi_slAddTail(&blocking_lock_queue, blr);
+ DLIST_ADD_END(blocking_lock_queue, blr, tmp);
/* Ensure we'll receive messages when this is unlocked. */
if (!set_lock_msg) {
@@ -516,10 +518,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr)
void remove_pending_lock_requests_by_fid(files_struct *fsp)
{
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
- blocking_lock_record *prev = NULL;
+ blocking_lock_record *blr, *next = NULL;
- while(blr != NULL) {
+ for(blr = blocking_lock_queue; blr; blr = next) {
+ next = blr->next;
if(blr->fsp->fnum == fsp->fnum) {
DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
@@ -529,13 +531,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
- continue;
+ free_blocking_lock_record(blr);
}
-
- prev = blr;
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
}
@@ -545,10 +542,10 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
void remove_pending_lock_requests_by_mid(int mid)
{
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
- blocking_lock_record *prev = NULL;
+ blocking_lock_record *blr, *next = NULL;
- while(blr != NULL) {
+ for(blr = blocking_lock_queue; blr; blr = next) {
+ next = blr->next;
if(SVAL(blr->inbuf,smb_mid) == mid) {
files_struct *fsp = blr->fsp;
@@ -559,13 +556,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
- continue;
+ free_blocking_lock_record(blr);
}
-
- prev = blr;
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
}
@@ -587,7 +579,7 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
{
unsigned timeout = default_timeout;
time_t t;
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue);
+ blocking_lock_record *blr = blocking_lock_queue;
/* note that we avoid the time() syscall if there are no blocking locks */
if (!blr)
@@ -595,12 +587,11 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
t = time(NULL);
- while (blr) {
+ for (; blr; blr = blr->next) {
if ((blr->expire_time != (time_t)-1) &&
(timeout > (blr->expire_time - t))) {
timeout = blr->expire_time - t;
}
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
if (timeout < 1)
@@ -615,21 +606,19 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
void process_blocking_lock_queue(time_t t)
{
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
- blocking_lock_record *prev = NULL;
-
- if(blr == NULL)
- return;
+ blocking_lock_record *blr, *next = NULL;
/*
* Go through the queue and see if we can get any of the locks.
*/
- while(blr != NULL) {
+ for (blr = blocking_lock_queue; blr; blr = next) {
connection_struct *conn = NULL;
uint16 vuid;
files_struct *fsp = NULL;
+ next = blr->next;
+
/*
* Ensure we don't have any old chain_fsp values
* sitting around....
@@ -658,8 +647,7 @@ void process_blocking_lock_queue(time_t t)
blr->offset, blr->count, True, NULL, NULL);
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
+ free_blocking_lock_record(blr);
continue;
}
@@ -675,8 +663,7 @@ void process_blocking_lock_queue(time_t t)
blr->lock_pid, sys_getpid(), conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
+ free_blocking_lock_record(blr);
continue;
}
@@ -691,8 +678,7 @@ void process_blocking_lock_queue(time_t t)
blr->lock_pid, sys_getpid(), conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
+ free_blocking_lock_record(blr);
change_to_root_user();
continue;
}
@@ -709,18 +695,8 @@ void process_blocking_lock_queue(time_t t)
blr->lock_pid, sys_getpid(), conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
- change_to_root_user();
- continue;
+ free_blocking_lock_record(blr);
}
-
change_to_root_user();
-
- /*
- * Move to the next in the list.
- */
- prev = blr;
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
}
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index 8ea5b9c60a3..af363d75a3f 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -1046,6 +1046,19 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
return NT_STATUS_ACCESS_DENIED;
}
+ /* Use external script to check password complexity */
+ if (lp_check_password_script() && *(lp_check_password_script())) {
+ int check_ret;
+
+ check_ret = smbrunsecret(lp_check_password_script(), new_passwd);
+ DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", lp_check_password_script(), check_ret));
+
+ if (check_ret != 0) {
+ DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ }
+
/*
* If unix password sync was requested, attempt to change
* the /etc/passwd database first. Return failure if this cannot
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index b88f687766d..2bda42f76dc 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -986,112 +986,3 @@ int TellDir(void *p)
return(dirp->pos);
}
-
-/*******************************************************************************
- This section manages a global directory cache.
- (It should probably be split into a separate module. crh)
-********************************************************************************/
-
-typedef struct {
- ubi_dlNode node;
- char *path;
- char *name;
- char *dname;
- int snum;
-} dir_cache_entry;
-
-static ubi_dlNewList( dir_cache );
-
-/*****************************************************************************
- Add an entry to the directory cache.
- Input: path -
- name -
- dname -
- snum -
- Output: None.
-*****************************************************************************/
-
-void DirCacheAdd( const char *path, const char *name, const char *dname, int snum )
-{
- int pathlen;
- int namelen;
- dir_cache_entry *entry;
-
- /*
- * Allocate the structure & string space in one go so that it can be freed
- * in one call to free().
- */
- pathlen = strlen(path) + 1; /* Bytes required to store path (with nul). */
- namelen = strlen(name) + 1; /* Bytes required to store name (with nul). */
- entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry )
- + pathlen
- + namelen
- + strlen( dname ) +1 );
- if( NULL == entry ) /* Not adding to the cache is not fatal, */
- return; /* so just return as if nothing happened. */
-
- /* Set pointers correctly and load values. */
- entry->path = memcpy( (char *)&entry[1], path, strlen(path)+1 );
- entry->name = memcpy( &(entry->path[pathlen]), name, strlen(name)+1 );
- entry->dname = memcpy( &(entry->name[namelen]), dname, strlen(dname)+1 );
- entry->snum = snum;
-
- /* Add the new entry to the linked list. */
- (void)ubi_dlAddHead( dir_cache, entry );
- DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) );
-
- /* Free excess cache entries. */
- while( DIRCACHESIZE < dir_cache->count )
- safe_free( ubi_dlRemTail( dir_cache ) );
-}
-
-/*****************************************************************************
- Search for an entry to the directory cache.
- Input: path -
- name -
- snum -
- Output: The dname string of the located entry, or NULL if the entry was
- not found.
-
- Notes: This uses a linear search, which is is okay because of
- the small size of the cache. Use a splay tree or hash
- for large caches.
-*****************************************************************************/
-
-char *DirCacheCheck( const char *path, const char *name, int snum )
-{
- dir_cache_entry *entry;
-
- for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
- NULL != entry;
- entry = (dir_cache_entry *)ubi_dlNext( entry ) ) {
- if( entry->snum == snum
- && entry->name && 0 == strcmp( name, entry->name )
- && entry->path && 0 == strcmp( path, entry->path ) ) {
- DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
- return( entry->dname );
- }
- }
-
- return(NULL);
-}
-
-/*****************************************************************************
- Remove all cache entries which have an snum that matches the input.
- Input: snum -
- Output: None.
-*****************************************************************************/
-
-void DirCacheFlush(int snum)
-{
- dir_cache_entry *entry;
- ubi_dlNodePtr next;
-
- for(entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
- NULL != entry; ) {
- next = ubi_dlNext( entry );
- if( entry->snum == snum )
- safe_free( ubi_dlRemThis( dir_cache, entry ) );
- entry = (dir_cache_entry *)next;
- }
-}
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index d3660addf11..fc874dc0867 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -95,9 +95,9 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect
static FAKE_FILE fake_files[] = {
#ifdef WITH_QUOTAS
- {FAKE_FILE_NAME_QUOTA, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle},
+ {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle},
#endif /* WITH_QUOTAS */
- {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL }
+ {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL }
};
int is_fake_file(char *fname)
@@ -156,7 +156,7 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
{
if (!fh||!(*fh))
- return ;
+ return;
if ((*fh)->free_pd)
(*fh)->free_pd(&(*fh)->pd);
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index c411ef0f79f..279c9dd3c45 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -26,8 +26,7 @@
#include "includes.h"
-static BOOL scan_directory(const char *path, char *name,size_t maxlength,
- connection_struct *conn,BOOL docache);
+static BOOL scan_directory(connection_struct *conn, const char *path, char *name,size_t maxlength);
/****************************************************************************
Check if two filenames are equal.
@@ -282,10 +281,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
*/
if (ms_has_wild(start) ||
- !scan_directory(dirpath, start,
- sizeof(pstring) - 1 - (start - name),
- conn,
- end?True:False)) {
+ !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) {
if (end) {
/*
* An intermediate part of the name can't be found.
@@ -434,8 +430,7 @@ BOOL check_name(pstring name,connection_struct *conn)
If the name looks like a mangled name then try via the mangling functions
****************************************************************************/
-static BOOL scan_directory(const char *path, char *name, size_t maxlength,
- connection_struct *conn,BOOL docache)
+static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength)
{
void *cur_dir;
const char *dname;
@@ -447,11 +442,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength,
if (*path == 0)
path = ".";
- if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
- safe_strcpy(name, dname, maxlength);
- return(True);
- }
-
/*
* The incoming name can be mangled, and if we de-mangle it
* here it will not compare correctly against the filename (name2)
@@ -489,8 +479,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength,
if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) {
/* we've found the file, change it's name and return */
- if (docache)
- DirCacheAdd(path,name,dname,SNUM(conn));
safe_strcpy(name, dname, maxlength);
CloseDir(cur_dir);
return(True);
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 13ec99a917f..26ddf1b3a3d 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -85,23 +85,6 @@
* if that character is in the illegal characters set.
* This is faster than using strchr_m().
*
- * mangled_cache - Cache header used for storing mangled -> original
- * reverse maps.
- *
- * mc_initialized - False until the mangled_cache structure has been
- * initialized via a call to reset_mangled_cache().
- *
- * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the
- * cache. A value of 0 indicates "infinite".
- *
- * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the
- * cache. When the cache was kept as an array of 256
- * byte strings, the default cache size was 50 entries.
- * This required a fixed 12.5Kbytes of memory. The
- * mangled stack parameter is no longer used (though
- * this might change). We're now using a fixed 16Kbyte
- * maximum cache size. This will probably be much more
- * than 50 entries.
*/
char magic_char = '~';
@@ -118,10 +101,7 @@ static BOOL ct_initialized = False;
#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
-static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
-static BOOL mc_initialized = False;
-#define MANGLED_CACHE_MAX_ENTRIES 1024
-#define MANGLED_CACHE_MAX_MEMORY 0
+static TDB_CONTEXT *tdb_mangled_cache;
/* -------------------------------------------------------------------- */
@@ -400,157 +380,69 @@ static BOOL is_mangled(const char *s)
return( False );
}
-/* ************************************************************************** **
- * Compare two cache keys and return a value indicating their ordinal
- * relationship.
- *
- * Input: ItemPtr - Pointer to a comparison key. In this case, this will
- * be a mangled name string.
- * NodePtr - Pointer to a node in the cache. The node structure
- * will be followed in memory by a mangled name string.
- *
- * Output: A signed integer, as follows:
- * (x < 0) <==> Key1 less than Key2
- * (x == 0) <==> Key1 equals Key2
- * (x > 0) <==> Key1 greater than Key2
- *
- * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for
- * more info.
- *
- * ************************************************************************** **
- */
-static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
-{
- char *Key1 = (char *)ItemPtr;
- char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
-
- return( StrCaseCmp( Key1, Key2 ) );
-}
-
-/* ************************************************************************** **
- * Free a cache entry.
- *
- * Input: WarrenZevon - Pointer to the entry that is to be returned to
- * Nirvana.
- * Output: none.
- *
- * Notes: This function gets around the possibility that the standard
- * free() function may be implemented as a macro, or other evil
- * subversions (oh, so much fun).
- *
- * ************************************************************************** **
- */
-static void cache_free_entry( ubi_trNodePtr WarrenZevon )
-{
- ZERO_STRUCTP(WarrenZevon);
- SAFE_FREE( WarrenZevon );
-}
-
-/* ************************************************************************** **
- * Initializes or clears the mangled cache.
- *
- * Input: none.
- * Output: none.
- *
- * Notes: There is a section below that is commented out. It shows how
- * one might use lp_ calls to set the maximum memory and entry size
- * of the cache. You might also want to remove the constants used
- * in ubi_cacheInit() and replace them with lp_ calls. If so, then
- * the calls to ubi_cacheSetMax*() would be moved into the else
- * clause. Another option would be to pass in the max_entries and
- * max_memory values as parameters. crh 09-Apr-1998.
- *
- * ************************************************************************** **
- */
+/***************************************************************************
+ Initializes or clears the mangled cache.
+***************************************************************************/
static void mangle_reset( void )
{
- if( !mc_initialized ) {
- (void)ubi_cacheInit( mangled_cache,
- cache_compare,
- cache_free_entry,
- MANGLED_CACHE_MAX_ENTRIES,
- MANGLED_CACHE_MAX_MEMORY );
- mc_initialized = True;
- } else {
- (void)ubi_cacheClear( mangled_cache );
- }
-
- /*
- (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
- (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
- */
+ /* We could close and re-open the tdb here... should we ? The old code did
+ the equivalent... JRA. */
}
-/* ************************************************************************** **
- * Add a mangled name into the cache.
- *
- * Notes: If the mangled cache has not been initialized, then the
- * function will simply fail. It could initialize the cache,
- * but that's not the way it was done before I changed the
- * cache mechanism, so I'm sticking with the old method.
- *
- * If the extension of the raw name maps directly to the
- * extension of the mangled name, then we'll store both names
- * *without* extensions. That way, we can provide consistent
- * reverse mangling for all names that match. The test here is
- * a bit more careful than the one done in earlier versions of
- * mangle.c:
- *
- * - the extension must exist on the raw name,
- * - it must be all lower case
- * - it must match the mangled extension (to prove that no
- * mangling occurred).
- *
- * crh 07-Apr-1998
- *
- * ************************************************************************** **
- */
-static void cache_mangled_name( char *mangled_name, char *raw_name )
+/***************************************************************************
+ Add a mangled name into the cache.
+ If the extension of the raw name maps directly to the
+ extension of the mangled name, then we'll store both names
+ *without* extensions. That way, we can provide consistent
+ reverse mangling for all names that match. The test here is
+ a bit more careful than the one done in earlier versions of
+ mangle.c:
+
+ - the extension must exist on the raw name,
+ - it must be all lower case
+ - it must match the mangled extension (to prove that no
+ mangling occurred).
+ crh 07-Apr-1998
+**************************************************************************/
+
+static void cache_mangled_name( const char mangled_name[13], char *raw_name )
{
- ubi_cacheEntryPtr new_entry;
- char *s1;
- char *s2;
- size_t mangled_len;
- size_t raw_len;
- size_t i;
+ TDB_DATA data_val;
+ char mangled_name_key[13];
+ char *s1;
+ char *s2;
/* If the cache isn't initialized, give up. */
- if( !mc_initialized )
+ if( !tdb_mangled_cache )
return;
/* Init the string lengths. */
- mangled_len = strlen( mangled_name );
- raw_len = strlen( raw_name );
+ safe_strcpy(mangled_name_key, mangled_name, sizeof(mangled_name_key)-1);
/* See if the extensions are unmangled. If so, store the entry
* without the extension, thus creating a "group" reverse map.
*/
- s1 = strrchr( mangled_name, '.' );
+ s1 = strrchr( mangled_name_key, '.' );
if( s1 && (s2 = strrchr( raw_name, '.' )) ) {
- i = 1;
+ size_t i = 1;
while( s1[i] && (tolower( s1[i] ) == s2[i]) )
i++;
if( !s1[i] && !s2[i] ) {
- mangled_len -= i;
- raw_len -= i;
+ /* Truncate at the '.' */
+ *s1 = '\0';
+ *s2 = '\0';
}
}
/* Allocate a new cache entry. If the allocation fails, just return. */
- i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
- new_entry = malloc( i );
- if( !new_entry )
- return;
-
- /* Fill the new cache entry, and add it to the cache. */
- s1 = (char *)(new_entry + 1);
- s2 = (char *)&(s1[mangled_len + 1]);
- memcpy( s1, mangled_name, mangled_len );
- s1[mangled_len] = '\0';
- memcpy( s2, raw_name, raw_len );
- s2[raw_len] = '\0';
- ubi_cachePut( mangled_cache, i, new_entry, s1 );
+ data_val.dptr = raw_name;
+ data_val.dsize = strlen(raw_name)+1;
+ if (tdb_store_bystring(tdb_mangled_cache, mangled_name_key, data_val, TDB_REPLACE) != 0) {
+ DEBUG(0,("cache_mangled_name: Error storing entry %s -> %s\n", mangled_name_key, raw_name));
+ } else {
+ DEBUG(5,("cache_mangled_name: Stored entry %s -> %s\n", mangled_name_key, raw_name));
+ }
}
/* ************************************************************************** **
@@ -570,26 +462,25 @@ static void cache_mangled_name( char *mangled_name, char *raw_name )
static BOOL check_cache( char *s, size_t maxlen )
{
- ubi_cacheEntryPtr FoundPtr;
- char *ext_start = NULL;
- char *found_name;
- char *saved_ext = NULL;
+ TDB_DATA data_val;
+ char *ext_start = NULL;
+ char *saved_ext = NULL;
/* If the cache isn't initialized, give up. */
- if( !mc_initialized )
+ if( !tdb_mangled_cache )
return( False );
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+ data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
/* If we didn't find the name *with* the extension, try without. */
- if( !FoundPtr ) {
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
ext_start = strrchr( s, '.' );
if( ext_start ) {
if((saved_ext = strdup(ext_start)) == NULL)
return False;
*ext_start = '\0';
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+ data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
/*
* At this point s is the name without the
* extension. We re-add the extension if saved_ext
@@ -599,7 +490,7 @@ static BOOL check_cache( char *s, size_t maxlen )
}
/* Okay, if we haven't found it we're done. */
- if( !FoundPtr ) {
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
if(saved_ext) {
/* Replace the saved_ext as it was truncated. */
(void)safe_strcat( s, saved_ext, maxlen );
@@ -609,16 +500,13 @@ static BOOL check_cache( char *s, size_t maxlen )
}
/* If we *did* find it, we need to copy it into the string buffer. */
- found_name = (char *)(FoundPtr + 1);
- found_name += (strlen( found_name ) + 1);
-
- (void)safe_strcpy( s, found_name, maxlen );
+ (void)safe_strcpy( s, data_val.dptr, maxlen );
if( saved_ext ) {
/* Replace the saved_ext as it was truncated. */
(void)safe_strcat( s, saved_ext, maxlen );
SAFE_FREE(saved_ext);
}
-
+ SAFE_FREE(data_val.dptr);
return( True );
}
@@ -767,5 +655,9 @@ struct mangle_fns *mangle_hash_init(void)
{
mangle_reset();
+ /* Create the in-memory tdb using our custom hash function. */
+ tdb_mangled_cache = tdb_open_ex("mangled_cache", 1031, TDB_INTERNAL,
+ (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash);
+
return &mangle_fns;
}
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index 5ff53f63007..447073acd84 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -249,6 +249,10 @@ static int reply_nt1(char *inbuf, char *outbuf)
(SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
negotiate_spnego = True;
capabilities |= CAP_EXTENDED_SECURITY;
+ add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
+ /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
+ partially constructed. */
+ SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
}
capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index f717efac63e..d9e321fd968 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -762,16 +762,21 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
set_posix_case_semantics(conn, file_attributes);
unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- restore_case_semantics(conn, file_attributes);
- END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- }
- /* All file access must go through check_name() */
- if (!check_name(fname,conn)) {
- restore_case_semantics(conn, file_attributes);
- END_PROFILE(SMBntcreateX);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+
+ /* FAKE_FILE is a special case */
+ if (fake_file_type == FAKE_FILE_TYPE_NONE) {
+ /* Normal file. */
+ if (bad_path) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+ /* All file access must go through check_name() */
+ if (!check_name(fname,conn)) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ }
}
/*
@@ -1075,7 +1080,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
TALLOC_CTX *mem_ctx;
BOOL ret;
- if (sd_len == 0) {
+ if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
return NT_STATUS_OK;
}
@@ -1409,7 +1414,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Now try and apply the desired SD.
*/
- if (sd_len && !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
+ if (lp_nt_acl_support(SNUM(conn)) && sd_len &&
+ !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
close_file(fsp,False);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 60ce1499e8d..5be68d9f0a1 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -1130,7 +1130,12 @@ const char *smb_fn_name(int type)
Helper functions for contruct_reply.
****************************************************************************/
-static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES;
+static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
+
+void add_to_common_flags2(uint32 v)
+{
+ common_flags2 |= v;
+}
void remove_from_common_flags2(uint32 v)
{
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 794b5332ac5..4d111e0ea35 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -804,7 +804,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
/* Handle non-Dfs clients attempting connections to msdfs proxy */
if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
- DEBUG(3, ("refusing connection to dfs proxy '%s'\n", service));
+ DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
+ service, lp_msdfs_proxy(snum)));
*status = NT_STATUS_BAD_NETWORK_NAME;
return NULL;
}
@@ -821,8 +822,6 @@ close a cnum
****************************************************************************/
void close_cnum(connection_struct *conn, uint16 vuid)
{
- DirCacheFlush(SNUM(conn));
-
if (IS_IPC(conn)) {
pipe_close_conn(conn);
} else {
diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c
index 5e78e9a4999..ba37d4927cc 100644
--- a/source/smbd/statcache.c
+++ b/source/smbd/statcache.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
stat cache code
Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Jeremy Allison 1999-2000
+ Copyright (C) Jeremy Allison 1999-2004
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
This program is free software; you can redistribute it and/or modify
@@ -26,15 +26,7 @@
Stat cache code used in unix_convert.
*****************************************************************************/
-typedef struct {
- char *original_path;
- char *translated_path;
- size_t translated_path_length;
- char names[2]; /* This is extended via malloc... */
-} stat_cache_entry;
-
-#define INIT_STAT_CACHE_SIZE 512
-static hash_table stat_cache;
+static TDB_CONTEXT *tdb_stat_cache;
/**
* Add an entry into the stat cache.
@@ -50,19 +42,17 @@ static hash_table stat_cache;
void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive)
{
- stat_cache_entry *scp;
- stat_cache_entry *found_scp;
char *translated_path;
size_t translated_path_length;
-
+ TDB_DATA data_val;
char *original_path;
size_t original_path_length;
- hash_element *hash_elem;
-
if (!lp_stat_cache())
return;
+ ZERO_STRUCT(data_val);
+
/*
* Don't cache trivial valid directory entries such as . and ..
*/
@@ -124,7 +114,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
return;
}
- /* we only want to store the first part of original_path,
+ /* we only want to index by the first part of original_path,
up to the length of translated_path */
original_path[translated_path_length] = '\0';
@@ -132,55 +122,26 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
}
/*
- * Check this name doesn't exist in the cache before we
- * add it.
- */
-
- if ((hash_elem = hash_lookup(&stat_cache, original_path))) {
- found_scp = (stat_cache_entry *)(hash_elem->value);
- if (strcmp((found_scp->translated_path), orig_translated_path) == 0) {
- /* already in hash table */
- SAFE_FREE(original_path);
- SAFE_FREE(translated_path);
- return;
- }
- /* hash collision - remove before we re-add */
- hash_remove(&stat_cache, hash_elem);
- }
-
- /*
- * New entry.
+ * New entry or replace old entry.
*/
- if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)
- +original_path_length
- +translated_path_length)) == NULL) {
- DEBUG(0,("stat_cache_add: Out of memory !\n"));
- SAFE_FREE(original_path);
- SAFE_FREE(translated_path);
- return;
- }
-
- scp->original_path = scp->names;
- /* pointer into the structure... */
- scp->translated_path = scp->names + original_path_length + 1;
- safe_strcpy(scp->original_path, original_path, original_path_length);
- safe_strcpy(scp->translated_path, translated_path, translated_path_length);
- scp->translated_path_length = translated_path_length;
+ data_val.dsize = translated_path_length + 1;
+ data_val.dptr = translated_path;
- hash_insert(&stat_cache, (char *)scp, original_path);
+ if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) {
+ DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path));
+ } else {
+ DEBUG(5,("stat_cache_add: Added entry (%x:size%x) %s -> %s\n",
+ (unsigned int)data_val.dptr, data_val.dsize, original_path, translated_path));
+ }
SAFE_FREE(original_path);
SAFE_FREE(translated_path);
-
- DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path));
}
/**
* Look through the stat cache for an entry
*
- * The hash-table's internals will promote it to the top if found.
- *
* @param conn A connection struct to do the stat() with.
* @param name The path we are attempting to cache, modified by this routine
* to be correct as far as the cache can tell us
@@ -195,11 +156,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
char **start, SMB_STRUCT_STAT *pst)
{
- stat_cache_entry *scp;
char *chk_name;
size_t namelen;
- hash_element *hash_elem;
- char *sp;
BOOL sizechanged = False;
unsigned int num_components = 0;
@@ -244,8 +202,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
}
while (1) {
- hash_elem = hash_lookup(&stat_cache, chk_name);
- if(hash_elem == NULL) {
+ TDB_DATA data_val;
+ char *sp;
+
+ data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name);
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name ));
/*
* Didn't find it - remove last component for next try.
@@ -275,63 +236,84 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
return False;
}
} else {
- scp = (stat_cache_entry *)(hash_elem->value);
- DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path ));
+ BOOL retval;
+ char *translated_path = data_val.dptr;
+ size_t translated_path_length = data_val.dsize - 1;
+
+ DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path ));
DO_PROFILE_INC(statcache_hits);
- if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) {
+ if(SMB_VFS_STAT(conn,translated_path, pst) != 0) {
/* Discard this entry - it doesn't exist in the filesystem. */
- hash_remove(&stat_cache, hash_elem);
+ tdb_delete_bystring(tdb_stat_cache, chk_name);
SAFE_FREE(chk_name);
+ SAFE_FREE(data_val.dptr);
return False;
}
if (!sizechanged) {
- memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length));
+ memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length));
} else if (num_components == 0) {
- pstrcpy(name, scp->translated_path);
+ pstrcpy(name, translated_path);
} else {
sp = strnrchr_m(name, '/', num_components);
if (sp) {
pstring last_component;
pstrcpy(last_component, sp);
- pstrcpy(name, scp->translated_path);
+ pstrcpy(name, translated_path);
pstrcat(name, last_component);
} else {
- pstrcpy(name, scp->translated_path);
+ pstrcpy(name, translated_path);
}
}
/* set pointer for 'where to start' on fixing the rest of the name */
- *start = &name[scp->translated_path_length];
+ *start = &name[translated_path_length];
if(**start == '/')
++*start;
- pstrcpy(dirpath, scp->translated_path);
+ pstrcpy(dirpath, translated_path);
+ retval = (namelen == translated_path_length) ? True : False;
SAFE_FREE(chk_name);
- return (namelen == scp->translated_path_length);
+ SAFE_FREE(data_val.dptr);
+ return retval;
}
}
}
-/*************************************************************************** **
- * Initializes or clears the stat cache.
- *
- * Input: none.
- * Output: none.
- *
- * ************************************************************************** **
- */
+/***************************************************************
+ Compute a hash value based on a string key value.
+ The function returns the bucket index number for the hashed key.
+ JRA. Use a djb-algorithm hash for speed.
+***************************************************************/
+
+u32 fast_string_hash(TDB_DATA *key)
+{
+ u32 n = 0;
+ const char *p;
+ for (p = key->dptr; *p != '\0'; p++) {
+ n = ((n << 5) + n) ^ (u32)(*p);
+ }
+ return n;
+}
+
+/***************************************************************************
+ Initializes or clears the stat cache.
+**************************************************************************/
+
BOOL reset_stat_cache( void )
{
- static BOOL initialised;
if (!lp_stat_cache())
return True;
- if (initialised) {
- hash_clear(&stat_cache);
+ if (tdb_stat_cache) {
+ tdb_close(tdb_stat_cache);
}
- initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE,
- (compare_function)(strcmp));
- return initialised;
+ /* Create the in-memory tdb using our custom hash function. */
+ tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL,
+ (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash);
+
+ if (!tdb_stat_cache)
+ return False;
+ return True;
}
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
index fec0b3094d3..ae4e439c903 100644
--- a/source/tdb/tdb.c
+++ b/source/tdb/tdb.c
@@ -276,7 +276,7 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
if (tdb->locked[list+1].count == 0) {
if (!tdb->read_only && tdb->header.rwlocks) {
if (tdb_spinlock(tdb, list, ltype)) {
- TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n",
+ TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n",
list, ltype));
return -1;
}
@@ -329,19 +329,6 @@ static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype)
return ret;
}
-/* This is based on the hash algorithm from gdbm */
-static u32 tdb_hash(TDB_DATA *key)
-{
- u32 value; /* Used to compute the hash value. */
- u32 i; /* Used to cycle through random values. */
-
- /* Set the initial value from the key size. */
- for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
- value = (value + (key->dptr[i] << (i*5 % 24)));
-
- return (1103515243 * value + 12345);
-}
-
/* check for an out of bounds access - if it is out of bounds then
see if the database has been expanded by someone else and expand
if necessary
@@ -1121,7 +1108,7 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
u32 hash;
/* find which hash bucket it is in */
- hash = tdb_hash(&key);
+ hash = tdb->hash_fn(&key);
if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb_null;
@@ -1153,7 +1140,7 @@ static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
{
- u32 hash = tdb_hash(&key);
+ u32 hash = tdb->hash_fn(&key);
return tdb_exists_hash(tdb, key, hash);
}
@@ -1413,7 +1400,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
if (!tdb->travlocks.off) {
/* No previous element: do normal find, and lock record */
- tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec);
+ tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
if (!tdb->travlocks.off)
return tdb_null;
tdb->travlocks.hash = BUCKET(rec.full_hash);
@@ -1457,7 +1444,7 @@ static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
{
- u32 hash = tdb_hash(&key);
+ u32 hash = tdb->hash_fn(&key);
return tdb_delete_hash(tdb, key, hash);
}
@@ -1475,7 +1462,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
int ret = 0;
/* find which hash bucket it is in */
- hash = tdb_hash(&key);
+ hash = tdb->hash_fn(&key);
if (!tdb_keylocked(tdb, hash))
return -1;
if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
@@ -1593,7 +1580,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
size_t new_data_size = 0;
/* find which hash bucket it is in */
- hash = tdb_hash(&key);
+ hash = tdb->hash_fn(&key);
if (!tdb_keylocked(tdb, hash))
return -1;
if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
@@ -1689,6 +1676,19 @@ static int tdb_already_open(dev_t device,
return 0;
}
+/* This is based on the hash algorithm from gdbm */
+static u32 default_tdb_hash(TDB_DATA *key)
+{
+ u32 value; /* Used to compute the hash value. */
+ u32 i; /* Used to cycle through random values. */
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
+ value = (value + (key->dptr[i] << (i*5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
+
/* open the database, creating it if necessary
The open_flags and mode are passed straight to the open call on the
@@ -1702,13 +1702,14 @@ static int tdb_already_open(dev_t device,
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode)
{
- return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL);
+ return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
}
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
- tdb_log_func log_fn)
+ tdb_log_func log_fn,
+ tdb_hash_func hash_fn)
{
TDB_CONTEXT *tdb;
struct stat st;
@@ -1728,7 +1729,8 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
tdb->flags = tdb_flags;
tdb->open_flags = open_flags;
tdb->log_fn = log_fn;
-
+ tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
+
if ((open_flags & O_ACCMODE) == O_WRONLY) {
TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
name));
@@ -1973,7 +1975,7 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[])
/* Insertion sort by bucket */
for (i = 0; i < number; i++) {
- hash = tdb_hash(&keys[i]);
+ hash = tdb->hash_fn(&keys[i]);
for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++);
memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j));
tdb->lockedkeys[j+1] = hash;
@@ -2008,22 +2010,22 @@ void tdb_unlockkeys(TDB_CONTEXT *tdb)
contention - it cannot guarantee how many records will be locked */
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK);
+ return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
}
int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK);
+ return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
}
int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK);
+ return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK);
+ return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
@@ -2033,7 +2035,6 @@ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , cons
tdb->log_fn = fn;
}
-
/* reopen a tdb - this can be used after a fork to ensure that we have an independent
seek pointer from our parent and to re-establish locks */
int tdb_reopen(TDB_CONTEXT *tdb)
diff --git a/source/tdb/tdb.h b/source/tdb/tdb.h
index eb120a8cecd..e8a6d201c59 100644
--- a/source/tdb/tdb.h
+++ b/source/tdb/tdb.h
@@ -31,6 +31,17 @@
extern "C" {
#endif
+#ifndef PRINTF_ATTRIBUTE
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#if (__GNUC__ >= 3)
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
/* flags to tdb_store() */
#define TDB_REPLACE 1
@@ -101,18 +112,21 @@ typedef struct tdb_context {
struct tdb_context *next; /* all tdbs to avoid multiple opens */
dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */
- void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */
+ void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
+ u32 (*hash_fn)(TDB_DATA *key);
int open_flags; /* flags used in the open - needed by reopen */
} TDB_CONTEXT;
typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
+typedef u32 (*tdb_hash_func)(TDB_DATA *key);
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
- tdb_log_func log_fn);
+ tdb_log_func log_fn,
+ tdb_hash_func hash_fn);
int tdb_reopen(TDB_CONTEXT *tdb);
int tdb_reopen_all(void);
diff --git a/source/tdb/tdbutil.c b/source/tdb/tdbutil.c
index 09e55e2e702..e57eccfe598 100644
--- a/source/tdb/tdbutil.c
+++ b/source/tdb/tdbutil.c
@@ -740,7 +740,7 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
tdb_flags |= TDB_NOMMAP;
tdb = tdb_open_ex(name, hash_size, tdb_flags,
- open_flags, mode, tdb_log);
+ open_flags, mode, tdb_log, NULL);
if (!tdb)
return NULL;
diff --git a/source/ubiqx/ubi_BinTree.c b/source/ubiqx/ubi_BinTree.c
index 8a4d4612800..e452ac10dc2 100644
--- a/source/ubiqx/ubi_BinTree.c
+++ b/source/ubiqx/ubi_BinTree.c
@@ -26,7 +26,16 @@
*
* -------------------------------------------------------------------------- **
*
- * Log: ubi_BinTree.c,v
+ * Log: ubi_BinTree.c,v
+ * Revision 4.12 2004/06/06 04:51:56 crh
+ * Fixed a small typo in ubi_BinTree.c (leftover testing cruft).
+ * Did a small amount of formatting touchup to ubi_BinTree.h.
+ *
+ * Revision 4.11 2004/06/06 03:14:09 crh
+ * Rewrote the ubi_btLeafNode() function. It now takes several paths in an
+ * effort to find a deeper leaf node. There is a small amount of extra
+ * overhead, but it is limited.
+ *
* Revision 4.10 2000/06/06 20:38:40 crh
* In the ReplaceNode() function, the old node header was being copied
* to the new node header using a byte-by-byte copy. This was causing
@@ -181,14 +190,15 @@
#include "ubi_BinTree.h" /* Header for this module. */
+
/* ========================================================================== **
* Static data.
*/
static char ModuleID[] = "ubi_BinTree\n\
-\tRevision: 4.10 \n\
-\tDate: 2000/06/06 20:38:40 \n\
-\tAuthor: crh \n";
+\tRevision: 4.12\n\
+\tDate: 2004/06/06 04:51:56\n\
+\tAuthor: crh\n";
/* ========================================================================== **
* Internal (private) functions.
@@ -1061,8 +1071,8 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
*
* Input: leader - Pointer to a node at which to start the descent.
*
- * Output: A pointer to a leaf node selected in a somewhat arbitrary
- * manner.
+ * Output: A pointer to a leaf node, selected in a somewhat arbitrary
+ * manner but with an effort to dig deep.
*
* Notes: I wrote this function because I was using splay trees as a
* database cache. The cache had a maximum size on it, and I
@@ -1071,7 +1081,7 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
* tend toward the bottom of the tree, meaning that leaf nodes
* are good candidates for removal. (I really can't think of
* any other reason to use this function.)
- * + In a simple binary tree or an AVL tree, the most recently
+ * + In a simple binary tree, or in an AVL tree, the most recently
* added nodes tend to be nearer the bottom, making this a *bad*
* way to choose which node to remove from the cache.
* + Randomizing the traversal order is probably a good idea. You
@@ -1079,25 +1089,55 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
* in pointers to nodes other than the root node each time. A
* pointer to any node in the tree will do. Of course, if you
* pass a pointer to a leaf node you'll get the same thing back.
+ * + In an unbalanced splay tree, if you simply traverse downward
+ * until you hit a leaf node it is possible to accidentally
+ * stumble onto a short path. The result will be a leaf node
+ * that is actually very high in the tree--possibly a very
+ * recently accessed node. Not good. This function can follow
+ * multiple paths in an effort to find a leaf node deeper
+ * in the tree. Following a single path, of course, is the
+ * fastest way to find a leaf node. A complete traversal would
+ * be sure to find the deepest leaf but would be very costly in
+ * terms of time. This function uses a compromise that has
+ * worked well in testing.
*
* ------------------------------------------------------------------------ **
*/
{
- ubi_btNodePtr follower = NULL;
+ #define MAXPATHS 4 /* Set higher for more maximum paths, lower for fewer. */
+ ubi_trNodePtr p[MAXPATHS];
+ ubi_trNodePtr q[MAXPATHS];
int whichway = ubi_trLEFT;
+ int paths;
+ int i, j;
+
+ /* If the subtree is empty, return NULL.
+ */
+ if( NULL == leader )
+ return( NULL );
- while( NULL != leader )
+ /* Initialize the p[] array with a pointer to the single node we've been
+ * given as a starting point.
+ */
+ p[0] = leader;
+ paths = 1;
+ while( paths > 0 )
{
- follower = leader;
- leader = follower->Link[ whichway ];
- if( NULL == leader )
+ for( i = 0; i < paths; i++ )
+ q[i] = p[i];
+
+ for( i = j = 0; (i < paths) && (j < MAXPATHS); i++ )
{
+ if( NULL != q[i]->Link[whichway] )
+ p[j++] = q[i]->Link[whichway];
whichway = ubi_trRevWay( whichway );
- leader = follower->Link[ whichway ];
+ if( (j < MAXPATHS) && (NULL != q[i]->Link[whichway]) )
+ p[j++] = q[i]->Link[whichway];
}
+ paths = j;
}
- return( follower );
+ return( q[0] );
} /* ubi_btLeafNode */
int ubi_btModuleID( int size, char *list[] )
diff --git a/source/ubiqx/ubi_BinTree.h b/source/ubiqx/ubi_BinTree.h
index c0c6d593094..43ca1a98716 100644
--- a/source/ubiqx/ubi_BinTree.h
+++ b/source/ubiqx/ubi_BinTree.h
@@ -28,7 +28,16 @@
*
* -------------------------------------------------------------------------- **
*
- * Log: ubi_BinTree.h,v
+ * Log: ubi_BinTree.h,v
+ * Revision 4.12 2004/06/06 04:51:56 crh
+ * Fixed a small typo in ubi_BinTree.c (leftover testing cruft).
+ * Did a small amount of formatting touchup to ubi_BinTree.h.
+ *
+ * Revision 4.11 2004/06/06 03:14:09 crh
+ * Rewrote the ubi_btLeafNode() function. It now takes several paths in an
+ * effort to find a deeper leaf node. There is a small amount of extra
+ * overhead, but it is limited.
+ *
* Revision 4.10 2000/06/06 20:38:40 crh
* In the ReplaceNode() function, the old node header was being copied
* to the new node header using a byte-by-byte copy. This was causing
@@ -260,6 +269,7 @@ typedef enum {
* is left as is.
* -------------------------------------------------------------------------- **
*/
+
#define ubi_trNormalize(W) ((char)( (W) - ubi_trEQUAL ))
#define ubi_trAbNormal(W) ((char)( ((char)ubi_btSgn( (long)(W) )) \
+ ubi_trEQUAL ))
@@ -270,6 +280,7 @@ typedef enum {
* DUPlicate KEY bits of the tree root flags field.
* -------------------------------------------------------------------------- **
*/
+
#define ubi_trDups_OK(A) \
((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE))
#define ubi_trOvwt_OK(A) \
@@ -337,6 +348,7 @@ typedef void *ubi_btItemPtr; /* A pointer to key data within a node. */
*
* ------------------------------------------------------------------------- **
*/
+
typedef struct ubi_btNodeStruct {
struct ubi_btNodeStruct *Link[ 3 ];
char gender;
@@ -747,8 +759,8 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
*
* Input: leader - Pointer to a node at which to start the descent.
*
- * Output: A pointer to a leaf node selected in a somewhat arbitrary
- * manner.
+ * Output: A pointer to a leaf node, selected in a somewhat arbitrary
+ * manner but with an effort to dig deep.
*
* Notes: I wrote this function because I was using splay trees as a
* database cache. The cache had a maximum size on it, and I
@@ -757,7 +769,7 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
* tend toward the bottom of the tree, meaning that leaf nodes
* are good candidates for removal. (I really can't think of
* any other reason to use this function.)
- * + In a simple binary tree or an AVL tree, the most recently
+ * + In a simple binary tree, or in an AVL tree, the most recently
* added nodes tend to be nearer the bottom, making this a *bad*
* way to choose which node to remove from the cache.
* + Randomizing the traversal order is probably a good idea. You
@@ -765,6 +777,17 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
* in pointers to nodes other than the root node each time. A
* pointer to any node in the tree will do. Of course, if you
* pass a pointer to a leaf node you'll get the same thing back.
+ * + In an unbalanced splay tree, if you simply traverse downward
+ * until you hit a leaf node it is possible to accidentally
+ * stumble onto a short path. The result will be a leaf node
+ * that is actually very high in the tree--possibly a very
+ * recently accessed node. Not good. This function can follow
+ * multiple paths in an effort to find a leaf node deeper
+ * in the tree. Following a single path, of course, is the
+ * fastest way to find a leaf node. A complete traversal would
+ * be sure to find the deepest leaf but would be very costly in
+ * terms of time. This function uses a compromise that has
+ * worked well in testing.
*
* ------------------------------------------------------------------------ **
*/
diff --git a/source/utils/net.c b/source/utils/net.c
index 67b138a43be..da1339aed10 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -78,6 +78,11 @@ BOOL opt_localgroup = False;
BOOL opt_domaingroup = False;
const char *opt_newntname = "";
int opt_rid = 0;
+int opt_acls = 0;
+int opt_attrs = 0;
+int opt_timestamps = 0;
+const char *opt_exclude = NULL;
+const char *opt_destination = NULL;
BOOL opt_have_ip = False;
struct in_addr opt_dest_ip;
@@ -126,12 +131,13 @@ int net_run_function(int argc, const char **argv, struct functable *table,
return usage_fn(argc, argv);
}
-
/****************************************************************************
-connect to \\server\ipc$
+connect to \\server\service
****************************************************************************/
-NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
- const char *server_name)
+NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip,
+ const char *server_name,
+ const char *service_name,
+ const char *service_type)
{
NTSTATUS nt_status;
@@ -144,7 +150,7 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
nt_status = cli_full_connection(c, NULL, server_name,
server_ip, opt_port,
- "IPC$", "IPC",
+ service_name, service_type,
opt_user_name, opt_workgroup,
opt_password, 0, Undefined, NULL);
@@ -171,6 +177,16 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
}
}
+
+/****************************************************************************
+connect to \\server\ipc$
+****************************************************************************/
+NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
+ const char *server_name)
+{
+ return connect_to_service(c, server_ip, server_name, "IPC$", "IPC");
+}
+
/****************************************************************************
connect to \\server\ipc$ anonymously
****************************************************************************/
@@ -193,6 +209,42 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
}
}
+/**
+ * Connect a server and open a given pipe
+ *
+ * @param cli_dst A cli_state
+ * @param pipe The pipe to open
+ * @param got_pipe boolean that stores if we got a pipe
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS connect_pipe(struct cli_state **cli_dst, int pipe_num, BOOL *got_pipe)
+{
+ NTSTATUS nt_status;
+ char *server_name = strdup("127.0.0.1");
+ struct cli_state *cli_tmp = NULL;
+
+ if (opt_destination)
+ server_name = strdup(opt_destination);
+
+ /* make a connection to a named pipe */
+ nt_status = connect_to_ipc(&cli_tmp, NULL, server_name);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ if (!cli_nt_session_open(cli_tmp, pipe_num)) {
+ DEBUG(0, ("couldn't not initialize pipe\n"));
+ cli_shutdown(cli_tmp);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ *cli_dst = cli_tmp;
+ *got_pipe = True;
+
+ return nt_status;
+}
+
+
/****************************************************************************
Use the local machine's password for this session
****************************************************************************/
@@ -690,6 +742,12 @@ static struct functable net_func[] = {
{"domain", 'D', POPT_ARG_NONE, &opt_domaingroup},
{"ntname", 'N', POPT_ARG_STRING, &opt_newntname},
{"rid", 'R', POPT_ARG_INT, &opt_rid},
+ /* Options for 'net rpc share migrate' */
+ {"acls", 0, POPT_ARG_NONE, &opt_acls},
+ {"attrs", 0, POPT_ARG_NONE, &opt_attrs},
+ {"timestamps", 0, POPT_ARG_NONE, &opt_timestamps},
+ {"exclude", 'e', POPT_ARG_STRING, &opt_exclude},
+ {"destination", 0, POPT_ARG_STRING, &opt_destination},
POPT_COMMON_SAMBA
{ 0, 0, 0, 0}
diff --git a/source/utils/net.h b/source/utils/net.h
index ba3a4e14352..d75a19e498e 100644
--- a/source/utils/net.h
+++ b/source/utils/net.h
@@ -62,6 +62,11 @@ extern BOOL opt_localgroup;
extern BOOL opt_domaingroup;
extern const char *opt_newntname;
extern int opt_rid;
+extern int opt_acls;
+extern int opt_attrs;
+extern int opt_timestamps;
+extern const char *opt_exclude;
+extern const char *opt_destination;
extern BOOL opt_have_ip;
extern struct in_addr opt_dest_ip;
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 7b8ace85b62..2efd470bbe7 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -77,9 +77,12 @@ static int net_ads_lookup(int argc, const char **argv)
ads_connect(ads);
- if (!ads || !ads->config.realm) {
+ if (!ads) {
d_printf("Didn't find the cldap server!\n");
return -1;
+ } if (!ads->config.realm) {
+ ads->config.realm = opt_target_workgroup;
+ ads->ldap_port = 389;
}
return ads_cldap_netlogon(ads);
diff --git a/source/utils/net_ads_cldap.c b/source/utils/net_ads_cldap.c
index 1903172cf75..f3c6c5ff4d2 100644
--- a/source/utils/net_ads_cldap.c
+++ b/source/utils/net_ads_cldap.c
@@ -280,8 +280,9 @@ int ads_cldap_netlogon(ADS_STRUCT *ads)
int sock;
int ret;
struct cldap_netlogon_reply reply;
+ const char *target = opt_host ? opt_host : inet_ntoa(ads->ldap_ip);
- sock = open_udp_socket(inet_ntoa(ads->ldap_ip), ads->ldap_port);
+ sock = open_udp_socket(target, ads->ldap_port);
if (sock == -1) {
d_printf("Failed to open udp socket to %s:%u\n",
inet_ntoa(ads->ldap_ip),
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index 38261be90a7..d6ef5e8a6c3 100644
--- a/source/utils/net_help.c
+++ b/source/utils/net_help.c
@@ -122,13 +122,29 @@ int net_help_share(int argc, const char **argv)
"on target server\n\n"
"net [<method>] share ADD <name=serverpath> [misc. options] [targets]"
"\n\tAdds a share from a server (makes the export active)\n\n"
- "net [<method>] share DELETE <sharename> [misc. options] [targets]\n"
- "\n\tDeletes a share from a server (makes the export inactive)\n");
+ "net [<method>] share DELETE <sharename> [misc. options] [targets]"
+ "\n\tDeletes a share from a server (makes the export inactive)\n\n"
+ "net [<method>] share MIGRATE FILES <sharename> [misc. options] [targets]"
+ "\n\tMigrates files from remote to local server\n\n"
+ "net [<method>] share MIGRATE SHARES <sharename> [misc. options] [targets]"
+ "\n\tMigrates shares from remote to local server\n\n"
+/* "net [<method>] share MIGRATE SECURITY <sharename> [misc. options] [targets]"
+ "\n\tMigrates share-ACLs from remote to local server\n\n" */
+ "net [<method>] share MIGRATE ALL <sharename> [misc. options] [targets]"
+ "\n\tMigrates shares (including directories, files) from remote\n"
+ "\tto local server\n\n"
+ );
net_common_methods_usage(argc, argv);
net_common_flags_usage(argc, argv);
d_printf(
"\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"
- "\t-M or --maxusers=<num>\t\tmax users allowed for share\n");
+ "\t-M or --maxusers=<num>\t\tmax users allowed for share\n"
+ "\t --acls\t\t\tcopies ACLs as well\n"
+ "\t --attrs\t\t\tcopies DOS Attributes as well\n"
+ "\t --timestampes\t\tpreserve timestampes while copying files\n"
+ "\t --destination\t\tmigration target server (default: localhost)\n"
+ "\t-e or --exclude\t\t\tlist of shares to be excluded from mirroring\n"
+ "\t-v or --verbose\t\t\tgive verbose output\n");
return -1;
}
@@ -149,6 +165,35 @@ int net_help_file(int argc, const char **argv)
return -1;
}
+int net_help_printer(int argc, const char **argv)
+{
+ d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"\
+ "\tlists all printers on print-server\n\n");
+ d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"\
+ "\tlists all printer-drivers on print-server\n\n");
+ d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printers from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-settings from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-drivers from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-forms from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-ACLs from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"\
+ "\n\tmigrates drivers, forms, queues, settings and acls from\n"\
+ "\tremote to local print-server\n\n");
+ net_common_methods_usage(argc, argv);
+ net_common_flags_usage(argc, argv);
+ d_printf(
+ "\t-v or --verbose\t\t\tgive verbose output\n"
+ "\t --destination\t\tmigration target server (default: localhost)\n");
+
+ return -1;
+}
+
+
int net_help_status(int argc, const char **argv)
{
d_printf(" net status sessions [parseable] "
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index e21f79df303..1a1d76b09a0 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -2351,6 +2351,7 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
uint32 type=0; /* only allow disk shares to be added */
uint32 num_users=0, perms=0;
char *password=NULL; /* don't allow a share password */
+ uint32 level = 2;
path = strchr(sharename, '=');
if (!path)
@@ -2359,7 +2360,8 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type,
opt_comment, perms, opt_maxusers,
- num_users, path, password);
+ num_users, path, password,
+ level, NULL);
return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
@@ -2492,6 +2494,486 @@ rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name,
}
/**
+ * Migrate shares from a remote RPC server to the local RPC srever
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ SRV_SHARE_INFO_CTR ctr_src;
+ ENUM_HND hnd;
+ uint32 type = 0; /* only allow disk shares to be added */
+ uint32 num_uses = 0, perms = 0, max_uses = 0;
+ char *password = NULL; /* don't allow a share password */
+ uint32 preferred_len = 0xffffffff, i;
+ BOOL got_dst_srvsvc_pipe = False;
+ struct cli_state *cli_dst = NULL;
+ uint32 level = 502; /* includes secdesc */
+ SEC_DESC *share_sd = NULL;
+
+ init_enum_hnd(&hnd, 0);
+
+ result = cli_srvsvc_net_share_enum(
+ cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* connect local PI_SRVSVC */
+ nt_status = connect_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ for (i = 0; i < ctr_src.num_entries; i++) {
+
+ fstring netname = "", remark = "", path = "";
+ /* reset error-code */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ rpcstr_pull_unistr2_fstring(
+ netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(
+ remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
+ rpcstr_pull_unistr2_fstring(
+ path, &ctr_src.share.info502[i].info_502_str.uni_path);
+ num_uses = ctr_src.share.info502[i].info_502.num_uses;
+ max_uses = ctr_src.share.info502[i].info_502.max_uses;
+ perms = ctr_src.share.info502[i].info_502.perms;
+
+
+ if (opt_acls)
+ share_sd = dup_sec_desc(
+ mem_ctx, ctr_src.share.info502[i].info_502_str.sd);
+
+ /* since we do not have NetShareGetInfo implemented in samba3 we
+ only can skip inside the enum-ctr_src */
+ if (argc == 1) {
+ char *one_share = talloc_strdup(mem_ctx, argv[0]);
+ if (!strequal(netname, one_share))
+ continue;
+ }
+
+ /* skip builtin shares */
+ /* FIXME: should print$ be added too ? */
+ if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
+ strequal(netname,"global"))
+ continue;
+
+ /* only work with file-shares */
+ if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+ d_printf("skipping [%s]: not a file share.\n", netname);
+ continue;
+ }
+
+ if (!cli_tdis(cli))
+ goto done;
+
+
+ /* finallly add the share on the dst server
+ please note that samba currently does not allow to
+ add a share without existing directory */
+
+ printf("migrating: [%s], path: %s, comment: %s, %s share-ACLs\n",
+ netname, path, remark, opt_acls ? "including" : "without" );
+
+ if (opt_verbose && opt_acls)
+ display_sec_desc(share_sd);
+
+ result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type,
+ remark, perms, max_uses,
+ num_uses, path, password,
+ level, share_sd);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
+ printf(" [%s] does already exist\n", netname);
+ continue;
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot add share: %s\n", dos_errstr(result));
+ goto done;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (got_dst_srvsvc_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+
+ return nt_status;
+
+}
+
+/**
+ * Migrate shares from a rpc-server to another
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_share_migrate_shares(int argc, const char **argv)
+{
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SRVSVC, 0,
+ rpc_share_migrate_shares_internals,
+ argc, argv);
+}
+
+typedef struct copy_clistate {
+ TALLOC_CTX *mem_ctx;
+ struct cli_state *cli_share_src;
+ struct cli_state *cli_share_dst;
+ const char *cwd;
+} copy_clistate;
+
+
+/**
+ * Copy a file/dir
+ *
+ * @param f file_info
+ * @param mask current search mask
+ * @param state arg-pointer
+ *
+ **/
+static void copy_fn(file_info *f, const char *mask, void *state)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct copy_clistate *local_state = (struct copy_clistate *)state;
+ fstring filename, new_mask, dir;
+
+ if (strequal(f->name, ".") || strequal(f->name, ".."))
+ return;
+
+ DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
+
+ /* DIRECTORY */
+ if (f->mode & aDIR) {
+
+ DEBUG(3,("got dir: %s\n", f->name));
+
+ fstrcpy(dir, local_state->cwd);
+ fstrcat(dir, "\\");
+ fstrcat(dir, f->name);
+
+ /* create that directory */
+ nt_status = net_copy_file(local_state->mem_ctx,
+ local_state->cli_share_src,
+ local_state->cli_share_dst,
+ dir, dir,
+ opt_acls? True : False,
+ opt_attrs? True : False,
+ opt_timestamps? True : False,
+ False);
+
+ if (!NT_STATUS_IS_OK(nt_status))
+ printf("could not copy dir %s: %s\n",
+ dir, nt_errstr(nt_status));
+
+ /* search below that directory */
+ fstrcpy(new_mask, dir);
+ fstrcat(new_mask, "\\*");
+
+ if (!sync_files(local_state->mem_ctx,
+ local_state->cli_share_src,
+ local_state->cli_share_dst,
+ new_mask, dir))
+
+ printf("could not sync files\n");
+
+ return;
+ }
+
+
+ /* FILE */
+ fstrcpy(filename, local_state->cwd);
+ fstrcat(filename, "\\");
+ fstrcat(filename, f->name);
+
+ DEBUG(3,("got file: %s\n", filename));
+
+ nt_status = net_copy_file(local_state->mem_ctx,
+ local_state->cli_share_src,
+ local_state->cli_share_dst,
+ filename, filename,
+ opt_acls? True : False,
+ opt_attrs? True : False,
+ opt_timestamps? True: False,
+ True);
+
+ if (!NT_STATUS_IS_OK(nt_status))
+ printf("could not copy file %s: %s\n",
+ filename, nt_errstr(nt_status));
+
+}
+
+/**
+ * sync files, can be called recursivly to list files
+ * and then call copy_fn for each file
+ *
+ * @param mem_ctx TALLOC_CTX
+ * @param cli_share_src a connected share on the originating server
+ * @param cli_share_dst a connected share on the destination server
+ * @param mask the current search mask
+ * @param cwd the current path
+ *
+ * @return Boolean result
+ **/
+BOOL sync_files(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ pstring mask, fstring cwd)
+
+{
+
+ uint16 attribute = aSYSTEM | aHIDDEN | aDIR;
+ struct copy_clistate clistate;
+
+ clistate.mem_ctx = mem_ctx;
+ clistate.cli_share_src = cli_share_src;
+ clistate.cli_share_dst = cli_share_dst;
+ clistate.cwd = cwd;
+
+ DEBUG(3,("calling cli_list with mask: %s\n", mask));
+
+ if (cli_list(cli_share_src, mask, attribute, copy_fn, &clistate) == -1) {
+ d_printf("listing %s failed with error: %s\n",
+ mask, cli_errstr(cli_share_src));
+ return False;
+ }
+
+ return True;
+}
+
+
+/**
+ * Sync all files inside a remote share to another share (over smb)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ SRV_SHARE_INFO_CTR ctr_src;
+ ENUM_HND hnd;
+ uint32 preferred_len = 0xffffffff, i;
+ uint32 level = 2;
+ struct cli_state *cli_share_src = NULL;
+ struct cli_state *cli_share_dst = NULL;
+ BOOL got_src_share = False;
+ BOOL got_dst_share = False;
+ pstring mask;
+ char *dst = NULL;
+
+ dst = strdup(opt_destination?opt_destination:"127.0.0.1");
+
+ init_enum_hnd(&hnd, 0);
+
+ result = cli_srvsvc_net_share_enum(
+ cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < ctr_src.num_entries; i++) {
+
+ fstring netname = "", remark = "", path = "";
+
+ rpcstr_pull_unistr2_fstring(
+ netname, &ctr_src.share.info2[i].info_2_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(
+ remark, &ctr_src.share.info2[i].info_2_str.uni_remark);
+ rpcstr_pull_unistr2_fstring(
+ path, &ctr_src.share.info2[i].info_2_str.uni_path);
+
+ /* since we do not have NetShareGetInfo implemented in samba3 we
+ only can skip inside the enum-ctr_src */
+ if (argc == 1) {
+ char *one_share = talloc_strdup(mem_ctx, argv[0]);
+ if (!strequal(netname, one_share))
+ continue;
+ }
+
+ /* skip builtin and hidden shares
+ In particular, one might not want to mirror whole discs :) */
+ if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$"))
+ continue;
+
+ if (strequal(netname, "print$") || netname[1] == '$') {
+ d_printf("skipping [%s]: builtin/hidden share\n", netname);
+ continue;
+ }
+
+ if (opt_exclude && in_list(netname, (char *)opt_exclude, False)) {
+ printf("excluding [%s]\n", netname);
+ continue;
+ }
+
+ /* only work with file-shares */
+ if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+ d_printf("skipping [%s]: not a file share.\n", netname);
+ continue;
+ }
+
+ if (!cli_tdis(cli))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ printf("syncing [%s] files and directories %s ACLs, %s DOS Attributes %s\n",
+ netname,
+ opt_acls ? "including" : "without",
+ opt_attrs ? "including" : "without",
+ opt_timestamps ? "(preserving timestamps)" : "");
+
+
+ /* open share source */
+ nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
+ cli->desthost, netname, "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+ got_src_share = True;
+
+
+ /* open share destination */
+ nt_status = connect_to_service(&cli_share_dst, NULL,
+ dst, netname, "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+ got_dst_share = True;
+
+
+ /* now call the filesync */
+ pstrcpy(mask, "\\*");
+
+ if (!sync_files(mem_ctx, cli_share_src, cli_share_dst, mask, NULL)) {
+ d_printf("could not sync files for share: %s\n", netname);
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_src_share)
+ cli_shutdown(cli_share_src);
+
+ if (got_dst_share)
+ cli_shutdown(cli_share_dst);
+
+ return nt_status;
+
+}
+
+static int rpc_share_migrate_files(int argc, const char **argv)
+{
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SRVSVC, 0,
+ rpc_share_migrate_files_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
+ * from one server to another
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ *
+ **/
+static int rpc_share_migrate_all(int argc, const char **argv)
+{
+ int ret;
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
+ if (ret)
+ return ret;
+#if 0
+ ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_security_internals, argc, argv);
+ if (ret)
+ return ret;
+#endif
+ return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
+}
+
+
+/**
+ * 'net rpc share migrate' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+static int rpc_share_migrate(int argc, const char **argv)
+{
+
+ struct functable func[] = {
+ {"all", rpc_share_migrate_all},
+ {"files", rpc_share_migrate_files},
+ {"help", rpc_share_usage},
+/* {"security", rpc_share_migrate_security},*/
+ {"shares", rpc_share_migrate_shares},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, rpc_share_usage);
+}
+
+/**
* 'net rpc share' entrypoint.
* @param argc Standard main() style argc
* @param argv Standard main() style argv. Initial components are already
@@ -2503,6 +2985,7 @@ int net_rpc_share(int argc, const char **argv)
struct functable func[] = {
{"add", rpc_share_add},
{"delete", rpc_share_delete},
+ {"migrate", rpc_share_migrate},
{NULL, NULL}
};
@@ -3570,6 +4053,252 @@ static int rpc_vampire(int argc, const char **argv) {
return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
argc, argv);
}
+
+/**
+ * Migrate everything from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ *
+ * The order is important !
+ * To successfully add drivers the print-queues have to exist !
+ * Applying ACLs should be the last step, because you're easily locked out
+ *
+ **/
+static int rpc_printer_migrate_all(int argc, const char **argv)
+{
+ int ret;
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
+
+}
+
+/**
+ * Migrate print-drivers from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_drivers(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_drivers_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate print-forms from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_forms(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_forms_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate printers from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_printers(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_printers_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate printer-ACLs from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_security(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_security_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate printer-settings from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_settings(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_settings_internals,
+ argc, argv);
+}
+
+/**
+ * 'net rpc printer' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+int rpc_printer_migrate(int argc, const char **argv)
+{
+
+ /* ouch: when addriver and setdriver are called from within
+ rpc_printer_migrate_drivers_internals, the printer-queue already
+ *has* to exist */
+
+ struct functable func[] = {
+ {"all", rpc_printer_migrate_all},
+ {"drivers", rpc_printer_migrate_drivers},
+ {"forms", rpc_printer_migrate_forms},
+ {"help", rpc_printer_usage},
+ {"printers", rpc_printer_migrate_printers},
+ {"security", rpc_printer_migrate_security},
+ {"settings", rpc_printer_migrate_settings},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, rpc_printer_usage);
+}
+
+
+/**
+ * List printers on a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_list(int argc, const char **argv)
+{
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_list_internals,
+ argc, argv);
+}
+
+/**
+ * List printer-drivers on a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_driver_list(int argc, const char **argv)
+{
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_driver_list_internals,
+ argc, argv);
+}
+
+/**
+ * Display rpc printer help page.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+int rpc_printer_usage(int argc, const char **argv)
+{
+ return net_help_printer(argc, argv);
+}
+
+/**
+ * 'net rpc printer' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+int net_rpc_printer(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"list", rpc_printer_list},
+ {"migrate", rpc_printer_migrate},
+ {"driver", rpc_printer_driver_list},
+ {NULL, NULL}
+ };
+
+ if (argc == 0)
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_list_internals,
+ argc, argv);
+
+ return net_run_function(argc, argv, func, rpc_printer_usage);
+}
+
/****************************************************************************/
@@ -3589,7 +4318,8 @@ int net_rpc_usage(int argc, const char **argv)
d_printf(" net rpc user \t\t\tto add, delete and list users\n");
d_printf(" net rpc password <username> [<password>] -Uadmin_username%%admin_pass");
d_printf(" net rpc group \t\tto list groups\n");
- d_printf(" net rpc share \t\tto add, delete, and list shares\n");
+ d_printf(" net rpc share \t\tto add, delete, list and migrate shares\n");
+ d_printf(" net rpc printer \t\tto list and migrate printers\n");
d_printf(" net rpc file \t\t\tto list open files\n");
d_printf(" net rpc changetrustpw \tto change the trust account password\n");
d_printf(" net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
@@ -3659,6 +4389,7 @@ int net_rpc(int argc, const char **argv)
{"group", net_rpc_group},
{"share", net_rpc_share},
{"file", net_rpc_file},
+ {"printer", net_rpc_printer},
{"changetrustpw", net_rpc_changetrustpw},
{"trustdom", rpc_trustdom},
{"abortshutdown", rpc_shutdown_abort},
diff --git a/source/utils/net_rpc_printer.c b/source/utils/net_rpc_printer.c
new file mode 100644
index 00000000000..51f4df7b05a
--- /dev/null
+++ b/source/utils/net_rpc_printer.c
@@ -0,0 +1,2339 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2004 Guenther Deschner (gd@samba.org)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "includes.h"
+#include "../utils/net.h"
+
+struct table_node {
+ const char *long_archi;
+ const char *short_archi;
+ int version;
+};
+
+
+/* support itanium as well */
+static const struct table_node archi_table[]= {
+
+ {"Windows 4.0", "WIN40", 0 },
+ {"Windows NT x86", "W32X86", 2 },
+ {"Windows NT R4000", "W32MIPS", 2 },
+ {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
+ {"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
+ {NULL, "", -1 }
+};
+
+
+/**
+ * The display-functions for Security-Descriptors were taken from rpcclient
+ *
+ * They reside here for debugging purpose and should
+ * possibly be removed later on
+ *
+ **/
+/****************************************************************************
+convert a security permissions into a string
+****************************************************************************/
+char *get_sec_mask_str(uint32 type)
+{
+ static fstring typestr="";
+
+ typestr[0] = 0;
+
+ if (type & GENERIC_ALL_ACCESS)
+ fstrcat(typestr, "Generic all access ");
+ if (type & GENERIC_EXECUTE_ACCESS)
+ fstrcat(typestr, "Generic execute access ");
+ if (type & GENERIC_WRITE_ACCESS)
+ fstrcat(typestr, "Generic write access ");
+ if (type & GENERIC_READ_ACCESS)
+ fstrcat(typestr, "Generic read access ");
+ if (type & MAXIMUM_ALLOWED_ACCESS)
+ fstrcat(typestr, "MAXIMUM_ALLOWED_ACCESS ");
+ if (type & SYSTEM_SECURITY_ACCESS)
+ fstrcat(typestr, "SYSTEM_SECURITY_ACCESS ");
+ if (type & SYNCHRONIZE_ACCESS)
+ fstrcat(typestr, "SYNCHRONIZE_ACCESS ");
+ if (type & WRITE_OWNER_ACCESS)
+ fstrcat(typestr, "WRITE_OWNER_ACCESS ");
+ if (type & WRITE_DAC_ACCESS)
+ fstrcat(typestr, "WRITE_DAC_ACCESS ");
+ if (type & READ_CONTROL_ACCESS)
+ fstrcat(typestr, "READ_CONTROL_ACCESS ");
+ if (type & DELETE_ACCESS)
+ fstrcat(typestr, "DELETE_ACCESS ");
+
+ printf("\t\tSpecific bits: 0x%lx\n", (unsigned long)type&SPECIFIC_RIGHTS_MASK);
+
+ return typestr;
+}
+
+
+/****************************************************************************
+ display sec_ace structure
+ ****************************************************************************/
+void display_sec_ace(SEC_ACE *ace)
+{
+ fstring sid_str;
+
+ printf("\tACE\n\t\ttype: ");
+ switch (ace->type) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED:
+ printf("ACCESS ALLOWED");
+ break;
+ case SEC_ACE_TYPE_ACCESS_DENIED:
+ printf("ACCESS DENIED");
+ break;
+ case SEC_ACE_TYPE_SYSTEM_AUDIT:
+ printf("SYSTEM AUDIT");
+ break;
+ case SEC_ACE_TYPE_SYSTEM_ALARM:
+ printf("SYSTEM ALARM");
+ break;
+ default:
+ printf("????");
+ break;
+ }
+ printf(" (%d) flags: %d\n", ace->type, ace->flags);
+ printf("\t\tPermissions: 0x%x: %s\n", ace->info.mask, get_sec_mask_str(ace->info.mask));
+
+ sid_to_string(sid_str, &ace->trustee);
+ printf("\t\tSID: %s\n\n", sid_str);
+}
+
+
+/****************************************************************************
+ display sec_acl structure
+ ****************************************************************************/
+void display_sec_acl(SEC_ACL *sec_acl)
+{
+ int i;
+
+ printf("\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
+ sec_acl->num_aces, sec_acl->revision);
+ printf("\t---\n");
+
+ if (sec_acl->size != 0 && sec_acl->num_aces != 0)
+ for (i = 0; i < sec_acl->num_aces; i++)
+ display_sec_ace(&sec_acl->ace[i]);
+
+}
+
+/****************************************************************************
+ display sec_desc structure
+ ****************************************************************************/
+void display_sec_desc(SEC_DESC *sec)
+{
+ fstring sid_str;
+
+ if (sec == NULL)
+ return;
+
+ if (sec->sacl) {
+ printf("SACL\n");
+ display_sec_acl(sec->sacl);
+ }
+
+ if (sec->dacl) {
+ printf("DACL\n");
+ display_sec_acl(sec->dacl);
+ }
+
+ if (sec->owner_sid) {
+ sid_to_string(sid_str, sec->owner_sid);
+ printf("\tOwner SID:\t%s\n", sid_str);
+ }
+
+ if (sec->grp_sid) {
+ sid_to_string(sid_str, sec->grp_sid);
+ printf("\tParent SID:\t%s\n", sid_str);
+ }
+}
+
+
+/**
+ * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
+ * It is here for debugging purpose and should be removed later on.
+ **/
+
+/****************************************************************************
+printer info level 3 display function
+****************************************************************************/
+static void display_print_driver_3(DRIVER_INFO_3 *i1)
+{
+ fstring name = "";
+ fstring architecture = "";
+ fstring driverpath = "";
+ fstring datafile = "";
+ fstring configfile = "";
+ fstring helpfile = "";
+ fstring dependentfiles = "";
+ fstring monitorname = "";
+ fstring defaultdatatype = "";
+
+ int length=0;
+ BOOL valid = True;
+
+ if (i1 == NULL)
+ return;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
+ rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
+ rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
+ rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+ rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
+ rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
+ rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
+
+ d_printf ("Printer Driver Info 3:\n");
+ d_printf ("\tVersion: [%x]\n", i1->version);
+ d_printf ("\tDriver Name: [%s]\n",name);
+ d_printf ("\tArchitecture: [%s]\n", architecture);
+ d_printf ("\tDriver Path: [%s]\n", driverpath);
+ d_printf ("\tDatafile: [%s]\n", datafile);
+ d_printf ("\tConfigfile: [%s]\n", configfile);
+ d_printf ("\tHelpfile: [%s]\n\n", helpfile);
+
+ while (valid) {
+ rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
+
+ length+=strlen(dependentfiles)+1;
+
+ if (strlen(dependentfiles) > 0) {
+ d_printf ("\tDependentfiles: [%s]\n", dependentfiles);
+ } else {
+ valid = False;
+ }
+ }
+
+ printf ("\n");
+
+ d_printf ("\tMonitorname: [%s]\n", monitorname);
+ d_printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
+
+ return;
+}
+
+
+static void display_reg_value(pstring subkey, REGISTRY_VALUE value)
+{
+ pstring text;
+
+ switch(value.type) {
+ case REG_DWORD:
+ d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename,
+ *((uint32 *) value.data_p));
+ break;
+
+ case REG_SZ:
+ rpcstr_pull(text, value.data_p, sizeof(text), value.size,
+ STR_TERMINATE);
+ d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
+ break;
+
+ case REG_BINARY:
+ d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n",
+ subkey, value.valuename);
+ break;
+
+ case REG_MULTI_SZ: {
+ uint16 *curstr = (uint16 *) value.data_p;
+ uint8 *start = value.data_p;
+ d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename);
+ while ((*curstr != 0) &&
+ ((uint8 *) curstr < start + value.size)) {
+ rpcstr_pull(text, curstr, sizeof(text), -1,
+ STR_TERMINATE);
+ d_printf("%s\n", text);
+ curstr += strlen(text) + 1;
+ }
+ }
+ break;
+
+ default:
+ d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
+ }
+
+}
+
+
+/**
+ * Copies ACLs, DOS-attributes and timestamps from one
+ * file or directory from one connected share to another connected share
+ *
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A connected cli_state
+ * @param cli_share_dst A connected cli_state
+ * @param src_file The source file-name
+ * @param dst_file The destination file-name
+ * @param copy_acls Whether to copy acls
+ * @param copy_attrs Whether to copy DOS attributes
+ * @param copy_timestamps Whether to preserve timestamps
+ * @param is_file Whether this file is a file or a dir
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+net_copy_fileattr(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ char *src_name, char *dst_name,
+ BOOL copy_acls, BOOL copy_attrs,
+ BOOL copy_timestamps, BOOL is_file)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int fnum_src = 0;
+ int fnum_dst = 0;
+ SEC_DESC *sd = NULL;
+ uint16 attr;
+ time_t atime, ctime, mtime;
+
+
+ if (!copy_timestamps && !copy_acls && !copy_attrs)
+ return NT_STATUS_OK;
+
+
+ /* open file/dir on the originating server */
+
+ DEBUGADD(3,("opening %s %s on originating server\n",
+ is_file?"file":"dir", src_name));
+
+ fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
+ if (fnum_src == -1) {
+ DEBUGADD(0,("cannot open %s %s on originating server %s\n",
+ is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+
+ if (copy_acls) {
+
+ /* get the security descriptor */
+ sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
+ if (!sd) {
+ DEBUG(0,("failed to get security descriptor: %s\n",
+ cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+ if (opt_verbose && DEBUGLEVEL >= 3)
+ display_sec_desc(sd);
+ }
+
+
+ if (copy_attrs || copy_timestamps) {
+
+ /* get file attributes */
+ if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
+ &ctime, &atime, &mtime)) {
+ DEBUG(0,("failed to get file-attrs: %s\n",
+ cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+ }
+
+
+ /* open the file/dir on the destination server */
+
+ fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
+ if (fnum_dst == -1) {
+ DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
+ is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ if (copy_timestamps) {
+
+ /* set timestamps */
+ if (!cli_setattrE(cli_share_dst, fnum_dst, ctime, atime, mtime)) {
+ DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
+ cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+ }
+
+ if (copy_acls) {
+
+ /* set acls */
+ if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
+ DEBUG(0,("could not set secdesc on %s: %s\n",
+ dst_name, cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+ }
+
+ if (copy_attrs) {
+
+ /* set attrs */
+ if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) {
+ DEBUG(0,("failed to set file-attrs: %s\n",
+ cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+ }
+
+
+ /* closing files */
+
+ if (!cli_close(cli_share_src, fnum_src)) {
+ d_printf("could not close %s on originating server: %s\n",
+ is_file?"file":"dir", cli_errstr(cli_share_src));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+ if (!cli_close(cli_share_dst, fnum_dst)) {
+ d_printf("could not close %s on destination server: %s\n",
+ is_file?"file":"dir", cli_errstr(cli_share_dst));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+
+ nt_status = NT_STATUS_OK;
+
+out:
+
+ /* cleaning up */
+ if (fnum_src)
+ cli_close(cli_share_src, fnum_src);
+
+ if (fnum_dst)
+ cli_close(cli_share_dst, fnum_dst);
+
+ return nt_status;
+}
+
+
+/**
+ * Copy a file or directory from a connected share to another connected share
+ *
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A connected cli_state
+ * @param cli_share_dst A connected cli_state
+ * @param src_file The source file-name
+ * @param dst_file The destination file-name
+ * @param copy_acls Whether to copy acls
+ * @param copy_attrs Whether to copy DOS attributes
+ * @param copy_timestamps Whether to preserve timestamps
+ * @param is_file Whether this file is a file or a dir
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ char *src_name, char *dst_name,
+ BOOL copy_acls, BOOL copy_attrs,
+ BOOL copy_timestamps, BOOL is_file)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int fnum_src = 0;
+ int fnum_dst = 0;
+ static int io_bufsize = 64512;
+ int read_size = io_bufsize;
+ char *data = NULL;
+ off_t start = 0;
+ off_t nread = 0;
+
+
+ if (!src_name || !dst_name)
+ goto out;
+
+ if (cli_share_dst == NULL || cli_share_dst == NULL)
+ goto out;
+
+
+ /* open on the originating server */
+ DEBUGADD(3,("opening %s %s on originating server\n",
+ is_file ? "file":"dir", src_name));
+ if (is_file)
+ fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
+ else
+ fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
+
+ if (fnum_src == -1) {
+ DEBUGADD(0,("cannot open file %s on originating server %s\n",
+ src_name, cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+
+ if (is_file) {
+
+ /* open file on the destination server */
+ DEBUGADD(3,("opening file %s on destination server\n", dst_name));
+ fnum_dst = cli_open(cli_share_dst, dst_name,
+ O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+
+ if (fnum_dst == -1) {
+ DEBUGADD(1,("cannot create file %s on destination server: %s\n",
+ dst_name, cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ /* allocate memory */
+ if (!(data = (char *)malloc(read_size))) {
+ d_printf("malloc fail for size %d\n", read_size);
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ }
+
+
+ if (opt_verbose) {
+
+ d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
+ "%s ACLs and %s DOS Attributes %s\n",
+ cli_share_src->desthost, cli_share_src->share, src_name,
+ cli_share_dst->desthost, cli_share_dst->share, dst_name,
+ copy_acls ? "with" : "without",
+ copy_attrs ? "with" : "without",
+ copy_timestamps ? "(preserving timestamps)" : "" );
+ }
+
+
+ while (is_file) {
+
+ /* copying file */
+ int n, ret;
+ n = cli_read(cli_share_src, fnum_src, data, nread + start,
+ read_size);
+
+ if (n <= 0)
+ break;
+
+ ret = cli_write(cli_share_dst, fnum_dst, 0, data,
+ nread + start, n);
+
+ if (n != ret) {
+ d_printf("Error writing file: %s\n",
+ cli_errstr(cli_share_dst));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ nread += n;
+ }
+
+
+ if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
+
+ /* creating dir */
+ DEBUGADD(3,("creating dir %s on the destination server\n",
+ dst_name));
+
+ if (!cli_mkdir(cli_share_dst, dst_name)) {
+ DEBUG(0,("cannot create directory %s: %s\n",
+ dst_name, cli_errstr(cli_share_dst)));
+ nt_status = NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!cli_chkpath(cli_share_dst, dst_name)) {
+ d_printf("cannot check for directory %s: %s\n",
+ dst_name, cli_errstr(cli_share_dst));
+ goto out;
+ }
+ }
+
+
+ /* closing files */
+ if (!cli_close(cli_share_src, fnum_src)) {
+ d_printf("could not close file on originating server: %s\n",
+ cli_errstr(cli_share_src));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+ if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
+ d_printf("could not close file on destination server: %s\n",
+ cli_errstr(cli_share_dst));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ /* possibly we have to copy some file-attributes / acls / sd */
+ nt_status = net_copy_fileattr(mem_ctx, cli_share_src, cli_share_dst,
+ src_name, dst_name, copy_acls,
+ copy_attrs, copy_timestamps, is_file);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto out;
+
+
+ nt_status = NT_STATUS_OK;
+
+out:
+
+ /* cleaning up */
+ if (fnum_src)
+ cli_close(cli_share_src, fnum_src);
+
+ if (fnum_dst)
+ cli_close(cli_share_dst, fnum_dst);
+
+ SAFE_FREE(data);
+
+ return nt_status;
+}
+
+
+/**
+ * Copy a driverfile from on connected share to another connected share
+ * This silently assumes that a driver-file is picked up from
+ *
+ * \\src_server\print$\{arch}\{version}\file
+ *
+ * and copied to
+ *
+ * \\dst_server\print$\{arch}\file
+ *
+ * to be added via setdriver-calls later.
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A cli_state connected to source print$-share
+ * @param cli_share_dst A cli_state connected to destination print$-share
+ * @param file The file-name to be copied
+ * @param short_archi The name of the driver-architecture (short form)
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ char *file, const char *short_archi) {
+
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ const char *p;
+ char *src_name;
+ char *dst_name;
+ fstring version;
+ fstring filename;
+ fstring tok;
+
+ /* scroll through the file until we have the part
+ beyond archi_table.short_archi */
+ p = file;
+ while (next_token(&p, tok, "\\", sizeof(tok))) {
+ if (strequal(tok, short_archi)) {
+ next_token(&p, version, "\\", sizeof(version));
+ next_token(&p, filename, "\\", sizeof(filename));
+ }
+ }
+
+ /* build source file name */
+ if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 )
+ return NT_STATUS_NO_MEMORY;
+
+
+ /* create destination file name */
+ if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
+ return NT_STATUS_NO_MEMORY;
+
+
+ /* finally copy the file */
+ nt_status = net_copy_file(mem_ctx, cli_share_src, cli_share_dst,
+ src_name, dst_name, False, False, False, True);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto out;
+
+ nt_status = NT_STATUS_OK;
+
+out:
+ SAFE_FREE(src_name);
+ SAFE_FREE(dst_name);
+
+ return nt_status;
+}
+
+
+/**
+ * Check for existing Architecture directory on a given server
+ *
+ * @param cli_share A cli_state connected to a print$-share
+ * @param short_archi The Architecture for the print-driver
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+check_arch_dir(struct cli_state *cli_share, const char *short_archi)
+{
+
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char *dir;
+
+ if (asprintf(&dir, "\\%s", short_archi) < 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DEBUG(10,("creating print-driver dir for architecture: %s\n",
+ short_archi));
+
+ if (!cli_mkdir(cli_share, dir)) {
+ DEBUG(1,("cannot create directory %s: %s\n",
+ dir, cli_errstr(cli_share)));
+ nt_status = NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!cli_chkpath(cli_share, dir)) {
+ d_printf("cannot check %s: %s\n",
+ dir, cli_errstr(cli_share));
+ goto out;
+ }
+
+ nt_status = NT_STATUS_OK;
+
+out:
+ SAFE_FREE(dir);
+ return nt_status;
+}
+
+
+/**
+ * Copy a print-driver (level 3) from one connected print$-share to another
+ * connected print$-share
+ *
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A cli_state connected to a print$-share
+ * @param cli_share_dst A cli_state connected to a print$-share
+ * @param short_archi The Architecture for the print-driver
+ * @param i1 The DRIVER_INFO_3-struct
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+copy_print_driver_3(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ const char *short_archi, DRIVER_INFO_3 *i1)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int length = 0;
+ BOOL valid = True;
+
+ fstring name = "";
+ fstring driverpath = "";
+ fstring datafile = "";
+ fstring configfile = "";
+ fstring helpfile = "";
+ fstring dependentfiles = "";
+
+ if (i1 == NULL)
+ return nt_status;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
+ rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
+ rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+ rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
+
+
+ if (opt_verbose)
+ d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
+ name, short_archi, i1->version);
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ driverpath, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ datafile, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ configfile, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ helpfile, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ while (valid) {
+ rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
+ length+=strlen(dependentfiles)+1;
+ if (strlen(dependentfiles) > 0) {
+
+ nt_status = net_copy_driverfile(mem_ctx,
+ cli_share_src, cli_share_dst,
+ dependentfiles, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+ } else {
+ valid = False;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ * net_spoolss-functions
+ * =====================
+ *
+ * the net_spoolss-functions aim to simplify spoolss-client-functions
+ * required during the migration-process wrt buffer-sizes, returned
+ * error-codes, etc.
+ *
+ * this greatly reduces the complexitiy of the migrate-functions.
+ *
+ **/
+
+static BOOL
+net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ char *name, uint32 flags, uint32 level,
+ uint32 *num_printers, PRINTER_INFO_CTR *ctr)
+{
+
+ WERROR result;
+ uint32 needed;
+
+ /* enum printers */
+ result = cli_spoolss_enum_printers(
+ cli, mem_ctx, 0, &needed, name, flags,
+ level, num_printers, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_enum_printers(
+ cli, mem_ctx, needed, NULL, name, flags,
+ level, num_printers, ctr);
+
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot enum printers: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ const char *printername, const char *datatype,
+ uint32 access_required, const char *servername,
+ const char *username, POLICY_HND *hnd)
+{
+ WERROR result;
+
+ fstring servername2;
+ slprintf(servername2, sizeof(servername2)-1, "\\\\%s", cli->desthost);
+
+ DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
+ servername2, username, printername, access_required));
+
+ /* open printer */
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", access_required,
+ servername2, username, hnd);
+
+ /* be more verbose */
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
+ d_printf("no access to printer [%s] on [%s] for user [%s] granted\n",
+ printername, servername2, username);
+ return False;
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ d_printf("cannot open printer %s on server %s: %s\n",
+ printername, servername2, dos_errstr(result));
+ return False;
+ }
+
+ DEBUG(2,("got printer handle for printer: %s, server: %s\n",
+ printername, servername2));
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 level,
+ PRINTER_INFO_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* getprinter call */
+ result = cli_spoolss_getprinter(cli,
+ mem_ctx, 0, &needed, hnd, level, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_getprinter(cli,
+ mem_ctx, needed, NULL, hnd, level, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot get printer-info: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 level,
+ PRINTER_INFO_CTR *ctr)
+{
+ WERROR result;
+
+ /* setprinter call */
+ result = cli_spoolss_setprinter(cli, mem_ctx, hnd, level, ctr, 0);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot set printer-info: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, REGISTRY_VALUE *value)
+{
+ WERROR result;
+
+ /* setprinterdata call */
+ result = cli_spoolss_setprinterdata(cli, mem_ctx, hnd, value);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf ("unable to set printerdata: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, const char *keyname,
+ uint16 **keylist)
+{
+ WERROR result;
+ uint32 needed, len;
+
+ /* enumprinterkey call */
+ result = cli_spoolss_enumprinterkey(
+ cli, mem_ctx, 0, &needed, hnd, keyname, NULL, NULL);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
+ result = cli_spoolss_enumprinterkey(
+ cli, mem_ctx, needed, NULL, hnd, keyname, keylist,
+ &len);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("enumprinterkey failed: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 offered,
+ POLICY_HND *hnd, const char *keyname,
+ REGVAL_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* enumprinterdataex call */
+ result = cli_spoolss_enumprinterdataex(
+ cli, mem_ctx, 0, &needed, hnd, keyname, NULL);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
+ result = cli_spoolss_enumprinterdataex(
+ cli, mem_ctx, needed, NULL, hnd, keyname, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("enumprinterdataex failed: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, char *keyname,
+ REGISTRY_VALUE *value)
+{
+ WERROR result;
+
+ /* setprinterdataex call */
+ result = cli_spoolss_setprinterdataex(cli, mem_ctx, hnd,
+ keyname, value);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("could not set printerdataex: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, int level, uint32 *num_forms,
+ FORM_1 **forms)
+
+{
+ WERROR result;
+ uint32 needed;
+
+ /* enumforms call */
+ result = cli_spoolss_enumforms(
+ cli, mem_ctx, 0, &needed, hnd, level, num_forms, forms);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_enumforms(
+ cli, mem_ctx, needed, NULL, hnd, level,
+ num_forms, forms);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("could not enum forms: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 level, const char *env,
+ uint32 *num_drivers,
+ PRINTER_DRIVER_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* enumprinterdrivers call */
+ result = cli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, 0, &needed, level,
+ env, num_drivers, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, needed, NULL, level,
+ env, num_drivers, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot enum drivers: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_getprinterdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 level,
+ const char *env, int version,
+ PRINTER_DRIVER_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* getprinterdriver call */
+ result = cli_spoolss_getprinterdriver(
+ cli, mem_ctx, 0, &needed, hnd, level,
+ env, version, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_getprinterdriver(
+ cli, mem_ctx, needed, NULL, hnd, level,
+ env, version, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
+ env, dos_errstr(result)));
+ if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER)) {
+ printf("cannot get driver: %s\n", dos_errstr(result));
+ }
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_addprinterdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, uint32 level,
+ PRINTER_DRIVER_CTR *ctr)
+{
+ WERROR result;
+
+ /* addprinterdriver call */
+ result = cli_spoolss_addprinterdriver(cli, mem_ctx, level, ctr);
+
+ /* be more verbose */
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
+ printf("You are not allowed to add drivers\n");
+ return False;
+ }
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot add driver: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+/**
+ * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr
+ * for a single printer or for all printers depending on argc/argv
+ **/
+static BOOL
+get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int level, int argc, const char **argv,
+ uint32 *num_printers, PRINTER_INFO_CTR *ctr)
+{
+
+ char *sharename;
+ fstring servername;
+ POLICY_HND hnd;
+
+ /* no arguments given, enumerate all printers */
+ if (argc == 0) {
+
+ if (!net_spoolss_enum_printers(cli, mem_ctx, NULL,
+ PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
+ level, num_printers, ctr))
+ return False;
+
+ goto out;
+ }
+
+
+ /* argument given, get a single printer by name */
+ sharename = strdup(argv[0]);
+
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername,
+ cli->user_name, &hnd))
+ return False;
+
+ if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, ctr)) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+ return False;
+ }
+
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ *num_printers = 1;
+
+out:
+ DEBUG(3,("got %d printers\n", *num_printers));
+
+ return True;
+
+}
+
+
+/**
+ * List print-queues (including local printers that are not shared)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i, num_printers;
+ uint32 level = 2;
+ pstring printername, sharename;
+ PRINTER_INFO_CTR ctr;
+
+ printf("listing printers\n");
+
+ if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr))
+ return nt_status;
+
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+
+ d_printf("printer %d: %s, shared as: %s\n",
+ i+1, printername, sharename);
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ * List printer-drivers from a server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i;
+ uint32 level = 3;
+ PRINTER_DRIVER_CTR drv_ctr_enum;
+ int d;
+
+ ZERO_STRUCT(drv_ctr_enum);
+
+
+ printf("listing printer-drivers\n");
+
+ for (i=0; archi_table[i].long_archi!=NULL; i++) {
+
+ int num_drivers;
+
+ /* enum remote drivers */
+ if (!net_spoolss_enumprinterdrivers(cli, mem_ctx, level,
+ archi_table[i].long_archi,
+ &num_drivers, &drv_ctr_enum)) {
+
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (num_drivers == 0) {
+ d_printf ("no drivers found on server for architecture: [%s].\n",
+ archi_table[i].long_archi);
+ continue;
+ }
+
+ d_printf("got %d printer-drivers for architecture: [%s]\n",
+ num_drivers, archi_table[i].long_archi);
+
+
+ /* do something for all drivers for architecture */
+ for (d = 0; d < num_drivers; d++) {
+ display_print_driver_3(&(drv_ctr_enum.info3[d]));
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ return nt_status;
+
+}
+
+
+/**
+ * Migrate Printer-ACLs from a source server to the destination server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ /* TODO: what now, info2 or info3 ?
+ convince jerry that we should add clientside setacls level 3 at least
+ */
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i = 0;
+ uint32 num_printers;
+ uint32 level = 2;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
+ struct cli_state *cli_dst = NULL;
+
+ ZERO_STRUCT(ctr_src);
+
+ DEBUG(3,("copying printer ACLs\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum source printers */
+ if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* 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;
+
+ d_printf("migrating printer ACLs for: [%s] / [%s]\n",
+ printername, sharename);
+
+ /* according to msdn you have specify these access-rights
+ to see the security descriptor
+ - READ_CONTROL (DACL)
+ - ACCESS_SYSTEM_SECURITY (SACL)
+ */
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli_dst->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
+ goto done;
+
+ /* check for existing src printer */
+ if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, 3, &ctr_src))
+ goto done;
+
+
+ /* Copy Security Descriptor */
+
+ /* copy secdesc (info level 2) */
+ ctr_dst.printers_2->devmode = NULL;
+ ctr_dst.printers_2->secdesc = dup_sec_desc(mem_ctx, ctr_src.printers_3->secdesc);
+
+ if (opt_verbose)
+ display_sec_desc(ctr_dst.printers_2->secdesc);
+
+ if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &ctr_dst))
+ goto done;
+
+ DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
+
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+}
+
+
+/**
+ * Migrate printer-forms from a src server to the dst server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ WERROR result;
+ uint32 i, f;
+ uint32 num_printers;
+ uint32 level = 1;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_INFO_CTR ctr_enum, ctr_dst;
+ uint32 num_forms;
+ FORM_1 *forms;
+ struct cli_state *cli_dst = NULL;
+
+ ZERO_STRUCT(ctr_enum);
+
+ DEBUG(3,("copying forms\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum src printers */
+ if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* 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;
+
+ d_printf("migrating printer forms for: [%s] / [%s]\n",
+ printername, sharename);
+
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
+ goto done;
+
+ /* finally migrate forms */
+ if (!net_spoolss_enumforms(cli, mem_ctx, &hnd_src, level, &num_forms, &forms))
+ goto done;
+
+ DEBUG(1,("got %d forms for printer\n", num_forms));
+
+
+ for (f = 0; f < num_forms; f++) {
+
+ FORM form;
+ fstring form_name;
+
+ /* only migrate FORM_PRINTER types, according to jerry
+ FORM_BUILTIN-types are hard-coded in samba */
+ if (forms[f].flag != FORM_PRINTER)
+ continue;
+
+ if (forms[f].name.buffer)
+ rpcstr_pull(form_name, forms[f].name.buffer,
+ sizeof(form_name), -1, STR_TERMINATE);
+
+ if (opt_verbose)
+ d_printf("\tmigrating form # %d [%s] of type [%d]\n",
+ f, form_name, forms[f].flag);
+
+ /* is there a more elegant way to do that ? */
+ form.flags = FORM_PRINTER;
+ form.size_x = forms[f].width;
+ form.size_y = forms[f].length;
+ form.left = forms[f].left;
+ form.top = forms[f].top;
+ form.right = forms[f].right;
+ form.bottom = forms[f].bottom;
+
+ init_unistr2(&form.name, form_name, UNI_STR_TERMINATE);
+
+ /* FIXME: there might be something wrong with samba's
+ builtin-forms */
+ result = cli_spoolss_addform(cli_dst, mem_ctx,
+ &hnd_dst, 1, &form);
+ if (!W_ERROR_IS_OK(result)) {
+ d_printf("\tAddForm form %d: [%s] refused.\n",
+ f, form_name);
+ continue;
+ }
+
+ DEBUGADD(1,("\tAddForm of [%s] succeeded\n", form_name));
+ }
+
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+
+}
+
+
+/**
+ * Migrate printer-drivers from a src server to the dst server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i, p;
+ uint32 num_printers;
+ uint32 level = 3;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ BOOL got_src_driver_share = False;
+ BOOL got_dst_driver_share = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
+ PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
+ struct cli_state *cli_dst = NULL;
+ struct cli_state *cli_share_src = NULL;
+ struct cli_state *cli_share_dst = NULL;
+ fstring drivername = "";
+
+ ZERO_STRUCT(drv_ctr_src);
+ ZERO_STRUCT(drv_ctr_dst);
+ ZERO_STRUCT(info_ctr_enum);
+ ZERO_STRUCT(info_ctr_dst);
+
+
+ DEBUG(3,("copying printer-drivers\n"));
+
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* open print$-share on the src server */
+ nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
+ cli->desthost, "print$", "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ got_src_driver_share = True;
+
+
+ /* open print$-share on the dst server */
+ nt_status = connect_to_service(&cli_share_dst, &cli_dst->dest_ip,
+ cli_dst->desthost, "print$", "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ got_dst_driver_share = True;
+
+
+ /* enum src printers */
+ if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (p = 0; p < num_printers; p++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, info_ctr_enum.printers_2[p].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, info_ctr_enum.printers_2[p].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* 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;
+
+ d_printf("migrating printer driver for: [%s] / [%s]\n",
+ printername, sharename);
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst))
+ goto done;
+
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* in a first step call getdriver for each shared printer (per arch)
+ to get a list of all files that have to be copied */
+
+ for (i=0; archi_table[i].long_archi!=NULL; i++) {
+
+ /* getdriver src */
+ if (!net_spoolss_getprinterdriver(cli, mem_ctx, &hnd_src,
+ level, archi_table[i].long_archi,
+ archi_table[i].version, &drv_ctr_src))
+ continue;
+
+ rpcstr_pull(drivername, drv_ctr_src.info3->name.buffer,
+ sizeof(drivername), -1, STR_TERMINATE);
+
+ if (opt_verbose)
+ display_print_driver_3(drv_ctr_src.info3);
+
+
+ /* check arch dir */
+ nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+
+ /* copy driver-files */
+ nt_status = copy_print_driver_3(mem_ctx, cli_share_src, cli_share_dst,
+ archi_table[i].short_archi,
+ drv_ctr_src.info3);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+
+ /* adddriver dst */
+ if (!net_spoolss_addprinterdriver(cli_dst, mem_ctx, level, &drv_ctr_src)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
+ drivername, printername));
+
+ }
+
+ /* setdriver dst */
+ init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
+
+ if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
+ drivername, printername));
+
+ /* close dst */
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+
+ /* close src */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+
+ if (got_src_driver_share)
+ cli_shutdown(cli_share_src);
+
+ if (got_dst_driver_share)
+ cli_shutdown(cli_share_dst);
+
+ return nt_status;
+
+}
+
+
+/**
+ * Migrate printer-queues from a src to the dst server
+ * (requires a working "addprinter command" to be installed for the local smbd)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i = 0, num_printers;
+ uint32 level = 2;
+ PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
+ struct cli_state *cli_dst = NULL;
+ POLICY_HND hnd_dst, hnd_src;
+ pstring printername, sharename;
+ fstring servername;
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+
+ DEBUG(3,("copying printers\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum printers */
+ if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* 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;
+
+ d_printf("migrating printer queue for: [%s] / [%s]\n",
+ printername, sharename);
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst)) {
+
+ DEBUG(1,("could not open printer: %s\n", sharename));
+ } else {
+ got_hnd_dst = True;
+ }
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
+ printf ("could not get printer, creating printer.\n");
+ } else {
+ DEBUG(1,("printer already exists: %s\n", sharename));
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+ continue;
+ }
+
+
+ /* now get again src printer ctr via getprinter,
+ we first need a handle for that */
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+ /* getprinter on the src server */
+ if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, level, &ctr_src))
+ goto done;
+
+
+ /* copy each src printer to a dst printer 1:1,
+ maybe some values have to be changed though */
+ d_printf("creating printer: %s\n", printername);
+ result = cli_spoolss_addprinterex (cli_dst, mem_ctx, level, &ctr_src);
+
+ if (W_ERROR_IS_OK(result))
+ d_printf ("printer [%s] successfully added.\n", printername);
+ else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
+ d_printf ("printer [%s] already exists.\n", printername);
+ else {
+ printf ("could not create printer\n");
+ goto done;
+ }
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+}
+
+
+/**
+ * Migrate Printer-Settings from a src server to the dst server
+ * (for this to work, printers and drivers already have to be migrated earlier)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+
+ /* FIXME: Here the nightmare begins */
+
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i = 0, p = 0, j = 0;
+ uint32 num_printers, val_needed, data_needed;
+ uint32 level = 2;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish;
+ REGVAL_CTR reg_ctr;
+ struct cli_state *cli_dst = NULL;
+ char *devicename = NULL, *unc_name = NULL, *url = NULL;
+ fstring longname;
+
+ const char *keyname = NULL;
+ uint16 *keylist = NULL, *curkey;
+
+ ZERO_STRUCT(ctr_enum);
+
+ DEBUG(3,("copying printer settings\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum src printers */
+ if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* needed for dns-strings in regkeys */
+ get_mydnsfullname(longname);
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ 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;
+
+ d_printf("migrating printer settings for: [%s] / [%s]\n",
+ printername, sharename);
+
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli_dst->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst,
+ level, &ctr_dst))
+ goto done;
+
+
+ /* STEP 1: COPY DEVICE-MODE and other
+ PRINTER_INFO_2-attributes
+ */
+
+ ctr_dst.printers_2 = &ctr_enum.printers_2[i];
+
+ /* why is the port always disconnected when the printer
+ is correctly installed (incl. driver ???) */
+ init_unistr( &ctr_dst.printers_2->portname, SAMBA_PRINTER_PORT_NAME);
+
+ /* check if printer is published */
+ if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
+ goto done;
+
+ ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH;
+
+ /* ignore False from setprinter due to WERR_IO_PENDING */
+ net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
+
+ DEBUG(3,("republished printer\n"));
+ }
+
+ /* copy devmode (info level 2) */
+ ctr_dst.printers_2->devmode = talloc_memdup(mem_ctx,
+ ctr_enum.printers_2[i].devmode, sizeof(DEVICEMODE));
+
+ /* 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;
+ goto done;
+ }
+
+ init_unistr(&ctr_dst.printers_2->devmode->devicename, devicename);
+#endif
+ if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst,
+ level, &ctr_dst))
+ goto done;
+
+ DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
+
+
+
+ /* STEP 2: COPY REGISTRY VALUES */
+
+ /* please keep in mind that samba parse_spools gives horribly
+ crippled results when used to cli_spoolss_enumprinterdataex
+ a win2k3-server.
+ FIXME: IIRC I've seen it too on a win2k-server
+ */
+
+ /* enumerate data on src handle */
+ result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0,
+ &val_needed, &data_needed, NULL);
+
+ /* loop for all printerdata */
+ while (W_ERROR_IS_OK(result)) {
+
+ REGISTRY_VALUE value;
+
+ result = cli_spoolss_enumprinterdata(
+ cli, mem_ctx, &hnd_src, p++, val_needed,
+ data_needed, 0, 0, &value);
+
+ /* loop for all reg_keys */
+ if (W_ERROR_IS_OK(result)) {
+
+ /* display_value */
+ if (opt_verbose)
+ display_reg_value(NULL, value);
+
+ /* set_value */
+ if (!net_spoolss_setprinterdata(cli_dst, mem_ctx,
+ &hnd_dst, &value))
+ goto done;
+
+ DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
+ value.valuename));
+ }
+ }
+
+ /* STEP 3: COPY SUBKEY VALUES */
+
+ /* here we need to enum all printer_keys and then work
+ on the result with enum_printer_key_ex. nt4 does not
+ respond to enumprinterkey, win2k does, so continue
+ in case of an error */
+
+ if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, keyname, &keylist)) {
+ printf("got no key-data\n");
+ continue;
+ }
+
+
+ /* work on a list of printer keys
+ each key has to be enumerated to get all required
+ information. information is then set via setprinterdataex-calls */
+
+ if (keylist == NULL)
+ continue;
+
+ curkey = keylist;
+ while (*curkey != 0) {
+
+ pstring subkey;
+ rpcstr_pull(subkey, curkey, sizeof(subkey), -1, STR_TERMINATE);
+
+ curkey += strlen(subkey) + 1;
+
+ /* enumerate all src subkeys */
+ if (!net_spoolss_enumprinterdataex(cli, mem_ctx, 0,
+ &hnd_src, subkey,
+ &reg_ctr))
+ goto done;
+
+ for (j=0; j < reg_ctr.num_values; j++) {
+
+ REGISTRY_VALUE value;
+ UNISTR2 data;
+
+ /* although samba replies with sane data in most cases we
+ should try to avoid writing wrong registry data */
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME)) {
+
+ /* although windows uses a multi-sz, we use a sz */
+ init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME)) {
+
+ if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL)) {
+
+ continue;
+
+#if 0
+ /* FIXME: should we really do that ??? */
+ if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ init_unistr2(&data, url, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_URL);
+#endif
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
+
+ init_unistr2(&data, longname, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME)) {
+
+ init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
+ }
+
+ value.type = REG_SZ;
+ value.size = data.uni_str_len * 2;
+ value.data_p = talloc_memdup(mem_ctx, data.buffer, value.size);
+
+ if (opt_verbose)
+ display_reg_value(subkey, value);
+
+ /* here we have to set all subkeys on the dst server */
+ if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst,
+ subkey, &value))
+ goto done;
+
+ } else {
+
+ if (opt_verbose)
+ display_reg_value(subkey, *(reg_ctr.values[j]));
+
+ /* here we have to set all subkeys on the dst server */
+ if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst,
+ subkey, reg_ctr.values[j]))
+ goto done;
+
+ }
+
+ DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
+ subkey, reg_ctr.values[j]->valuename));
+
+ }
+
+ regval_ctr_destroy(&reg_ctr);
+ }
+
+ safe_free(keylist);
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ SAFE_FREE(devicename);
+ SAFE_FREE(url);
+ SAFE_FREE(unc_name);
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+}
diff --git a/source/utils/smbcacls.c b/source/utils/smbcacls.c
index cb82ad831eb..4dc89aecb9d 100644
--- a/source/utils/smbcacls.c
+++ b/source/utils/smbcacls.c
@@ -761,11 +761,13 @@ static struct cli_state *connect_one(const char *share)
ctx=talloc_init("main");
- setlinebuf(stdout);
-
+ /* set default debug level to 0 regardless of what smb.conf sets */
+ setup_logging( "smbcacls", True );
+ DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
dbf = x_stderr;
+ x_setbuf( x_stderr, NULL );
- setup_logging(argv[0],True);
+ setlinebuf(stdout);
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();
diff --git a/source/utils/smbcquotas.c b/source/utils/smbcquotas.c
index 0bd87554209..81f7dd42bbc 100644
--- a/source/utils/smbcquotas.c
+++ b/source/utils/smbcquotas.c
@@ -236,8 +236,9 @@ static int do_quota(struct cli_state *cli, enum SMB_QUOTA_TYPE qtype, uint16 cmd
}
if (!cli_get_quota_handle(cli, &quota_fnum)) {
- d_printf("Failed to open \\%s %s.\n",
- FAKE_FILE_NAME_QUOTA,cli_errstr(cli));
+ d_printf("Quotas are not enabled on this share.\n");
+ d_printf("Failed to open %s %s.\n",
+ FAKE_FILE_NAME_QUOTA_WIN32,cli_errstr(cli));
return -1;
}
@@ -419,14 +420,15 @@ FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" },
ZERO_STRUCT(qt);
- setlinebuf(stdout);
-
+ /* set default debug level to 1 regardless of what smb.conf sets */
+ setup_logging( "smbcquotas", True );
+ DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
dbf = x_stderr;
+ x_setbuf( x_stderr, NULL );
- fault_setup(NULL);
-
- setup_logging(argv[0],True);
+ setlinebuf(stdout);
+ fault_setup(NULL);
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();