r2565: syncing up for 3.0.8pre1
authorGerald Carter <jerry@samba.org>
Thu, 23 Sep 2004 12:21:10 +0000 (12:21 +0000)
committerGerald Carter <jerry@samba.org>
Thu, 23 Sep 2004 12:21:10 +0000 (12:21 +0000)
89 files changed:
README
Roadmap
examples/auth/crackcheck/Makefile [new file with mode: 0644]
examples/auth/crackcheck/crackcheck.c [new file with mode: 0644]
packaging/SuSE/samba3-vscan.diff
source/Makefile.in
source/VERSION
source/client/client.c
source/client/clitar.c
source/configure.in
source/include/charset.h
source/include/fake_file.h
source/include/hash.h [deleted file]
source/include/includes.h
source/include/rpc_spoolss.h
source/include/smb.h
source/include/smb_macros.h
source/include/smbldap.h
source/lib/charcnv.c
source/lib/hash.c [deleted file]
source/lib/iconv.c
source/lib/ms_fnmatch.c
source/lib/smbldap.c
source/lib/smbrun.c
source/lib/util.c
source/lib/util_file.c
source/lib/util_str.c
source/lib/util_uuid.c
source/libads/kerberos.c
source/libsmb/cliconnect.c
source/libsmb/clifile.c
source/libsmb/clikrb5.c
source/libsmb/cliquota.c
source/libsmb/clireadwrite.c
source/locking/locking.c
source/modules/weird.c
source/nmbd/nmbd.c
source/nmbd/nmbd_workgroupdb.c
source/nsswitch/pam_winbind.c
source/nsswitch/pam_winbind.h
source/nsswitch/wbinfo.c
source/nsswitch/winbind_nss_linux.c
source/nsswitch/winbindd.c
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_dual.c
source/nsswitch/winbindd_group.c
source/nsswitch/winbindd_sid.c
source/nsswitch/winbindd_user.c
source/nsswitch/winbindd_util.c
source/param/loadparm.c
source/passdb/pdb_ldap.c
source/passdb/pdb_smbpasswd.c
source/passdb/pdb_xml.c
source/printing/nt_printing.c
source/rpc_client/cli_spoolss.c
source/rpc_client/cli_srvsvc.c
source/rpc_parse/parse_net.c
source/rpc_parse/parse_spoolss.c
source/rpc_parse/parse_srv.c
source/rpc_server/srv_netlog_nt.c
source/rpc_server/srv_samr_nt.c
source/rpc_server/srv_spoolss_nt.c
source/rpcclient/cmd_spoolss.c
source/script/mkproto.awk
source/smbd/blocking.c
source/smbd/chgpasswd.c
source/smbd/dir.c
source/smbd/fake_file.c
source/smbd/filename.c
source/smbd/mangle_hash.c
source/smbd/negprot.c
source/smbd/nttrans.c
source/smbd/process.c
source/smbd/service.c
source/smbd/statcache.c
source/tdb/tdb.c
source/tdb/tdb.h
source/tdb/tdbutil.c
source/ubiqx/ubi_BinTree.c
source/ubiqx/ubi_BinTree.h
source/utils/net.c
source/utils/net.h
source/utils/net_ads.c
source/utils/net_ads_cldap.c
source/utils/net_help.c
source/utils/net_rpc.c
source/utils/net_rpc_printer.c [new file with mode: 0644]
source/utils/smbcacls.c
source/utils/smbcquotas.c

diff --git a/README b/README
index f529610ef43da7b137c08719035be9fd514af2c2..d6c5e15bdf7c189c76bf3af3e878445fbc3a0aa8 100644 (file)
--- 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 42c63f78098e180b85e55aca81828586bc91a2b4..6d678783f5721af7a5d57b3c7b8d224ba3fd3ef5 100644 (file)
--- 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 (file)
index 0000000..84377aa
--- /dev/null
@@ -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 (file)
index 0000000..3384337
--- /dev/null
@@ -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);
+
+}
+
index 330b470af2cb0dba17e9f548ad5df5cfc8da8271..cf474c97d0093add256f1b294d7da05ca09171b3 100644 (file)
@@ -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 ) {
 -                                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 ) {
index 5d3462913c1c3e32a2a892005bfbff6e52d4614b..b6fe22b5934706192ff5cc15cc64362c53354941 100644 (file)
@@ -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
index ab14d54bdd0be6a5466e059b553e981aad36aca6..f33e71fb577b57bc20362237238c2ace9cf965f1 100644 (file)
@@ -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                #
index 1fccfaa581ca0d33ee97a839bc41b9b9811af225..e14bcaa261653af0ce379cc407ab383f1d04e4b1 100644 (file)
@@ -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);
index 64c194b54dae7d91997e3fcd7b985083c2bcdbee..4cadef558d61ccc6c75a93279b1fc03718737155 100644 (file)
@@ -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;
 }
 
 /****************************************************************************
index 53267f0cd9574891343ed487369a7c580a2a5479..69152d8fc8f85f187587ccdcbee5da6312af374e 100644 (file)
@@ -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)],
index 7a9b12ef55dfd4727de646bf2e9df8205e299f7d..c5d03a62e8920aff79751e1b101c6e3bcc3f8990 100644 (file)
@@ -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);                               \
 }                                                                                              \
 
-
index cfcd16f683009fb2f2aea934b6a6e8ed457d924f..63ba41d7860753026b7681c998f327160bf89d0c 100644 (file)
@@ -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 (file)
index 40cc8b7..0000000
+++ /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_ */
index 1d913d3f32ac04c2e0f1761c411cec1a40fb8cf7..3ea4eaa35a94fb4e6a3f0d7db3a8d410ba63ab77 100644 (file)
 #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)
 #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
 
 #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
 
 #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"
index cf7d1ba341265f67d16cad947dbb0ffeadf4679e..f2b78f91bc08691f39e7003b4996673bd4201f0f 100755 (executable)
@@ -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;
 
index 32dba0cf78f02a3aa0b59d9e249c1466e7ba6172..7317fd16b0fb287391e38e53160b1b6a68ddc5e9 100644 (file)
@@ -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;
index bcbaa64f8633b2a7f441df4b95884dfa309c8655..a9e911c066ac2ced4d836a4051815271754c2d17 100644 (file)
@@ -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... */
index 953937fb75d1aead91f2e4cde9a4fcd6bfc173c6..58502ec34e759632682dbbed3c4411ba6b668bee 100644 (file)
@@ -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[];
index 6cbf7562b06dc92c34c2e42fbcbf759fb634d1a3..40004826b4a209a3de67129932f2c90918b12797 100644 (file)
@@ -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 (file)
index 18b6534..0000000
+++ /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;
-}
index 4c9ecf992e6790190e0ee1e4e0598de9ff237863..66a6e6cd8bc91adb6d455421d8d26130605d847f 100644 (file)
  * @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;
 }
+
index 24232c3b523b1293e32f43b2e0c24574aa008324..42c91bd18df9067048f801c3e2bf3c351185649c 100644 (file)
@@ -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;
                        }
index e66fb3640cfc6601290b981dc10feefeb8aa95fc..57aab70a5ba1859515f3e3d2d3bb820d506e71b6 100644 (file)
@@ -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 {
index 592543bc43be89dc7fd8ab722a7145f00bd7c401..43cb209174e29f9ff2ae0141bd28a8e7c5580e50 100644 (file)
@@ -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;
+}
index 8d01d9e7c9c063993f2fc7d5f2f5792b6b3f1264..a456395cad1387b612c4aae4953eb777ff0a1d33 100644 (file)
@@ -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);
index bd505ac921c37f0f89098da39677f4c646bf92e6..303d961df57de7b8b7dfa680d8d2016a87743bf2 100644 (file)
@@ -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;
index 6eee62c14aa70af86e212f031f589f7a83c55d73..65a616ad4198851b8168b6b5f8840747e3e4130a 100644 (file)
@@ -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;
 }
 
index 8f86c2109ea48ef1cd82c993b89f54d8f0d7933e..df70740b33c1b7fb5db4cd64d1c777970a80e33c 100644 (file)
 
 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;
index 97b895a2418a976b272512da720c528c2e3beacb..327a76826ef28ae5df641901e4b4c5307bac7a48 100644 (file)
@@ -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);
index 559538aac9bb60cf9763e2feb2ef4a33751c4e4c..4ff60c1b1cacc8c4158640cf732ba717d8b18aa5 100644 (file)
@@ -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;
index 398c7cc4f0afa5290eb938f8c80e28b58b675ab8..ff0edc6bb4e40c1dcee02cddcdf197b53f773105 100644 (file)
@@ -982,6 +982,47 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
        return True;
 }
 
+/****************************************************************************
+ 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.
 ****************************************************************************/
index 5fcde4654add633112f7af778ba1d23dab73428a..f7f84f1e2976aaa258ad782722f360c3e67efa7f 100644 (file)
        krb5_error_code rc;
        int num_kdcs, i;
        struct sockaddr *sa;
+       struct addrinfo *ai;
 
        *addr_pp = NULL;
        *naddrs = 0;
                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);
index ed808aa1f5c480e8e62307d83d704335f8a02a94..af8b4422b78f8ceec5ffffe35c073b8c42c60580 100644 (file)
 
 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;
index 8eac7d07d8be3bdac338be38d1e1b5e4ae430620..3f14e530943d634bd7b9ad01fc2067acff059429 100644 (file)
@@ -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)) {
index 8f53b55fc54a45e93cf53bc5ba97f914dbb78c63..d4e8c493d501f84cac37ba0364c5af9a5ae44b09 100644 (file)
@@ -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.
index 444853f3831c25c7264a5847fd21a9920d2bf512..3c59fd9d61f18b35115df84d0cb64b468524fd05 100644 (file)
@@ -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;
index 880de7f91bf26ce4a318c0ff8934a508aa3e4e34..f8006a22a9edcbb6952f7752c4a0f7d5e77756d5 100644 (file)
@@ -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 );
        
index 8880cb58bb407bcb4a53369a157ac36aacbd19ce..8f3ae36b65d015e4b74a1fda68525f4367c3a984 100644 (file)
@@ -40,6 +40,27 @@ static void add_workgroup(struct subnet_record *subrec, struct work_record *work
        subrec->work_changed = True;
 }
 
+/****************************************************************************
+ 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);
                }
index 123f67036656f423fdbc5930d9e851dd8402d7f2..64e21738221a38539fc8f019aae4a1694e5cae29 100644 (file)
@@ -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
index 0afcceb6aa2e8d01bd8572e78ee179ea9ed97e1a..7cae477714bd42bc043e8201c9dadd2ac8bef6e2 100644 (file)
@@ -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
index 0028982d201f83b277b862b53cdea0ecd8d5d354..b6a09bf2a1f38d54d922fa53df618988a55d4444 100644 (file)
@@ -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);
index ae2bcc7ade98c60e3b6dc4171b2b0588229e9873..0ea5db74da6e91d4d8bca08a7cc4b84437958ffd 100644 (file)
@@ -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;
                }
        }
        
index d08aa84face0263c02dac35161b0a35c784db0cd..455fb74f1716b426c71c066bc136366d70d76bcd 100644 (file)
@@ -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();
@@ -712,6 +715,15 @@ static void process_loop(void)
             
                        /* Process activity on client connections */
             
+                       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) {
                 
@@ -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();
 
index b81f8ecd45ada9a49129b35e88996d82f0df6fe3..493255a5a653167a83dcbb69cd2b63f1f68e6b25 100644 (file)
@@ -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);
 }
 
index a9796afa3679712e0e6c18617e5b0bac81e0618d..d4ec6e586db29510a28252ac9de961ea3cf63492 100644 (file)
@@ -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;
        }
index ca7f72d01789e570acc355d05209f78a3363794a..a3b826278b56a3113878d502f3f9d168c0535525 100644 (file)
@@ -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)
index 61da9b3d92f097050d0db9e3898800018fa8ebc3..c6e503bef39d6651a142a1895ec65e1b8a9e0947 100644 (file)
@@ -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 */
index 795d657aae744db881793ad4df06a55a4536c49a..6f5a86f43aeb86bd489af9806394d902d90158e9 100644 (file)
@@ -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;
index faa6e8d8da45720f3663d7cacafd6fcd33bb540f..a9197d356163df3b0e5266c7d840875c547c9c70 100644 (file)
@@ -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)
index 14981b97c4203cb222061bc92c1f4efd650a1799..24811af37ddf7eb8c91ba378fe1f4a2284dd12dd 100644 (file)
@@ -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)
index 9af34705df50c05c74df316d907221db59808588..454aa8d8702f1472f3546795639c0ee5c5db51d8 100644 (file)
@@ -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)  {
index 6ebac1c01a5a4b3f6d929c1a6ac9b27a50d5cdaa..805201615cea27cda84a82e7b5a60ae7267527fc 100644 (file)
@@ -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)
 {
index 64cb73ba5a4aa401a50c35228f36ad985c012743..6eff57d365e350016de209fe17a8b6913968d18b 100644 (file)
@@ -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;
index 7850924aacb899fb02f57e8225bfd65bb67568e1..c3551c9d90ad4b60525387d349f7c65e23277fe5 100644 (file)
@@ -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 }
 };
 
index 8f5f2413deec38d4daa829568fc433970912ddd7..5303f83bf9c2a163da85f0bb02534f6b7947b789 100644 (file)
@@ -130,6 +130,27 @@ static void decode_printer_info_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
         *info=inf;
 }
 
+/**********************************************************************
+**********************************************************************/
+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, 
@@ -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;
                }                       
        }
        
index 68eb17074f63fcb89bb6792f2e0f3fe3c596c77b..f8580d0fe2e765be23a9c51ede8c7233b520b73d 100644 (file)
@@ -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 */
 
index b42b9b2a8b41cba99cca0e2924a55d29d7ba4fcc..813316177ac74e2f2a7dede2b87439ea0b7ffd7c 100644 (file)
@@ -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;
 }
index ae087c7f7746844e1f11e27ed5fea6f2e4d2c609..2b2038d16ac7a357580f6b37029fa346546b4e81 100644 (file)
@@ -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;
 }
 
 /*******************************************************************
index 6349fc1632575c25d5ed1706d2014a9bd69e9605..8313c82c93dcc49c1495c4704e03177e5b620a29 100644 (file)
@@ -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;
+       }
 }
 
 
index b5871a7e56dfa572a32dc381963d3a7d307ab993..3e0762fa43b433254b5272b24f24687549e5a08f 100644 (file)
@@ -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;
 
index ce6d9dd37ec4f323d0dcbc15c8c5870f56844a60..37617db5e8fc2c5a58bf38ef079b2ba1565a2b1d 100644 (file)
@@ -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))
index 812939ddf50ce97e76a3d637554b7b6d5c504b59..d50237905aefba2f375ab39477eec8871a18fbc0 100644 (file)
@@ -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);
index 5fa59e1903b52396cd760e4f983a86775ec00b98..e99cd9f905689cd3f025572e8e578eb4220ca148 100644 (file)
@@ -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;
                        
index 4c9507dcf9b6c61b2719c3f753d5e40a7c20fd86..4edc7abc63a42a39f32f0ac0252f4092d639745c 100644 (file)
@@ -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;
   }
 
index 3983a4cbdfbadeca884e7f7f80f6b155e5e95877..e143999a785d2d38c7f3dcafcdf01740a35df2ae 100644 (file)
@@ -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);
        }
 }
index 8ea5b9c60a3c37c093f77b04603b0e4a22ff4ef4..af363d75a3f9fcd7ba65b5ccc4b96c6676a71d87 100644 (file)
@@ -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
index b88f687766d88ba9766956024a5159f4950a51c2..2bda42f76dc84c5097e6a4df23e7b5d7fce11d15 100644 (file)
@@ -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;
-       }
-}
index d3660addf1153f0ccda044650f895338d052dd5a..fc874dc0867fde27af748f7a3fcebed9e81802ba 100644 (file)
@@ -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);             
index c411ef0f79f26738a79e1343ea4f8bec522a82e7..279c9dd3c45bddd3b3c251cd6d9c9a5700768a15 100644 (file)
@@ -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);
index 13ec99a917f7bebbac5b640420958c19cecd46fc..26ddf1b3a3d4b757eddd5aac8e994b2193d8efc0 100644 (file)
  *                  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;
 }
index 5ff53f63007113dd579e76842a58216d9193d937..447073acd841e271b541f63ee875d5dc88e9a622 100644 (file)
@@ -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;
index f717efac63eb9f88b1096621afc0411c57e0ff61..d9e321fd96875a2b61b8a1401b086515d03182da 100644 (file)
@@ -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);
index 60ce1499e8dc1c3fa48decd153c5b3b22ae7ce3f..5be68d9f0a18ddcea579679a3fb14ca5ad99ee64 100644 (file)
@@ -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)
 {
index 794b5332ac5eaaf7fff503faac68bbb4d60b94eb..4d111e0ea358f5f0a7c7bc5d0d52b5a17996844e 100644 (file)
@@ -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 {
index 5e78e9a49998d3c481194ab77c0745c0459cd310..ba37d4927ccbfc62ca322c88fd9a7a7a87209fca 100644 (file)
@@ -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
  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;
 }
index fec0b3094d366e0176e21da820e4b57cc29d868d..ae4e439c90330cfa1cf6669ec37c7e87dc83a7f4 100644 (file)
@@ -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)
index eb120a8cecd4e67ce906a22b6bd5a8d01a4ff331..e8a6d201c5978639e15405f36a4e2cd15f2ab4e0 100644 (file)
 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);
index 09e55e2e70276a390a79b8439b5961e1c83b618a..e57eccfe59812967da055d931bc5e7fa1bed852e 100644 (file)
@@ -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;
 
index 8a4d46128007e3470e87cb736cee617f277aa177..e452ac10dc2b6476dd21e9caa21b4ca4b728db83 100644 (file)
  *
  * -------------------------------------------------------------------------- **
  *
- * 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
 
 #include "ubi_BinTree.h"  /* Header for this module.   */
 
+
 /* ========================================================================== **
  * Static data.
  */
 
 static char ModuleID[] = "ubi_BinTree\n\
-\tRevision: 4.1\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[] )
index c0c6d59309400af168520615a1a11aa49c0ec9b4..43ca1a98716479b309c93951a17449c8144c23dc 100644 (file)
  *
  * -------------------------------------------------------------------------- **
  *
- * 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.
    *
    * ------------------------------------------------------------------------ **
    */
index 67b138a43bed4578b6bedfe1dd9e14fcc63471cc..da1339aed10c132cdc2cd472d9c63b02592bf0d9 100644 (file)
@@ -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}
index ba3a4e14352c317e48cc4bdfea795f4cd7f367b9..d75a19e498ee19eb603cca8ae634c5f865457ca5 100644 (file)
@@ -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;
index 7b8ace85b6248f51c3e2028a019875e7fda6b4a9..2efd470bbe711970360ffc02ba09ffc7cecf97f0 100644 (file)
@@ -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);
index 1903172cf75d8ac8790f83e3d04cddf96c473cde..f3c6c5ff4d276ae89f8f17f583cecae94d9446d9 100644 (file)
@@ -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), 
index 38261be90a7ef6de6cac3c3f5cd3cf89ba6d1a0f..d6ef5e8a6c300d8d59d0a80ea73222ae7486d7f2 100644 (file)
@@ -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] "
index e21f79df303a698be265f8b16fb6ea557d0dcc00..1a1d76b09a0042059dce79cf9168debd060fc440 100644 (file)
@@ -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;
 }
 
@@ -2491,6 +2493,486 @@ rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
+/** 
+ * 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
@@ -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 (file)
index 0000000..51f4df7
--- /dev/null
@@ -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;
+}
index cb82ad831eb6e713c0428edbeed28d5560ff7622..4dc89aecb9de4fb5f7766c982b3969d8d34de5f6 100644 (file)
@@ -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();
index 0bd8755420991fe9fb3afc62cbd56c6bde00336a..81f7dd42bbc2c56f014d32577c090693d00c825e 100644 (file)
@@ -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();