summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/Makefile.in68
-rw-r--r--source/VERSION4
-rw-r--r--source/client/client.c2
-rw-r--r--source/client/clitar.c8
-rw-r--r--source/configure.in19
-rw-r--r--source/include/charset.h9
-rw-r--r--source/include/fake_file.h4
-rw-r--r--source/include/hash.h74
-rw-r--r--source/include/includes.h51
-rwxr-xr-xsource/include/rpc_spoolss.h1
-rw-r--r--source/include/smb.h6
-rw-r--r--source/include/smb_macros.h1
-rw-r--r--source/include/smbldap.h2
-rw-r--r--source/lib/charcnv.c30
-rw-r--r--source/lib/hash.c316
-rw-r--r--source/lib/iconv.c347
-rw-r--r--source/lib/ms_fnmatch.c3
-rw-r--r--source/lib/smbldap.c55
-rw-r--r--source/lib/smbrun.c123
-rw-r--r--source/lib/util.c5
-rw-r--r--source/lib/util_file.c492
-rw-r--r--source/lib/util_str.c13
-rw-r--r--source/lib/util_uuid.c66
-rw-r--r--source/libads/kerberos.c10
-rw-r--r--source/libsmb/cliconnect.c8
-rw-r--r--source/libsmb/clifile.c41
-rw-r--r--source/libsmb/clikrb5.c18
-rw-r--r--source/libsmb/cliquota.c4
-rw-r--r--source/libsmb/clireadwrite.c8
-rw-r--r--source/locking/locking.c13
-rw-r--r--source/modules/weird.c4
-rw-r--r--source/nmbd/nmbd.c8
-rw-r--r--source/nmbd/nmbd_workgroupdb.c43
-rw-r--r--source/nsswitch/pam_winbind.c64
-rw-r--r--source/nsswitch/pam_winbind.h1
-rw-r--r--source/nsswitch/wbinfo.c41
-rw-r--r--source/nsswitch/winbind_nss_linux.c41
-rw-r--r--source/nsswitch/winbindd.c25
-rw-r--r--source/nsswitch/winbindd_cache.c4
-rw-r--r--source/nsswitch/winbindd_dual.c2
-rw-r--r--source/nsswitch/winbindd_group.c7
-rw-r--r--source/nsswitch/winbindd_sid.c78
-rw-r--r--source/nsswitch/winbindd_user.c2
-rw-r--r--source/nsswitch/winbindd_util.c8
-rw-r--r--source/param/loadparm.c4
-rw-r--r--source/passdb/pdb_ldap.c45
-rw-r--r--source/passdb/pdb_smbpasswd.c1823
-rw-r--r--source/passdb/pdb_xml.c73
-rw-r--r--source/printing/nt_printing.c2
-rw-r--r--source/rpc_client/cli_spoolss.c24
-rw-r--r--source/rpc_client/cli_srvsvc.c6
-rw-r--r--source/rpc_parse/parse_net.c8
-rw-r--r--source/rpc_parse/parse_spoolss.c68
-rw-r--r--source/rpc_parse/parse_srv.c45
-rw-r--r--source/rpc_server/srv_netlog_nt.c48
-rw-r--r--source/rpc_server/srv_samr_nt.c33
-rw-r--r--source/rpc_server/srv_spoolss_nt.c21
-rw-r--r--source/rpcclient/cmd_spoolss.c23
-rw-r--r--source/script/mkproto.awk2
-rw-r--r--source/smbd/blocking.c74
-rw-r--r--source/smbd/chgpasswd.c13
-rw-r--r--source/smbd/dir.c109
-rw-r--r--source/smbd/fake_file.c6
-rw-r--r--source/smbd/filename.c18
-rw-r--r--source/smbd/mangle_hash.c218
-rw-r--r--source/smbd/negprot.c4
-rw-r--r--source/smbd/nttrans.c30
-rw-r--r--source/smbd/process.c7
-rw-r--r--source/smbd/service.c5
-rw-r--r--source/smbd/statcache.c150
-rw-r--r--source/tdb/tdb.c59
-rw-r--r--source/tdb/tdb.h18
-rw-r--r--source/tdb/tdbutil.c2
-rw-r--r--source/ubiqx/ubi_BinTree.c68
-rw-r--r--source/ubiqx/ubi_BinTree.h31
-rw-r--r--source/utils/net.c68
-rw-r--r--source/utils/net.h5
-rw-r--r--source/utils/net_ads.c5
-rw-r--r--source/utils/net_ads_cldap.c3
-rw-r--r--source/utils/net_help.c51
-rw-r--r--source/utils/net_rpc.c735
-rw-r--r--source/utils/net_rpc_printer.c2339
-rw-r--r--source/utils/smbcacls.c8
-rw-r--r--source/utils/smbcquotas.c16
84 files changed, 5897 insertions, 2499 deletions
diff --git a/source/Makefile.in b/source/Makefile.in
index 5d3462913c1..b6fe22b5934 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -35,8 +35,6 @@ IDMAP_LIBS=@IDMAP_LIBS@
KRB5LIBS=@KRB5_LIBS@
LDAP_LIBS=@LDAP_LIBS@
-LINK=$(CC) $(FLAGS) $(LDFLAGS)
-
INSTALLCMD=@INSTALL@
INSTALLCLIENTCMD_SH=@INSTALLCLIENTCMD_SH@
INSTALLCLIENTCMD_A=@INSTALLCLIENTCMD_A@
@@ -199,7 +197,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/util_str.o lib/clobber.o lib/util_sid.o lib/util_uuid.o \
lib/util_unistr.o lib/util_file.o lib/data_blob.o \
lib/util.o lib/util_sock.o lib/sock_exec.o lib/util_sec.o \
- lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \
+ lib/talloc.o lib/substitute.o lib/fsusage.o \
lib/ms_fnmatch.o lib/select.o lib/messages.o \
lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \
lib/md5.o lib/hmacmd5.o lib/iconv.o \
@@ -397,7 +395,7 @@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \
$(LIBMSRPC_OBJ) \
$(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \
$(LIB_SMBD_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
- $(UBIQX_OBJ) $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
+ $(BUILDOPT_OBJ) $(SMBLDAP_OBJ)
PRINTING_OBJ = printing/pcap.o printing/print_svid.o \
printing/print_cups.o printing/print_generic.o \
@@ -533,7 +531,7 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
- utils/net_status.o
+ utils/net_status.o utils/net_rpc_printer.o
NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -847,27 +845,27 @@ bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy
bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(PROFILES_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
bin/editreg@EXEEXT@: $(EDITREG_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(EDITREG_OBJ) $(LDFLAGS) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(EDITREG_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@
bin/smbspool@EXEEXT@: $(CUPS_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbmount@EXEEXT@: $(MOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbmnt@EXEEXT@: $(MNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MNT_OBJ) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(MNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/smbumount@EXEEXT@: $(UMOUNT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(UMOUNT_OBJ) $(LDFLAGS)
+ @$(CC) $(FLAGS) -o $@ $(UMOUNT_OBJ) $(DYNEXP) $(LDFLAGS)
bin/testparm@EXEEXT@: $(TESTPARM_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -919,15 +917,15 @@ bin/smbtorture@EXEEXT@: $(SMBTORTURE_OBJ) bin/.dummy
bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(TALLOCTORT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
bin/masktest@EXEEXT@: $(MASKTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(SECRETS_OBJ)
+ @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(SECRETS_OBJ)
bin/msgtest@EXEEXT@: $(MSGTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbcacls@EXEEXT@: $(SMBCACLS_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -939,11 +937,11 @@ bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy
bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
@@ -955,11 +953,11 @@ bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy
bin/log2pcap@EXEEXT@: $(LOG2PCAP_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) @POPTLIBS@ $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) $(DYNEXP) @POPTLIBS@ $(LIBS)
bin/locktest2@EXEEXT@: $(LOCKTEST2_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy
@echo Linking $@
@@ -967,15 +965,15 @@ bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy
bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(LIBS)
+ @$(CC) $(FLAGS) -o $@ $(DEBUG2HTML_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS)
bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS)
bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy
@echo Linking $@
@@ -989,7 +987,7 @@ bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy
bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS)
@echo Linking libsmbclient shared library $@
- @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \
$(KRB5LIBS) $(LDAP_LIBS) \
@SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR)
@@ -1064,7 +1062,8 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ)
bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
@echo "Linking $@"
- @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(WINBINDD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \
+ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
# libraries. Add to the appropriate PICOBJ variable instead.
@@ -1225,13 +1224,14 @@ bin/afsacl.@SHLIBEXT@: $(VFS_AFSACL_OBJ:.o=.po)
bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@
bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(LINK) -o $@ $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
- $(UBIQX_OBJ) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
+ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(DYNEXP) $(NTLM_AUTH_OBJ) \
+ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(LIBS) \
+ @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS)
bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ)
@echo "Linking shared library $@"
@@ -1242,28 +1242,28 @@ bin/libmsrpc.a: $(LIBMSRPC_PICOBJ)
bin/tdbbackup@EXEEXT@: $(TDBBACKUP_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(TDBBACKUP_OBJ)
+ @$(CC) $(FLAGS) -o $@ $(DYNEXP) $(TDBBACKUP_OBJ)
bin/tdbdump@EXEEXT@: $(TDBDUMP_OBJ) bin/.dummy
@echo Linking $@
- @$(CC) $(FLAGS) -o $@ $(TDBDUMP_OBJ)
+ @$(CC) $(FLAGS) -o $@ $(DYNEXP) $(TDBDUMP_OBJ)
bin/t_strcmp@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strcmp.o -L ./bin -lbigballofmud
bin/t_strstr@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o
- $(CC) $(FLAGS) -o $@ torture/t_stringoverflow.o -L./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud
bin/t_doschar@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_doschar.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud
bin/t_push_ucs2@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_push_ucs2.o
- $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud
bin/t_snprintf@EXEEXT@: lib/snprintf.c
- $(CC) $(FLAGS) -o $@ -DTEST_SNPRINTF lib/snprintf.c -lm
+ $(CC) $(FLAGS) -o $@ $(DYNEXP) -DTEST_SNPRINTF lib/snprintf.c -lm
install: installbin installman installscripts installdat installswat installmodules @INSTALLCLIENT@
install-everything: install installmodules
diff --git a/source/VERSION b/source/VERSION
index ab14d54bdd0..f33e71fb577 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -19,7 +19,7 @@
########################################################
SAMBA_VERSION_MAJOR=3
SAMBA_VERSION_MINOR=0
-SAMBA_VERSION_RELEASE=7
+SAMBA_VERSION_RELEASE=8
########################################################
# For 'pre' releases the version will be #
@@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=7
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=
+SAMBA_VERSION_PRE_RELEASE=1
########################################################
# For 'rc' releases the version will be #
diff --git a/source/client/client.c b/source/client/client.c
index 1fccfaa581c..e14bcaa2616 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -592,7 +592,7 @@ static int cmd_dir(void)
else
pstrcat(mask,p);
} else {
- pstrcat(mask,"*");
+ pstrcat(mask,"\\*");
}
do_list(mask, attribute, display_finfo, recurse, True);
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 64c194b54da..4cadef558d6 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -1345,8 +1345,9 @@ Principal command for creating / extracting
int cmd_tar(void)
{
fstring buf;
- char **argl;
- int argcl;
+ char **argl = NULL;
+ int argcl = 0;
+ int ret;
if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) {
DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
@@ -1357,8 +1358,9 @@ int cmd_tar(void)
if (!tar_parseargs(argcl, argl, buf, 0))
return 1;
+ ret = process_tar();
SAFE_FREE(argl);
- return process_tar();
+ return ret;
}
/****************************************************************************
diff --git a/source/configure.in b/source/configure.in
index 53267f0cd95..69152d8fc8f 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -414,7 +414,6 @@ case "$host_os" in
AC_DEFINE(_MAX_ALIGNMENT, 4, [Maximum alignment])
;;
esac
- DYNEXP="-Wl,-E"
;;
#
@@ -1215,9 +1214,9 @@ if test "$enable_shared" = "yes"; then
# Use special PIC flags for the native HP-UX compiler.
if test $ac_cv_prog_cc_Ae = yes; then
BLDSHARED="true"
- SHLD="/usr/bin/ld"
- LDSHFLAGS="-B symbolic -b -z"
- SONAMEFLAG="+h "
+ SHLD="cc"
+ LDSHFLAGS="-b -Wl,-B,symbolic,-b,-z"
+ SONAMEFLAG="-Wl,+h "
PICFLAGS="+z"
elif test "${GCC}" = "yes"; then
PICFLAGS="-fPIC"
@@ -1302,13 +1301,14 @@ fi
if test $BLDSHARED = true; then
AC_CACHE_CHECK([whether building shared libraries actually works],
[ac_cv_shlib_works],[
- ac_cv_shlib_works=no
# try building a trivial shared library
+ ac_cv_shlib_works=no
+ # The $SHLD and $LDSHFLAGS variables may contain references to other
+ # variables so they need to be eval'ed.
$CC $CPPFLAGS $CFLAGS $PICFLAGS -c -o \
shlib.$PICSUFFIX ${srcdir-.}/tests/shlib.c && \
- $CC $CPPFLAGS $CFLAGS `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" \
- shlib.$PICSUFFIX && \
- ac_cv_shlib_works=yes
+ `eval echo $SHLD` `eval echo $LDSHFLAGS` -o "shlib.$SHLIBEXT" \
+ shlib.$PICSUFFIX && ac_cv_shlib_works=yes
rm -f "shlib.$SHLIBEXT" shlib.$PICSUFFIX
])
if test $ac_cv_shlib_works = no; then
@@ -2761,6 +2761,7 @@ if test x"$with_ads_support" != x"no"; then
AC_CHECK_FUNC_EXT(krb5_free_unparsed_name, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_free_keytab_entry_contents, $KRB5_LIBS)
AC_CHECK_FUNC_EXT(krb5_kt_free_entry, $KRB5_LIBS)
+ AC_CHECK_FUNC_EXT(krb5_krbhst_get_addrinfo, $KRB5_LIBS)
LIBS="$LIBS $KRB5_LIBS"
@@ -4235,7 +4236,7 @@ AC_SUBST(WINBIND_NSS_LDSHFLAGS)
AC_SUBST(WINBIND_NSS_EXTRA_OBJS)
AC_SUBST(WINBIND_NSS_EXTRA_LIBS)
-# Check the setting of --with-winbindd
+# Check the setting of --with-winbind
AC_ARG_WITH(winbind,
[ --with-winbind Build winbind (default, if supported by OS)],
diff --git a/source/include/charset.h b/source/include/charset.h
index 7a9b12ef55d..c5d03a62e89 100644
--- a/source/include/charset.h
+++ b/source/include/charset.h
@@ -31,9 +31,9 @@ typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t
struct charset_functions {
const char *name;
- size_t (*pull)(void *, char **inbuf, size_t *inbytesleft,
+ size_t (*pull)(void *, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
- size_t (*push)(void *, char **inbuf, size_t *inbytesleft,
+ size_t (*push)(void *, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
struct charset_functions *prev, *next;
};
@@ -57,7 +57,7 @@ struct charset_gap_table {
*
* */
#define SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CHARSETNAME) \
-static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft, \
+static size_t CHARSETNAME ## _push(void *cd, const char **inbuf, size_t *inbytesleft, \
char **outbuf, size_t *outbytesleft) \
{ \
while (*inbytesleft >= 2 && *outbytesleft >= 1) { \
@@ -97,7 +97,7 @@ static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft,
return 0; \
} \
\
-static size_t CHARSETNAME ## _pull(void *cd, char **inbuf, size_t *inbytesleft, \
+static size_t CHARSETNAME ## _pull(void *cd, const char **inbuf, size_t *inbytesleft, \
char **outbuf, size_t *outbytesleft) \
{ \
while (*inbytesleft >= 1 && *outbytesleft >= 2) { \
@@ -124,4 +124,3 @@ NTSTATUS charset_ ## CHARSETNAME ## _init(void) \
return smb_register_charset(& CHARSETNAME ## _functions); \
} \
-
diff --git a/source/include/fake_file.h b/source/include/fake_file.h
index cfcd16f6830..63ba41d7860 100644
--- a/source/include/fake_file.h
+++ b/source/include/fake_file.h
@@ -28,9 +28,9 @@ enum FAKE_FILE_TYPE {
/*
we now get the unix name --metze
-#define FAKE_FILE_NAME_QUOTA "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"
*/
-#define FAKE_FILE_NAME_QUOTA "$Extend/$Quota:$Q:$INDEX_ALLOCATION"
+#define FAKE_FILE_NAME_QUOTA_WIN32 "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"
+#define FAKE_FILE_NAME_QUOTA_UNIX "$Extend/$Quota:$Q:$INDEX_ALLOCATION"
typedef struct _FAKE_FILE_HANDLE {
enum FAKE_FILE_TYPE type;
diff --git a/source/include/hash.h b/source/include/hash.h
deleted file mode 100644
index 40cc8b7cab3..00000000000
--- a/source/include/hash.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Ying Chen 2000.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _HASH_H_
-#define _HASH_H_
-
-#define MAX_HASH_TABLE_SIZE 16384
-#define HASH_TABLE_INCREMENT 2
-
-typedef int (*compare_function)(char *, char *);
-typedef int (*hash_function)(int, char *);
-
-/*
- * lru_link: links the node to the LRU list.
- * hash_elem: the pointer to the element that is tied onto the link.
- */
-typedef struct lru_node {
- ubi_dlNode lru_link;
- void *hash_elem;
-} lru_node;
-
-/*
- * bucket_link: link the hash element to the bucket chain that it belongs to.
- * lru_link: this element ties the hash element to the lru list.
- * bucket: a pointer to the hash bucket that this element belongs to.
- * value: a pointer to the hash element content. It can be anything.
- * key: stores the string key. The hash_element is always allocated with
- * more memory space than the structure shown below to accomodate the space
- * used for the whole string. But the memory is always appended at the
- * end of the structure, so keep "key" at the end of the structure.
- * Don't move it.
- */
-typedef struct hash_element {
- ubi_dlNode bucket_link;
- lru_node lru_link;
- ubi_dlList *bucket;
- void *value;
- char key[1];
-} hash_element;
-
-/*
- * buckets: a list of buckets, implemented as a dLinkList.
- * lru_chain: the lru list of all the hash elements.
- * num_elements: the # of elements in the hash table.
- * size: the hash table size.
- * comp_func: the compare function used during hash key comparisons.
- */
-
-typedef struct hash_table {
- ubi_dlList *buckets;
- ubi_dlList lru_chain;
- unsigned num_elements;
- unsigned size;
- compare_function comp_func;
-} hash_table;
-
-#endif /* _HASH_H_ */
diff --git a/source/include/includes.h b/source/include/includes.h
index 1d913d3f32a..3ea4eaa35a9 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -45,10 +45,11 @@
#undef HAVE_TERMIOS_H
#endif
-#ifdef __GNUC__
+#if (__GNUC__ >= 3)
/** Use gcc attribute to check printf fns. a1 is the 1-based index of
* the parameter containing the format, and a2 the index of the first
- * argument. **/
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
#else
#define PRINTF_ATTRIBUTE(a1, a2)
@@ -309,6 +310,19 @@
#endif
#ifdef HAVE_SHADOW_H
+/*
+ * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
+ * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
+ * them again without checking if they already exsist. This generates
+ * two "Redefinition of macro" warnings for every single .c file that is
+ * compiled.
+ */
+#if defined(HPUX) && defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(HPUX) && defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
#include <shadow.h>
#endif
@@ -361,6 +375,19 @@
#if defined(HAVE_SYS_SECURITY_H) && defined(HAVE_RPC_AUTH_ERROR_CONFLICT)
#undef AUTH_ERROR
#endif
+/*
+ * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
+ * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
+ * them again without checking if they already exsist. This generates
+ * two "Redefinition of macro" warnings for every single .c file that is
+ * compiled.
+ */
+#if defined(HPUX) && defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(HPUX) && defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
#include <rpc/rpc.h>
#endif
@@ -369,12 +396,25 @@
#endif
#if defined (HAVE_NETGROUP)
-#if defined(HAVE_RPCSVC_YPCLNT_H)
-#include <rpcsvc/ypclnt.h>
-#endif
#if defined(HAVE_RPCSVC_YP_PROT_H)
+/*
+ * HP-UX 11.X has TCP_NODELAY and TCP_MAXSEG defined in <netinet/tcp.h> which
+ * was included above. However <rpc/rpc.h> includes <sys/xti.h> which defines
+ * them again without checking if they already exsist. This generates
+ * two "Redefinition of macro" warnings for every single .c file that is
+ * compiled.
+ */
+#if defined(HPUX) && defined(TCP_NODELAY)
+#undef TCP_NODELAY
+#endif
+#if defined(HPUX) && defined(TCP_MAXSEG)
+#undef TCP_MAXSEG
+#endif
#include <rpcsvc/yp_prot.h>
#endif
+#if defined(HAVE_RPCSVC_YPCLNT_H)
+#include <rpcsvc/ypclnt.h>
+#endif
#endif /* HAVE_NETGROUP */
#if defined(HAVE_SYS_IPC_H)
@@ -760,7 +800,6 @@ extern int errno;
#include "nt_status.h"
#include "ads.h"
#include "interfaces.h"
-#include "hash.h"
#include "trans2.h"
#include "nterr.h"
#include "ntioctl.h"
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index cf7d1ba3412..f2b78f91bc0 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -1026,6 +1026,7 @@ typedef struct printer_info_ctr_info
PRINTER_INFO_3 *printers_3;
PRINTER_INFO_4 *printers_4;
PRINTER_INFO_5 *printers_5;
+ PRINTER_INFO_7 *printers_7;
}
PRINTER_INFO_CTR;
diff --git a/source/include/smb.h b/source/include/smb.h
index 32dba0cf78f..7317fd16b0f 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1658,11 +1658,11 @@ struct unix_error_map {
/* generic iconv conversion structure */
typedef struct {
- size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
+ size_t (*direct)(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
- size_t (*pull)(void *cd, char **inbuf, size_t *inbytesleft,
+ size_t (*pull)(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
- size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft,
+ size_t (*push)(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft);
void *cd_direct, *cd_pull, *cd_push;
char *from_name, *to_name;
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index bcbaa64f863..a9e911c066a 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -26,7 +26,6 @@
/* Misc bit macros */
#define BOOLSTR(b) ((b) ? "Yes" : "No")
-#define BITSETB(ptr,bit) ((((char *)ptr)[0] & (1<<(bit)))!=0)
#define BITSETW(ptr,bit) ((SVAL(ptr,0) & (1<<(bit)))!=0)
/* for readability... */
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index 953937fb75d..58502ec34e7 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -107,7 +107,9 @@ typedef struct _attrib_map_entry {
/* structures */
extern ATTRIB_MAP_ENTRY attrib_map_v22[];
+extern ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[];
extern ATTRIB_MAP_ENTRY attrib_map_v30[];
+extern ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[];
extern ATTRIB_MAP_ENTRY dominfo_attr_list[];
extern ATTRIB_MAP_ENTRY groupmap_attr_list[];
extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[];
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 6cbf7562b06..40004826b4a 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -56,7 +56,7 @@ static const char *charset_name(charset_t ch)
{
const char *ret = NULL;
- if (ch == CH_UCS2) ret = "UCS-2LE";
+ if (ch == CH_UCS2) ret = "UTF-16LE";
else if (ch == CH_UNIX) ret = lp_unix_charset();
else if (ch == CH_DOS) ret = lp_dos_charset();
else if (ch == CH_DISPLAY) ret = lp_display_charset();
@@ -116,10 +116,10 @@ void init_iconv(void)
/* so that charset_name() works we need to get the UNIX<->UCS2 going
first */
if (!conv_handles[CH_UNIX][CH_UCS2])
- conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
+ conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII");
if (!conv_handles[CH_UCS2][CH_UNIX])
- conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
+ conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2));
for (c1=0;c1<NUM_CHARSETS;c1++) {
for (c2=0;c2<NUM_CHARSETS;c2++) {
@@ -216,7 +216,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
again:
- retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len);
+ retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
if(retval==(size_t)-1) {
const char *reason="unknown error";
switch(errno) {
@@ -229,14 +229,18 @@ static size_t convert_string_internal(charset_t from, charset_t to,
break;
case E2BIG:
reason="No more room";
- if (!conv_silent)
- DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n",
- (unsigned long)srclen, (unsigned long)destlen));
- /* we are not sure we need srclen bytes,
- may be more, may be less.
- We only know we need more than destlen
- bytes ---simo */
- break;
+ if (!conv_silent) {
+ if (from == CH_UNIX) {
+ DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
+ charset_name(from), charset_name(to),
+ (unsigned int)srclen, (unsigned int)destlen, (const char *)src));
+ } else {
+ DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
+ charset_name(from), charset_name(to),
+ (unsigned int)srclen, (unsigned int)destlen));
+ }
+ }
+ break;
case EILSEQ:
reason="Illegal multibyte sequence";
if (!conv_silent)
@@ -531,7 +535,7 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
again:
retval = smb_iconv(descriptor,
- (char **)&inbuf, &i_len,
+ &inbuf, &i_len,
&outbuf, &o_len);
if(retval == (size_t)-1) {
const char *reason="unknown error";
diff --git a/source/lib/hash.c b/source/lib/hash.c
deleted file mode 100644
index 18b6534dec2..00000000000
--- a/source/lib/hash.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Ying Chen 2000.
- Copyright (C) Jeremy Allison 2000.
- - added some defensive programming.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/*
- * NB. We may end up replacing this functionality in a future 2.x
- * release to reduce the number of hashing/lookup methods we support. JRA.
- */
-
-#include "includes.h"
-
-static BOOL enlarge_hash_table(hash_table *table);
-static unsigned primes[] =
- {17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 16411};
-
-/****************************************************************************
- * This function initializes the hash table.
- * This hash function hashes on string keys.
- * This number of hash buckets is always rounded up to a power of
- * 2 first, then to a prime number that is large than the power of two.
- * Input:
- * table -- the hash table pointer.
- * num_buckets -- the number of buckets to be allocated. This
- * hash function can dynamically increase its size when the
- * the hash table size becomes small. There is a MAX hash table
- * size defined in hash.h.
- * compare_func -- the function pointer to a comparison function
- * used by the hash key comparison.
- ****************************************************************************
- */
-
-BOOL hash_table_init(hash_table *table, unsigned num_buckets, compare_function compare_func)
-{
- unsigned i;
- ubi_dlList *bucket;
-
- table->num_elements = 0;
- table->size = 2;
- table->comp_func = compare_func;
- while (table->size < num_buckets)
- table->size <<= 1;
- for (i = 0; i < ARRAY_SIZE(primes); i++) {
- if (primes[i] > table->size) {
- table->size = primes[i];
- break;
- }
- }
-
- DEBUG(5, ("Hash size = %d.\n", table->size));
-
- if(!(table->buckets = (ubi_dlList *) malloc(sizeof(ubi_dlList) * table->size))) {
- DEBUG(0,("hash_table_init: malloc fail !\n"));
- return False;
- }
- ubi_dlInitList(&(table->lru_chain));
- for (i=0, bucket = table->buckets; i < table->size; i++, bucket++)
- ubi_dlInitList(bucket);
-
- return True;
-}
-
-/*
- **************************************************************
- * Compute a hash value based on a string key value.
- * Make the string key into an array of int's if possible.
- * For the last few chars that cannot be int'ed, use char instead.
- * The function returns the bucket index number for the hashed
- * key.
- * JRA. Use a djb-algorithm hash for speed.
- **************************************************************
- */
-
-static int string_hash(int hash_size, const char *key)
-{
- u32 n = 0;
- const char *p;
- for (p = key; *p != '\0'; p++) {
- n = ((n << 5) + n) ^ (u32)(*p);
- }
- return (n % hash_size);
-}
-
-/* *************************************************************************
- * Search the hash table for the entry in the hash chain.
- * The function returns the pointer to the
- * element found in the chain or NULL if none is found.
- * If the element is found, the element is also moved to
- * the head of the LRU list.
- *
- * Input:
- * table -- The hash table where the element is stored in.
- * hash_chain -- The pointer to the bucket that stores the
- * element to be found.
- * key -- The hash key to be found.
- ***************************************************************************
- */
-
-static hash_element *hash_chain_find(hash_table *table, ubi_dlList *hash_chain, char *key)
-{
- hash_element *hash_elem;
- ubi_dlNodePtr lru_item;
- unsigned int i = 0;
-
- for (hash_elem = (hash_element *)(ubi_dlFirst(hash_chain)); i < hash_chain->count;
- i++, hash_elem = (hash_element *)(ubi_dlNext(hash_elem))) {
- if ((table->comp_func)(hash_elem->key, key) == 0) {
- /* Move to the head of the lru List. */
- lru_item = ubi_dlRemove(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- ubi_dlAddHead(&(table->lru_chain), lru_item);
- return(hash_elem);
- }
- }
- return ((hash_element *) NULL);
-}
-
-/* ***************************************************************************
- *
- * Lookup a hash table for an element with key.
- * The function returns a pointer to the hash element.
- * If no element is found, the function returns NULL.
- *
- * Input:
- * table -- The hash table to be searched on.
- * key -- The key to be found.
- *****************************************************************************
- */
-
-hash_element *hash_lookup(hash_table *table, char *key)
-{
- return (hash_chain_find(table, &table->buckets[string_hash(table->size, key)], key));
-}
-
-/* ***************************************************************
- *
- * This function first checks if an element with key "key"
- * exists in the hash table. If so, the function moves the
- * element to the front of the LRU list. Otherwise, a new
- * hash element corresponding to "value" and "key" is allocated
- * and inserted into the hash table. The new elements are
- * always inserted in the LRU order to the LRU list as well.
- *
- * Input:
- * table -- The hash table to be inserted in.
- * value -- The content of the element to be inserted.
- * key -- The key of the new element to be inserted.
- *
- ****************************************************************
- */
-
-hash_element *hash_insert(hash_table *table, char *value, char *key)
-{
- hash_element *hash_elem;
- ubi_dlNodePtr lru_item;
- ubi_dlList *bucket;
- size_t string_length;
-
- /*
- * If the hash table size has not reached the MAX_HASH_TABLE_SIZE,
- * the hash table may be enlarged if the current hash table is full.
- * If the hash table size has reached the MAX_HASH_TABLE_SIZE,
- * use LRU to remove the oldest element from the hash table.
- */
-
- if ((table->num_elements >= table->size) &&
- (table->num_elements < MAX_HASH_TABLE_SIZE)) {
- if(!enlarge_hash_table(table))
- return (hash_element *)NULL;
- table->num_elements += 1;
- } else if (table->num_elements >= MAX_HASH_TABLE_SIZE) {
- /* Do an LRU replacement. */
- lru_item = ubi_dlLast(&(table->lru_chain));
- hash_elem = (hash_element *)(((lru_node *)lru_item)->hash_elem);
- bucket = hash_elem->bucket;
- ubi_dlRemThis(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- ubi_dlRemThis(bucket, (ubi_dlNodePtr)hash_elem);
- SAFE_FREE(hash_elem->value);
- SAFE_FREE(hash_elem);
- } else {
- table->num_elements += 1;
- }
-
- bucket = &table->buckets[string_hash(table->size, key)];
-
- /* Since we only have 1-byte for the key string, we need to
- * allocate extra space in the hash_element to store the entire key
- * string.
- */
-
- string_length = strlen(key);
- if(!(hash_elem = (hash_element *) malloc(sizeof(hash_element) + string_length))) {
- DEBUG(0,("hash_insert: malloc fail !\n"));
- return (hash_element *)NULL;
- }
-
- safe_strcpy((char *) hash_elem->key, key, string_length);
-
- hash_elem->value = (char *)value;
- hash_elem->bucket = bucket;
- /* Insert in front of the lru list and the bucket list. */
- ubi_dlAddHead(bucket, hash_elem);
- hash_elem->lru_link.hash_elem = hash_elem;
- ubi_dlAddHead(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
-
- return(hash_elem);
-}
-
-/* **************************************************************************
- *
- * Remove a hash element from the hash table. The hash element is
- * removed from both the LRU list and the hash bucket chain.
- *
- * Input:
- * table -- the hash table to be manipulated on.
- * hash_elem -- the element to be removed.
- **************************************************************************
- */
-
-void hash_remove(hash_table *table, hash_element *hash_elem)
-{
- if (hash_elem) {
- ubi_dlRemove(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- ubi_dlRemove(hash_elem->bucket, (ubi_dlNodePtr) hash_elem);
- SAFE_FREE(hash_elem->value);
- SAFE_FREE(hash_elem);
- table->num_elements--;
- }
-}
-
-/* ******************************************************************
- * Increase the hash table size if it is too small.
- * The hash table size is increased by the HASH_TABLE_INCREMENT
- * ratio.
- * Input:
- * table -- the hash table to be enlarged.
- ******************************************************************
- */
-
-static BOOL enlarge_hash_table(hash_table *table)
-{
- hash_element *hash_elem;
- int size, hash_value;
- ubi_dlList *buckets;
- ubi_dlList *old_bucket;
- ubi_dlList *bucket;
- ubi_dlList lru_chain;
-
- buckets = table->buckets;
- lru_chain = table->lru_chain;
- size = table->size;
-
- /* Reinitialize the hash table. */
- if(!hash_table_init(table, table->size * HASH_TABLE_INCREMENT, table->comp_func))
- return False;
-
- for (old_bucket = buckets; size > 0; size--, old_bucket++) {
- while (old_bucket->count != 0) {
- hash_elem = (hash_element *) ubi_dlRemHead(old_bucket);
- ubi_dlRemove(&lru_chain, &(hash_elem->lru_link.lru_link));
- hash_value = string_hash(table->size, (char *) hash_elem->key);
- bucket = &(table->buckets[hash_value]);
- ubi_dlAddHead(bucket, hash_elem);
- ubi_dlAddHead(&(table->lru_chain), &(hash_elem->lru_link.lru_link));
- hash_elem->bucket = bucket;
- hash_elem->lru_link.hash_elem = hash_elem;
- table->num_elements++;
- }
- }
- SAFE_FREE(buckets);
-
- return True;
-}
-
-/* **********************************************************************
- *
- * Remove everything from a hash table and free up the memory it
- * occupies.
- * Input:
- * table -- the hash table to be cleared.
- *
- *************************************************************************
- */
-
-void hash_clear(hash_table *table)
-{
- unsigned int i;
- ubi_dlList *bucket = table->buckets;
- hash_element *hash_elem;
- for (i = 0; i < table->size; bucket++, i++) {
- while (bucket->count != 0) {
- hash_elem = (hash_element *) ubi_dlRemHead(bucket);
- SAFE_FREE(hash_elem->value);
- SAFE_FREE(hash_elem);
- }
- }
- table->size = 0;
- SAFE_FREE(table->buckets);
- table->buckets = NULL;
-}
diff --git a/source/lib/iconv.c b/source/lib/iconv.c
index 4c9ecf992e6..66a6e6cd8bc 100644
--- a/source/lib/iconv.c
+++ b/source/lib/iconv.c
@@ -51,18 +51,26 @@
* @sa Samba Developers Guide
**/
-static size_t ascii_pull(void *,char **, size_t *, char **, size_t *);
-static size_t ascii_push(void *,char **, size_t *, char **, size_t *);
-static size_t latin1_push(void *,char **, size_t *, char **, size_t *);
-static size_t utf8_pull(void *,char **, size_t *, char **, size_t *);
-static size_t utf8_push(void *,char **, size_t *, char **, size_t *);
-static size_t ucs2hex_pull(void *,char **, size_t *, char **, size_t *);
-static size_t ucs2hex_push(void *,char **, size_t *, char **, size_t *);
-static size_t iconv_copy(void *,char **, size_t *, char **, size_t *);
+static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *);
+static size_t ascii_push(void *,const char **, size_t *, char **, size_t *);
+static size_t latin1_push(void *,const char **, size_t *, char **, size_t *);
+static size_t utf8_pull(void *,const char **, size_t *, char **, size_t *);
+static size_t utf8_push(void *,const char **, size_t *, char **, size_t *);
+static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *);
+static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *);
+static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *);
+static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *);
static struct charset_functions builtin_functions[] = {
+ /* windows is really neither UCS-2 not UTF-16 */
{"UCS-2LE", iconv_copy, iconv_copy},
+ {"UTF-16LE", iconv_copy, iconv_copy},
+ {"UCS-2BE", iconv_swab, iconv_swab},
+ {"UTF-16BE", iconv_swab, iconv_swab},
+
+ /* we include the UTF-8 alias to cope with differing locale settings */
{"UTF8", utf8_pull, utf8_push},
+ {"UTF-8", utf8_pull, utf8_push},
{"ASCII", ascii_pull, ascii_push},
{"646", ascii_pull, ascii_push},
{"ISO-8859-1", ascii_pull, latin1_push},
@@ -122,12 +130,12 @@ static void lazy_initialize_iconv(void)
this ensures that we don't have a shift state remaining for
character sets like SJIS */
static size_t sys_iconv(void *cd,
- char **inbuf, size_t *inbytesleft,
+ const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
#ifdef HAVE_NATIVE_ICONV
size_t ret = iconv((iconv_t)cd,
- inbuf, inbytesleft,
+ (char **)inbuf, inbytesleft,
outbuf, outbytesleft);
if (ret == (size_t)-1) {
int saved_errno = errno;
@@ -148,7 +156,7 @@ static size_t sys_iconv(void *cd,
* enough that Samba works on systems that don't have iconv.
**/
size_t smb_iconv(smb_iconv_t cd,
- char **inbuf, size_t *inbytesleft,
+ const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
char cvtbuf[2048];
@@ -158,7 +166,7 @@ size_t smb_iconv(smb_iconv_t cd,
/* in many cases we can go direct */
if (cd->direct) {
return cd->direct(cd->cd_direct,
- (char **)inbuf, inbytesleft, outbuf, outbytesleft);
+ inbuf, inbytesleft, outbuf, outbytesleft);
}
@@ -168,20 +176,27 @@ size_t smb_iconv(smb_iconv_t cd,
bufsize = sizeof(cvtbuf);
if (cd->pull(cd->cd_pull,
- (char **)inbuf, inbytesleft, &bufp, &bufsize) == -1
+ inbuf, inbytesleft, &bufp, &bufsize) == -1
&& errno != E2BIG) return -1;
bufp = cvtbuf;
bufsize = sizeof(cvtbuf) - bufsize;
if (cd->push(cd->cd_push,
- &bufp, &bufsize,
+ (const char **)&bufp, &bufsize,
outbuf, outbytesleft) == -1) return -1;
}
return 0;
}
+
+static BOOL is_utf16(const char *name)
+{
+ return strcasecmp(name, "UCS-2LE") == 0 ||
+ strcasecmp(name, "UTF-16LE") == 0;
+}
+
/*
simple iconv_open() wrapper
*/
@@ -220,13 +235,17 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
/* check if we can use iconv for this conversion */
#ifdef HAVE_NATIVE_ICONV
if (!ret->pull) {
- ret->cd_pull = iconv_open("UCS-2LE", fromcode);
+ ret->cd_pull = iconv_open("UTF-16LE", fromcode);
+ if (ret->cd_pull == (iconv_t)-1)
+ ret->cd_pull = iconv_open("UCS-2LE", fromcode);
if (ret->cd_pull != (iconv_t)-1)
ret->pull = sys_iconv;
}
if (!ret->push) {
- ret->cd_push = iconv_open(tocode, "UCS-2LE");
+ ret->cd_push = iconv_open(tocode, "UTF-16LE");
+ if (ret->cd_push == (iconv_t)-1)
+ ret->cd_push = iconv_open(tocode, "UCS-2LE");
if (ret->cd_push != (iconv_t)-1)
ret->push = sys_iconv;
}
@@ -256,13 +275,13 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
}
/* check for conversion to/from ucs2 */
- if (strcasecmp(fromcode, "UCS-2LE") == 0 && to) {
+ if (is_utf16(fromcode) && to) {
ret->direct = to->push;
ret->push = ret->pull = NULL;
return ret;
}
- if (strcasecmp(tocode, "UCS-2LE") == 0 && from) {
+ if (is_utf16(tocode) && from) {
ret->direct = from->pull;
ret->push = ret->pull = NULL;
return ret;
@@ -270,13 +289,13 @@ smb_iconv_t smb_iconv_open(const char *tocode, const char *fromcode)
/* Check if we can do the conversion direct */
#ifdef HAVE_NATIVE_ICONV
- if (strcasecmp(fromcode, "UCS-2LE") == 0) {
+ if (is_utf16(fromcode)) {
ret->direct = sys_iconv;
ret->cd_direct = ret->cd_push;
ret->cd_push = NULL;
return ret;
}
- if (strcasecmp(tocode, "UCS-2LE") == 0) {
+ if (is_utf16(tocode)) {
ret->direct = sys_iconv;
ret->cd_direct = ret->cd_pull;
ret->cd_pull = NULL;
@@ -313,7 +332,7 @@ int smb_iconv_close (smb_iconv_t cd)
multi-byte character set support for english users
***********************************************************************/
-static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 1 && *outbytesleft >= 2) {
@@ -333,7 +352,7 @@ static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int ir_count=0;
@@ -360,7 +379,7 @@ static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft,
return ir_count;
}
-static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int ir_count=0;
@@ -387,7 +406,7 @@ static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft,
return ir_count;
}
-static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 1 && *outbytesleft >= 2) {
@@ -430,7 +449,7 @@ static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 2 && *outbytesleft >= 1) {
@@ -471,8 +490,32 @@ static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
+static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft,
+ char **outbuf, size_t *outbytesleft)
+{
+ int n;
+
+ n = MIN(*inbytesleft, *outbytesleft);
+
+ swab(*inbuf, *outbuf, (n&~1));
+ if (n&1) {
+ (*outbuf)[n-1] = 0;
+ }
+
+ (*inbytesleft) -= n;
+ (*outbytesleft) -= n;
+ (*inbuf) += n;
+ (*outbuf) += n;
+
+ if (*inbytesleft > 0) {
+ errno = E2BIG;
+ return -1;
+ }
-static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft,
+ return 0;
+}
+
+static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int n;
@@ -494,102 +537,234 @@ static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t utf8_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
- while (*inbytesleft >= 1 && *outbytesleft >= 2) {
- unsigned char *c = (unsigned char *)*inbuf;
- unsigned char *uc = (unsigned char *)*outbuf;
- int len = 1;
+ size_t in_left=*inbytesleft, out_left=*outbytesleft;
+ const uint8 *c = (const uint8 *)*inbuf;
+ uint8 *uc = (uint8 *)*outbuf;
+ while (in_left >= 1 && out_left >= 2) {
if ((c[0] & 0x80) == 0) {
uc[0] = c[0];
uc[1] = 0;
- } else if ((c[0] & 0xf0) == 0xe0) {
- if (*inbytesleft < 3) {
- DEBUG(0,("short utf8 char\n"));
- goto badseq;
+ c += 1;
+ in_left -= 1;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ if ((c[0] & 0xe0) == 0xc0) {
+ if (in_left < 2 ||
+ (c[1] & 0xc0) != 0x80) {
+ errno = EILSEQ;
+ goto error;
+ }
+ uc[1] = (c[0]>>2) & 0x7;
+ uc[0] = (c[0]<<6) | (c[1]&0x3f);
+ c += 2;
+ in_left -= 2;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ if ((c[0] & 0xf0) == 0xe0) {
+ if (in_left < 3 ||
+ (c[1] & 0xc0) != 0x80 ||
+ (c[2] & 0xc0) != 0x80) {
+ errno = EILSEQ;
+ goto error;
}
uc[1] = ((c[0]&0xF)<<4) | ((c[1]>>2)&0xF);
uc[0] = (c[1]<<6) | (c[2]&0x3f);
- len = 3;
- } else if ((c[0] & 0xe0) == 0xc0) {
- if (*inbytesleft < 2) {
- DEBUG(0,("short utf8 char\n"));
- goto badseq;
+ c += 3;
+ in_left -= 3;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ if ((c[0] & 0xf8) == 0xf0) {
+ unsigned int codepoint;
+ if (in_left < 4 ||
+ (c[1] & 0xc0) != 0x80 ||
+ (c[2] & 0xc0) != 0x80 ||
+ (c[3] & 0xc0) != 0x80) {
+ errno = EILSEQ;
+ goto error;
}
- uc[1] = (c[0]>>2) & 0x7;
- uc[0] = (c[0]<<6) | (c[1]&0x3f);
- len = 2;
+ codepoint =
+ (c[3]&0x3f) |
+ ((c[2]&0x3f)<<6) |
+ ((c[1]&0x3f)<<12) |
+ ((c[0]&0x7)<<18);
+ if (codepoint < 0x10000) {
+ /* accept UTF-8 characters that are not
+ minimally packed, but pack the result */
+ uc[0] = (codepoint & 0xFF);
+ uc[1] = (codepoint >> 8);
+ c += 4;
+ in_left -= 4;
+ out_left -= 2;
+ uc += 2;
+ continue;
+ }
+
+ codepoint -= 0x10000;
+
+ if (out_left < 4) {
+ errno = E2BIG;
+ goto error;
+ }
+
+ uc[0] = (codepoint>>10) & 0xFF;
+ uc[1] = (codepoint>>18) | 0xd8;
+ uc[2] = codepoint & 0xFF;
+ uc[3] = ((codepoint>>8) & 0x3) | 0xdc;
+ c += 4;
+ in_left -= 4;
+ out_left -= 4;
+ uc += 4;
+ continue;
}
- (*inbuf) += len;
- (*inbytesleft) -= len;
- (*outbytesleft) -= 2;
- (*outbuf) += 2;
+ /* we don't handle 5 byte sequences */
+ errno = EINVAL;
+ goto error;
}
- if (*inbytesleft > 0) {
+ if (in_left > 0) {
errno = E2BIG;
- return -1;
+ goto error;
}
-
+
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = c;
+ *outbuf = uc;
return 0;
-badseq:
- errno = EINVAL;
+error:
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = c;
+ *outbuf = uc;
return -1;
}
-static size_t utf8_push(void *cd, char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft)
+static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft,
+ char **outbuf, size_t *outbytesleft)
{
- while (*inbytesleft >= 2 && *outbytesleft >= 1) {
- unsigned char *c = (unsigned char *)*outbuf;
- unsigned char *uc = (unsigned char *)*inbuf;
- int len=1;
-
- if (uc[1] & 0xf8) {
- if (*outbytesleft < 3) {
- DEBUG(0,("short utf8 write\n"));
- goto toobig;
+ size_t in_left=*inbytesleft, out_left=*outbytesleft;
+ uint8 *c = (uint8 *)*outbuf;
+ const uint8 *uc = (const uint8 *)*inbuf;
+
+ while (in_left >= 2 && out_left >= 1) {
+ unsigned int codepoint;
+
+ if (uc[1] == 0 && !(uc[0] & 0x80)) {
+ /* simplest case */
+ c[0] = uc[0];
+ in_left -= 2;
+ out_left -= 1;
+ uc += 2;
+ c += 1;
+ continue;
+ }
+
+ if ((uc[1]&0xf8) == 0) {
+ /* next simplest case */
+ if (out_left < 2) {
+ errno = E2BIG;
+ goto error;
}
- c[0] = 0xe0 | (uc[1]>>4);
- c[1] = 0x80 | ((uc[1]&0xF)<<2) | (uc[0]>>6);
- c[2] = 0x80 | (uc[0]&0x3f);
- len = 3;
- } else if (uc[1] | (uc[0] & 0x80)) {
- if (*outbytesleft < 2) {
- DEBUG(0,("short utf8 write\n"));
- goto toobig;
+ c[0] = 0xc0 | (uc[0]>>6) | (uc[1]<<2);
+ c[1] = 0x80 | (uc[0] & 0x3f);
+ in_left -= 2;
+ out_left -= 2;
+ uc += 2;
+ c += 2;
+ continue;
+ }
+
+ if ((uc[1] & 0xfc) == 0xdc) {
+ /* its the second part of a 4 byte sequence. Illegal */
+ if (in_left < 4) {
+ errno = EINVAL;
+ } else {
+ errno = EILSEQ;
}
- c[0] = 0xc0 | (uc[1]<<2) | (uc[0]>>6);
- c[1] = 0x80 | (uc[0]&0x3f);
- len = 2;
- } else {
- c[0] = uc[0];
+ goto error;
}
+ if ((uc[1] & 0xfc) != 0xd8) {
+ codepoint = uc[0] | (uc[1]<<8);
+ if (out_left < 3) {
+ errno = E2BIG;
+ goto error;
+ }
+ c[0] = 0xe0 | (codepoint >> 12);
+ c[1] = 0x80 | ((codepoint >> 6) & 0x3f);
+ c[2] = 0x80 | (codepoint & 0x3f);
+
+ in_left -= 2;
+ out_left -= 3;
+ uc += 2;
+ c += 3;
+ continue;
+ }
- (*inbytesleft) -= 2;
- (*outbytesleft) -= len;
- (*inbuf) += 2;
- (*outbuf) += len;
+ /* its the first part of a 4 byte sequence */
+ if (in_left < 4) {
+ errno = EINVAL;
+ goto error;
+ }
+ if ((uc[3] & 0xfc) != 0xdc) {
+ errno = EILSEQ;
+ goto error;
+ }
+ codepoint = 0x10000 + (uc[2] | ((uc[3] & 0x3)<<8) |
+ (uc[0]<<10) | ((uc[1] & 0x3)<<18));
+
+ if (out_left < 4) {
+ errno = E2BIG;
+ goto error;
+ }
+ c[0] = 0xf0 | (codepoint >> 18);
+ c[1] = 0x80 | ((codepoint >> 12) & 0x3f);
+ c[2] = 0x80 | ((codepoint >> 6) & 0x3f);
+ c[3] = 0x80 | (codepoint & 0x3f);
+
+ in_left -= 4;
+ out_left -= 4;
+ uc += 4;
+ c += 4;
}
- if (*inbytesleft == 1) {
+ if (in_left == 1) {
errno = EINVAL;
- return -1;
+ goto error;
}
- if (*inbytesleft > 1) {
+ if (in_left > 1) {
errno = E2BIG;
- return -1;
+ goto error;
}
+
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = uc;
+ *outbuf = c;
return 0;
-toobig:
- errno = E2BIG;
+error:
+ *inbytesleft = in_left;
+ *outbytesleft = out_left;
+ *inbuf = uc;
+ *outbuf = c;
return -1;
}
+
diff --git a/source/lib/ms_fnmatch.c b/source/lib/ms_fnmatch.c
index 24232c3b523..42c91bd18df 100644
--- a/source/lib/ms_fnmatch.c
+++ b/source/lib/ms_fnmatch.c
@@ -179,6 +179,9 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string,
break;
case UCS2_CHAR('*'):
+ while (*p == UCS2_CHAR('*')) {
+ p++;
+ }
for (; *n; n++) {
if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0;
}
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index e66fb3640cf..57aab70a5ba 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -66,6 +66,29 @@ ATTRIB_MAP_ENTRY attrib_map_v22[] = {
{ LDAP_ATTR_DOMAIN, "domain" },
{ LDAP_ATTR_OBJCLASS, "objectClass" },
{ LDAP_ATTR_ACB_INFO, "acctFlags" },
+ { LDAP_ATTR_MOD_TIMESTAMP, "modifyTimestamp" },
+ { LDAP_ATTR_LIST_END, NULL }
+};
+
+ATTRIB_MAP_ENTRY attrib_map_to_delete_v22[] = {
+ { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" },
+ { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" },
+ { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" },
+ { LDAP_ATTR_LOGON_TIME, "logonTime" },
+ { LDAP_ATTR_LOGOFF_TIME, "logoffTime" },
+ { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" },
+ { LDAP_ATTR_DISPLAY_NAME, "displayName" },
+ { LDAP_ATTR_HOME_PATH, "smbHome" },
+ { LDAP_ATTR_HOME_DRIVE, "homeDrives" },
+ { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" },
+ { LDAP_ATTR_PROFILE_PATH, "profilePath" },
+ { LDAP_ATTR_USER_WKS, "userWorkstations"},
+ { LDAP_ATTR_USER_RID, "rid" },
+ { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"},
+ { LDAP_ATTR_LMPW, "lmPassword" },
+ { LDAP_ATTR_NTPW, "ntPassword" },
+ { LDAP_ATTR_DOMAIN, "domain" },
+ { LDAP_ATTR_ACB_INFO, "acctFlags" },
{ LDAP_ATTR_LIST_END, NULL }
};
@@ -106,6 +129,32 @@ ATTRIB_MAP_ENTRY attrib_map_v30[] = {
{ LDAP_ATTR_LIST_END, NULL }
};
+ATTRIB_MAP_ENTRY attrib_map_to_delete_v30[] = {
+ { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" },
+ { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" },
+ { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" },
+ { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" },
+ { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" },
+ { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" },
+ { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" },
+ { LDAP_ATTR_HOME_PATH, "sambaHomePath" },
+ { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" },
+ { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" },
+ { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" },
+ { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID },
+ { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" },
+ { LDAP_ATTR_LMPW, "sambaLMPassword" },
+ { LDAP_ATTR_NTPW, "sambaNTPassword" },
+ { LDAP_ATTR_DOMAIN, "sambaDomainName" },
+ { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" },
+ { LDAP_ATTR_MUNGED_DIAL, "sambaMungedDial" },
+ { LDAP_ATTR_BAD_PASSWORD_COUNT, "sambaBadPasswordCount" },
+ { LDAP_ATTR_BAD_PASSWORD_TIME, "sambaBadPasswordTime" },
+ { LDAP_ATTR_PWD_HISTORY, "sambaPasswordHistory" },
+ { LDAP_ATTR_LOGON_HOURS, "sambaLogonHours" },
+ { LDAP_ATTR_LIST_END, NULL }
+};
+
/* attributes used for allocating RIDs */
ATTRIB_MAP_ENTRY dominfo_attr_list[] = {
@@ -428,6 +477,12 @@ static BOOL fetch_ldap_pw(char **dn, char** pw)
char oldval[2048]; /* current largest allowed value is mungeddial */
BOOL existed;
+ if (attribute == NULL) {
+ /* This can actually happen for ldapsam_compat where we for
+ * example don't have a password history */
+ return;
+ }
+
if (existing != NULL) {
existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval, sizeof(oldval));
} else {
diff --git a/source/lib/smbrun.c b/source/lib/smbrun.c
index 592543bc43b..43cb209174e 100644
--- a/source/lib/smbrun.c
+++ b/source/lib/smbrun.c
@@ -90,7 +90,7 @@ int smbrun(char *cmd, int *outfd)
*outfd = -1;
}
return errno;
- }
+ }
if (pid) {
/*
@@ -178,3 +178,124 @@ int smbrun(char *cmd, int *outfd)
exit(82);
return 1;
}
+
+
+/****************************************************************************
+run a command being careful about uid/gid handling and putting the output in
+outfd (or discard it if outfd is NULL).
+sends the provided secret to the child stdin.
+****************************************************************************/
+
+int smbrunsecret(char *cmd, char *secret)
+{
+ pid_t pid;
+ uid_t uid = current_user.uid;
+ gid_t gid = current_user.gid;
+ int ifd[2];
+
+ /*
+ * Lose any kernel oplock capabilities we may have.
+ */
+ oplock_set_capability(False, False);
+
+ /* build up an input pipe */
+ if(pipe(ifd)) {
+ return -1;
+ }
+
+ /* in this method we will exec /bin/sh with the correct
+ arguments, after first setting stdout to point at the file */
+
+ /*
+ * We need to temporarily stop CatchChild from eating
+ * SIGCLD signals as it also eats the exit status code. JRA.
+ */
+
+ CatchChildLeaveStatus();
+
+ if ((pid=sys_fork()) < 0) {
+ DEBUG(0, ("smbrunsecret: fork failed with error %s\n", strerror(errno)));
+ CatchChild();
+ return errno;
+ }
+
+ if (pid) {
+ /*
+ * Parent.
+ */
+ int status = 0;
+ pid_t wpid;
+
+ close(ifd[0]);
+ /* send the secret */
+ write(ifd[1], secret, strlen(secret));
+ fsync(ifd[1]);
+ close(ifd[1]);
+
+ /* the parent just waits for the child to exit */
+ while((wpid = sys_waitpid(pid, &status, 0)) < 0) {
+ if(errno == EINTR) {
+ errno = 0;
+ continue;
+ }
+ break;
+ }
+
+ CatchChild();
+
+ if (wpid != pid) {
+ DEBUG(2, ("waitpid(%d) : %s\n", (int)pid, strerror(errno)));
+ return -1;
+ }
+
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+ if (WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ }
+#endif
+
+ return status;
+ }
+
+ CatchChild();
+
+ /* we are in the child. we exec /bin/sh to do the work for us. we
+ don't directly exec the command we want because it may be a
+ pipeline or anything else the config file specifies */
+
+ close(ifd[1]);
+ close(0);
+ if (sys_dup2(ifd[0], 0) != 0) {
+ DEBUG(2,("Failed to create stdin file descriptor\n"));
+ close(ifd[0]);
+ exit(80);
+ }
+
+ /* now completely lose our privileges. This is a fairly paranoid
+ way of doing it, but it does work on all systems that I know of */
+
+ become_user_permanently(uid, gid);
+
+ if (getuid() != uid || geteuid() != uid ||
+ getgid() != gid || getegid() != gid) {
+ /* we failed to lose our privileges - do not execute
+ the command */
+ exit(81); /* we can't print stuff at this stage,
+ instead use exit codes for debugging */
+ }
+
+#ifndef __INSURE__
+ /* close all other file descriptors, leaving only 0, 1 and 2. 0 and
+ 2 point to /dev/null from the startup code */
+ {
+ int fd;
+ for (fd = 3; fd < 256; fd++) close(fd);
+ }
+#endif
+
+ execl("/bin/sh", "sh", "-c", cmd, NULL);
+
+ /* not reached */
+ exit(82);
+ return 1;
+}
diff --git a/source/lib/util.c b/source/lib/util.c
index 8d01d9e7c9c..a456395cad1 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -1491,14 +1491,13 @@ BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensit
pstring last_component;
char *p;
- DEBUG(8, ("is_in_path: %s\n", name));
-
/* if we have no list it's obviously not in the path */
if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
- DEBUG(8,("is_in_path: no name list.\n"));
return False;
}
+ DEBUG(8, ("is_in_path: %s\n", name));
+
/* Get the last component of the unix name. */
p = strrchr_m(name, '/');
strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
diff --git a/source/lib/util_file.c b/source/lib/util_file.c
index bd505ac921c..303d961df57 100644
--- a/source/lib/util_file.c
+++ b/source/lib/util_file.c
@@ -24,7 +24,6 @@
#define MAP_FAILED ((void *)-1)
#endif
-
static int gotalarm;
/***************************************************************
@@ -33,7 +32,7 @@ static int gotalarm;
static void gotalarm_sig(void)
{
- gotalarm = 1;
+ gotalarm = 1;
}
/***************************************************************
@@ -43,34 +42,33 @@ static void gotalarm_sig(void)
BOOL do_file_lock(int fd, int waitsecs, int type)
{
- SMB_STRUCT_FLOCK lock;
- int ret;
- void (*oldsig_handler)(int);
-
- gotalarm = 0;
- oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
-
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 1;
- lock.l_pid = 0;
-
- alarm(waitsecs);
- /* Note we must *NOT* use sys_fcntl here ! JRA */
- ret = fcntl(fd, SMB_F_SETLKW, &lock);
- alarm(0);
- CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
-
- if (gotalarm) {
- DEBUG(0, ("do_file_lock: failed to %s file.\n",
- type == F_UNLCK ? "unlock" : "lock"));
- return False;
- }
-
- return (ret == 0);
-}
+ SMB_STRUCT_FLOCK lock;
+ int ret;
+ void (*oldsig_handler)(int);
+
+ gotalarm = 0;
+ oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+
+ lock.l_type = type;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 1;
+ lock.l_pid = 0;
+
+ alarm(waitsecs);
+ /* Note we must *NOT* use sys_fcntl here ! JRA */
+ ret = fcntl(fd, SMB_F_SETLKW, &lock);
+ alarm(0);
+ CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
+
+ if (gotalarm) {
+ DEBUG(0, ("do_file_lock: failed to %s file.\n",
+ type == F_UNLCK ? "unlock" : "lock"));
+ return False;
+ }
+ return (ret == 0);
+}
/***************************************************************
Lock an fd. Abandon after waitsecs seconds.
@@ -78,21 +76,19 @@ BOOL do_file_lock(int fd, int waitsecs, int type)
BOOL file_lock(int fd, int type, int secs, int *plock_depth)
{
- if (fd < 0)
- return False;
+ if (fd < 0)
+ return False;
- (*plock_depth)++;
+ (*plock_depth)++;
- if ((*plock_depth) == 0)
- {
- if (!do_file_lock(fd, secs, type)) {
- DEBUG(10,("file_lock: locking file failed, error = %s.\n",
- strerror(errno)));
- return False;
- }
- }
+ if ((*plock_depth) == 0) {
+ if (!do_file_lock(fd, secs, type)) {
+ DEBUG(10,("file_lock: locking file failed, error = %s.\n", strerror(errno)));
+ return False;
+ }
+ }
- return True;
+ return True;
}
/***************************************************************
@@ -101,105 +97,107 @@ BOOL file_lock(int fd, int type, int secs, int *plock_depth)
BOOL file_unlock(int fd, int *plock_depth)
{
- BOOL ret=True;
+ BOOL ret=True;
- if(*plock_depth == 1)
- ret = do_file_lock(fd, 5, F_UNLCK);
+ if(*plock_depth == 1) {
+ ret = do_file_lock(fd, 5, F_UNLCK);
+ }
- (*plock_depth)--;
+ (*plock_depth)--;
- if(!ret)
- DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n",
- strerror(errno)));
- return ret;
+ if(!ret) {
+ DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n", strerror(errno)));
+ }
+ return ret;
}
/***************************************************************
- locks a file for enumeration / modification.
+ Locks a file for enumeration / modification.
update to be set = True if modification is required.
****************************************************************/
void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
int *file_lock_depth, BOOL update)
{
- FILE *fp = NULL;
+ FILE *fp = NULL;
- if (!*pfile)
- {
- DEBUG(0, ("startfilepwent: No file set\n"));
- return (NULL);
- }
- DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
+ if (!*pfile) {
+ DEBUG(0, ("startfilepwent: No file set\n"));
+ return (NULL);
+ }
+ DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
- fp = sys_fopen(pfile, update ? "r+b" : "rb");
+ fp = sys_fopen(pfile, update ? "r+b" : "rb");
- if (fp == NULL) {
- DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
- return NULL;
- }
+ if (fp == NULL) {
+ DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
+ return NULL;
+ }
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, s_readbuf, _IOFBF, bufsize);
+ /* Set a buffer to do more efficient reads */
+ setvbuf(fp, s_readbuf, _IOFBF, bufsize);
- if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
- {
- DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
- fclose(fp);
- return NULL;
- }
+ if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth)) {
+ DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
+ fclose(fp);
+ return NULL;
+ }
- /* Make sure it is only rw by the owner */
- chmod(pfile, 0600);
+ /* Make sure it is only rw by the owner */
+ chmod(pfile, 0600);
- /* We have a lock on the file. */
- return (void *)fp;
+ /* We have a lock on the file. */
+ return (void *)fp;
}
/***************************************************************
End enumeration of the file.
****************************************************************/
+
void endfilepwent(void *vp, int *file_lock_depth)
{
- FILE *fp = (FILE *)vp;
+ FILE *fp = (FILE *)vp;
- file_unlock(fileno(fp), file_lock_depth);
- fclose(fp);
- DEBUG(7, ("endfilepwent: closed file.\n"));
+ file_unlock(fileno(fp), file_lock_depth);
+ fclose(fp);
+ DEBUG(7, ("endfilepwent: closed file.\n"));
}
/*************************************************************************
Return the current position in the file list as an SMB_BIG_UINT.
This must be treated as an opaque token.
*************************************************************************/
+
SMB_BIG_UINT getfilepwpos(void *vp)
{
- return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
+ return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
}
/*************************************************************************
Set the current position in the file list from an SMB_BIG_UINT.
This must be treated as an opaque token.
*************************************************************************/
+
BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
{
- return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
+ return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
}
/*************************************************************************
- gets a line out of a file.
+ Gets a line out of a file.
line is of format "xxxx:xxxxxx:xxxxx:".
lines with "#" at the front are ignored.
*************************************************************************/
+
int getfileline(void *vp, char *linebuf, int linebuf_size)
{
/* Static buffers we will return. */
FILE *fp = (FILE *)vp;
unsigned char c;
unsigned char *p;
- size_t linebuf_len;
+ size_t linebuf_len;
- if (fp == NULL)
- {
+ if (fp == NULL) {
DEBUG(0,("getfileline: Bad file pointer.\n"));
return -1;
}
@@ -207,13 +205,11 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
/*
* Scan the file, a line at a time.
*/
- while (!feof(fp))
- {
+ while (!feof(fp)) {
linebuf[0] = '\0';
fgets(linebuf, linebuf_size, fp);
- if (ferror(fp))
- {
+ if (ferror(fp)) {
return -1;
}
@@ -223,47 +219,38 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
*/
linebuf_len = strlen(linebuf);
- if (linebuf_len == 0)
- {
+ if (linebuf_len == 0) {
linebuf[0] = '\0';
return 0;
}
- if (linebuf[linebuf_len - 1] != '\n')
- {
+ if (linebuf[linebuf_len - 1] != '\n') {
c = '\0';
- while (!ferror(fp) && !feof(fp))
- {
+ while (!ferror(fp) && !feof(fp)) {
c = fgetc(fp);
- if (c == '\n')
- {
+ if (c == '\n') {
break;
}
}
- }
- else
- {
+ } else {
linebuf[linebuf_len - 1] = '\0';
}
#ifdef DEBUG_PASSWORD
DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
#endif
- if ((linebuf[0] == 0) && feof(fp))
- {
+ if ((linebuf[0] == 0) && feof(fp)) {
DEBUG(4, ("getfileline: end of file reached\n"));
return 0;
}
- if (linebuf[0] == '#' || linebuf[0] == '\0')
- {
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
DEBUG(6, ("getfileline: skipping comment or blank line\n"));
continue;
}
p = (unsigned char *) strchr_m(linebuf, ':');
- if (p == NULL)
- {
+ if (p == NULL) {
DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
continue;
}
@@ -272,85 +259,89 @@ int getfileline(void *vp, char *linebuf, int linebuf_size)
return -1;
}
-
/****************************************************************************
-read a line from a file with possible \ continuation chars.
-Blanks at the start or end of a line are stripped.
-The string will be allocated if s2 is NULL
+ Read a line from a file with possible \ continuation chars.
+ Blanks at the start or end of a line are stripped.
+ The string will be allocated if s2 is NULL.
****************************************************************************/
+
char *fgets_slash(char *s2,int maxlen,XFILE *f)
{
- char *s=s2;
- int len = 0;
- int c;
- BOOL start_of_line = True;
-
- if (x_feof(f))
- return(NULL);
-
- if (maxlen <2) return(NULL);
-
- if (!s2)
- {
- maxlen = MIN(maxlen,8);
- s = (char *)malloc(maxlen);
- }
-
- if (!s) return(NULL);
-
- *s = 0;
-
- while (len < maxlen-1)
- {
- c = x_getc(f);
- switch (c)
- {
- case '\r':
- break;
- case '\n':
- while (len > 0 && s[len-1] == ' ')
- {
- s[--len] = 0;
- }
- if (len > 0 && s[len-1] == '\\')
- {
- s[--len] = 0;
- start_of_line = True;
- break;
- }
- return(s);
- case EOF:
- if (len <= 0 && !s2)
- SAFE_FREE(s);
- return(len>0?s:NULL);
- case ' ':
- if (start_of_line)
- break;
- default:
- start_of_line = False;
- s[len++] = c;
- s[len] = 0;
- }
- if (!s2 && len > maxlen-3)
- {
- char *t;
+ char *s=s2;
+ int len = 0;
+ int c;
+ BOOL start_of_line = True;
+
+ if (x_feof(f)) {
+ return(NULL);
+ }
+
+ if (maxlen <2) {
+ return(NULL);
+ }
+
+ if (!s2) {
+ maxlen = MIN(maxlen,8);
+ s = (char *)malloc(maxlen);
+ }
+
+ if (!s) {
+ return(NULL);
+ }
+
+ *s = 0;
+
+ while (len < maxlen-1) {
+ c = x_getc(f);
+ switch (c) {
+ case '\r':
+ break;
+ case '\n':
+ while (len > 0 && s[len-1] == ' ') {
+ s[--len] = 0;
+ }
+ if (len > 0 && s[len-1] == '\\') {
+ s[--len] = 0;
+ start_of_line = True;
+ break;
+ }
+ return(s);
+ case EOF:
+ if (len <= 0 && !s2) {
+ SAFE_FREE(s);
+ }
+ return(len>0?s:NULL);
+ case ' ':
+ if (start_of_line) {
+ break;
+ }
+ default:
+ start_of_line = False;
+ s[len++] = c;
+ s[len] = 0;
+ }
+
+ if (!s2 && len > maxlen-3) {
+ char *t;
- maxlen *= 2;
- t = (char *)Realloc(s,maxlen);
- if (!t) {
- DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
- SAFE_FREE(s);
- return(NULL);
- } else s = t;
- }
- }
- return(s);
+ maxlen *= 2;
+ t = (char *)Realloc(s,maxlen);
+ if (!t) {
+ DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
+ SAFE_FREE(s);
+ return(NULL);
+ } else {
+ s = t;
+ }
+ }
+ }
+ return(s);
}
-
/****************************************************************************
-load from a pipe into memory
+ Load from a pipe into memory.
****************************************************************************/
+
char *file_pload(char *syscmd, size_t *size)
{
int fd, n;
@@ -359,7 +350,9 @@ char *file_pload(char *syscmd, size_t *size)
size_t total;
fd = sys_popen(syscmd);
- if (fd == -1) return NULL;
+ if (fd == -1) {
+ return NULL;
+ }
p = NULL;
total = 0;
@@ -371,7 +364,9 @@ char *file_pload(char *syscmd, size_t *size)
close(fd);
SAFE_FREE(p);
return NULL;
- } else p = tp;
+ } else {
+ p = tp;
+ }
memcpy(p+total, buf, n);
total += n;
}
@@ -382,13 +377,15 @@ char *file_pload(char *syscmd, size_t *size)
* truncated. */
sys_pclose(fd);
- if (size) *size = total;
+ if (size) {
+ *size = total;
+ }
return p;
}
/****************************************************************************
-load a file into memory from a fd.
+ Load a file into memory from a fd.
****************************************************************************/
char *fd_load(int fd, size_t *size)
@@ -396,10 +393,14 @@ char *fd_load(int fd, size_t *size)
SMB_STRUCT_STAT sbuf;
char *p;
- if (sys_fstat(fd, &sbuf) != 0) return NULL;
+ if (sys_fstat(fd, &sbuf) != 0) {
+ return NULL;
+ }
p = (char *)malloc(sbuf.st_size+1);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
SAFE_FREE(p);
@@ -407,79 +408,85 @@ char *fd_load(int fd, size_t *size)
}
p[sbuf.st_size] = 0;
- if (size) *size = sbuf.st_size;
+ if (size) {
+ *size = sbuf.st_size;
+ }
return p;
}
/****************************************************************************
-load a file into memory
+ Load a file into memory.
****************************************************************************/
+
char *file_load(const char *fname, size_t *size)
{
int fd;
char *p;
- if (!fname || !*fname) return NULL;
+ if (!fname || !*fname) {
+ return NULL;
+ }
fd = open(fname,O_RDONLY);
- if (fd == -1) return NULL;
+ if (fd == -1) {
+ return NULL;
+ }
p = fd_load(fd, size);
-
close(fd);
-
return p;
}
-
/*******************************************************************
-mmap (if possible) or read a file
+ mmap (if possible) or read a file.
********************************************************************/
+
void *map_file(char *fname, size_t size)
{
size_t s2 = 0;
void *p = NULL;
#ifdef HAVE_MMAP
- if (lp_use_mmap()) {
- int fd;
- fd = open(fname, O_RDONLY, 0);
- if (fd == -1) {
- DEBUG(2,("Failed to load %s - %s\n", fname, strerror(errno)));
- return NULL;
- }
- p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
- close(fd);
- if (p == MAP_FAILED) {
- DEBUG(1,("Failed to mmap %s - %s\n", fname, strerror(errno)));
- return NULL;
- }
+ int fd;
+ fd = open(fname, O_RDONLY, 0);
+ if (fd == -1) {
+ DEBUG(2,("map_file: Failed to load %s - %s\n", fname, strerror(errno)));
+ return NULL;
+ }
+ p = mmap(NULL, size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
+ close(fd);
+ if (p == MAP_FAILED) {
+ DEBUG(1,("map_file: Failed to mmap %s - %s\n", fname, strerror(errno)));
+ return NULL;
}
#endif
if (!p) {
p = file_load(fname, &s2);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
if (s2 != size) {
- DEBUG(1,("incorrect size for %s - got %lu expected %lu\n",
+ DEBUG(1,("map_file: incorrect size for %s - got %lu expected %lu\n",
fname, (unsigned long)s2, (unsigned long)size));
- if (p) free(p);
+ SAFE_FREE(p);
return NULL;
}
}
-
return p;
}
-
/****************************************************************************
-parse a buffer into lines
+ Parse a buffer into lines.
****************************************************************************/
+
static char **file_lines_parse(char *p, size_t size, int *numlines)
{
int i;
char *s, **ret;
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
for (s = p, i=0; s < p+size; s++) {
if (s[0] == '\n') i++;
@@ -491,7 +498,9 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
return NULL;
}
memset(ret, 0, sizeof(ret[0])*(i+2));
- if (numlines) *numlines = i;
+ if (numlines) {
+ *numlines = i;
+ }
ret[0] = p;
for (s = p, i=0; s < p+size; s++) {
@@ -500,75 +509,87 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
i++;
ret[i] = s+1;
}
- if (s[0] == '\r') s[0] = 0;
+ if (s[0] == '\r') {
+ s[0] = 0;
+ }
}
return ret;
}
-
/****************************************************************************
-load a file into memory and return an array of pointers to lines in the file
-must be freed with file_lines_free().
+ Load a file into memory and return an array of pointers to lines in the file
+ must be freed with file_lines_free().
****************************************************************************/
+
char **file_lines_load(const char *fname, int *numlines)
{
char *p;
size_t size;
p = file_load(fname, &size);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
return file_lines_parse(p, size, numlines);
}
/****************************************************************************
-load a fd into memory and return an array of pointers to lines in the file
-must be freed with file_lines_free(). If convert is true calls unix_to_dos on
-the list.
+ Load a fd into memory and return an array of pointers to lines in the file
+ must be freed with file_lines_free(). If convert is true calls unix_to_dos on
+ the list.
****************************************************************************/
+
char **fd_lines_load(int fd, int *numlines)
{
char *p;
size_t size;
p = fd_load(fd, &size);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
return file_lines_parse(p, size, numlines);
}
-
/****************************************************************************
-load a pipe into memory and return an array of pointers to lines in the data
-must be freed with file_lines_free().
+ Load a pipe into memory and return an array of pointers to lines in the data
+ must be freed with file_lines_free().
****************************************************************************/
+
char **file_lines_pload(char *syscmd, int *numlines)
{
char *p;
size_t size;
p = file_pload(syscmd, &size);
- if (!p) return NULL;
+ if (!p) {
+ return NULL;
+ }
return file_lines_parse(p, size, numlines);
}
/****************************************************************************
-free lines loaded with file_lines_load
+ Free lines loaded with file_lines_load.
****************************************************************************/
+
void file_lines_free(char **lines)
{
- if (!lines) return;
+ if (!lines) {
+ return;
+ }
SAFE_FREE(lines[0]);
SAFE_FREE(lines);
}
-
/****************************************************************************
-take a lislist of lines and modify them to produce a list where \ continues
-a line
+ Take a list of lines and modify them to produce a list where \ continues
+ a line.
****************************************************************************/
+
void file_lines_slashcont(char **lines)
{
int i, j;
@@ -579,8 +600,12 @@ void file_lines_slashcont(char **lines)
lines[i][len-1] = ' ';
if (lines[i+1]) {
char *p = &lines[i][len];
- while (p < lines[i+1]) *p++ = ' ';
- for (j = i+1; lines[j]; j++) lines[j] = lines[j+1];
+ while (p < lines[i+1]) {
+ *p++ = ' ';
+ }
+ for (j = i+1; lines[j]; j++) {
+ lines[j] = lines[j+1];
+ }
}
} else {
i++;
@@ -588,9 +613,10 @@ void file_lines_slashcont(char **lines)
}
}
-/*
- save a lump of data into a file. Mostly used for debugging
-*/
+/****************************************************************************
+ Save a lump of data into a file. Mostly used for debugging.
+****************************************************************************/
+
BOOL file_save(const char *fname, void *packet, size_t length)
{
int fd;
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 6eee62c14aa..65a616ad419 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -134,17 +134,20 @@ char **toktocliplist(int *ctok, const char *sep)
*ctok=ictok;
s=(char *)last_ptr;
- if (!(ret=iret=malloc(ictok*sizeof(char *))))
+ if (!(ret=iret=malloc((ictok+1)*sizeof(char *))))
return NULL;
while(ictok--) {
*iret++=s;
- while(*s++)
- ;
- while(!*s)
- s++;
+ if (ictok > 0) {
+ while(*s++)
+ ;
+ while(!*s)
+ s++;
+ }
}
+ ret[*ctok] = NULL;
return ret;
}
diff --git a/source/lib/util_uuid.c b/source/lib/util_uuid.c
index 8f86c2109ea..df70740b33c 100644
--- a/source/lib/util_uuid.c
+++ b/source/lib/util_uuid.c
@@ -29,11 +29,11 @@
void smb_uuid_pack(const struct uuid uu, UUID_FLAT *ptr)
{
- SIVAL(ptr, 0, uu.time_low);
- SSVAL(ptr, 4, uu.time_mid);
- SSVAL(ptr, 6, uu.time_hi_and_version);
- memcpy(ptr+8, uu.clock_seq, 2);
- memcpy(ptr+10, uu.node, 6);
+ SIVAL(ptr->info, 0, uu.time_low);
+ SSVAL(ptr->info, 4, uu.time_mid);
+ SSVAL(ptr->info, 6, uu.time_hi_and_version);
+ memcpy(ptr->info+8, uu.clock_seq, 2);
+ memcpy(ptr->info+10, uu.node, 6);
}
void smb_uuid_unpack(const UUID_FLAT in, struct uuid *uu)
@@ -96,6 +96,7 @@ BOOL smb_string_to_uuid(const char *in, struct uuid* uu)
const char *ptr = in;
char *end = (char *)in;
int i;
+ unsigned v1, v2;
if (!in || !uu) goto out;
@@ -111,61 +112,22 @@ BOOL smb_string_to_uuid(const char *in, struct uuid* uu)
if ((end - ptr) != 4 || *end != '-') goto out;
ptr = (end + 1);
- for (i = 0; i < 2; i++) {
- int adj = 0;
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
- goto out;
- }
- uu->clock_seq[i] = (*ptr - adj) << 4;
- ptr++;
-
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
- goto out;
- }
- uu->clock_seq[i] |= (*ptr - adj);
- ptr++;
+ if (sscanf(ptr, "%02x%02x", &v1, &v2) != 2) {
+ goto out;
}
+ uu->clock_seq[0] = v1;
+ uu->clock_seq[1] = v2;
+ ptr += 4;
if (*ptr != '-') goto out;
ptr++;
for (i = 0; i < 6; i++) {
- int adj = 0;
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
- goto out;
- }
- uu->node[i] = (*ptr - adj) << 4;
- ptr++;
-
- if (*ptr >= '0' && *ptr <= '9') {
- adj = '0';
- } else if (*ptr >= 'a' && *ptr <= 'f') {
- adj = 'a';
- } else if (*ptr >= 'A' && *ptr <= 'F') {
- adj = 'A';
- } else {
+ if (sscanf(ptr, "%02x", &v1) != 1) {
goto out;
}
- uu->node[i] |= (*ptr - adj);
- ptr++;
+ uu->node[i] = v1;
+ ptr += 2;
}
ret = True;
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index 97b895a2418..327a76826ef 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -146,7 +146,8 @@ int ads_kdestroy(const char *cc_name)
krb5_ccache cc = NULL;
if ((code = krb5_init_context (&ctx))) {
- DEBUG(3, ("ads_kdestroy: kdb5_init_context rc=%d\n", code));
+ DEBUG(3, ("ads_kdestroy: kdb5_init_context failed: %s\n",
+ error_message(code)));
return code;
}
@@ -157,15 +158,16 @@ int ads_kdestroy(const char *cc_name)
}
} else {
if ((code = krb5_cc_resolve(ctx, cc_name, &cc))) {
- DEBUG(3, ("ads_kdestroy: krb5_cc_resolve rc=%d\n",
- code));
+ DEBUG(3, ("ads_kdestroy: krb5_cc_resolve failed: %s\n",
+ error_message(code)));
krb5_free_context(ctx);
return code;
}
}
if ((code = krb5_cc_destroy (ctx, cc))) {
- DEBUG(3, ("ads_kdestroy: krb5_cc_destroy rc=%d\n", code));
+ DEBUG(3, ("ads_kdestroy: krb5_cc_destroy failed: %s\n",
+ error_message(code)));
}
krb5_free_context (ctx);
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 559538aac9b..4ff60c1b1ca 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -668,11 +668,16 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
ntlmssp_state->session_key.length);
DATA_BLOB null_blob = data_blob(NULL, 0);
+ BOOL res;
fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
cli_set_session_key(cli, ntlmssp_state->session_key);
- if (cli_simple_set_signing(cli, key, null_blob)) {
+ res = cli_simple_set_signing(cli, key, null_blob);
+
+ data_blob_free(&key);
+
+ if (res) {
/* 'resign' the last message, so we get the right sequence numbers
for checking the first reply from the server */
@@ -1133,6 +1138,7 @@ BOOL cli_negprot(struct cli_state *cli)
cli->use_spnego = False;
cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
+ cli->max_mux = SVAL(cli->inbuf, smb_vwv3);
cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
cli->serverzone *= 60;
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index 398c7cc4f0a..ff0edc6bb4e 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -983,6 +983,47 @@ BOOL cli_getatr(struct cli_state *cli, const char *fname,
}
/****************************************************************************
+ Do a SMBsetattrE call.
+****************************************************************************/
+
+BOOL cli_setattrE(struct cli_state *cli, int fd,
+ time_t c_time, time_t a_time, time_t m_time)
+
+{
+ char *p;
+
+ memset(cli->outbuf,'\0',smb_size);
+ memset(cli->inbuf,'\0',smb_size);
+
+ set_message(cli->outbuf,7,0,True);
+
+ SCVAL(cli->outbuf,smb_com,SMBsetattrE);
+ SSVAL(cli->outbuf,smb_tid,cli->cnum);
+ cli_setup_packet(cli);
+
+ SSVAL(cli->outbuf,smb_vwv0, fd);
+ put_dos_date3(cli->outbuf,smb_vwv1, c_time);
+ put_dos_date3(cli->outbuf,smb_vwv3, a_time);
+ put_dos_date3(cli->outbuf,smb_vwv5, m_time);
+
+ p = smb_buf(cli->outbuf);
+ *p++ = 4;
+
+ cli_setup_bcc(cli, p);
+
+ cli_send_smb(cli);
+ if (!cli_receive_smb(cli)) {
+ return False;
+ }
+
+ if (cli_is_error(cli)) {
+ return False;
+ }
+
+ return True;
+}
+
+/****************************************************************************
Do a SMBsetatr call.
****************************************************************************/
diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c
index 5fcde4654ad..f7f84f1e297 100644
--- a/source/libsmb/clikrb5.c
+++ b/source/libsmb/clikrb5.c
@@ -190,6 +190,7 @@
krb5_error_code rc;
int num_kdcs, i;
struct sockaddr *sa;
+ struct addrinfo *ai;
*addr_pp = NULL;
*naddrs = 0;
@@ -219,10 +220,19 @@
return -1;
}
+ *addr_pp = malloc(sizeof(struct sockaddr) * num_kdcs);
memset(*addr_pp, '\0', sizeof(struct sockaddr) * num_kdcs );
for (i = 0; i < num_kdcs && (rc = krb5_krbhst_next(ctx, hnd, &hinfo) == 0); i++) {
- if (hinfo->ai->ai_family == AF_INET)
+
+#if defined(HAVE_KRB5_KRBHST_GET_ADDRINFO)
+ rc = krb5_krbhst_get_addrinfo(ctx, hinfo, &ai);
+ if (rc) {
+ DEBUG(0,("krb5_krbhst_get_addrinfo failed: %s\n", error_message(rc)));
+ continue;
+ }
+#endif
+ if (hinfo->ai && hinfo->ai->ai_family == AF_INET)
memcpy(&sa[i], hinfo->ai->ai_addr, sizeof(struct sockaddr));
}
@@ -420,14 +430,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
failed:
if ( context ) {
-/* Removed by jra. They really need to fix their kerberos so we don't leak memory.
- JERRY -- disabled since it causes heimdal 0.6.1rc3 to die
- SuSE 9.1 Pro
-*/
if (ccdef)
-#if 0 /* redisabled by gd :) at least until any official heimdal version has it fixed. */
krb5_cc_close(context, ccdef);
-#endif
if (auth_context)
krb5_auth_con_free(context, auth_context);
krb5_free_context(context);
diff --git a/source/libsmb/cliquota.c b/source/libsmb/cliquota.c
index ed808aa1f5c..af8b4422b78 100644
--- a/source/libsmb/cliquota.c
+++ b/source/libsmb/cliquota.c
@@ -22,13 +22,13 @@
BOOL cli_get_quota_handle(struct cli_state *cli, int *quota_fnum)
{
- *quota_fnum = cli_nt_create_full(cli, FAKE_FILE_NAME_QUOTA,
+ *quota_fnum = cli_nt_create_full(cli, FAKE_FILE_NAME_QUOTA_WIN32,
0x00000016, DESIRED_ACCESS_PIPE,
0x00000000, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, 0x00000000, 0x03);
if (*quota_fnum == (-1)) {
- return False;
+ return False;
}
return True;
diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c
index 8eac7d07d8b..3f14e530943 100644
--- a/source/libsmb/clireadwrite.c
+++ b/source/libsmb/clireadwrite.c
@@ -325,10 +325,16 @@ ssize_t cli_write(struct cli_state *cli,
int bwritten = 0;
int issued = 0;
int received = 0;
- int mpx = MAX(cli->max_mux-1, 1);
+ int mpx = 1;
int block = cli->max_xmit - (smb_size+32);
int blocks = (size + (block-1)) / block;
+ if(cli->max_mux > 1) {
+ mpx = cli->max_mux-1;
+ } else {
+ mpx = 1;
+ }
+
while (received < blocks) {
while ((issued - received < mpx) && (issued < blocks)) {
diff --git a/source/locking/locking.c b/source/locking/locking.c
index 8f53b55fc54..d4e8c493d50 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -1043,18 +1043,6 @@ int get_deferred_opens(connection_struct *conn,
static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2)
{
-#if 1 /* JRA PARANOIA TEST - REMOVE LATER */
- if (e1->pid == e2->pid &&
- e1->port == e2->port &&
- e1->dev == e2->dev &&
- e1->inode == e2->inode &&
- ((e1->time.tv_sec != e2->time.tv_sec) ||
- (e1->time.tv_usec != e2->time.tv_usec) ||
- (e1->mid != e2->mid))) {
- smb_panic("PANIC: deferred_open_entries_identical: logic error.\n");
- }
-#endif
-
return (e1->pid == e2->pid &&
e1->mid == e2->mid &&
e1->port == e2->port &&
@@ -1064,7 +1052,6 @@ static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_o
e1->time.tv_usec == e2->time.tv_usec);
}
-
/*******************************************************************
Delete a specific deferred open entry.
Ignore if no entry deleted.
diff --git a/source/modules/weird.c b/source/modules/weird.c
index 444853f3831..3c59fd9d61f 100644
--- a/source/modules/weird.c
+++ b/source/modules/weird.c
@@ -31,7 +31,7 @@ static struct {
{0, NULL}
};
-static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t weird_pull(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
while (*inbytesleft >= 1 && *outbytesleft >= 2) {
@@ -74,7 +74,7 @@ static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft,
return 0;
}
-static size_t weird_push(void *cd, char **inbuf, size_t *inbytesleft,
+static size_t weird_push(void *cd, const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft)
{
int ir_count=0;
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 880de7f91bf..f8006a22a9e 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -29,6 +29,8 @@ int global_nmb_port = -1;
extern BOOL global_in_nmbd;
+extern BOOL override_logfile;
+
/* are we running as a daemon ? */
static BOOL is_daemon;
@@ -623,8 +625,10 @@ static BOOL open_sockets(BOOL isdaemon, int port)
sys_srandom(time(NULL) ^ sys_getpid());
- slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
+ if (!override_logfile) {
+ slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
+ }
fault_setup((void (*)(void *))fault_continue );
diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c
index 8880cb58bb4..8f3ae36b65d 100644
--- a/source/nmbd/nmbd_workgroupdb.c
+++ b/source/nmbd/nmbd_workgroupdb.c
@@ -41,6 +41,27 @@ static void add_workgroup(struct subnet_record *subrec, struct work_record *work
}
/****************************************************************************
+ Copy name to unstring. Used by create_workgroup() and find_workgroup_on_subnet().
+**************************************************************************/
+
+static void name_to_unstring(unstring unname, const char *name)
+{
+ nstring nname;
+
+ errno = 0;
+ push_ascii_nstring(nname, name);
+ if (errno == E2BIG) {
+ unstring tname;
+ pull_ascii_nstring(tname, sizeof(tname), nname);
+ unstrcpy(unname, tname);
+ DEBUG(0,("name_to_nstring: workgroup name %s is too long. Truncating to %s\n",
+ name, tname));
+ } else {
+ unstrcpy(unname, name);
+ }
+}
+
+/****************************************************************************
Create an empty workgroup.
**************************************************************************/
@@ -48,8 +69,6 @@ static struct work_record *create_workgroup(const char *name, int ttl)
{
struct work_record *work;
struct subnet_record *subrec;
- nstring nname;
-
int t = -1;
if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) {
@@ -58,17 +77,8 @@ static struct work_record *create_workgroup(const char *name, int ttl)
}
memset((char *)work, '\0', sizeof(*work));
- errno = 0;
- push_ascii_nstring(nname, name);
- if (errno == E2BIG) {
- unstring tname;
- pull_ascii_nstring(tname, sizeof(tname), nname);
- unstrcpy(work->work_group,tname);
- DEBUG(0,("create_workgroup: workgroup name %s is too long. Truncating to %s\n",
- name, tname));
- } else {
- unstrcpy(work->work_group,name);
- }
+ name_to_unstring(work->work_group, name);
+
work->serverlist = NULL;
work->RunningElection = False;
@@ -157,12 +167,15 @@ struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec,
const char *name)
{
struct work_record *ret;
-
+ unstring un_name;
+
DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ",
name, subrec->subnet_name));
+ name_to_unstring(un_name, name);
+
for (ret = subrec->workgrouplist; ret; ret = ret->next) {
- if (strequal(ret->work_group,name)) {
+ if (strequal(ret->work_group,un_name)) {
DEBUGADD(4, ("found.\n"));
return(ret);
}
diff --git a/source/nsswitch/pam_winbind.c b/source/nsswitch/pam_winbind.c
index 123f6703665..64e21738221 100644
--- a/source/nsswitch/pam_winbind.c
+++ b/source/nsswitch/pam_winbind.c
@@ -45,6 +45,8 @@ static int _pam_parse(int argc, const char **argv)
ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
else if (!strcasecmp(*argv, "unknown_ok"))
ctrl |= WINBIND_UNKNOWN_OK_ARG;
+ else if (!strncasecmp(*argv, "required_membership", strlen("required_membership")))
+ ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
else {
_pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
}
@@ -148,7 +150,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
switch (retval) {
case PAM_AUTH_ERR:
/* incorrect password */
- _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user);
+ _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password or invalid membership)", user);
return retval;
case PAM_ACCT_EXPIRED:
/* account expired */
@@ -174,7 +176,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
case PAM_SUCCESS:
if (req_type == WINBINDD_PAM_AUTH) {
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted acces", user);
+ _pam_log(LOG_NOTICE, "user '%s' granted access", user);
} else if (req_type == WINBINDD_PAM_CHAUTHTOK) {
/* Otherwise, the authentication looked good */
_pam_log(LOG_NOTICE, "user '%s' password changed", user);
@@ -192,7 +194,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
}
/* talk to winbindd */
-static int winbind_auth_request(const char *user, const char *pass, int ctrl)
+static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl)
{
struct winbindd_request request;
struct winbindd_response response;
@@ -204,7 +206,35 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
strncpy(request.data.auth.pass, pass,
sizeof(request.data.auth.pass)-1);
-
+
+ if (member == NULL )
+ return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+
+ /* lookup name? */
+ if (!strncmp("S-", member, 2) == 0) {
+
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (ctrl & WINBIND_DEBUG_ARG)
+ _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member);
+
+ /* fortunatly winbindd can handle non-separated names */
+ strcpy(request.data.name.name, member);
+
+ if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &request, &response, ctrl, user)) {
+ _pam_log(LOG_INFO, "could not lookup name: %s\n", member);
+ return PAM_AUTH_ERR;
+ }
+
+ member = strdup(response.data.sid.sid);
+ }
+
+ strncpy(request.data.auth.required_membership_sid, member,
+ sizeof(request.data.auth.required_membership_sid)-1);
return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
}
@@ -419,7 +449,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
{
const char *username;
const char *password;
+ const char *member = NULL;
int retval = PAM_AUTH_ERR;
+ int i;
/* parse arguments */
int ctrl = _pam_parse(argc, argv);
@@ -453,8 +485,25 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
#endif
}
+ /* Retrieve membership-string here */
+ for ( i=0; i<argc; i++ ) {
+
+ if (!strncmp(argv[i], "required_membership", strlen("required_membership"))) {
+
+ char *p;
+ char *parm = strdup(argv[i]);
+
+ if ( (p = strchr( parm, '=' )) == NULL) {
+ _pam_log(LOG_INFO, "no \"=\" delimiter for \"required_membership\" found\n");
+ break;
+ }
+
+ member = strdup(p+1);
+ }
+ }
+
/* Now use the username to look up password */
- return winbind_auth_request(username, password, ctrl);
+ return winbind_auth_request(username, password, member, ctrl);
}
PAM_EXTERN
@@ -502,7 +551,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
return PAM_USER_UNKNOWN;
case 0:
/* Otherwise, the authentication looked good */
- _pam_log(LOG_NOTICE, "user '%s' granted acces", username);
+ _pam_log(LOG_NOTICE, "user '%s' granted access", username);
return PAM_SUCCESS;
default:
/* we don't know anything about this return value */
@@ -546,6 +595,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
/* <DO NOT free() THESE> */
const char *user;
+ const char *member = NULL;
char *pass_old, *pass_new;
/* </DO NOT free() THESE> */
@@ -606,7 +656,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
}
/* verify that this is the password for this user */
- retval = winbind_auth_request(user, pass_old, ctrl);
+ retval = winbind_auth_request(user, pass_old, member, ctrl);
if (retval != PAM_ACCT_EXPIRED
&& retval != PAM_AUTHTOK_EXPIRED
diff --git a/source/nsswitch/pam_winbind.h b/source/nsswitch/pam_winbind.h
index 0afcceb6aa2..7cae477714b 100644
--- a/source/nsswitch/pam_winbind.h
+++ b/source/nsswitch/pam_winbind.h
@@ -82,6 +82,7 @@ do { \
#define WINBIND_TRY_FIRST_PASS_ARG (1<<3)
#define WINBIND_USE_FIRST_PASS_ARG (1<<4)
#define WINBIND__OLD_PASSWORD (1<<5)
+#define WINBIND_REQUIRED_MEMBERSHIP (1<<6)
/*
* here is the string to inform the user that the new passwords they
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 0028982d201..b6a09bf2a1f 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -398,27 +398,6 @@ static BOOL wbinfo_sid_to_uid(char *sid)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* First see whether the SID is actually a user -- otherwise
- * winbind might end up a uid number for a group SID and this
- * is asking for trouble later. */
-
- fstrcpy(request.data.sid, sid);
-
- if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("Could not lookup sid %s\n", sid);
- return False;
- }
-
- if (response.data.name.type != SID_NAME_USER) {
- d_printf("SID is of type %s\n",
- sid_type_lookup(response.data.name.type));
- return False;
- }
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
/* Send request */
fstrcpy(request.data.sid, sid);
@@ -442,26 +421,6 @@ static BOOL wbinfo_sid_to_gid(char *sid)
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- /* First see whether the SID is actually a group -- otherwise
- * winbind might end up a gid number for a user SID and this
- * is asking for trouble later. */
-
- fstrcpy(request.data.sid, sid);
-
- if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_printf("Could not lookup sid %s\n", sid);
- return False;
- }
-
- if ((response.data.name.type != SID_NAME_DOM_GRP) &&
- (response.data.name.type != SID_NAME_ALIAS) &&
- (response.data.name.type != SID_NAME_WKN_GRP)) {
- d_printf("SID is of type %s\n",
- sid_type_lookup(response.data.name.type));
- return False;
- }
-
/* Send request */
fstrcpy(request.data.sid, sid);
diff --git a/source/nsswitch/winbind_nss_linux.c b/source/nsswitch/winbind_nss_linux.c
index ae2bcc7ade9..0ea5db74da6 100644
--- a/source/nsswitch/winbind_nss_linux.c
+++ b/source/nsswitch/winbind_nss_linux.c
@@ -833,25 +833,40 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
/* Skip primary group */
- if (gid_list[i] == group) continue;
-
- /* Add to buffer */
+ if (gid_list[i] == group) {
+ continue;
+ }
- if (*start == *size && limit <= 0) {
- (*groups) = realloc(
- (*groups), (2 * (*size) + 1) * sizeof(**groups));
- if (! *groups) goto done;
- *size = 2 * (*size) + 1;
+ /* Filled buffer ? If so, resize. */
+
+ if (*start == *size) {
+ long int newsize;
+ gid_t *newgroups;
+
+ newsize = 2 * (*size);
+ if (limit > 0) {
+ if (*size == limit) {
+ goto done;
+ }
+ if (newsize > limit) {
+ newsize = limit;
+ }
+ }
+
+ newgroups = realloc((*groups), newsize * sizeof(**groups));
+ if (!newgroups) {
+ *errnop = ENOMEM;
+ ret = NSS_STATUS_NOTFOUND;
+ goto done;
+ }
+ *groups = newgroups;
+ *size = newsize;
}
- if (*start == *size) goto done;
+ /* Add to buffer */
(*groups)[*start] = gid_list[i];
*start += 1;
-
- /* Filled buffer? */
-
- if (*start == limit) goto done;
}
}
diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c
index d08aa84face..455fb74f171 100644
--- a/source/nsswitch/winbindd.c
+++ b/source/nsswitch/winbindd.c
@@ -28,6 +28,8 @@
BOOL opt_nocache = False;
BOOL opt_dual_daemon = True;
+extern BOOL override_logfile;
+
/* Reload configuration */
static BOOL reload_services_file(void)
@@ -587,6 +589,7 @@ static void process_loop(void)
int maxfd, listen_sock, listen_priv_sock, selret;
struct timeval timeout;
+ again:
/* Handle messages */
message_dispatch();
@@ -715,6 +718,15 @@ static void process_loop(void)
for (state = winbindd_client_list(); state;
state = state->next) {
+ /* Data available for writing */
+
+ if (FD_ISSET(state->sock, &w_fds))
+ client_write(state);
+ }
+
+ for (state = winbindd_client_list(); state;
+ state = state->next) {
+
/* Data available for reading */
if (FD_ISSET(state->sock, &r_fds)) {
@@ -747,13 +759,10 @@ static void process_loop(void)
if (state->read_buf_len ==
sizeof(state->request)) {
winbind_process_packet(state);
+ winbindd_demote_client(state);
+ goto again;
}
}
-
- /* Data available for writing */
-
- if (FD_ISSET(state->sock, &w_fds))
- client_write(state);
}
}
@@ -846,8 +855,10 @@ int main(int argc, char **argv)
exit(1);
}
- pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
+ if (!override_logfile) {
+ pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE);
+ lp_set_logfile(logfile);
+ }
setup_logging("winbindd", log_stdout);
reopen_logs();
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index b81f8ecd45a..493255a5a65 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -609,7 +609,6 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
{
struct cache_entry *centry;
fstring uname;
- fstring sid_string;
centry = centry_start(domain, status);
if (!centry)
@@ -619,7 +618,8 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain,
fstrcpy(uname, name);
strupper_m(uname);
centry_end(centry, "NS/%s/%s", domain_name, uname);
- DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string));
+ DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname,
+ sid_string_static(sid)));
centry_free(centry);
}
diff --git a/source/nsswitch/winbindd_dual.c b/source/nsswitch/winbindd_dual.c
index a9796afa367..d4ec6e586db 100644
--- a/source/nsswitch/winbindd_dual.c
+++ b/source/nsswitch/winbindd_dual.c
@@ -155,7 +155,7 @@ void do_dual_daemon(void)
dual_daemon_pipe = fdpair[1];
state.sock = fdpair[0];
- if (fork() != 0) {
+ if (sys_fork() != 0) {
close(fdpair[0]);
return;
}
diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c
index ca7f72d0178..a3b826278b5 100644
--- a/source/nsswitch/winbindd_group.c
+++ b/source/nsswitch/winbindd_group.c
@@ -495,8 +495,6 @@ enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state)
The dispinfo_ndx field is incremented to the index of the next group to
fetch. Return True if some groups were returned, False otherwise. */
-#define MAX_FETCH_SAM_ENTRIES 100
-
static BOOL get_sam_group_entries(struct getent_state *ent)
{
NTSTATUS status;
@@ -925,14 +923,11 @@ static void add_gid_to_array_unique(gid_t gid, gid_t **gids, int *num)
{
int i;
- if ((*num) >= groups_max())
- return;
-
for (i=0; i<*num; i++) {
if ((*gids)[i] == gid)
return;
}
-
+
*gids = Realloc(*gids, (*num+1) * sizeof(gid_t));
if (*gids == NULL)
diff --git a/source/nsswitch/winbindd_sid.c b/source/nsswitch/winbindd_sid.c
index 61da9b3d92f..c6e503bef39 100644
--- a/source/nsswitch/winbindd_sid.c
+++ b/source/nsswitch/winbindd_sid.c
@@ -119,7 +119,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 flags = 0x0;
+ NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -166,8 +166,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
/* But first check and see if we don't already have a mapping */
- flags = ID_QUERY_ONLY;
- if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) )
+ if ( NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), ID_QUERY_ONLY)) )
return WINBINDD_OK;
/* now fall back to the hard way */
@@ -191,17 +190,37 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
}
- if ( state->request.flags & WBFLAG_QUERY_ONLY )
- flags = ID_QUERY_ONLY;
-
/* Find uid for this sid and return it */
-
- if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) {
- DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
+ ID_QUERY_ONLY);
+
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ if (state->request.flags & WBFLAG_QUERY_ONLY)
return WINBINDD_ERROR;
+
+ /* The query-only did not work, allocate a new uid *if* it's a user */
+
+ {
+ fstring dom_name, name;
+ enum SID_NAME_USE type;
+
+ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type))
+ return WINBINDD_ERROR;
+
+ if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))
+ return WINBINDD_ERROR;
}
+
+ result = idmap_sid_to_uid(&sid, &(state->response.data.uid), 0);
- return WINBINDD_OK;
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid));
+ return WINBINDD_ERROR;
}
/* Convert a sid to a gid. We assume we only have one rid attached to the
@@ -210,7 +229,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
{
DOM_SID sid;
- uint32 flags = 0x0;
+ NTSTATUS result;
/* Ensure null termination */
state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -256,8 +275,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
/* But first check and see if we don't already have a mapping */
- flags = ID_QUERY_ONLY;
- if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) )
+ if ( NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), ID_QUERY_ONLY)) )
return WINBINDD_OK;
/* now fall back to the hard way */
@@ -281,16 +299,38 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
}
- if ( state->request.flags & WBFLAG_QUERY_ONLY )
- flags = ID_QUERY_ONLY;
-
/* Find gid for this sid and return it */
- if ( !NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) {
- DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
+
+ result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
+ ID_QUERY_ONLY);
+
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ if (state->request.flags & WBFLAG_QUERY_ONLY)
return WINBINDD_ERROR;
+
+ /* The query-only did not work, allocate a new gid *if* it's a group */
+
+ {
+ fstring dom_name, name;
+ enum SID_NAME_USE type;
+
+ if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type))
+ return WINBINDD_ERROR;
+
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+ (type != SID_NAME_WKN_GRP))
+ return WINBINDD_ERROR;
}
+
+ result = idmap_sid_to_gid(&sid, &(state->response.data.gid), 0);
- return WINBINDD_OK;
+ if (NT_STATUS_IS_OK(result))
+ return WINBINDD_OK;
+
+ DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid));
+ return WINBINDD_ERROR;
}
/* Convert a uid to a sid */
diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c
index 795d657aae7..6f5a86f43ae 100644
--- a/source/nsswitch/winbindd_user.c
+++ b/source/nsswitch/winbindd_user.c
@@ -385,8 +385,6 @@ enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state)
field is incremented to the index of the next user to fetch. Return True if
some users were returned, False otherwise. */
-#define MAX_FETCH_SAM_ENTRIES 100
-
static BOOL get_sam_user_entries(struct getent_state *ent)
{
NTSTATUS status;
diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c
index faa6e8d8da4..a9197d35616 100644
--- a/source/nsswitch/winbindd_util.c
+++ b/source/nsswitch/winbindd_util.c
@@ -736,6 +736,14 @@ void winbindd_remove_client(struct winbindd_cli_state *cli)
_num_clients--;
}
+/* Demote a client to be the last in the list */
+
+void winbindd_demote_client(struct winbindd_cli_state *cli)
+{
+ struct winbindd_cli_state *tmp;
+ DLIST_DEMOTE(_client_list, cli, tmp);
+}
+
/* Close all open clients */
void winbindd_kill_all_clients(void)
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 14981b97c42..24811af37dd 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -156,6 +156,7 @@ typedef struct
char *szAddMachineScript;
char *szShutdownScript;
char *szAbortShutdownScript;
+ char *szCheckPasswordScript;
char *szWINSHook;
char *szWINSPartners;
char *szUtmpDir;
@@ -811,6 +812,7 @@ static struct parm_struct parm_table[] = {
{"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED},
{"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED},
{"passwd chat timeout", P_INTEGER, P_GLOBAL, &Globals.iPasswdChatTimeout, NULL, NULL, FLAG_ADVANCED},
+ {"check password script", P_STRING, P_GLOBAL, &Globals.szCheckPasswordScript, NULL, NULL, FLAG_ADVANCED},
{"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED},
{"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED},
{"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED},
@@ -1678,6 +1680,8 @@ FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
FN_GLOBAL_STRING(lp_shutdown_script, &Globals.szShutdownScript)
FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
+FN_GLOBAL_STRING(lp_check_password_script, &Globals.szCheckPasswordScript)
+
FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup)
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 9af34705df5..454aa8d8702 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -148,6 +148,27 @@ static char** get_userattr_list( int schema_ver )
return NULL;
}
+/**************************************************************************
+ Return the list of attribute names to delete given a user schema version.
+**************************************************************************/
+
+static char** get_userattr_delete_list( int schema_ver )
+{
+ switch ( schema_ver ) {
+ case SCHEMAVER_SAMBAACCOUNT:
+ return get_attr_list( attrib_map_to_delete_v22 );
+
+ case SCHEMAVER_SAMBASAMACCOUNT:
+ return get_attr_list( attrib_map_to_delete_v30 );
+ default:
+ DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
+ break;
+ }
+
+ return NULL;
+}
+
+
/*******************************************************************
Generate the LDAP search filter for the objectclass based on the
version of the schema we are using.
@@ -299,11 +320,16 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
really exist. */
for (attrib = attrs; *attrib != NULL; attrib++) {
- if ((StrCaseCmp(*attrib, name) == 0) &&
- !(StrCaseCmp(*attrib,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MOD_TIMESTAMP)))) {
- DEBUG(10, ("ldapsam_delete_entry: deleting attribute %s\n", name));
- smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL);
+ /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
+ if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
+ LDAP_ATTR_MOD_TIMESTAMP))) {
+ continue;
+ }
+ if (strequal(*attrib, name)) {
+ DEBUG(10, ("ldapsam_delete_entry: deleting "
+ "attribute %s\n", name));
+ smbldap_set_mod(&mods, LDAP_MOD_DELETE, name,
+ NULL);
}
}
@@ -1229,8 +1255,13 @@ static void append_attr(char ***attr_list, const char *new_attr)
{
int i;
- for (i=0; (*attr_list)[i] != NULL; i++)
+ if (new_attr == NULL) {
+ return;
+ }
+
+ for (i=0; (*attr_list)[i] != NULL; i++) {
;
+ }
(*attr_list) = Realloc((*attr_list), sizeof(**attr_list) * (i+2));
SMB_ASSERT((*attr_list) != NULL);
@@ -1515,7 +1546,7 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
- attr_list= get_userattr_list( ldap_state->schema_ver );
+ attr_list= get_userattr_delete_list( ldap_state->schema_ver );
rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
if (rc != LDAP_SUCCESS) {
diff --git a/source/passdb/pdb_smbpasswd.c b/source/passdb/pdb_smbpasswd.c
index 6ebac1c01a5..805201615ce 100644
--- a/source/passdb/pdb_smbpasswd.c
+++ b/source/passdb/pdb_smbpasswd.c
@@ -70,20 +70,21 @@ enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
{
- if (fd < 0)
- return False;
+ if (fd < 0) {
+ return False;
+ }
- if(*plock_depth == 0) {
- if (!do_file_lock(fd, secs, type)) {
- DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
- strerror(errno)));
- return False;
- }
- }
+ if(*plock_depth == 0) {
+ if (!do_file_lock(fd, secs, type)) {
+ DEBUG(10,("pw_file_lock: locking file failed, error = %s.\n",
+ strerror(errno)));
+ return False;
+ }
+ }
- (*plock_depth)++;
+ (*plock_depth)++;
- return True;
+ return True;
}
/***************************************************************
@@ -92,25 +93,27 @@ static BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
static BOOL pw_file_unlock(int fd, int *plock_depth)
{
- BOOL ret=True;
+ BOOL ret=True;
- if (fd == 0 || *plock_depth == 0) {
- return True;
- }
+ if (fd == 0 || *plock_depth == 0) {
+ return True;
+ }
- if(*plock_depth == 1)
- ret = do_file_lock(fd, 5, F_UNLCK);
+ if(*plock_depth == 1) {
+ ret = do_file_lock(fd, 5, F_UNLCK);
+ }
- if (*plock_depth > 0)
- (*plock_depth)--;
+ if (*plock_depth > 0) {
+ (*plock_depth)--;
+ }
- if(!ret)
- DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
- strerror(errno)));
- return ret;
+ if(!ret) {
+ DEBUG(10,("pw_file_unlock: unlocking file failed, error = %s.\n",
+ strerror(errno)));
+ }
+ return ret;
}
-
/**************************************************************
Intialize a smb_passwd struct
*************************************************************/
@@ -133,153 +136,160 @@ static void pdb_init_smb(struct smb_passwd *user)
static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
{
- FILE *fp = NULL;
- const char *open_mode = NULL;
- int race_loop = 0;
- int lock_type = F_RDLCK;
-
- if (!*pfile) {
- DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
- return (NULL);
- }
-
- switch(type) {
- case PWF_READ:
- open_mode = "rb";
- lock_type = F_RDLCK;
- break;
- case PWF_UPDATE:
- open_mode = "r+b";
- lock_type = F_WRLCK;
- break;
- case PWF_CREATE:
- /*
- * Ensure atomic file creation.
- */
- {
- int i, fd = -1;
-
- for(i = 0; i < 5; i++) {
- if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1)
- break;
- sys_usleep(200); /* Spin, spin... */
- }
- if(fd == -1) {
- DEBUG(0,("startsmbfilepwent_internal: too many race conditions creating file %s\n", pfile));
- return NULL;
- }
- close(fd);
- open_mode = "r+b";
- lock_type = F_WRLCK;
- break;
- }
- }
+ FILE *fp = NULL;
+ const char *open_mode = NULL;
+ int race_loop = 0;
+ int lock_type = F_RDLCK;
+
+ if (!*pfile) {
+ DEBUG(0, ("startsmbfilepwent: No SMB password file set\n"));
+ return (NULL);
+ }
+
+ switch(type) {
+ case PWF_READ:
+ open_mode = "rb";
+ lock_type = F_RDLCK;
+ break;
+ case PWF_UPDATE:
+ open_mode = "r+b";
+ lock_type = F_WRLCK;
+ break;
+ case PWF_CREATE:
+ /*
+ * Ensure atomic file creation.
+ */
+ {
+ int i, fd = -1;
+
+ for(i = 0; i < 5; i++) {
+ if((fd = sys_open(pfile, O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600))!=-1) {
+ break;
+ }
+ sys_usleep(200); /* Spin, spin... */
+ }
+ if(fd == -1) {
+ DEBUG(0,("startsmbfilepwent_internal: too many race conditions \
+creating file %s\n", pfile));
+ return NULL;
+ }
+ close(fd);
+ open_mode = "r+b";
+ lock_type = F_WRLCK;
+ break;
+ }
+ }
- for(race_loop = 0; race_loop < 5; race_loop++) {
- DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
+ for(race_loop = 0; race_loop < 5; race_loop++) {
+ DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile));
+
+ if((fp = sys_fopen(pfile, open_mode)) == NULL) {
+
+ /*
+ * If smbpasswd file doesn't exist, then create new one. This helps to avoid
+ * confusing error msg when adding user account first time.
+ */
+ if (errno == ENOENT) {
+ if ((fp = sys_fopen(pfile, "a+")) != NULL) {
+ DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
+exist. File successfully created.\n", pfile));
+ } else {
+ DEBUG(0, ("startsmbfilepwent_internal: file %s did not \
+exist. Couldn't create new one. Error was: %s",
+ pfile, strerror(errno)));
+ return NULL;
+ }
+ } else {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. \
+Error was: %s\n", pfile, strerror(errno)));
+ return NULL;
+ }
+ }
- if((fp = sys_fopen(pfile, open_mode)) == NULL) {
-
- /*
- * If smbpasswd file doesn't exist, then create new one. This helps to avoid
- * confusing error msg when adding user account first time.
- */
- if (errno == ENOENT) {
- if ((fp = sys_fopen(pfile, "a+")) != NULL) {
- DEBUG(0, ("startsmbfilepwent_internal: file %s did not exist. File successfully created.\n", pfile));
-
- } else {
- DEBUG(0, ("startsmbfilepwent_internal: file %s did not exist. Couldn't create new one. Error was: %s",
- pfile, strerror(errno)));
- return NULL;
- }
-
- } else {
- DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. Error was: %s\n", pfile, strerror(errno)));
- return NULL;
- }
- }
-
- if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
- DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. Error was %s\n", pfile, strerror(errno) ));
- fclose(fp);
- return NULL;
- }
-
- /*
- * Only check for replacement races on update or create.
- * For read we don't mind if the data is one record out of date.
- */
-
- if(type == PWF_READ) {
- break;
- } else {
- SMB_STRUCT_STAT sbuf1, sbuf2;
-
- /*
- * Avoid the potential race condition between the open and the lock
- * by doing a stat on the filename and an fstat on the fd. If the
- * two inodes differ then someone did a rename between the open and
- * the lock. Back off and try the open again. Only do this 5 times to
- * prevent infinate loops. JRA.
- */
-
- if (sys_stat(pfile,&sbuf1) != 0) {
- DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. Error was %s\n", pfile, strerror(errno)));
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- return NULL;
- }
-
- if (sys_fstat(fileno(fp),&sbuf2) != 0) {
- DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. Error was %s\n", pfile, strerror(errno)));
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- return NULL;
- }
-
- if( sbuf1.st_ino == sbuf2.st_ino) {
- /* No race. */
- break;
- }
-
- /*
- * Race occurred - back off and try again...
- */
-
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- }
- }
-
- if(race_loop == 5) {
- DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
- return NULL;
- }
-
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, (char *)NULL, _IOFBF, 1024);
-
- /* Make sure it is only rw by the owner */
+ if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to lock file %s. \
+Error was %s\n", pfile, strerror(errno) ));
+ fclose(fp);
+ return NULL;
+ }
+
+ /*
+ * Only check for replacement races on update or create.
+ * For read we don't mind if the data is one record out of date.
+ */
+
+ if(type == PWF_READ) {
+ break;
+ } else {
+ SMB_STRUCT_STAT sbuf1, sbuf2;
+
+ /*
+ * Avoid the potential race condition between the open and the lock
+ * by doing a stat on the filename and an fstat on the fd. If the
+ * two inodes differ then someone did a rename between the open and
+ * the lock. Back off and try the open again. Only do this 5 times to
+ * prevent infinate loops. JRA.
+ */
+
+ if (sys_stat(pfile,&sbuf1) != 0) {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to stat file %s. \
+Error was %s\n", pfile, strerror(errno)));
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ return NULL;
+ }
+
+ if (sys_fstat(fileno(fp),&sbuf2) != 0) {
+ DEBUG(0, ("startsmbfilepwent_internal: unable to fstat file %s. \
+Error was %s\n", pfile, strerror(errno)));
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ return NULL;
+ }
+
+ if( sbuf1.st_ino == sbuf2.st_ino) {
+ /* No race. */
+ break;
+ }
+
+ /*
+ * Race occurred - back off and try again...
+ */
+
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ }
+ }
+
+ if(race_loop == 5) {
+ DEBUG(0, ("startsmbfilepwent_internal: too many race conditions opening file %s\n", pfile));
+ return NULL;
+ }
+
+ /* Set a buffer to do more efficient reads */
+ setvbuf(fp, (char *)NULL, _IOFBF, 1024);
+
+ /* Make sure it is only rw by the owner */
#ifdef HAVE_FCHMOD
- if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) {
+ if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) {
#else
- if(chmod(pfile, S_IRUSR|S_IWUSR) == -1) {
+ if(chmod(pfile, S_IRUSR|S_IWUSR) == -1) {
#endif
- DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
+ DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \
Error was %s\n.", pfile, strerror(errno) ));
- pw_file_unlock(fileno(fp), lock_depth);
- fclose(fp);
- return NULL;
- }
+ pw_file_unlock(fileno(fp), lock_depth);
+ fclose(fp);
+ return NULL;
+ }
- /* We have a lock on the file. */
- return fp;
+ /* We have a lock on the file. */
+ return fp;
}
/***************************************************************
End enumeration of the smbpasswd list.
****************************************************************/
+
static void endsmbfilepwent(FILE *fp, int *lock_depth)
{
if (!fp) {
@@ -297,225 +307,235 @@ static void endsmbfilepwent(FILE *fp, int *lock_depth)
static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp)
{
- /* Static buffers we will return. */
- struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
- char *user_name = smbpasswd_state->user_name;
- unsigned char *smbpwd = smbpasswd_state->smbpwd;
- unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
- char linebuf[256];
- unsigned char c;
- unsigned char *p;
- long uidval;
- size_t linebuf_len;
-
- if(fp == NULL) {
- DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
- return NULL;
- }
-
- pdb_init_smb(pw_buf);
-
- pw_buf->acct_ctrl = ACB_NORMAL;
-
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
- while (!feof(fp)) {
- linebuf[0] = '\0';
-
- fgets(linebuf, 256, fp);
- if (ferror(fp)) {
- return NULL;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- if ((linebuf_len = strlen(linebuf)) == 0)
- continue;
-
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n')
- break;
- }
- } else
- linebuf[linebuf_len - 1] = '\0';
+ /* Static buffers we will return. */
+ struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
+ char *user_name = smbpasswd_state->user_name;
+ unsigned char *smbpwd = smbpasswd_state->smbpwd;
+ unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
+ char linebuf[256];
+ unsigned char c;
+ unsigned char *p;
+ long uidval;
+ size_t linebuf_len;
+
+ if(fp == NULL) {
+ DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
+ return NULL;
+ }
+
+ pdb_init_smb(pw_buf);
+ pw_buf->acct_ctrl = ACB_NORMAL;
+
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+ while (!feof(fp)) {
+ linebuf[0] = '\0';
+
+ fgets(linebuf, 256, fp);
+ if (ferror(fp)) {
+ return NULL;
+ }
+
+ /*
+ * Check if the string is terminated with a newline - if not
+ * then we must keep reading and discard until we get one.
+ */
+ if ((linebuf_len = strlen(linebuf)) == 0) {
+ continue;
+ }
+
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n') {
+ break;
+ }
+ }
+ } else {
+ linebuf[linebuf_len - 1] = '\0';
+ }
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf));
+ DEBUG(100, ("getsmbfilepwent: got line |%s|\n", linebuf));
#endif
- if ((linebuf[0] == 0) && feof(fp)) {
- DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
- break;
- }
- /*
- * The line we have should be of the form :-
- *
- * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
- *
- * if Windows NT compatible passwords are also present.
- * [Account type] is an ascii encoding of the type of account.
- * LCT-(8 hex digits) is the time_t value of the last change time.
- */
-
- if (linebuf[0] == '#' || linebuf[0] == '\0') {
- DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
- continue;
- }
- p = (unsigned char *) strchr_m(linebuf, ':');
- if (p == NULL) {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
- continue;
- }
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
- SMB_ASSERT(sizeof(pstring) > sizeof(linebuf));
-
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
-
- /* Get smb uid. */
-
- p++; /* Go past ':' */
-
- if(*p == '-') {
- DEBUG(0, ("getsmbfilepwent: uids in the smbpasswd file must not be negative.\n"));
- continue;
- }
-
- if (!isdigit(*p)) {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (uid not number)\n"));
- continue;
- }
-
- uidval = atoi((char *) p);
-
- while (*p && isdigit(*p))
- p++;
-
- if (*p != ':') {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (no : after uid)\n"));
- continue;
- }
-
- pw_buf->smb_name = user_name;
- pw_buf->smb_userid = uidval;
-
- /*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
- */
-
- /* Skip the ':' */
- p++;
-
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (passwd too short)\n"));
- continue;
- }
-
- if (p[32] != ':') {
- DEBUG(0, ("getsmbfilepwent: malformed password entry (no terminating :)\n"));
- continue;
- }
-
- if (strnequal((char *) p, "NO PASSWORD", 11)) {
- pw_buf->smb_passwd = NULL;
- pw_buf->acct_ctrl |= ACB_PWNOTREQ;
- } else {
- if (*p == '*' || *p == 'X') {
- /* NULL LM password */
- pw_buf->smb_passwd = NULL;
- DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name));
- } else if (pdb_gethexpwd((char *)p, smbpwd)) {
- pw_buf->smb_passwd = smbpwd;
- } else {
- pw_buf->smb_passwd = NULL;
- DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
- }
- }
-
- /*
- * Now check if the NT compatible password is
- * available.
- */
- pw_buf->smb_nt_passwd = NULL;
-
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
- if (*p != '*' && *p != 'X') {
- if(pdb_gethexpwd((char *)p,smbntpwd))
- pw_buf->smb_nt_passwd = smbntpwd;
- }
- p += 33; /* Move to the first character of the line after
- the NT password. */
- }
-
- DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
- user_name, uidval));
-
- if (*p == '[')
- {
- unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
- pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
-
- /* Must have some account type set. */
- if(pw_buf->acct_ctrl == 0)
- pw_buf->acct_ctrl = ACB_NORMAL;
-
- /* Now try and get the last change time. */
- if(end_p)
- p = end_p + 1;
- if(*p == ':') {
- p++;
- if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
- int i;
- p += 4;
- for(i = 0; i < 8; i++) {
- if(p[i] == '\0' || !isxdigit(p[i]))
- break;
- }
- if(i == 8) {
- /*
- * p points at 8 characters of hex digits -
- * read into a time_t as the seconds since
- * 1970 that the password was last changed.
- */
- pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
- }
- }
- }
- } else {
- /* 'Old' style file. Fake up based on user name. */
- /*
- * Currently trust accounts are kept in the same
- * password file as 'normal accounts'. If this changes
- * we will have to fix this code. JRA.
- */
- if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
- pw_buf->acct_ctrl &= ~ACB_NORMAL;
- pw_buf->acct_ctrl |= ACB_WSTRUST;
- }
- }
-
- return pw_buf;
- }
-
- DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
- return NULL;
+ if ((linebuf[0] == 0) && feof(fp)) {
+ DEBUG(4, ("getsmbfilepwent: end of file reached\n"));
+ break;
+ }
+
+ /*
+ * The line we have should be of the form :-
+ *
+ * username:uid:32hex bytes:[Account type]:LCT-12345678....other flags presently
+ * ignored....
+ *
+ * or,
+ *
+ * username:uid:32hex bytes:32hex bytes:[Account type]:LCT-12345678....ignored....
+ *
+ * if Windows NT compatible passwords are also present.
+ * [Account type] is an ascii encoding of the type of account.
+ * LCT-(8 hex digits) is the time_t value of the last change time.
+ */
+
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
+ DEBUG(6, ("getsmbfilepwent: skipping comment or blank line\n"));
+ continue;
+ }
+ p = (unsigned char *) strchr_m(linebuf, ':');
+ if (p == NULL) {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry (no :)\n"));
+ continue;
+ }
+
+ /*
+ * As 256 is shorter than a pstring we don't need to check
+ * length here - if this ever changes....
+ */
+ SMB_ASSERT(sizeof(pstring) > sizeof(linebuf));
+
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+
+ /* Get smb uid. */
+
+ p++; /* Go past ':' */
+
+ if(*p == '-') {
+ DEBUG(0, ("getsmbfilepwent: user name %s has a negative uid.\n", user_name));
+ continue;
+ }
+
+ if (!isdigit(*p)) {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (uid not number)\n",
+ user_name));
+ continue;
+ }
+
+ uidval = atoi((char *) p);
+
+ while (*p && isdigit(*p)) {
+ p++;
+ }
+
+ if (*p != ':') {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no : after uid)\n",
+ user_name));
+ continue;
+ }
+
+ pw_buf->smb_name = user_name;
+ pw_buf->smb_userid = uidval;
+
+ /*
+ * Now get the password value - this should be 32 hex digits
+ * which are the ascii representations of a 16 byte string.
+ * Get two at a time and put them into the password.
+ */
+
+ /* Skip the ':' */
+ p++;
+
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (passwd too short)\n",
+ user_name ));
+ continue;
+ }
+
+ if (p[32] != ':') {
+ DEBUG(0, ("getsmbfilepwent: malformed password entry for user %s (no terminating :)\n",
+ user_name));
+ continue;
+ }
+
+ if (strnequal((char *) p, "NO PASSWORD", 11)) {
+ pw_buf->smb_passwd = NULL;
+ pw_buf->acct_ctrl |= ACB_PWNOTREQ;
+ } else {
+ if (*p == '*' || *p == 'X') {
+ /* NULL LM password */
+ pw_buf->smb_passwd = NULL;
+ DEBUG(10, ("getsmbfilepwent: LM password for user %s invalidated\n", user_name));
+ } else if (pdb_gethexpwd((char *)p, smbpwd)) {
+ pw_buf->smb_passwd = smbpwd;
+ } else {
+ pw_buf->smb_passwd = NULL;
+ DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry for user %s \
+(non hex chars)\n", user_name));
+ }
+ }
+
+ /*
+ * Now check if the NT compatible password is
+ * available.
+ */
+ pw_buf->smb_nt_passwd = NULL;
+ p += 33; /* Move to the first character of the line after the lanman password. */
+ if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
+ if (*p != '*' && *p != 'X') {
+ if(pdb_gethexpwd((char *)p,smbntpwd)) {
+ pw_buf->smb_nt_passwd = smbntpwd;
+ }
+ }
+ p += 33; /* Move to the first character of the line after the NT password. */
+ }
+
+ DEBUG(5,("getsmbfilepwent: returning passwd entry for user %s, uid %ld\n",
+ user_name, uidval));
+
+ if (*p == '[') {
+ unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
+ pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
+
+ /* Must have some account type set. */
+ if(pw_buf->acct_ctrl == 0) {
+ pw_buf->acct_ctrl = ACB_NORMAL;
+ }
+
+ /* Now try and get the last change time. */
+ if(end_p) {
+ p = end_p + 1;
+ }
+ if(*p == ':') {
+ p++;
+ if(*p && (StrnCaseCmp((char *)p, "LCT-", 4)==0)) {
+ int i;
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i])) {
+ break;
+ }
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
+ }
+ }
+ }
+ } else {
+ /* 'Old' style file. Fake up based on user name. */
+ /*
+ * Currently trust accounts are kept in the same
+ * password file as 'normal accounts'. If this changes
+ * we will have to fix this code. JRA.
+ */
+ if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
+ pw_buf->acct_ctrl &= ~ACB_NORMAL;
+ pw_buf->acct_ctrl |= ACB_WSTRUST;
+ }
+ }
+
+ return pw_buf;
+ }
+
+ DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
+ return NULL;
}
/************************************************************************
@@ -524,35 +544,38 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
{
- int new_entry_length;
- char *new_entry;
- char *p;
-
- new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
+ int new_entry_length;
+ char *new_entry;
+ char *p;
- if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
- DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n", newpwd->smb_name ));
- return NULL;
- }
+ new_entry_length = strlen(newpwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 +
+ NEW_PW_FORMAT_SPACE_PADDED_LEN + 1 + 13 + 2;
- slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
-
- p = new_entry+strlen(new_entry);
-
- pdb_sethexpwd(p, newpwd->smb_passwd, newpwd->acct_ctrl);
+ if((new_entry = (char *)malloc( new_entry_length )) == NULL) {
+ DEBUG(0, ("format_new_smbpasswd_entry: Malloc failed adding entry for user %s.\n",
+ newpwd->smb_name ));
+ return NULL;
+ }
- p+=strlen(p); *p = ':'; p++;
+ slprintf(new_entry, new_entry_length - 1, "%s:%u:", newpwd->smb_name, (unsigned)newpwd->smb_userid);
- pdb_sethexpwd(p, newpwd->smb_nt_passwd, newpwd->acct_ctrl);
+ p = new_entry+strlen(new_entry);
+ pdb_sethexpwd(p, newpwd->smb_passwd, newpwd->acct_ctrl);
+ p+=strlen(p);
+ *p = ':';
+ p++;
- p+=strlen(p); *p = ':'; p++;
+ pdb_sethexpwd(p, newpwd->smb_nt_passwd, newpwd->acct_ctrl);
+ p+=strlen(p);
+ *p = ':';
+ p++;
- /* Add the account encoding and the last change time. */
- slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
- pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
- (uint32)newpwd->pass_last_set_time);
+ /* Add the account encoding and the last change time. */
+ slprintf((char *)p, new_entry_length - 1 - (p - new_entry), "%s:LCT-%08X:\n",
+ pdb_encode_acct_ctrl(newpwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN),
+ (uint32)newpwd->pass_last_set_time);
- return new_entry;
+ return new_entry;
}
/************************************************************************
@@ -561,101 +584,95 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd)
{
- const char *pfile = smbpasswd_state->smbpasswd_file;
- struct smb_passwd *pwd = NULL;
- FILE *fp = NULL;
- int wr_len;
- int fd;
- size_t new_entry_length;
- char *new_entry;
- SMB_OFF_T offpos;
- uint32 max_found_uid = 0;
+ const char *pfile = smbpasswd_state->smbpasswd_file;
+ struct smb_passwd *pwd = NULL;
+ FILE *fp = NULL;
+ int wr_len;
+ int fd;
+ size_t new_entry_length;
+ char *new_entry;
+ SMB_OFF_T offpos;
+ uint32 max_found_uid = 0;
- /* Open the smbpassword file - for update. */
- fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth));
-
- if (fp == NULL && errno == ENOENT) {
- /* Try again - create. */
- fp = startsmbfilepwent(pfile, PWF_CREATE, &(smbpasswd_state->pw_file_lock_depth));
- }
-
- if (fp == NULL) {
- DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
- return False;
- }
-
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
-
- while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL)
- {
- if (strequal(newpwd->smb_name, pwd->smb_name))
- {
- DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
+ /* Open the smbpassword file - for update. */
+ fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth);
+
+ if (fp == NULL && errno == ENOENT) {
+ /* Try again - create. */
+ fp = startsmbfilepwent(pfile, PWF_CREATE, &smbpasswd_state->pw_file_lock_depth);
+ }
+
+ if (fp == NULL) {
+ DEBUG(0, ("add_smbfilepwd_entry: unable to open file.\n"));
+ return False;
+ }
+
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
+ if (strequal(newpwd->smb_name, pwd->smb_name)) {
+ DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
- /* Look for a free uid for use in non-unix accounts */
- if (pwd->smb_userid > max_found_uid) {
- max_found_uid = pwd->smb_userid;
- }
- }
-
- /* Ok - entry doesn't exist. We can add it */
-
- /* Create a new smb passwd entry and set it to the given password. */
- /*
- * The add user write needs to be atomic - so get the fd from
- * the fp and do a raw write() call.
- */
- fd = fileno(fp);
-
- if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1)
- {
- DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
+ /* Look for a free uid for use in non-unix accounts */
+ if (pwd->smb_userid > max_found_uid) {
+ max_found_uid = pwd->smb_userid;
+ }
+ }
+
+ /* Ok - entry doesn't exist. We can add it */
+
+ /* Create a new smb passwd entry and set it to the given password. */
+ /*
+ * The add user write needs to be atomic - so get the fd from
+ * the fp and do a raw write() call.
+ */
+ fd = fileno(fp);
+
+ if((offpos = sys_lseek(fd, 0, SEEK_END)) == -1) {
+ DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
- if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL)
- {
- DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
+ if((new_entry = format_new_smbpasswd_entry(newpwd)) == NULL) {
+ DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
- new_entry_length = strlen(new_entry);
+ new_entry_length = strlen(new_entry);
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|",
- fd, new_entry_length, new_entry));
+ DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|",
+ fd, new_entry_length, new_entry));
#endif
- if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length)
- {
- DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
+ if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
+ DEBUG(0, ("add_smbfilepwd_entry(write): %d Failed to add entry for user %s to file %s. \
Error was %s\n", wr_len, newpwd->smb_name, pfile, strerror(errno)));
- /* Remove the entry we just wrote. */
- if(sys_ftruncate(fd, offpos) == -1)
- {
- DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
+ /* Remove the entry we just wrote. */
+ if(sys_ftruncate(fd, offpos) == -1) {
+ DEBUG(0, ("add_smbfilepwd_entry: ERROR failed to ftruncate file %s. \
Error was %s. Password file may be corrupt ! Please examine by hand !\n",
- newpwd->smb_name, strerror(errno)));
- }
+ newpwd->smb_name, strerror(errno)));
+ }
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- free(new_entry);
- return False;
- }
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ free(new_entry);
+ return False;
+ }
- free(new_entry);
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return True;
+ free(new_entry);
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return True;
}
/************************************************************************
@@ -669,350 +686,356 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
{
- /* Static buffers we will return. */
+ /* Static buffers we will return. */
pstring user_name;
- char linebuf[256];
- char readbuf[1024];
- unsigned char c;
- fstring ascii_p16;
- fstring encode_bits;
- unsigned char *p = NULL;
- size_t linebuf_len = 0;
- FILE *fp;
- int lockfd;
- const char *pfile = smbpasswd_state->smbpasswd_file;
- BOOL found_entry = False;
- BOOL got_pass_last_set_time = False;
-
- SMB_OFF_T pwd_seekpos = 0;
-
- int i;
- int wr_len;
- int fd;
-
- if (!*pfile) {
- DEBUG(0, ("No SMB password file set\n"));
- return False;
- }
- DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
-
- fp = sys_fopen(pfile, "r+");
-
- if (fp == NULL) {
- DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
- return False;
- }
- /* Set a buffer to do more efficient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- lockfd = fileno(fp);
-
- if (!pw_file_lock(lockfd, F_WRLCK, 5, &(smbpasswd_state->pw_file_lock_depth))) {
- DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
- fclose(fp);
- return False;
- }
-
- /* Make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* We have a write lock on the file. */
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
- while (!feof(fp)) {
- pwd_seekpos = sys_ftell(fp);
-
- linebuf[0] = '\0';
-
- fgets(linebuf, sizeof(linebuf), fp);
- if (ferror(fp)) {
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- linebuf_len = strlen(linebuf);
- if (linebuf[linebuf_len - 1] != '\n') {
- c = '\0';
- while (!ferror(fp) && !feof(fp)) {
- c = fgetc(fp);
- if (c == '\n') {
- break;
- }
- }
- } else {
- linebuf[linebuf_len - 1] = '\0';
- }
+ char linebuf[256];
+ char readbuf[1024];
+ unsigned char c;
+ fstring ascii_p16;
+ fstring encode_bits;
+ unsigned char *p = NULL;
+ size_t linebuf_len = 0;
+ FILE *fp;
+ int lockfd;
+ const char *pfile = smbpasswd_state->smbpasswd_file;
+ BOOL found_entry = False;
+ BOOL got_pass_last_set_time = False;
+
+ SMB_OFF_T pwd_seekpos = 0;
+
+ int i;
+ int wr_len;
+ int fd;
+
+ if (!*pfile) {
+ DEBUG(0, ("No SMB password file set\n"));
+ return False;
+ }
+ DEBUG(10, ("mod_smbfilepwd_entry: opening file %s\n", pfile));
+
+ fp = sys_fopen(pfile, "r+");
+
+ if (fp == NULL) {
+ DEBUG(0, ("mod_smbfilepwd_entry: unable to open file %s\n", pfile));
+ return False;
+ }
+ /* Set a buffer to do more efficient reads */
+ setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
+
+ lockfd = fileno(fp);
+
+ if (!pw_file_lock(lockfd, F_WRLCK, 5, &smbpasswd_state->pw_file_lock_depth)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
+ fclose(fp);
+ return False;
+ }
+
+ /* Make sure it is only rw by the owner */
+ chmod(pfile, 0600);
+
+ /* We have a write lock on the file. */
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+ while (!feof(fp)) {
+ pwd_seekpos = sys_ftell(fp);
+
+ linebuf[0] = '\0';
+
+ fgets(linebuf, sizeof(linebuf), fp);
+ if (ferror(fp)) {
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /*
+ * Check if the string is terminated with a newline - if not
+ * then we must keep reading and discard until we get one.
+ */
+ linebuf_len = strlen(linebuf);
+ if (linebuf[linebuf_len - 1] != '\n') {
+ c = '\0';
+ while (!ferror(fp) && !feof(fp)) {
+ c = fgetc(fp);
+ if (c == '\n') {
+ break;
+ }
+ }
+ } else {
+ linebuf[linebuf_len - 1] = '\0';
+ }
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf));
+ DEBUG(100, ("mod_smbfilepwd_entry: got line |%s|\n", linebuf));
#endif
- if ((linebuf[0] == 0) && feof(fp)) {
- DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
- break;
- }
-
- /*
- * The line we have should be of the form :-
- *
- * username:uid:[32hex bytes]:....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
- *
- * if Windows NT compatible passwords are also present.
- */
-
- if (linebuf[0] == '#' || linebuf[0] == '\0') {
- DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
- continue;
- }
-
- p = (unsigned char *) strchr_m(linebuf, ':');
-
- if (p == NULL) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
- continue;
- }
-
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
-
- SMB_ASSERT(sizeof(user_name) > sizeof(linebuf));
-
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
- if (strequal(user_name, pwd->smb_name)) {
- found_entry = True;
- break;
- }
- }
-
- if (!found_entry) {
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
-
- DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n",
- pwd->smb_name));
- return False;
- }
-
- DEBUG(6, ("mod_smbfilepwd_entry: entry exists\n"));
-
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
-
- if (!isdigit(*p)) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n"));
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- while (*p && isdigit(*p))
- p++;
- if (*p != ':') {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n"));
- pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
- */
- p++;
-
- /* Record exact password position */
- pwd_seekpos += PTR_DIFF(p, linebuf);
-
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return (False);
- }
-
- if (p[32] != ':') {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return (False);
- }
-
- if (p[32] != ':') {
- DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /*
- * Now check if the account info and the password last
- * change time is available.
- */
- p += 33; /* Move to the first character of the line after
- the NT password. */
-
- if (*p == '[') {
-
- i = 0;
- encode_bits[i++] = *p++;
- while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']'))
- encode_bits[i++] = *p++;
-
- encode_bits[i++] = ']';
- encode_bits[i++] = '\0';
-
- if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) {
- /*
- * We are using a new format, space padded
- * acct ctrl field. Encode the given acct ctrl
- * bits into it.
- */
- fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
- } else {
- DEBUG(0,("mod_smbfilepwd_entry: Using old smbpasswd format. This is no longer supported.!\n"));
- DEBUG(0,("mod_smbfilepwd_entry: No changes made, failing.!\n"));
- return False;
- }
-
- /* Go past the ']' */
- if(linebuf_len > PTR_DIFF(p, linebuf))
- p++;
-
- if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
- p++;
-
- /* We should be pointing at the LCT entry. */
- if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
-
- p += 4;
- for(i = 0; i < 8; i++) {
- if(p[i] == '\0' || !isxdigit(p[i]))
- break;
- }
- if(i == 8) {
- /*
- * p points at 8 characters of hex digits -
- * read into a time_t as the seconds since
- * 1970 that the password was last changed.
- */
- got_pass_last_set_time = True;
- } /* i == 8 */
- } /* *p && StrnCaseCmp() */
- } /* p == ':' */
- } /* p == '[' */
-
- /* Entry is correctly formed. */
-
- /* Create the 32 byte representation of the new p16 */
- pdb_sethexpwd(ascii_p16, pwd->smb_passwd, pwd->acct_ctrl);
-
- /* Add on the NT md4 hash */
- ascii_p16[32] = ':';
- wr_len = 66;
- pdb_sethexpwd(ascii_p16+33, pwd->smb_nt_passwd, pwd->acct_ctrl);
- ascii_p16[65] = ':';
- ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */
-
- /* Add on the account info bits and the time of last
- password change. */
-
- if(got_pass_last_set_time) {
- slprintf(&ascii_p16[strlen(ascii_p16)],
- sizeof(ascii_p16)-(strlen(ascii_p16)+1),
- "%s:LCT-%08X:",
- encode_bits, (uint32)pwd->pass_last_set_time );
- wr_len = strlen(ascii_p16);
- }
+ if ((linebuf[0] == 0) && feof(fp)) {
+ DEBUG(4, ("mod_smbfilepwd_entry: end of file reached\n"));
+ break;
+ }
+
+ /*
+ * The line we have should be of the form :-
+ *
+ * username:uid:[32hex bytes]:....other flags presently
+ * ignored....
+ *
+ * or,
+ *
+ * username:uid:[32hex bytes]:[32hex bytes]:[attributes]:LCT-XXXXXXXX:...ignored.
+ *
+ * if Windows NT compatible passwords are also present.
+ */
+
+ if (linebuf[0] == '#' || linebuf[0] == '\0') {
+ DEBUG(6, ("mod_smbfilepwd_entry: skipping comment or blank line\n"));
+ continue;
+ }
+
+ p = (unsigned char *) strchr_m(linebuf, ':');
+
+ if (p == NULL) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no :)\n"));
+ continue;
+ }
+
+ /*
+ * As 256 is shorter than a pstring we don't need to check
+ * length here - if this ever changes....
+ */
+
+ SMB_ASSERT(sizeof(user_name) > sizeof(linebuf));
+
+ strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
+ user_name[PTR_DIFF(p, linebuf)] = '\0';
+ if (strequal(user_name, pwd->smb_name)) {
+ found_entry = True;
+ break;
+ }
+ }
+
+ if (!found_entry) {
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+
+ DEBUG(2, ("Cannot update entry for user %s, as they don't exist in the smbpasswd file!\n",
+ pwd->smb_name));
+ return False;
+ }
+
+ DEBUG(6, ("mod_smbfilepwd_entry: entry exists for user %s\n", pwd->smb_name));
+
+ /* User name matches - get uid and password */
+ p++; /* Go past ':' */
+
+ if (!isdigit(*p)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (uid not number)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ while (*p && isdigit(*p)) {
+ p++;
+ }
+ if (*p != ':') {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no : after uid)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /*
+ * Now get the password value - this should be 32 hex digits
+ * which are the ascii representations of a 16 byte string.
+ * Get two at a time and put them into the password.
+ */
+ p++;
+
+ /* Record exact password position */
+ pwd_seekpos += PTR_DIFF(p, linebuf);
+
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return (False);
+ }
+
+ if (p[32] != ':') {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /* Now check if the NT compatible password is available. */
+ p += 33; /* Move to the first character of the line after the lanman password. */
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (passwd too short)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return (False);
+ }
+
+ if (p[32] != ':') {
+ DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry for user %s (no terminating :)\n",
+ pwd->smb_name));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /*
+ * Now check if the account info and the password last
+ * change time is available.
+ */
+ p += 33; /* Move to the first character of the line after the NT password. */
+
+ if (*p == '[') {
+ i = 0;
+ encode_bits[i++] = *p++;
+ while((linebuf_len > PTR_DIFF(p, linebuf)) && (*p != ']')) {
+ encode_bits[i++] = *p++;
+ }
+
+ encode_bits[i++] = ']';
+ encode_bits[i++] = '\0';
+
+ if(i == NEW_PW_FORMAT_SPACE_PADDED_LEN) {
+ /*
+ * We are using a new format, space padded
+ * acct ctrl field. Encode the given acct ctrl
+ * bits into it.
+ */
+ fstrcpy(encode_bits, pdb_encode_acct_ctrl(pwd->acct_ctrl, NEW_PW_FORMAT_SPACE_PADDED_LEN));
+ } else {
+ DEBUG(0,("mod_smbfilepwd_entry: Using old smbpasswd format for user %s. \
+This is no longer supported.!\n", pwd->smb_name));
+ DEBUG(0,("mod_smbfilepwd_entry: No changes made, failing.!\n"));
+ pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /* Go past the ']' */
+ if(linebuf_len > PTR_DIFF(p, linebuf)) {
+ p++;
+ }
+
+ if((linebuf_len > PTR_DIFF(p, linebuf)) && (*p == ':')) {
+ p++;
+
+ /* We should be pointing at the LCT entry. */
+ if((linebuf_len > (PTR_DIFF(p, linebuf) + 13)) && (StrnCaseCmp((char *)p, "LCT-", 4) == 0)) {
+ p += 4;
+ for(i = 0; i < 8; i++) {
+ if(p[i] == '\0' || !isxdigit(p[i])) {
+ break;
+ }
+ }
+ if(i == 8) {
+ /*
+ * p points at 8 characters of hex digits -
+ * read into a time_t as the seconds since
+ * 1970 that the password was last changed.
+ */
+ got_pass_last_set_time = True;
+ } /* i == 8 */
+ } /* *p && StrnCaseCmp() */
+ } /* p == ':' */
+ } /* p == '[' */
+
+ /* Entry is correctly formed. */
+
+ /* Create the 32 byte representation of the new p16 */
+ pdb_sethexpwd(ascii_p16, pwd->smb_passwd, pwd->acct_ctrl);
+
+ /* Add on the NT md4 hash */
+ ascii_p16[32] = ':';
+ wr_len = 66;
+ pdb_sethexpwd(ascii_p16+33, pwd->smb_nt_passwd, pwd->acct_ctrl);
+ ascii_p16[65] = ':';
+ ascii_p16[66] = '\0'; /* null-terminate the string so that strlen works */
+
+ /* Add on the account info bits and the time of last password change. */
+ if(got_pass_last_set_time) {
+ slprintf(&ascii_p16[strlen(ascii_p16)],
+ sizeof(ascii_p16)-(strlen(ascii_p16)+1),
+ "%s:LCT-%08X:",
+ encode_bits, (uint32)pwd->pass_last_set_time );
+ wr_len = strlen(ascii_p16);
+ }
#ifdef DEBUG_PASSWORD
- DEBUG(100,("mod_smbfilepwd_entry: "));
- dump_data(100, ascii_p16, wr_len);
+ DEBUG(100,("mod_smbfilepwd_entry: "));
+ dump_data(100, ascii_p16, wr_len);
#endif
- if(wr_len > sizeof(linebuf)) {
- DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return (False);
- }
-
- /*
- * Do an atomic write into the file at the position defined by
- * seekpos.
- */
-
- /* The mod user write needs to be atomic - so get the fd from
- the fp and do a raw write() call.
- */
-
- fd = fileno(fp);
-
- if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
- DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- /* Sanity check - ensure the areas we are writing are framed by ':' */
- if (read(fd, linebuf, wr_len+1) != wr_len+1) {
- DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) {
- DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
+ if(wr_len > sizeof(linebuf)) {
+ DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return (False);
+ }
+
+ /*
+ * Do an atomic write into the file at the position defined by
+ * seekpos.
+ */
+
+ /* The mod user write needs to be atomic - so get the fd from
+ the fp and do a raw write() call.
+ */
+
+ fd = fileno(fp);
+
+ if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
+ DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ /* Sanity check - ensure the areas we are writing are framed by ':' */
+ if (read(fd, linebuf, wr_len+1) != wr_len+1) {
+ DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) {
+ DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
- if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
- DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- if (write(fd, ascii_p16, wr_len) != wr_len) {
- DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return False;
- }
-
- pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
- fclose(fp);
- return True;
+ if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
+ DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ if (write(fd, ascii_p16, wr_len) != wr_len) {
+ DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return False;
+ }
+
+ pw_file_unlock(lockfd,&smbpasswd_state->pw_file_lock_depth);
+ fclose(fp);
+ return True;
}
/************************************************************************
@@ -1022,100 +1045,97 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
{
const char *pfile = smbpasswd_state->smbpasswd_file;
- pstring pfile2;
- struct smb_passwd *pwd = NULL;
- FILE *fp = NULL;
- FILE *fp_write = NULL;
- int pfile2_lockdepth = 0;
-
- slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)sys_getpid() );
-
- /*
- * Open the smbpassword file - for update. It needs to be update
- * as we need any other processes to wait until we have replaced
- * it.
- */
-
- if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth))) == NULL) {
- DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
- return False;
- }
-
- /*
- * Create the replacement password file.
- */
- if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
- DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- return False;
- }
-
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
-
- while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
- char *new_entry;
- size_t new_entry_length;
-
- if (strequal(name, pwd->smb_name)) {
- DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
- continue;
- }
-
- /*
- * We need to copy the entry out into the second file.
- */
-
- if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL)
- {
- DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
+ pstring pfile2;
+ struct smb_passwd *pwd = NULL;
+ FILE *fp = NULL;
+ FILE *fp_write = NULL;
+ int pfile2_lockdepth = 0;
+
+ slprintf(pfile2, sizeof(pfile2)-1, "%s.%u", pfile, (unsigned)sys_getpid() );
+
+ /*
+ * Open the smbpassword file - for update. It needs to be update
+ * as we need any other processes to wait until we have replaced
+ * it.
+ */
+
+ if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &smbpasswd_state->pw_file_lock_depth)) == NULL) {
+ DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
+ return False;
+ }
+
+ /*
+ * Create the replacement password file.
+ */
+ if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
+ DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ return False;
+ }
+
+ /*
+ * Scan the file, a line at a time and check if the name matches.
+ */
+
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
+ char *new_entry;
+ size_t new_entry_length;
+
+ if (strequal(name, pwd->smb_name)) {
+ DEBUG(10, ("add_smbfilepwd_entry: found entry with name %s - deleting it.\n", name));
+ continue;
+ }
+
+ /*
+ * We need to copy the entry out into the second file.
+ */
+
+ if((new_entry = format_new_smbpasswd_entry(pwd)) == NULL) {
+ DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
- unlink(pfile2);
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write, &pfile2_lockdepth);
- return False;
- }
+ unlink(pfile2);
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write, &pfile2_lockdepth);
+ return False;
+ }
- new_entry_length = strlen(new_entry);
+ new_entry_length = strlen(new_entry);
- if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length)
- {
- DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
+ if(fwrite(new_entry, 1, new_entry_length, fp_write) != new_entry_length) {
+ DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
- unlink(pfile2);
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write, &pfile2_lockdepth);
- free(new_entry);
- return False;
- }
+ unlink(pfile2);
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write, &pfile2_lockdepth);
+ free(new_entry);
+ return False;
+ }
- free(new_entry);
- }
+ free(new_entry);
+ }
- /*
- * Ensure pfile2 is flushed before rename.
- */
+ /*
+ * Ensure pfile2 is flushed before rename.
+ */
- if(fflush(fp_write) != 0)
- {
- DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write,&pfile2_lockdepth);
- return False;
- }
+ if(fflush(fp_write) != 0) {
+ DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write,&pfile2_lockdepth);
+ return False;
+ }
- /*
- * Do an atomic rename - then release the locks.
- */
+ /*
+ * Do an atomic rename - then release the locks.
+ */
- if(rename(pfile2,pfile) != 0) {
- unlink(pfile2);
- }
+ if(rename(pfile2,pfile) != 0) {
+ unlink(pfile2);
+ }
- endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
- endsmbfilepwent(fp_write,&pfile2_lockdepth);
- return True;
+ endsmbfilepwent(fp, &smbpasswd_state->pw_file_lock_depth);
+ endsmbfilepwent(fp_write,&pfile2_lockdepth);
+ return True;
}
/*********************************************************************
@@ -1123,6 +1143,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
We will not allocate any new memory. The smb_passwd struct
should only stay around as long as the SAM_ACCOUNT does.
********************************************************************/
+
static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass)
{
uint32 rid;
@@ -1166,6 +1187,7 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
/*********************************************************************
Create a SAM_ACCOUNT from a smb_passwd struct
********************************************************************/
+
static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf)
{
@@ -1203,6 +1225,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
/*****************************************************************
Functions to be implemented by the new passdb API
****************************************************************/
+
static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL update)
{
struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
@@ -1212,15 +1235,13 @@ static NTSTATUS smbpasswd_setsampwent (struct pdb_methods *my_methods, BOOL upda
&(smbpasswd_state->pw_file_lock_depth));
/* did we fail? Should we try to create it? */
- if (!smbpasswd_state->pw_file && update && errno == ENOENT)
- {
+ if (!smbpasswd_state->pw_file && update && errno == ENOENT) {
FILE *fp;
/* slprintf(msg_str,msg_str_len-1,
"smbpasswd file did not exist - attempting to create it.\n"); */
DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w");
- if (fp)
- {
+ if (fp) {
fprintf(fp, "# Samba SMB password file\n");
fclose(fp);
}
@@ -1244,6 +1265,7 @@ static void smbpasswd_endsampwent (struct pdb_methods *my_methods)
/*****************************************************************
****************************************************************/
+
static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -1260,8 +1282,7 @@ static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUN
return nt_status;
}
- while (!done)
- {
+ while (!done) {
/* do we have an entry? */
pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
if (pw_buf == NULL)
@@ -1280,12 +1301,12 @@ static NTSTATUS smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUN
return NT_STATUS_OK;
}
-
/****************************************************************
Search smbpasswd file by iterating over the entries. Do not
call getpwnam() for unix account information until we have found
the correct entry
***************************************************************/
+
static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods,
SAM_ACCOUNT *sam_acct, const char *username)
{
diff --git a/source/passdb/pdb_xml.c b/source/passdb/pdb_xml.c
index 64cb73ba5a4..6eff57d365e 100644
--- a/source/passdb/pdb_xml.c
+++ b/source/passdb/pdb_xml.c
@@ -40,6 +40,27 @@ static int xmlsam_debug_level = DBGC_ALL;
#undef DBGC_CLASS
#define DBGC_CLASS xmlsam_debug_level
+
+/* Helper utilities for charset conversion */
+static xmlNodePtr smbXmlNewChild(xmlNodePtr prnt, xmlNsPtr ns, const xmlChar *name, const char *content)
+{
+ char *string_utf8;
+ xmlNodePtr ret;
+
+ if(!content) return xmlNewChild(prnt, ns, name, NULL);
+
+
+ if(push_utf8_allocate(&string_utf8,content) == (size_t)-1)
+ return NULL;
+
+ ret = xmlNewTextChild(prnt, ns, name, string_utf8);
+
+ SAFE_FREE(string_utf8);
+
+ return ret;
+}
+
+
static char * iota(int a) {
static char tmp[10];
@@ -394,72 +415,72 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT
root = xmlNewDocNode(data->doc, NULL, "samba", NULL);
cur = xmlDocSetRootElement(data->doc, root);
data->ns = xmlNewNs(root, XML_URL, "samba");
- data->users = xmlNewChild(root, data->ns, "users", NULL);
+ data->users = smbXmlNewChild(root, data->ns, "users", NULL);
}
- user = xmlNewChild(data->users, data->ns, "user", NULL);
+ user = smbXmlNewChild(data->users, data->ns, "user", NULL);
xmlNewProp(user, "sid",
sid_to_string(sid_str, pdb_get_user_sid(u)));
if (pdb_get_username(u) && strcmp(pdb_get_username(u), ""))
xmlNewProp(user, "name", pdb_get_username(u));
- cur = xmlNewChild(user, data->ns, "group", NULL);
+ cur = smbXmlNewChild(user, data->ns, "group", NULL);
xmlNewProp(cur, "sid",
sid_to_string(sid_str, pdb_get_group_sid(u)));
if (pdb_get_init_flags(u, PDB_LOGONTIME) != PDB_DEFAULT)
- xmlNewChild(user, data->ns, "logon_time",
+ smbXmlNewChild(user, data->ns, "logon_time",
iota(pdb_get_logon_time(u)));
if (pdb_get_init_flags(u, PDB_LOGOFFTIME) != PDB_DEFAULT)
- xmlNewChild(user, data->ns, "logoff_time",
+ smbXmlNewChild(user, data->ns, "logoff_time",
iota(pdb_get_logoff_time(u)));
if (pdb_get_init_flags(u, PDB_KICKOFFTIME) != PDB_DEFAULT)
- xmlNewChild(user, data->ns, "kickoff_time",
+ smbXmlNewChild(user, data->ns, "kickoff_time",
iota(pdb_get_kickoff_time(u)));
if (pdb_get_domain(u) && strcmp(pdb_get_domain(u), ""))
- xmlNewChild(user, data->ns, "domain", pdb_get_domain(u));
+ smbXmlNewChild(user, data->ns, "domain", pdb_get_domain(u));
if (pdb_get_nt_username(u) && strcmp(pdb_get_nt_username(u), ""))
- xmlNewChild(user, data->ns, "nt_username", pdb_get_nt_username(u));
+ smbXmlNewChild(user, data->ns, "nt_username", pdb_get_nt_username(u));
if (pdb_get_fullname(u) && strcmp(pdb_get_fullname(u), ""))
- xmlNewChild(user, data->ns, "fullname", pdb_get_fullname(u));
+ smbXmlNewChild(user, data->ns, "fullname", pdb_get_fullname(u));
if (pdb_get_homedir(u) && strcmp(pdb_get_homedir(u), ""))
- xmlNewChild(user, data->ns, "homedir", pdb_get_homedir(u));
+ smbXmlNewChild(user, data->ns, "homedir", pdb_get_homedir(u));
if (pdb_get_dir_drive(u) && strcmp(pdb_get_dir_drive(u), ""))
- xmlNewChild(user, data->ns, "dir_drive", pdb_get_dir_drive(u));
+ smbXmlNewChild(user, data->ns, "dir_drive", pdb_get_dir_drive(u));
if (pdb_get_logon_script(u) && strcmp(pdb_get_logon_script(u), ""))
- xmlNewChild(user, data->ns, "logon_script",
+ smbXmlNewChild(user, data->ns, "logon_script",
pdb_get_logon_script(u));
if (pdb_get_profile_path(u) && strcmp(pdb_get_profile_path(u), ""))
- xmlNewChild(user, data->ns, "profile_path",
+ smbXmlNewChild(user, data->ns, "profile_path",
pdb_get_profile_path(u));
if (pdb_get_acct_desc(u) && strcmp(pdb_get_acct_desc(u), ""))
- xmlNewChild(user, data->ns, "acct_desc", pdb_get_acct_desc(u));
+ smbXmlNewChild(user, data->ns, "acct_desc", pdb_get_acct_desc(u));
if (pdb_get_workstations(u) && strcmp(pdb_get_workstations(u), ""))
- xmlNewChild(user, data->ns, "workstations",
+ smbXmlNewChild(user, data->ns, "workstations",
pdb_get_workstations(u));
if (pdb_get_unknown_str(u) && strcmp(pdb_get_unknown_str(u), ""))
- xmlNewChild(user, data->ns, "unknown_str", pdb_get_unknown_str(u));
+ smbXmlNewChild(user, data->ns, "unknown_str", pdb_get_unknown_str(u));
if (pdb_get_munged_dial(u) && strcmp(pdb_get_munged_dial(u), ""))
- xmlNewChild(user, data->ns, "munged_dial", pdb_get_munged_dial(u));
+ smbXmlNewChild(user, data->ns, "munged_dial", pdb_get_munged_dial(u));
/* Password stuff */
- pass = xmlNewChild(user, data->ns, "password", NULL);
+ pass = smbXmlNewChild(user, data->ns, "password", NULL);
if (pdb_get_pass_last_set_time(u))
xmlNewProp(pass, "last_set", iota(pdb_get_pass_last_set_time(u)));
if (pdb_get_init_flags(u, PDB_CANCHANGETIME) != PDB_DEFAULT)
@@ -474,29 +495,29 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT
if (pdb_get_lanman_passwd(u)) {
pdb_sethexpwd(temp, pdb_get_lanman_passwd(u),
pdb_get_acct_ctrl(u));
- cur = xmlNewChild(pass, data->ns, "crypt", temp);
+ cur = smbXmlNewChild(pass, data->ns, "crypt", temp);
xmlNewProp(cur, "type", "lanman");
}
if (pdb_get_nt_passwd(u)) {
pdb_sethexpwd(temp, pdb_get_nt_passwd(u), pdb_get_acct_ctrl(u));
- cur = xmlNewChild(pass, data->ns, "crypt", temp);
+ cur = smbXmlNewChild(pass, data->ns, "crypt", temp);
xmlNewProp(cur, "type", "nt");
}
- xmlNewChild(user, data->ns, "acct_ctrl", iota(pdb_get_acct_ctrl(u)));
+ smbXmlNewChild(user, data->ns, "acct_ctrl", iota(pdb_get_acct_ctrl(u)));
if (pdb_get_logon_divs(u))
- xmlNewChild(user, data->ns, "logon_divs",
+ smbXmlNewChild(user, data->ns, "logon_divs",
iota(pdb_get_logon_divs(u)));
if (pdb_get_hours_len(u))
- xmlNewChild(user, data->ns, "hours_len",
+ smbXmlNewChild(user, data->ns, "hours_len",
iota(pdb_get_hours_len(u)));
- xmlNewChild(user, data->ns, "bad_password_count", iota(pdb_get_bad_password_count(u)));
- xmlNewChild(user, data->ns, "logon_count", iota(pdb_get_logon_count(u)));
- xmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u)));
+ smbXmlNewChild(user, data->ns, "bad_password_count", iota(pdb_get_bad_password_count(u)));
+ smbXmlNewChild(user, data->ns, "logon_count", iota(pdb_get_logon_count(u)));
+ smbXmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u)));
xmlSaveFile(data->location, data->doc);
return NT_STATUS_OK;
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 7850924aacb..c3551c9d90a 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -209,6 +209,7 @@ struct table_node {
#define SPL_ARCH_W32MIPS "W32MIPS"
#define SPL_ARCH_W32ALPHA "W32ALPHA"
#define SPL_ARCH_W32PPC "W32PPC"
+#define SPL_ARCH_IA64 "IA64"
static const struct table_node archi_table[]= {
@@ -217,6 +218,7 @@ static const struct table_node archi_table[]= {
{"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
{"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
{"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
+ {"Windows IA64", SPL_ARCH_IA64, 3 },
{NULL, "", -1 }
};
diff --git a/source/rpc_client/cli_spoolss.c b/source/rpc_client/cli_spoolss.c
index 8f5f2413dee..5303f83bf9c 100644
--- a/source/rpc_client/cli_spoolss.c
+++ b/source/rpc_client/cli_spoolss.c
@@ -132,6 +132,27 @@ static void decode_printer_info_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
/**********************************************************************
**********************************************************************/
+static void decode_printer_info_7(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
+ uint32 returned, PRINTER_INFO_7 **info)
+{
+ uint32 i;
+ PRINTER_INFO_7 *inf;
+
+ inf=(PRINTER_INFO_7 *)talloc(mem_ctx, returned*sizeof(PRINTER_INFO_7));
+ memset(inf, 0, returned*sizeof(PRINTER_INFO_7));
+
+ prs_set_offset(&buffer->prs,0);
+
+ for (i=0; i<returned; i++) {
+ smb_io_printer_info_7("", buffer, &inf[i], 0);
+ }
+
+ *info=inf;
+}
+
+
+/**********************************************************************
+**********************************************************************/
static void decode_port_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer,
uint32 returned, PORT_INFO_1 **info)
{
@@ -626,6 +647,9 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
case 3:
decode_printer_info_3(mem_ctx, r.buffer, 1, &ctr->printers_3);
break;
+ case 7:
+ decode_printer_info_7(mem_ctx, r.buffer, 1, &ctr->printers_7);
+ break;
}
}
diff --git a/source/rpc_client/cli_srvsvc.c b/source/rpc_client/cli_srvsvc.c
index 68eb17074f6..f8580d0fe2e 100644
--- a/source/rpc_client/cli_srvsvc.c
+++ b/source/rpc_client/cli_srvsvc.c
@@ -269,7 +269,8 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
const char *netname, uint32 type,
const char *remark, uint32 perms,
uint32 max_uses, uint32 num_uses,
- const char *path, const char *passwd)
+ const char *path, const char *passwd,
+ int level, SEC_DESC *sd)
{
prs_struct qbuf, rbuf;
SRV_Q_NET_SHARE_ADD q;
@@ -285,7 +286,8 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
- perms, max_uses, num_uses, path, passwd);
+ perms, max_uses, num_uses, path, passwd,
+ level, sd);
/* Marshall data and send request */
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index b42b9b2a8b4..813316177ac 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -2399,11 +2399,9 @@ static BOOL net_io_sam_alias_info(const char *desc, SAM_ALIAS_INFO * info,
info->hdr_sec_desc.buffer, ps, depth))
return False;
- if (info->hdr_als_desc.buffer != 0) {
- if (!smb_io_unistr2("uni_als_desc", &info->uni_als_desc,
- info->hdr_als_name.buffer, ps, depth))
- return False;
- }
+ if (!smb_io_unistr2("uni_als_desc", &info->uni_als_desc,
+ info->hdr_als_desc.buffer, ps, depth))
+ return False;
return True;
}
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index ae087c7f774..2b2038d16ac 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -1053,6 +1053,54 @@ BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2
return True;
}
+/*******************************************************************
+create a SPOOL_PRINTER_INFO_3 struct from a PRINTER_INFO_3 struct
+*******************************************************************/
+
+BOOL make_spoolss_printer_info_3(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3 **spool_info3,
+ PRINTER_INFO_3 *info)
+{
+
+ SPOOL_PRINTER_INFO_LEVEL_3 *inf;
+
+ /* allocate the necessary memory */
+ if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_3*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_3)))) {
+ DEBUG(0,("make_spoolss_printer_info_3: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_3 sruct!\n"));
+ return False;
+ }
+
+ inf->secdesc_ptr = (info->secdesc!=NULL)?1:0;
+
+ *spool_info3 = inf;
+
+ return True;
+}
+
+/*******************************************************************
+create a SPOOL_PRINTER_INFO_7 struct from a PRINTER_INFO_7 struct
+*******************************************************************/
+
+BOOL make_spoolss_printer_info_7(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7 **spool_info7,
+ PRINTER_INFO_7 *info)
+{
+
+ SPOOL_PRINTER_INFO_LEVEL_7 *inf;
+
+ /* allocate the necessary memory */
+ if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_7*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_7)))) {
+ DEBUG(0,("make_spoolss_printer_info_7: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_7 struct!\n"));
+ return False;
+ }
+
+ inf->guid_ptr = (info->guid.buffer!=NULL)?1:0;
+ inf->action = info->action;
+ init_unistr2_from_unistr(&inf->guid, &info->guid);
+
+ *spool_info7 = inf;
+
+ return True;
+}
+
/*******************************************************************
* read a structure.
@@ -4113,6 +4161,24 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
q_u->devmode_ctr.devmode = NULL;
#endif
break;
+ case 3:
+ secdesc = info->printers_3->secdesc;
+
+ make_spoolss_printer_info_3 (mem_ctx, &q_u->info.info_3, info->printers_3);
+
+ q_u->secdesc_ctr = (SEC_DESC_BUF*)malloc(sizeof(SEC_DESC_BUF));
+ if (!q_u->secdesc_ctr)
+ return False;
+ q_u->secdesc_ctr->ptr = (secdesc != NULL) ? 1: 0;
+ q_u->secdesc_ctr->max_len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
+ q_u->secdesc_ctr->len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
+ q_u->secdesc_ctr->sec = secdesc;
+
+ break;
+ case 7:
+ make_spoolss_printer_info_7 (mem_ctx, &q_u->info.info_7, info->printers_7);
+ break;
+
default:
DEBUG(0,("make_spoolss_q_setprinter: Unknown info level [%d]\n", level));
break;
@@ -7358,7 +7424,7 @@ BOOL spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX
if (!prs_set_offset(ps, end_offset))
return False;
- return True;
+ return True;
}
/*******************************************************************
diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c
index 6349fc16325..8313c82c93d 100644
--- a/source/rpc_parse/parse_srv.c
+++ b/source/rpc_parse/parse_srv.c
@@ -1456,19 +1456,38 @@ BOOL srv_io_q_net_share_add(const char *desc, SRV_Q_NET_SHARE_ADD *q_n, prs_stru
void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, const char *srvname,
const char *netname, uint32 type, const char *remark,
uint32 perms, uint32 max_uses, uint32 num_uses,
- const char *path, const char *passwd)
-{
- q->ptr_srv_name = 1;
- init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
- q->info.switch_value = q->info_level = 2;
-
- q->info.ptr_share_ctr = 1;
- init_srv_share_info2(&q->info.share.info2.info_2, netname, type,
- remark, perms, max_uses, num_uses, path, passwd);
- init_srv_share_info2_str(&q->info.share.info2.info_2_str, netname,
- remark, path, passwd);
- q->ptr_err_index = 1;
- q->err_index = 0;
+ const char *path, const char *passwd,
+ int level, SEC_DESC *sd)
+{
+ switch(level) {
+ case 502: {
+ size_t sd_size = sec_desc_size(sd);
+ q->ptr_srv_name = 1;
+ init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
+ q->info.switch_value = q->info_level = level;
+ q->info.ptr_share_ctr = 1;
+ init_srv_share_info502(&q->info.share.info502.info_502, netname, type,
+ remark, perms, max_uses, num_uses, path, passwd, sd, sd_size);
+ init_srv_share_info502_str(&q->info.share.info502.info_502_str, netname,
+ remark, path, passwd, sd, sd_size);
+ q->ptr_err_index = 1;
+ q->err_index = 0;
+ }
+ break;
+ case 2:
+ default:
+ q->ptr_srv_name = 1;
+ init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE);
+ q->info.switch_value = q->info_level = level;
+ q->info.ptr_share_ctr = 1;
+ init_srv_share_info2(&q->info.share.info2.info_2, netname, type,
+ remark, perms, max_uses, num_uses, path, passwd);
+ init_srv_share_info2_str(&q->info.share.info2.info_2_str, netname,
+ remark, path, passwd);
+ q->ptr_err_index = 1;
+ q->err_index = 0;
+ break;
+ }
}
diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c
index b5871a7e56d..3e0762fa43b 100644
--- a/source/rpc_server/srv_netlog_nt.c
+++ b/source/rpc_server/srv_netlog_nt.c
@@ -445,6 +445,7 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
unsigned char pwd[16];
int i;
uint32 acct_ctrl;
+ const uchar *old_pw;
/* checks and updates credentials. creates reply credentials */
if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)))
@@ -482,34 +483,43 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
return NT_STATUS_ACCOUNT_DISABLED;
}
+ cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
+
DEBUG(100,("Server password set : new given value was :\n"));
for(i = 0; i < 16; i++)
DEBUG(100,("%02X ", q_u->pwd[i]));
DEBUG(100,("\n"));
- cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
+ old_pw = pdb_get_nt_passwd(sampass);
- /* lies! nt and lm passwords are _not_ the same: don't care */
- if (!pdb_set_lanman_passwd (sampass, pwd, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
- return NT_STATUS_NO_MEMORY;
- }
+ if (old_pw && memcmp(pwd, old_pw, 16) == 0) {
+ /* Avoid backend modificiations and other fun if the
+ client changed the password to the *same thing* */
- if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) {
- pdb_free_sam(&sampass);
- return NT_STATUS_NO_MEMORY;
- }
+ ret = True;
+ } else {
- if (!pdb_set_pass_changed_now (sampass)) {
- pdb_free_sam(&sampass);
- /* Not quite sure what this one qualifies as, but this will do */
- return NT_STATUS_UNSUCCESSFUL;
+ /* LM password should be NULL for machines */
+ if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) {
+ pdb_free_sam(&sampass);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) {
+ pdb_free_sam(&sampass);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!pdb_set_pass_changed_now (sampass)) {
+ pdb_free_sam(&sampass);
+ /* Not quite sure what this one qualifies as, but this will do */
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ become_root();
+ ret = pdb_update_sam_account (sampass);
+ unbecome_root();
}
-
- become_root();
- ret = pdb_update_sam_account (sampass);
- unbecome_root();
-
if (ret)
status = NT_STATUS_OK;
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index ce6d9dd37ec..37617db5e8f 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -728,7 +728,17 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN
for (i = 0; i < num_entries; i++) {
pwd = &disp_user_info[i+start_idx];
temp_name = pdb_get_username(pwd);
- init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE);
+
+ /*
+ * usrmgr expects a non-NULL terminated string with
+ * trust relationships
+ */
+ if (pdb_get_acct_ctrl(pwd) & ACB_DOMTRUST) {
+ init_unistr2(&uni_temp_name, temp_name, UNI_FLAGS_NONE);
+ } else {
+ init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE);
+ }
+
user_sid = pdb_get_user_sid(pwd);
if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) {
@@ -2240,7 +2250,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
if (*add_script) {
int add_ret;
- all_string_sub(add_script, "%u", account, sizeof(account));
+ all_string_sub(add_script, "%u", account, sizeof(add_script));
add_ret = smbrun(add_script,NULL);
DEBUG(3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
}
@@ -3626,7 +3636,7 @@ static int smb_delete_user(const char *unix_user)
pstrcpy(del_script, lp_deluser_script());
if (! *del_script)
return -1;
- all_string_sub(del_script, "%u", unix_user, sizeof(pstring));
+ all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
ret = smbrun(del_script,NULL);
DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
@@ -3665,7 +3675,14 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
return NT_STATUS_NO_SUCH_USER;
}
- /* delete the unix side */
+ /* First delete the samba side */
+ if (!pdb_delete_sam_account(sam_pass)) {
+ DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
+ pdb_free_sam(&sam_pass);
+ return NT_STATUS_CANNOT_DELETE;
+ }
+
+ /* Now delete the unix side */
/*
* note: we don't check if the delete really happened
* as the script is not necessary present
@@ -3673,13 +3690,7 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
*/
smb_delete_user(pdb_get_username(sam_pass));
- /* and delete the samba side */
- if (!pdb_delete_sam_account(sam_pass)) {
- DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass)));
- pdb_free_sam(&sam_pass);
- return NT_STATUS_CANNOT_DELETE;
- }
-
+
pdb_free_sam(&sam_pass);
if (!close_policy_hnd(p, &q_u->user_pol))
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index 812939ddf50..d50237905ae 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -64,14 +64,14 @@ struct table_node {
static Printer_entry *printers_list;
typedef struct _counter_printer_0 {
- ubi_dlNode Next;
- ubi_dlNode Prev;
+ struct _counter_printer_0 *next;
+ struct _counter_printer_0 *prev;
int snum;
uint32 counter;
} counter_printer_0;
-static ubi_dlList counter_list;
+static counter_printer_0 *counter_list;
static struct cli_state notify_cli; /* print notify back-channel */
static uint32 smb_connections=0;
@@ -1982,6 +1982,7 @@ static int get_version_id (char * arch)
{"Windows NT R4000", "W32MIPS", 2 },
{"Windows NT Alpha_AXP", "W32ALPHA", 2 },
{"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
{NULL, "", -1 }
};
@@ -3948,9 +3949,7 @@ static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *p
count = print_queue_length(snum, &status);
/* check if we already have a counter for this printer */
- session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
-
- for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
+ for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
if (session_counter->snum == snum)
break;
}
@@ -3964,7 +3963,7 @@ static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *p
ZERO_STRUCTP(session_counter);
session_counter->snum=snum;
session_counter->counter=0;
- ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
+ DLIST_ADD(counter_list, session_counter);
}
/* increment it */
@@ -6238,6 +6237,7 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET
DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
uint32 command = q_u->command;
+ WERROR result;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
@@ -6251,7 +6251,12 @@ WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SET
case 0:
return control_printer(handle, command, p);
case 2:
- return update_printer(p, handle, level, info, devmode_ctr.devmode);
+ result = update_printer(p, handle, level, info, devmode_ctr.devmode);
+ if (!W_ERROR_IS_OK(result))
+ return result;
+ if (secdesc_ctr)
+ result = update_printer_sec(handle, level, info, p, secdesc_ctr);
+ return result;
case 3:
return update_printer_sec(handle, level, info, p,
secdesc_ctr);
diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c
index 5fa59e1903b..e99cd9f9056 100644
--- a/source/rpcclient/cmd_spoolss.c
+++ b/source/rpcclient/cmd_spoolss.c
@@ -39,6 +39,7 @@ static const struct table_node archi_table[]= {
{"Windows NT R4000", "W32MIPS", 2 },
{"Windows NT Alpha_AXP", "W32ALPHA", 2 },
{"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
{NULL, "", -1 }
};
@@ -296,6 +297,18 @@ static void display_print_info_3(PRINTER_INFO_3 *i3)
printf("\n");
}
+/****************************************************************************
+printer info level 7 display function
+****************************************************************************/
+static void display_print_info_7(PRINTER_INFO_7 *i7)
+{
+ fstring guid = "";
+ rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
+ printf("\tguid:[%s]\n", guid);
+ printf("\taction:[0x%x]\n", i7->action);
+}
+
+
/* Enumerate printers */
static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
@@ -686,6 +699,9 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
case 3:
display_print_info_3(ctr.printers_3);
break;
+ case 7:
+ display_print_info_7(ctr.printers_7);
+ break;
default:
printf("unknown info level %d\n", info_level);
break;
@@ -1126,6 +1142,13 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
cli, mem_ctx, needed, NULL, info_level,
archi_table[i].long_archi, &returned, &ctr);
+ if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
+ printf ("Server does not support environment [%s]\n",
+ archi_table[i].long_archi);
+ werror = WERR_OK;
+ continue;
+ }
+
if (returned == 0)
continue;
diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk
index 4c9507dcf9b..4edc7abc63a 100644
--- a/source/script/mkproto.awk
+++ b/source/script/mkproto.awk
@@ -132,7 +132,7 @@ END {
gotstart = 1;
}
- if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP/ ) {
+ if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2|^LOGIN_CACHE|^krb5_error_code|^LDAP|^u32/ ) {
gotstart = 1;
}
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index 3983a4cbdfb..e143999a785 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -27,8 +27,9 @@ extern char *OutBuffer;
notify. It consists of the requesting SMB and the expiry time.
*****************************************************************************/
-typedef struct {
- ubi_slNode msg_next;
+typedef struct _blocking_lock_record {
+ struct _blocking_lock_record *next;
+ struct _blocking_lock_record *prev;
int com_type;
files_struct *fsp;
time_t expire_time;
@@ -40,7 +41,7 @@ typedef struct {
int length;
} blocking_lock_record;
-static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0};
+static blocking_lock_record *blocking_lock_queue;
/****************************************************************************
Destructor for the above structure.
@@ -48,6 +49,7 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu
static void free_blocking_lock_record(blocking_lock_record *blr)
{
+ DLIST_REMOVE(blocking_lock_queue, blr);
SAFE_FREE(blr->inbuf);
SAFE_FREE(blr);
}
@@ -90,7 +92,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count)
{
static BOOL set_lock_msg;
- blocking_lock_record *blr;
+ blocking_lock_record *blr, *tmp;
BOOL my_lock_ctx = False;
NTSTATUS status;
@@ -136,7 +138,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
return False;
}
- ubi_slAddTail(&blocking_lock_queue, blr);
+ DLIST_ADD_END(blocking_lock_queue, blr, tmp);
/* Ensure we'll receive messages when this is unlocked. */
if (!set_lock_msg) {
@@ -516,10 +518,10 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr)
void remove_pending_lock_requests_by_fid(files_struct *fsp)
{
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
- blocking_lock_record *prev = NULL;
+ blocking_lock_record *blr, *next = NULL;
- while(blr != NULL) {
+ for(blr = blocking_lock_queue; blr; blr = next) {
+ next = blr->next;
if(blr->fsp->fnum == fsp->fnum) {
DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \
@@ -529,13 +531,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
- continue;
+ free_blocking_lock_record(blr);
}
-
- prev = blr;
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
}
@@ -545,10 +542,10 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
void remove_pending_lock_requests_by_mid(int mid)
{
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
- blocking_lock_record *prev = NULL;
+ blocking_lock_record *blr, *next = NULL;
- while(blr != NULL) {
+ for(blr = blocking_lock_queue; blr; blr = next) {
+ next = blr->next;
if(SVAL(blr->inbuf,smb_mid) == mid) {
files_struct *fsp = blr->fsp;
@@ -559,13 +556,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
- continue;
+ free_blocking_lock_record(blr);
}
-
- prev = blr;
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
}
@@ -587,7 +579,7 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
{
unsigned timeout = default_timeout;
time_t t;
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue);
+ blocking_lock_record *blr = blocking_lock_queue;
/* note that we avoid the time() syscall if there are no blocking locks */
if (!blr)
@@ -595,12 +587,11 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
t = time(NULL);
- while (blr) {
+ for (; blr; blr = blr->next) {
if ((blr->expire_time != (time_t)-1) &&
(timeout > (blr->expire_time - t))) {
timeout = blr->expire_time - t;
}
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
if (timeout < 1)
@@ -615,21 +606,19 @@ unsigned blocking_locks_timeout(unsigned default_timeout)
void process_blocking_lock_queue(time_t t)
{
- blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
- blocking_lock_record *prev = NULL;
-
- if(blr == NULL)
- return;
+ blocking_lock_record *blr, *next = NULL;
/*
* Go through the queue and see if we can get any of the locks.
*/
- while(blr != NULL) {
+ for (blr = blocking_lock_queue; blr; blr = next) {
connection_struct *conn = NULL;
uint16 vuid;
files_struct *fsp = NULL;
+ next = blr->next;
+
/*
* Ensure we don't have any old chain_fsp values
* sitting around....
@@ -658,8 +647,7 @@ void process_blocking_lock_queue(time_t t)
blr->offset, blr->count, True, NULL, NULL);
blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
+ free_blocking_lock_record(blr);
continue;
}
@@ -675,8 +663,7 @@ void process_blocking_lock_queue(time_t t)
blr->lock_pid, sys_getpid(), conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
+ free_blocking_lock_record(blr);
continue;
}
@@ -691,8 +678,7 @@ void process_blocking_lock_queue(time_t t)
blr->lock_pid, sys_getpid(), conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
+ free_blocking_lock_record(blr);
change_to_root_user();
continue;
}
@@ -709,18 +695,8 @@ void process_blocking_lock_queue(time_t t)
blr->lock_pid, sys_getpid(), conn->cnum,
blr->offset, blr->count, True, NULL, NULL);
- free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
- blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
- change_to_root_user();
- continue;
+ free_blocking_lock_record(blr);
}
-
change_to_root_user();
-
- /*
- * Move to the next in the list.
- */
- prev = blr;
- blr = (blocking_lock_record *)ubi_slNext(blr);
}
}
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index 8ea5b9c60a3..af363d75a3f 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -1046,6 +1046,19 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
return NT_STATUS_ACCESS_DENIED;
}
+ /* Use external script to check password complexity */
+ if (lp_check_password_script() && *(lp_check_password_script())) {
+ int check_ret;
+
+ check_ret = smbrunsecret(lp_check_password_script(), new_passwd);
+ DEBUG(5, ("change_oem_password: check password script (%s) returned [%d]\n", lp_check_password_script(), check_ret));
+
+ if (check_ret != 0) {
+ DEBUG(1, ("change_oem_password: check password script said new password is not good enough!\n"));
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ }
+
/*
* If unix password sync was requested, attempt to change
* the /etc/passwd database first. Return failure if this cannot
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index b88f687766d..2bda42f76dc 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -986,112 +986,3 @@ int TellDir(void *p)
return(dirp->pos);
}
-
-/*******************************************************************************
- This section manages a global directory cache.
- (It should probably be split into a separate module. crh)
-********************************************************************************/
-
-typedef struct {
- ubi_dlNode node;
- char *path;
- char *name;
- char *dname;
- int snum;
-} dir_cache_entry;
-
-static ubi_dlNewList( dir_cache );
-
-/*****************************************************************************
- Add an entry to the directory cache.
- Input: path -
- name -
- dname -
- snum -
- Output: None.
-*****************************************************************************/
-
-void DirCacheAdd( const char *path, const char *name, const char *dname, int snum )
-{
- int pathlen;
- int namelen;
- dir_cache_entry *entry;
-
- /*
- * Allocate the structure & string space in one go so that it can be freed
- * in one call to free().
- */
- pathlen = strlen(path) + 1; /* Bytes required to store path (with nul). */
- namelen = strlen(name) + 1; /* Bytes required to store name (with nul). */
- entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry )
- + pathlen
- + namelen
- + strlen( dname ) +1 );
- if( NULL == entry ) /* Not adding to the cache is not fatal, */
- return; /* so just return as if nothing happened. */
-
- /* Set pointers correctly and load values. */
- entry->path = memcpy( (char *)&entry[1], path, strlen(path)+1 );
- entry->name = memcpy( &(entry->path[pathlen]), name, strlen(name)+1 );
- entry->dname = memcpy( &(entry->name[namelen]), dname, strlen(dname)+1 );
- entry->snum = snum;
-
- /* Add the new entry to the linked list. */
- (void)ubi_dlAddHead( dir_cache, entry );
- DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) );
-
- /* Free excess cache entries. */
- while( DIRCACHESIZE < dir_cache->count )
- safe_free( ubi_dlRemTail( dir_cache ) );
-}
-
-/*****************************************************************************
- Search for an entry to the directory cache.
- Input: path -
- name -
- snum -
- Output: The dname string of the located entry, or NULL if the entry was
- not found.
-
- Notes: This uses a linear search, which is is okay because of
- the small size of the cache. Use a splay tree or hash
- for large caches.
-*****************************************************************************/
-
-char *DirCacheCheck( const char *path, const char *name, int snum )
-{
- dir_cache_entry *entry;
-
- for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
- NULL != entry;
- entry = (dir_cache_entry *)ubi_dlNext( entry ) ) {
- if( entry->snum == snum
- && entry->name && 0 == strcmp( name, entry->name )
- && entry->path && 0 == strcmp( path, entry->path ) ) {
- DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
- return( entry->dname );
- }
- }
-
- return(NULL);
-}
-
-/*****************************************************************************
- Remove all cache entries which have an snum that matches the input.
- Input: snum -
- Output: None.
-*****************************************************************************/
-
-void DirCacheFlush(int snum)
-{
- dir_cache_entry *entry;
- ubi_dlNodePtr next;
-
- for(entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
- NULL != entry; ) {
- next = ubi_dlNext( entry );
- if( entry->snum == snum )
- safe_free( ubi_dlRemThis( dir_cache, entry ) );
- entry = (dir_cache_entry *)next;
- }
-}
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index d3660addf11..fc874dc0867 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -95,9 +95,9 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect
static FAKE_FILE fake_files[] = {
#ifdef WITH_QUOTAS
- {FAKE_FILE_NAME_QUOTA, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle},
+ {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle},
#endif /* WITH_QUOTAS */
- {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL }
+ {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL }
};
int is_fake_file(char *fname)
@@ -156,7 +156,7 @@ struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
{
if (!fh||!(*fh))
- return ;
+ return;
if ((*fh)->free_pd)
(*fh)->free_pd(&(*fh)->pd);
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index c411ef0f79f..279c9dd3c45 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -26,8 +26,7 @@
#include "includes.h"
-static BOOL scan_directory(const char *path, char *name,size_t maxlength,
- connection_struct *conn,BOOL docache);
+static BOOL scan_directory(connection_struct *conn, const char *path, char *name,size_t maxlength);
/****************************************************************************
Check if two filenames are equal.
@@ -282,10 +281,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
*/
if (ms_has_wild(start) ||
- !scan_directory(dirpath, start,
- sizeof(pstring) - 1 - (start - name),
- conn,
- end?True:False)) {
+ !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) {
if (end) {
/*
* An intermediate part of the name can't be found.
@@ -434,8 +430,7 @@ BOOL check_name(pstring name,connection_struct *conn)
If the name looks like a mangled name then try via the mangling functions
****************************************************************************/
-static BOOL scan_directory(const char *path, char *name, size_t maxlength,
- connection_struct *conn,BOOL docache)
+static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength)
{
void *cur_dir;
const char *dname;
@@ -447,11 +442,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength,
if (*path == 0)
path = ".";
- if (docache && (dname = DirCacheCheck(path,name,SNUM(conn)))) {
- safe_strcpy(name, dname, maxlength);
- return(True);
- }
-
/*
* The incoming name can be mangled, and if we de-mangle it
* here it will not compare correctly against the filename (name2)
@@ -489,8 +479,6 @@ static BOOL scan_directory(const char *path, char *name, size_t maxlength,
if ((mangled && mangled_equal(name,dname,SNUM(conn))) || fname_equal(name, dname, conn->case_sensitive)) {
/* we've found the file, change it's name and return */
- if (docache)
- DirCacheAdd(path,name,dname,SNUM(conn));
safe_strcpy(name, dname, maxlength);
CloseDir(cur_dir);
return(True);
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 13ec99a917f..26ddf1b3a3d 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -85,23 +85,6 @@
* if that character is in the illegal characters set.
* This is faster than using strchr_m().
*
- * mangled_cache - Cache header used for storing mangled -> original
- * reverse maps.
- *
- * mc_initialized - False until the mangled_cache structure has been
- * initialized via a call to reset_mangled_cache().
- *
- * MANGLED_CACHE_MAX_ENTRIES - Default maximum number of entries for the
- * cache. A value of 0 indicates "infinite".
- *
- * MANGLED_CACHE_MAX_MEMORY - Default maximum amount of memory for the
- * cache. When the cache was kept as an array of 256
- * byte strings, the default cache size was 50 entries.
- * This required a fixed 12.5Kbytes of memory. The
- * mangled stack parameter is no longer used (though
- * this might change). We're now using a fixed 16Kbyte
- * maximum cache size. This will probably be much more
- * than 50 entries.
*/
char magic_char = '~';
@@ -118,10 +101,7 @@ static BOOL ct_initialized = False;
#define isbasechar(C) ( (chartest[ ((C) & 0xff) ]) & BASECHAR_MASK )
#define isillegal(C) ( (chartest[ ((C) & 0xff) ]) & ILLEGAL_MASK )
-static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
-static BOOL mc_initialized = False;
-#define MANGLED_CACHE_MAX_ENTRIES 1024
-#define MANGLED_CACHE_MAX_MEMORY 0
+static TDB_CONTEXT *tdb_mangled_cache;
/* -------------------------------------------------------------------- */
@@ -400,157 +380,69 @@ static BOOL is_mangled(const char *s)
return( False );
}
-/* ************************************************************************** **
- * Compare two cache keys and return a value indicating their ordinal
- * relationship.
- *
- * Input: ItemPtr - Pointer to a comparison key. In this case, this will
- * be a mangled name string.
- * NodePtr - Pointer to a node in the cache. The node structure
- * will be followed in memory by a mangled name string.
- *
- * Output: A signed integer, as follows:
- * (x < 0) <==> Key1 less than Key2
- * (x == 0) <==> Key1 equals Key2
- * (x > 0) <==> Key1 greater than Key2
- *
- * Notes: This is a ubiqx-style comparison routine. See ubi_BinTree for
- * more info.
- *
- * ************************************************************************** **
- */
-static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
-{
- char *Key1 = (char *)ItemPtr;
- char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
-
- return( StrCaseCmp( Key1, Key2 ) );
-}
-
-/* ************************************************************************** **
- * Free a cache entry.
- *
- * Input: WarrenZevon - Pointer to the entry that is to be returned to
- * Nirvana.
- * Output: none.
- *
- * Notes: This function gets around the possibility that the standard
- * free() function may be implemented as a macro, or other evil
- * subversions (oh, so much fun).
- *
- * ************************************************************************** **
- */
-static void cache_free_entry( ubi_trNodePtr WarrenZevon )
-{
- ZERO_STRUCTP(WarrenZevon);
- SAFE_FREE( WarrenZevon );
-}
-
-/* ************************************************************************** **
- * Initializes or clears the mangled cache.
- *
- * Input: none.
- * Output: none.
- *
- * Notes: There is a section below that is commented out. It shows how
- * one might use lp_ calls to set the maximum memory and entry size
- * of the cache. You might also want to remove the constants used
- * in ubi_cacheInit() and replace them with lp_ calls. If so, then
- * the calls to ubi_cacheSetMax*() would be moved into the else
- * clause. Another option would be to pass in the max_entries and
- * max_memory values as parameters. crh 09-Apr-1998.
- *
- * ************************************************************************** **
- */
+/***************************************************************************
+ Initializes or clears the mangled cache.
+***************************************************************************/
static void mangle_reset( void )
{
- if( !mc_initialized ) {
- (void)ubi_cacheInit( mangled_cache,
- cache_compare,
- cache_free_entry,
- MANGLED_CACHE_MAX_ENTRIES,
- MANGLED_CACHE_MAX_MEMORY );
- mc_initialized = True;
- } else {
- (void)ubi_cacheClear( mangled_cache );
- }
-
- /*
- (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
- (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
- */
+ /* We could close and re-open the tdb here... should we ? The old code did
+ the equivalent... JRA. */
}
-/* ************************************************************************** **
- * Add a mangled name into the cache.
- *
- * Notes: If the mangled cache has not been initialized, then the
- * function will simply fail. It could initialize the cache,
- * but that's not the way it was done before I changed the
- * cache mechanism, so I'm sticking with the old method.
- *
- * If the extension of the raw name maps directly to the
- * extension of the mangled name, then we'll store both names
- * *without* extensions. That way, we can provide consistent
- * reverse mangling for all names that match. The test here is
- * a bit more careful than the one done in earlier versions of
- * mangle.c:
- *
- * - the extension must exist on the raw name,
- * - it must be all lower case
- * - it must match the mangled extension (to prove that no
- * mangling occurred).
- *
- * crh 07-Apr-1998
- *
- * ************************************************************************** **
- */
-static void cache_mangled_name( char *mangled_name, char *raw_name )
+/***************************************************************************
+ Add a mangled name into the cache.
+ If the extension of the raw name maps directly to the
+ extension of the mangled name, then we'll store both names
+ *without* extensions. That way, we can provide consistent
+ reverse mangling for all names that match. The test here is
+ a bit more careful than the one done in earlier versions of
+ mangle.c:
+
+ - the extension must exist on the raw name,
+ - it must be all lower case
+ - it must match the mangled extension (to prove that no
+ mangling occurred).
+ crh 07-Apr-1998
+**************************************************************************/
+
+static void cache_mangled_name( const char mangled_name[13], char *raw_name )
{
- ubi_cacheEntryPtr new_entry;
- char *s1;
- char *s2;
- size_t mangled_len;
- size_t raw_len;
- size_t i;
+ TDB_DATA data_val;
+ char mangled_name_key[13];
+ char *s1;
+ char *s2;
/* If the cache isn't initialized, give up. */
- if( !mc_initialized )
+ if( !tdb_mangled_cache )
return;
/* Init the string lengths. */
- mangled_len = strlen( mangled_name );
- raw_len = strlen( raw_name );
+ safe_strcpy(mangled_name_key, mangled_name, sizeof(mangled_name_key)-1);
/* See if the extensions are unmangled. If so, store the entry
* without the extension, thus creating a "group" reverse map.
*/
- s1 = strrchr( mangled_name, '.' );
+ s1 = strrchr( mangled_name_key, '.' );
if( s1 && (s2 = strrchr( raw_name, '.' )) ) {
- i = 1;
+ size_t i = 1;
while( s1[i] && (tolower( s1[i] ) == s2[i]) )
i++;
if( !s1[i] && !s2[i] ) {
- mangled_len -= i;
- raw_len -= i;
+ /* Truncate at the '.' */
+ *s1 = '\0';
+ *s2 = '\0';
}
}
/* Allocate a new cache entry. If the allocation fails, just return. */
- i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
- new_entry = malloc( i );
- if( !new_entry )
- return;
-
- /* Fill the new cache entry, and add it to the cache. */
- s1 = (char *)(new_entry + 1);
- s2 = (char *)&(s1[mangled_len + 1]);
- memcpy( s1, mangled_name, mangled_len );
- s1[mangled_len] = '\0';
- memcpy( s2, raw_name, raw_len );
- s2[raw_len] = '\0';
- ubi_cachePut( mangled_cache, i, new_entry, s1 );
+ data_val.dptr = raw_name;
+ data_val.dsize = strlen(raw_name)+1;
+ if (tdb_store_bystring(tdb_mangled_cache, mangled_name_key, data_val, TDB_REPLACE) != 0) {
+ DEBUG(0,("cache_mangled_name: Error storing entry %s -> %s\n", mangled_name_key, raw_name));
+ } else {
+ DEBUG(5,("cache_mangled_name: Stored entry %s -> %s\n", mangled_name_key, raw_name));
+ }
}
/* ************************************************************************** **
@@ -570,26 +462,25 @@ static void cache_mangled_name( char *mangled_name, char *raw_name )
static BOOL check_cache( char *s, size_t maxlen )
{
- ubi_cacheEntryPtr FoundPtr;
- char *ext_start = NULL;
- char *found_name;
- char *saved_ext = NULL;
+ TDB_DATA data_val;
+ char *ext_start = NULL;
+ char *saved_ext = NULL;
/* If the cache isn't initialized, give up. */
- if( !mc_initialized )
+ if( !tdb_mangled_cache )
return( False );
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+ data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
/* If we didn't find the name *with* the extension, try without. */
- if( !FoundPtr ) {
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
ext_start = strrchr( s, '.' );
if( ext_start ) {
if((saved_ext = strdup(ext_start)) == NULL)
return False;
*ext_start = '\0';
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+ data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
/*
* At this point s is the name without the
* extension. We re-add the extension if saved_ext
@@ -599,7 +490,7 @@ static BOOL check_cache( char *s, size_t maxlen )
}
/* Okay, if we haven't found it we're done. */
- if( !FoundPtr ) {
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
if(saved_ext) {
/* Replace the saved_ext as it was truncated. */
(void)safe_strcat( s, saved_ext, maxlen );
@@ -609,16 +500,13 @@ static BOOL check_cache( char *s, size_t maxlen )
}
/* If we *did* find it, we need to copy it into the string buffer. */
- found_name = (char *)(FoundPtr + 1);
- found_name += (strlen( found_name ) + 1);
-
- (void)safe_strcpy( s, found_name, maxlen );
+ (void)safe_strcpy( s, data_val.dptr, maxlen );
if( saved_ext ) {
/* Replace the saved_ext as it was truncated. */
(void)safe_strcat( s, saved_ext, maxlen );
SAFE_FREE(saved_ext);
}
-
+ SAFE_FREE(data_val.dptr);
return( True );
}
@@ -767,5 +655,9 @@ struct mangle_fns *mangle_hash_init(void)
{
mangle_reset();
+ /* Create the in-memory tdb using our custom hash function. */
+ tdb_mangled_cache = tdb_open_ex("mangled_cache", 1031, TDB_INTERNAL,
+ (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash);
+
return &mangle_fns;
}
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index 5ff53f63007..447073acd84 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -249,6 +249,10 @@ static int reply_nt1(char *inbuf, char *outbuf)
(SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
negotiate_spnego = True;
capabilities |= CAP_EXTENDED_SECURITY;
+ add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
+ /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
+ partially constructed. */
+ SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
}
capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index f717efac63e..d9e321fd968 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -762,16 +762,21 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
set_posix_case_semantics(conn, file_attributes);
unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (bad_path) {
- restore_case_semantics(conn, file_attributes);
- END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- }
- /* All file access must go through check_name() */
- if (!check_name(fname,conn)) {
- restore_case_semantics(conn, file_attributes);
- END_PROFILE(SMBntcreateX);
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+
+ /* FAKE_FILE is a special case */
+ if (fake_file_type == FAKE_FILE_TYPE_NONE) {
+ /* Normal file. */
+ if (bad_path) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+ /* All file access must go through check_name() */
+ if (!check_name(fname,conn)) {
+ restore_case_semantics(conn, file_attributes);
+ END_PROFILE(SMBntcreateX);
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
+ }
}
/*
@@ -1075,7 +1080,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
TALLOC_CTX *mem_ctx;
BOOL ret;
- if (sd_len == 0) {
+ if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
return NT_STATUS_OK;
}
@@ -1409,7 +1414,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* Now try and apply the desired SD.
*/
- if (sd_len && !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
+ if (lp_nt_acl_support(SNUM(conn)) && sd_len &&
+ !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
close_file(fsp,False);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 60ce1499e8d..5be68d9f0a1 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -1130,7 +1130,12 @@ const char *smb_fn_name(int type)
Helper functions for contruct_reply.
****************************************************************************/
-static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_EXTENDED_SECURITY|FLAGS2_32_BIT_ERROR_CODES;
+static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
+
+void add_to_common_flags2(uint32 v)
+{
+ common_flags2 |= v;
+}
void remove_from_common_flags2(uint32 v)
{
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 794b5332ac5..4d111e0ea35 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -804,7 +804,8 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
/* Handle non-Dfs clients attempting connections to msdfs proxy */
if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
- DEBUG(3, ("refusing connection to dfs proxy '%s'\n", service));
+ DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
+ service, lp_msdfs_proxy(snum)));
*status = NT_STATUS_BAD_NETWORK_NAME;
return NULL;
}
@@ -821,8 +822,6 @@ close a cnum
****************************************************************************/
void close_cnum(connection_struct *conn, uint16 vuid)
{
- DirCacheFlush(SNUM(conn));
-
if (IS_IPC(conn)) {
pipe_close_conn(conn);
} else {
diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c
index 5e78e9a4999..ba37d4927cc 100644
--- a/source/smbd/statcache.c
+++ b/source/smbd/statcache.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
stat cache code
Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Jeremy Allison 1999-2000
+ Copyright (C) Jeremy Allison 1999-2004
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
This program is free software; you can redistribute it and/or modify
@@ -26,15 +26,7 @@
Stat cache code used in unix_convert.
*****************************************************************************/
-typedef struct {
- char *original_path;
- char *translated_path;
- size_t translated_path_length;
- char names[2]; /* This is extended via malloc... */
-} stat_cache_entry;
-
-#define INIT_STAT_CACHE_SIZE 512
-static hash_table stat_cache;
+static TDB_CONTEXT *tdb_stat_cache;
/**
* Add an entry into the stat cache.
@@ -50,19 +42,17 @@ static hash_table stat_cache;
void stat_cache_add( const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive)
{
- stat_cache_entry *scp;
- stat_cache_entry *found_scp;
char *translated_path;
size_t translated_path_length;
-
+ TDB_DATA data_val;
char *original_path;
size_t original_path_length;
- hash_element *hash_elem;
-
if (!lp_stat_cache())
return;
+ ZERO_STRUCT(data_val);
+
/*
* Don't cache trivial valid directory entries such as . and ..
*/
@@ -124,7 +114,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
return;
}
- /* we only want to store the first part of original_path,
+ /* we only want to index by the first part of original_path,
up to the length of translated_path */
original_path[translated_path_length] = '\0';
@@ -132,55 +122,26 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
}
/*
- * Check this name doesn't exist in the cache before we
- * add it.
- */
-
- if ((hash_elem = hash_lookup(&stat_cache, original_path))) {
- found_scp = (stat_cache_entry *)(hash_elem->value);
- if (strcmp((found_scp->translated_path), orig_translated_path) == 0) {
- /* already in hash table */
- SAFE_FREE(original_path);
- SAFE_FREE(translated_path);
- return;
- }
- /* hash collision - remove before we re-add */
- hash_remove(&stat_cache, hash_elem);
- }
-
- /*
- * New entry.
+ * New entry or replace old entry.
*/
- if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry)
- +original_path_length
- +translated_path_length)) == NULL) {
- DEBUG(0,("stat_cache_add: Out of memory !\n"));
- SAFE_FREE(original_path);
- SAFE_FREE(translated_path);
- return;
- }
-
- scp->original_path = scp->names;
- /* pointer into the structure... */
- scp->translated_path = scp->names + original_path_length + 1;
- safe_strcpy(scp->original_path, original_path, original_path_length);
- safe_strcpy(scp->translated_path, translated_path, translated_path_length);
- scp->translated_path_length = translated_path_length;
+ data_val.dsize = translated_path_length + 1;
+ data_val.dptr = translated_path;
- hash_insert(&stat_cache, (char *)scp, original_path);
+ if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) {
+ DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path));
+ } else {
+ DEBUG(5,("stat_cache_add: Added entry (%x:size%x) %s -> %s\n",
+ (unsigned int)data_val.dptr, data_val.dsize, original_path, translated_path));
+ }
SAFE_FREE(original_path);
SAFE_FREE(translated_path);
-
- DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path));
}
/**
* Look through the stat cache for an entry
*
- * The hash-table's internals will promote it to the top if found.
- *
* @param conn A connection struct to do the stat() with.
* @param name The path we are attempting to cache, modified by this routine
* to be correct as far as the cache can tell us
@@ -195,11 +156,8 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
char **start, SMB_STRUCT_STAT *pst)
{
- stat_cache_entry *scp;
char *chk_name;
size_t namelen;
- hash_element *hash_elem;
- char *sp;
BOOL sizechanged = False;
unsigned int num_components = 0;
@@ -244,8 +202,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
}
while (1) {
- hash_elem = hash_lookup(&stat_cache, chk_name);
- if(hash_elem == NULL) {
+ TDB_DATA data_val;
+ char *sp;
+
+ data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name);
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name ));
/*
* Didn't find it - remove last component for next try.
@@ -275,63 +236,84 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
return False;
}
} else {
- scp = (stat_cache_entry *)(hash_elem->value);
- DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path ));
+ BOOL retval;
+ char *translated_path = data_val.dptr;
+ size_t translated_path_length = data_val.dsize - 1;
+
+ DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path ));
DO_PROFILE_INC(statcache_hits);
- if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) {
+ if(SMB_VFS_STAT(conn,translated_path, pst) != 0) {
/* Discard this entry - it doesn't exist in the filesystem. */
- hash_remove(&stat_cache, hash_elem);
+ tdb_delete_bystring(tdb_stat_cache, chk_name);
SAFE_FREE(chk_name);
+ SAFE_FREE(data_val.dptr);
return False;
}
if (!sizechanged) {
- memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length));
+ memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length));
} else if (num_components == 0) {
- pstrcpy(name, scp->translated_path);
+ pstrcpy(name, translated_path);
} else {
sp = strnrchr_m(name, '/', num_components);
if (sp) {
pstring last_component;
pstrcpy(last_component, sp);
- pstrcpy(name, scp->translated_path);
+ pstrcpy(name, translated_path);
pstrcat(name, last_component);
} else {
- pstrcpy(name, scp->translated_path);
+ pstrcpy(name, translated_path);
}
}
/* set pointer for 'where to start' on fixing the rest of the name */
- *start = &name[scp->translated_path_length];
+ *start = &name[translated_path_length];
if(**start == '/')
++*start;
- pstrcpy(dirpath, scp->translated_path);
+ pstrcpy(dirpath, translated_path);
+ retval = (namelen == translated_path_length) ? True : False;
SAFE_FREE(chk_name);
- return (namelen == scp->translated_path_length);
+ SAFE_FREE(data_val.dptr);
+ return retval;
}
}
}
-/*************************************************************************** **
- * Initializes or clears the stat cache.
- *
- * Input: none.
- * Output: none.
- *
- * ************************************************************************** **
- */
+/***************************************************************
+ Compute a hash value based on a string key value.
+ The function returns the bucket index number for the hashed key.
+ JRA. Use a djb-algorithm hash for speed.
+***************************************************************/
+
+u32 fast_string_hash(TDB_DATA *key)
+{
+ u32 n = 0;
+ const char *p;
+ for (p = key->dptr; *p != '\0'; p++) {
+ n = ((n << 5) + n) ^ (u32)(*p);
+ }
+ return n;
+}
+
+/***************************************************************************
+ Initializes or clears the stat cache.
+**************************************************************************/
+
BOOL reset_stat_cache( void )
{
- static BOOL initialised;
if (!lp_stat_cache())
return True;
- if (initialised) {
- hash_clear(&stat_cache);
+ if (tdb_stat_cache) {
+ tdb_close(tdb_stat_cache);
}
- initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE,
- (compare_function)(strcmp));
- return initialised;
+ /* Create the in-memory tdb using our custom hash function. */
+ tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL,
+ (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash);
+
+ if (!tdb_stat_cache)
+ return False;
+ return True;
}
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
index fec0b3094d3..ae4e439c903 100644
--- a/source/tdb/tdb.c
+++ b/source/tdb/tdb.c
@@ -276,7 +276,7 @@ static int tdb_lock(TDB_CONTEXT *tdb, int list, int ltype)
if (tdb->locked[list+1].count == 0) {
if (!tdb->read_only && tdb->header.rwlocks) {
if (tdb_spinlock(tdb, list, ltype)) {
- TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list ltype=%d\n",
+ TDB_LOG((tdb, 0, "tdb_lock spinlock failed on list %d ltype=%d\n",
list, ltype));
return -1;
}
@@ -329,19 +329,6 @@ static int tdb_unlock(TDB_CONTEXT *tdb, int list, int ltype)
return ret;
}
-/* This is based on the hash algorithm from gdbm */
-static u32 tdb_hash(TDB_DATA *key)
-{
- u32 value; /* Used to compute the hash value. */
- u32 i; /* Used to cycle through random values. */
-
- /* Set the initial value from the key size. */
- for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
- value = (value + (key->dptr[i] << (i*5 % 24)));
-
- return (1103515243 * value + 12345);
-}
-
/* check for an out of bounds access - if it is out of bounds then
see if the database has been expanded by someone else and expand
if necessary
@@ -1121,7 +1108,7 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key)
u32 hash;
/* find which hash bucket it is in */
- hash = tdb_hash(&key);
+ hash = tdb->hash_fn(&key);
if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec)))
return tdb_null;
@@ -1153,7 +1140,7 @@ static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key)
{
- u32 hash = tdb_hash(&key);
+ u32 hash = tdb->hash_fn(&key);
return tdb_exists_hash(tdb, key, hash);
}
@@ -1413,7 +1400,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey)
if (!tdb->travlocks.off) {
/* No previous element: do normal find, and lock record */
- tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec);
+ tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb->hash_fn(&oldkey), F_WRLCK, &rec);
if (!tdb->travlocks.off)
return tdb_null;
tdb->travlocks.hash = BUCKET(rec.full_hash);
@@ -1457,7 +1444,7 @@ static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash)
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key)
{
- u32 hash = tdb_hash(&key);
+ u32 hash = tdb->hash_fn(&key);
return tdb_delete_hash(tdb, key, hash);
}
@@ -1475,7 +1462,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
int ret = 0;
/* find which hash bucket it is in */
- hash = tdb_hash(&key);
+ hash = tdb->hash_fn(&key);
if (!tdb_keylocked(tdb, hash))
return -1;
if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
@@ -1593,7 +1580,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf)
size_t new_data_size = 0;
/* find which hash bucket it is in */
- hash = tdb_hash(&key);
+ hash = tdb->hash_fn(&key);
if (!tdb_keylocked(tdb, hash))
return -1;
if (tdb_lock(tdb, BUCKET(hash), F_WRLCK) == -1)
@@ -1689,6 +1676,19 @@ static int tdb_already_open(dev_t device,
return 0;
}
+/* This is based on the hash algorithm from gdbm */
+static u32 default_tdb_hash(TDB_DATA *key)
+{
+ u32 value; /* Used to compute the hash value. */
+ u32 i; /* Used to cycle through random values. */
+
+ /* Set the initial value from the key size. */
+ for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
+ value = (value + (key->dptr[i] << (i*5 % 24)));
+
+ return (1103515243 * value + 12345);
+}
+
/* open the database, creating it if necessary
The open_flags and mode are passed straight to the open call on the
@@ -1702,13 +1702,14 @@ static int tdb_already_open(dev_t device,
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode)
{
- return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL);
+ return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL);
}
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
- tdb_log_func log_fn)
+ tdb_log_func log_fn,
+ tdb_hash_func hash_fn)
{
TDB_CONTEXT *tdb;
struct stat st;
@@ -1728,7 +1729,8 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
tdb->flags = tdb_flags;
tdb->open_flags = open_flags;
tdb->log_fn = log_fn;
-
+ tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
+
if ((open_flags & O_ACCMODE) == O_WRONLY) {
TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n",
name));
@@ -1973,7 +1975,7 @@ int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[])
/* Insertion sort by bucket */
for (i = 0; i < number; i++) {
- hash = tdb_hash(&keys[i]);
+ hash = tdb->hash_fn(&keys[i]);
for (j = 0; j < i && BUCKET(tdb->lockedkeys[j+1]) < BUCKET(hash); j++);
memmove(&tdb->lockedkeys[j+2], &tdb->lockedkeys[j+1], sizeof(u32) * (i-j));
tdb->lockedkeys[j+1] = hash;
@@ -2008,22 +2010,22 @@ void tdb_unlockkeys(TDB_CONTEXT *tdb)
contention - it cannot guarantee how many records will be locked */
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK);
+ return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
}
int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_WRLCK);
+ return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
}
int tdb_chainlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_lock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK);
+ return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
int tdb_chainunlock_read(TDB_CONTEXT *tdb, TDB_DATA key)
{
- return tdb_unlock(tdb, BUCKET(tdb_hash(&key)), F_RDLCK);
+ return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_RDLCK);
}
@@ -2033,7 +2035,6 @@ void tdb_logging_function(TDB_CONTEXT *tdb, void (*fn)(TDB_CONTEXT *, int , cons
tdb->log_fn = fn;
}
-
/* reopen a tdb - this can be used after a fork to ensure that we have an independent
seek pointer from our parent and to re-establish locks */
int tdb_reopen(TDB_CONTEXT *tdb)
diff --git a/source/tdb/tdb.h b/source/tdb/tdb.h
index eb120a8cecd..e8a6d201c59 100644
--- a/source/tdb/tdb.h
+++ b/source/tdb/tdb.h
@@ -31,6 +31,17 @@
extern "C" {
#endif
+#ifndef PRINTF_ATTRIBUTE
+/** Use gcc attribute to check printf fns. a1 is the 1-based index of
+ * the parameter containing the format, and a2 the index of the first
+ * argument. Note that some gcc 2.x versions don't handle this
+ * properly **/
+#if (__GNUC__ >= 3)
+#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
+#else
+#define PRINTF_ATTRIBUTE(a1, a2)
+#endif
+#endif
/* flags to tdb_store() */
#define TDB_REPLACE 1
@@ -101,18 +112,21 @@ typedef struct tdb_context {
struct tdb_context *next; /* all tdbs to avoid multiple opens */
dev_t device; /* uniquely identifies this tdb */
ino_t inode; /* uniquely identifies this tdb */
- void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...); /* logging function */
+ void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */
+ u32 (*hash_fn)(TDB_DATA *key);
int open_flags; /* flags used in the open - needed by reopen */
} TDB_CONTEXT;
typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
typedef void (*tdb_log_func)(TDB_CONTEXT *, int , const char *, ...);
+typedef u32 (*tdb_hash_func)(TDB_DATA *key);
TDB_CONTEXT *tdb_open(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode);
TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
int open_flags, mode_t mode,
- tdb_log_func log_fn);
+ tdb_log_func log_fn,
+ tdb_hash_func hash_fn);
int tdb_reopen(TDB_CONTEXT *tdb);
int tdb_reopen_all(void);
diff --git a/source/tdb/tdbutil.c b/source/tdb/tdbutil.c
index 09e55e2e702..e57eccfe598 100644
--- a/source/tdb/tdbutil.c
+++ b/source/tdb/tdbutil.c
@@ -740,7 +740,7 @@ TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags,
tdb_flags |= TDB_NOMMAP;
tdb = tdb_open_ex(name, hash_size, tdb_flags,
- open_flags, mode, tdb_log);
+ open_flags, mode, tdb_log, NULL);
if (!tdb)
return NULL;
diff --git a/source/ubiqx/ubi_BinTree.c b/source/ubiqx/ubi_BinTree.c
index 8a4d4612800..e452ac10dc2 100644
--- a/source/ubiqx/ubi_BinTree.c
+++ b/source/ubiqx/ubi_BinTree.c
@@ -26,7 +26,16 @@
*
* -------------------------------------------------------------------------- **
*
- * Log: ubi_BinTree.c,v
+ * Log: ubi_BinTree.c,v
+ * Revision 4.12 2004/06/06 04:51:56 crh
+ * Fixed a small typo in ubi_BinTree.c (leftover testing cruft).
+ * Did a small amount of formatting touchup to ubi_BinTree.h.
+ *
+ * Revision 4.11 2004/06/06 03:14:09 crh
+ * Rewrote the ubi_btLeafNode() function. It now takes several paths in an
+ * effort to find a deeper leaf node. There is a small amount of extra
+ * overhead, but it is limited.
+ *
* Revision 4.10 2000/06/06 20:38:40 crh
* In the ReplaceNode() function, the old node header was being copied
* to the new node header using a byte-by-byte copy. This was causing
@@ -181,14 +190,15 @@
#include "ubi_BinTree.h" /* Header for this module. */
+
/* ========================================================================== **
* Static data.
*/
static char ModuleID[] = "ubi_BinTree\n\
-\tRevision: 4.10 \n\
-\tDate: 2000/06/06 20:38:40 \n\
-\tAuthor: crh \n";
+\tRevision: 4.12\n\
+\tDate: 2004/06/06 04:51:56\n\
+\tAuthor: crh\n";
/* ========================================================================== **
* Internal (private) functions.
@@ -1061,8 +1071,8 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
*
* Input: leader - Pointer to a node at which to start the descent.
*
- * Output: A pointer to a leaf node selected in a somewhat arbitrary
- * manner.
+ * Output: A pointer to a leaf node, selected in a somewhat arbitrary
+ * manner but with an effort to dig deep.
*
* Notes: I wrote this function because I was using splay trees as a
* database cache. The cache had a maximum size on it, and I
@@ -1071,7 +1081,7 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
* tend toward the bottom of the tree, meaning that leaf nodes
* are good candidates for removal. (I really can't think of
* any other reason to use this function.)
- * + In a simple binary tree or an AVL tree, the most recently
+ * + In a simple binary tree, or in an AVL tree, the most recently
* added nodes tend to be nearer the bottom, making this a *bad*
* way to choose which node to remove from the cache.
* + Randomizing the traversal order is probably a good idea. You
@@ -1079,25 +1089,55 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader )
* in pointers to nodes other than the root node each time. A
* pointer to any node in the tree will do. Of course, if you
* pass a pointer to a leaf node you'll get the same thing back.
+ * + In an unbalanced splay tree, if you simply traverse downward
+ * until you hit a leaf node it is possible to accidentally
+ * stumble onto a short path. The result will be a leaf node
+ * that is actually very high in the tree--possibly a very
+ * recently accessed node. Not good. This function can follow
+ * multiple paths in an effort to find a leaf node deeper
+ * in the tree. Following a single path, of course, is the
+ * fastest way to find a leaf node. A complete traversal would
+ * be sure to find the deepest leaf but would be very costly in
+ * terms of time. This function uses a compromise that has
+ * worked well in testing.
*
* ------------------------------------------------------------------------ **
*/
{
- ubi_btNodePtr follower = NULL;
+ #define MAXPATHS 4 /* Set higher for more maximum paths, lower for fewer. */
+ ubi_trNodePtr p[MAXPATHS];
+ ubi_trNodePtr q[MAXPATHS];
int whichway = ubi_trLEFT;
+ int paths;
+ int i, j;
+
+ /* If the subtree is empty, return NULL.
+ */
+ if( NULL == leader )
+ return( NULL );
- while( NULL != leader )
+ /* Initialize the p[] array with a pointer to the single node we've been
+ * given as a starting point.
+ */
+ p[0] = leader;
+ paths = 1;
+ while( paths > 0 )
{
- follower = leader;
- leader = follower->Link[ whichway ];
- if( NULL == leader )
+ for( i = 0; i < paths; i++ )
+ q[i] = p[i];
+
+ for( i = j = 0; (i < paths) && (j < MAXPATHS); i++ )
{
+ if( NULL != q[i]->Link[whichway] )
+ p[j++] = q[i]->Link[whichway];
whichway = ubi_trRevWay( whichway );
- leader = follower->Link[ whichway ];
+ if( (j < MAXPATHS) && (NULL != q[i]->Link[whichway]) )
+ p[j++] = q[i]->Link[whichway];
}
+ paths = j;
}
- return( follower );
+ return( q[0] );
} /* ubi_btLeafNode */
int ubi_btModuleID( int size, char *list[] )
diff --git a/source/ubiqx/ubi_BinTree.h b/source/ubiqx/ubi_BinTree.h
index c0c6d593094..43ca1a98716 100644
--- a/source/ubiqx/ubi_BinTree.h
+++ b/source/ubiqx/ubi_BinTree.h
@@ -28,7 +28,16 @@
*
* -------------------------------------------------------------------------- **
*
- * Log: ubi_BinTree.h,v
+ * Log: ubi_BinTree.h,v
+ * Revision 4.12 2004/06/06 04:51:56 crh
+ * Fixed a small typo in ubi_BinTree.c (leftover testing cruft).
+ * Did a small amount of formatting touchup to ubi_BinTree.h.
+ *
+ * Revision 4.11 2004/06/06 03:14:09 crh
+ * Rewrote the ubi_btLeafNode() function. It now takes several paths in an
+ * effort to find a deeper leaf node. There is a small amount of extra
+ * overhead, but it is limited.
+ *
* Revision 4.10 2000/06/06 20:38:40 crh
* In the ReplaceNode() function, the old node header was being copied
* to the new node header using a byte-by-byte copy. This was causing
@@ -260,6 +269,7 @@ typedef enum {
* is left as is.
* -------------------------------------------------------------------------- **
*/
+
#define ubi_trNormalize(W) ((char)( (W) - ubi_trEQUAL ))
#define ubi_trAbNormal(W) ((char)( ((char)ubi_btSgn( (long)(W) )) \
+ ubi_trEQUAL ))
@@ -270,6 +280,7 @@ typedef enum {
* DUPlicate KEY bits of the tree root flags field.
* -------------------------------------------------------------------------- **
*/
+
#define ubi_trDups_OK(A) \
((ubi_trDUPKEY & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE))
#define ubi_trOvwt_OK(A) \
@@ -337,6 +348,7 @@ typedef void *ubi_btItemPtr; /* A pointer to key data within a node. */
*
* ------------------------------------------------------------------------- **
*/
+
typedef struct ubi_btNodeStruct {
struct ubi_btNodeStruct *Link[ 3 ];
char gender;
@@ -747,8 +759,8 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
*
* Input: leader - Pointer to a node at which to start the descent.
*
- * Output: A pointer to a leaf node selected in a somewhat arbitrary
- * manner.
+ * Output: A pointer to a leaf node, selected in a somewhat arbitrary
+ * manner but with an effort to dig deep.
*
* Notes: I wrote this function because I was using splay trees as a
* database cache. The cache had a maximum size on it, and I
@@ -757,7 +769,7 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
* tend toward the bottom of the tree, meaning that leaf nodes
* are good candidates for removal. (I really can't think of
* any other reason to use this function.)
- * + In a simple binary tree or an AVL tree, the most recently
+ * + In a simple binary tree, or in an AVL tree, the most recently
* added nodes tend to be nearer the bottom, making this a *bad*
* way to choose which node to remove from the cache.
* + Randomizing the traversal order is probably a good idea. You
@@ -765,6 +777,17 @@ ubi_btNodePtr ubi_btLeafNode( ubi_btNodePtr leader );
* in pointers to nodes other than the root node each time. A
* pointer to any node in the tree will do. Of course, if you
* pass a pointer to a leaf node you'll get the same thing back.
+ * + In an unbalanced splay tree, if you simply traverse downward
+ * until you hit a leaf node it is possible to accidentally
+ * stumble onto a short path. The result will be a leaf node
+ * that is actually very high in the tree--possibly a very
+ * recently accessed node. Not good. This function can follow
+ * multiple paths in an effort to find a leaf node deeper
+ * in the tree. Following a single path, of course, is the
+ * fastest way to find a leaf node. A complete traversal would
+ * be sure to find the deepest leaf but would be very costly in
+ * terms of time. This function uses a compromise that has
+ * worked well in testing.
*
* ------------------------------------------------------------------------ **
*/
diff --git a/source/utils/net.c b/source/utils/net.c
index 67b138a43be..da1339aed10 100644
--- a/source/utils/net.c
+++ b/source/utils/net.c
@@ -78,6 +78,11 @@ BOOL opt_localgroup = False;
BOOL opt_domaingroup = False;
const char *opt_newntname = "";
int opt_rid = 0;
+int opt_acls = 0;
+int opt_attrs = 0;
+int opt_timestamps = 0;
+const char *opt_exclude = NULL;
+const char *opt_destination = NULL;
BOOL opt_have_ip = False;
struct in_addr opt_dest_ip;
@@ -126,12 +131,13 @@ int net_run_function(int argc, const char **argv, struct functable *table,
return usage_fn(argc, argv);
}
-
/****************************************************************************
-connect to \\server\ipc$
+connect to \\server\service
****************************************************************************/
-NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
- const char *server_name)
+NTSTATUS connect_to_service(struct cli_state **c, struct in_addr *server_ip,
+ const char *server_name,
+ const char *service_name,
+ const char *service_type)
{
NTSTATUS nt_status;
@@ -144,7 +150,7 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
nt_status = cli_full_connection(c, NULL, server_name,
server_ip, opt_port,
- "IPC$", "IPC",
+ service_name, service_type,
opt_user_name, opt_workgroup,
opt_password, 0, Undefined, NULL);
@@ -171,6 +177,16 @@ NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
}
}
+
+/****************************************************************************
+connect to \\server\ipc$
+****************************************************************************/
+NTSTATUS connect_to_ipc(struct cli_state **c, struct in_addr *server_ip,
+ const char *server_name)
+{
+ return connect_to_service(c, server_ip, server_name, "IPC$", "IPC");
+}
+
/****************************************************************************
connect to \\server\ipc$ anonymously
****************************************************************************/
@@ -193,6 +209,42 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
}
}
+/**
+ * Connect a server and open a given pipe
+ *
+ * @param cli_dst A cli_state
+ * @param pipe The pipe to open
+ * @param got_pipe boolean that stores if we got a pipe
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS connect_pipe(struct cli_state **cli_dst, int pipe_num, BOOL *got_pipe)
+{
+ NTSTATUS nt_status;
+ char *server_name = strdup("127.0.0.1");
+ struct cli_state *cli_tmp = NULL;
+
+ if (opt_destination)
+ server_name = strdup(opt_destination);
+
+ /* make a connection to a named pipe */
+ nt_status = connect_to_ipc(&cli_tmp, NULL, server_name);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ if (!cli_nt_session_open(cli_tmp, pipe_num)) {
+ DEBUG(0, ("couldn't not initialize pipe\n"));
+ cli_shutdown(cli_tmp);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ *cli_dst = cli_tmp;
+ *got_pipe = True;
+
+ return nt_status;
+}
+
+
/****************************************************************************
Use the local machine's password for this session
****************************************************************************/
@@ -690,6 +742,12 @@ static struct functable net_func[] = {
{"domain", 'D', POPT_ARG_NONE, &opt_domaingroup},
{"ntname", 'N', POPT_ARG_STRING, &opt_newntname},
{"rid", 'R', POPT_ARG_INT, &opt_rid},
+ /* Options for 'net rpc share migrate' */
+ {"acls", 0, POPT_ARG_NONE, &opt_acls},
+ {"attrs", 0, POPT_ARG_NONE, &opt_attrs},
+ {"timestamps", 0, POPT_ARG_NONE, &opt_timestamps},
+ {"exclude", 'e', POPT_ARG_STRING, &opt_exclude},
+ {"destination", 0, POPT_ARG_STRING, &opt_destination},
POPT_COMMON_SAMBA
{ 0, 0, 0, 0}
diff --git a/source/utils/net.h b/source/utils/net.h
index ba3a4e14352..d75a19e498e 100644
--- a/source/utils/net.h
+++ b/source/utils/net.h
@@ -62,6 +62,11 @@ extern BOOL opt_localgroup;
extern BOOL opt_domaingroup;
extern const char *opt_newntname;
extern int opt_rid;
+extern int opt_acls;
+extern int opt_attrs;
+extern int opt_timestamps;
+extern const char *opt_exclude;
+extern const char *opt_destination;
extern BOOL opt_have_ip;
extern struct in_addr opt_dest_ip;
diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c
index 7b8ace85b62..2efd470bbe7 100644
--- a/source/utils/net_ads.c
+++ b/source/utils/net_ads.c
@@ -77,9 +77,12 @@ static int net_ads_lookup(int argc, const char **argv)
ads_connect(ads);
- if (!ads || !ads->config.realm) {
+ if (!ads) {
d_printf("Didn't find the cldap server!\n");
return -1;
+ } if (!ads->config.realm) {
+ ads->config.realm = opt_target_workgroup;
+ ads->ldap_port = 389;
}
return ads_cldap_netlogon(ads);
diff --git a/source/utils/net_ads_cldap.c b/source/utils/net_ads_cldap.c
index 1903172cf75..f3c6c5ff4d2 100644
--- a/source/utils/net_ads_cldap.c
+++ b/source/utils/net_ads_cldap.c
@@ -280,8 +280,9 @@ int ads_cldap_netlogon(ADS_STRUCT *ads)
int sock;
int ret;
struct cldap_netlogon_reply reply;
+ const char *target = opt_host ? opt_host : inet_ntoa(ads->ldap_ip);
- sock = open_udp_socket(inet_ntoa(ads->ldap_ip), ads->ldap_port);
+ sock = open_udp_socket(target, ads->ldap_port);
if (sock == -1) {
d_printf("Failed to open udp socket to %s:%u\n",
inet_ntoa(ads->ldap_ip),
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index 38261be90a7..d6ef5e8a6c3 100644
--- a/source/utils/net_help.c
+++ b/source/utils/net_help.c
@@ -122,13 +122,29 @@ int net_help_share(int argc, const char **argv)
"on target server\n\n"
"net [<method>] share ADD <name=serverpath> [misc. options] [targets]"
"\n\tAdds a share from a server (makes the export active)\n\n"
- "net [<method>] share DELETE <sharename> [misc. options] [targets]\n"
- "\n\tDeletes a share from a server (makes the export inactive)\n");
+ "net [<method>] share DELETE <sharename> [misc. options] [targets]"
+ "\n\tDeletes a share from a server (makes the export inactive)\n\n"
+ "net [<method>] share MIGRATE FILES <sharename> [misc. options] [targets]"
+ "\n\tMigrates files from remote to local server\n\n"
+ "net [<method>] share MIGRATE SHARES <sharename> [misc. options] [targets]"
+ "\n\tMigrates shares from remote to local server\n\n"
+/* "net [<method>] share MIGRATE SECURITY <sharename> [misc. options] [targets]"
+ "\n\tMigrates share-ACLs from remote to local server\n\n" */
+ "net [<method>] share MIGRATE ALL <sharename> [misc. options] [targets]"
+ "\n\tMigrates shares (including directories, files) from remote\n"
+ "\tto local server\n\n"
+ );
net_common_methods_usage(argc, argv);
net_common_flags_usage(argc, argv);
d_printf(
"\t-C or --comment=<comment>\tdescriptive comment (for add only)\n"
- "\t-M or --maxusers=<num>\t\tmax users allowed for share\n");
+ "\t-M or --maxusers=<num>\t\tmax users allowed for share\n"
+ "\t --acls\t\t\tcopies ACLs as well\n"
+ "\t --attrs\t\t\tcopies DOS Attributes as well\n"
+ "\t --timestampes\t\tpreserve timestampes while copying files\n"
+ "\t --destination\t\tmigration target server (default: localhost)\n"
+ "\t-e or --exclude\t\t\tlist of shares to be excluded from mirroring\n"
+ "\t-v or --verbose\t\t\tgive verbose output\n");
return -1;
}
@@ -149,6 +165,35 @@ int net_help_file(int argc, const char **argv)
return -1;
}
+int net_help_printer(int argc, const char **argv)
+{
+ d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"\
+ "\tlists all printers on print-server\n\n");
+ d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"\
+ "\tlists all printer-drivers on print-server\n\n");
+ d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printers from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-settings from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-drivers from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-forms from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"\
+ "\n\tmigrates printer-ACLs from remote to local server\n\n");
+ d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"\
+ "\n\tmigrates drivers, forms, queues, settings and acls from\n"\
+ "\tremote to local print-server\n\n");
+ net_common_methods_usage(argc, argv);
+ net_common_flags_usage(argc, argv);
+ d_printf(
+ "\t-v or --verbose\t\t\tgive verbose output\n"
+ "\t --destination\t\tmigration target server (default: localhost)\n");
+
+ return -1;
+}
+
+
int net_help_status(int argc, const char **argv)
{
d_printf(" net status sessions [parseable] "
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index e21f79df303..1a1d76b09a0 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -2351,6 +2351,7 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
uint32 type=0; /* only allow disk shares to be added */
uint32 num_users=0, perms=0;
char *password=NULL; /* don't allow a share password */
+ uint32 level = 2;
path = strchr(sharename, '=');
if (!path)
@@ -2359,7 +2360,8 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type,
opt_comment, perms, opt_maxusers,
- num_users, path, password);
+ num_users, path, password,
+ level, NULL);
return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
}
@@ -2492,6 +2494,486 @@ rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name,
}
/**
+ * Migrate shares from a remote RPC server to the local RPC srever
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ SRV_SHARE_INFO_CTR ctr_src;
+ ENUM_HND hnd;
+ uint32 type = 0; /* only allow disk shares to be added */
+ uint32 num_uses = 0, perms = 0, max_uses = 0;
+ char *password = NULL; /* don't allow a share password */
+ uint32 preferred_len = 0xffffffff, i;
+ BOOL got_dst_srvsvc_pipe = False;
+ struct cli_state *cli_dst = NULL;
+ uint32 level = 502; /* includes secdesc */
+ SEC_DESC *share_sd = NULL;
+
+ init_enum_hnd(&hnd, 0);
+
+ result = cli_srvsvc_net_share_enum(
+ cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ /* connect local PI_SRVSVC */
+ nt_status = connect_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ for (i = 0; i < ctr_src.num_entries; i++) {
+
+ fstring netname = "", remark = "", path = "";
+ /* reset error-code */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ rpcstr_pull_unistr2_fstring(
+ netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(
+ remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
+ rpcstr_pull_unistr2_fstring(
+ path, &ctr_src.share.info502[i].info_502_str.uni_path);
+ num_uses = ctr_src.share.info502[i].info_502.num_uses;
+ max_uses = ctr_src.share.info502[i].info_502.max_uses;
+ perms = ctr_src.share.info502[i].info_502.perms;
+
+
+ if (opt_acls)
+ share_sd = dup_sec_desc(
+ mem_ctx, ctr_src.share.info502[i].info_502_str.sd);
+
+ /* since we do not have NetShareGetInfo implemented in samba3 we
+ only can skip inside the enum-ctr_src */
+ if (argc == 1) {
+ char *one_share = talloc_strdup(mem_ctx, argv[0]);
+ if (!strequal(netname, one_share))
+ continue;
+ }
+
+ /* skip builtin shares */
+ /* FIXME: should print$ be added too ? */
+ if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
+ strequal(netname,"global"))
+ continue;
+
+ /* only work with file-shares */
+ if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+ d_printf("skipping [%s]: not a file share.\n", netname);
+ continue;
+ }
+
+ if (!cli_tdis(cli))
+ goto done;
+
+
+ /* finallly add the share on the dst server
+ please note that samba currently does not allow to
+ add a share without existing directory */
+
+ printf("migrating: [%s], path: %s, comment: %s, %s share-ACLs\n",
+ netname, path, remark, opt_acls ? "including" : "without" );
+
+ if (opt_verbose && opt_acls)
+ display_sec_desc(share_sd);
+
+ result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type,
+ remark, perms, max_uses,
+ num_uses, path, password,
+ level, share_sd);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
+ printf(" [%s] does already exist\n", netname);
+ continue;
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot add share: %s\n", dos_errstr(result));
+ goto done;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (got_dst_srvsvc_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+
+ return nt_status;
+
+}
+
+/**
+ * Migrate shares from a rpc-server to another
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_share_migrate_shares(int argc, const char **argv)
+{
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SRVSVC, 0,
+ rpc_share_migrate_shares_internals,
+ argc, argv);
+}
+
+typedef struct copy_clistate {
+ TALLOC_CTX *mem_ctx;
+ struct cli_state *cli_share_src;
+ struct cli_state *cli_share_dst;
+ const char *cwd;
+} copy_clistate;
+
+
+/**
+ * Copy a file/dir
+ *
+ * @param f file_info
+ * @param mask current search mask
+ * @param state arg-pointer
+ *
+ **/
+static void copy_fn(file_info *f, const char *mask, void *state)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ struct copy_clistate *local_state = (struct copy_clistate *)state;
+ fstring filename, new_mask, dir;
+
+ if (strequal(f->name, ".") || strequal(f->name, ".."))
+ return;
+
+ DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
+
+ /* DIRECTORY */
+ if (f->mode & aDIR) {
+
+ DEBUG(3,("got dir: %s\n", f->name));
+
+ fstrcpy(dir, local_state->cwd);
+ fstrcat(dir, "\\");
+ fstrcat(dir, f->name);
+
+ /* create that directory */
+ nt_status = net_copy_file(local_state->mem_ctx,
+ local_state->cli_share_src,
+ local_state->cli_share_dst,
+ dir, dir,
+ opt_acls? True : False,
+ opt_attrs? True : False,
+ opt_timestamps? True : False,
+ False);
+
+ if (!NT_STATUS_IS_OK(nt_status))
+ printf("could not copy dir %s: %s\n",
+ dir, nt_errstr(nt_status));
+
+ /* search below that directory */
+ fstrcpy(new_mask, dir);
+ fstrcat(new_mask, "\\*");
+
+ if (!sync_files(local_state->mem_ctx,
+ local_state->cli_share_src,
+ local_state->cli_share_dst,
+ new_mask, dir))
+
+ printf("could not sync files\n");
+
+ return;
+ }
+
+
+ /* FILE */
+ fstrcpy(filename, local_state->cwd);
+ fstrcat(filename, "\\");
+ fstrcat(filename, f->name);
+
+ DEBUG(3,("got file: %s\n", filename));
+
+ nt_status = net_copy_file(local_state->mem_ctx,
+ local_state->cli_share_src,
+ local_state->cli_share_dst,
+ filename, filename,
+ opt_acls? True : False,
+ opt_attrs? True : False,
+ opt_timestamps? True: False,
+ True);
+
+ if (!NT_STATUS_IS_OK(nt_status))
+ printf("could not copy file %s: %s\n",
+ filename, nt_errstr(nt_status));
+
+}
+
+/**
+ * sync files, can be called recursivly to list files
+ * and then call copy_fn for each file
+ *
+ * @param mem_ctx TALLOC_CTX
+ * @param cli_share_src a connected share on the originating server
+ * @param cli_share_dst a connected share on the destination server
+ * @param mask the current search mask
+ * @param cwd the current path
+ *
+ * @return Boolean result
+ **/
+BOOL sync_files(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ pstring mask, fstring cwd)
+
+{
+
+ uint16 attribute = aSYSTEM | aHIDDEN | aDIR;
+ struct copy_clistate clistate;
+
+ clistate.mem_ctx = mem_ctx;
+ clistate.cli_share_src = cli_share_src;
+ clistate.cli_share_dst = cli_share_dst;
+ clistate.cwd = cwd;
+
+ DEBUG(3,("calling cli_list with mask: %s\n", mask));
+
+ if (cli_list(cli_share_src, mask, attribute, copy_fn, &clistate) == -1) {
+ d_printf("listing %s failed with error: %s\n",
+ mask, cli_errstr(cli_share_src));
+ return False;
+ }
+
+ return True;
+}
+
+
+/**
+ * Sync all files inside a remote share to another share (over smb)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passes through.
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ SRV_SHARE_INFO_CTR ctr_src;
+ ENUM_HND hnd;
+ uint32 preferred_len = 0xffffffff, i;
+ uint32 level = 2;
+ struct cli_state *cli_share_src = NULL;
+ struct cli_state *cli_share_dst = NULL;
+ BOOL got_src_share = False;
+ BOOL got_dst_share = False;
+ pstring mask;
+ char *dst = NULL;
+
+ dst = strdup(opt_destination?opt_destination:"127.0.0.1");
+
+ init_enum_hnd(&hnd, 0);
+
+ result = cli_srvsvc_net_share_enum(
+ cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
+
+ if (!W_ERROR_IS_OK(result))
+ goto done;
+
+ for (i = 0; i < ctr_src.num_entries; i++) {
+
+ fstring netname = "", remark = "", path = "";
+
+ rpcstr_pull_unistr2_fstring(
+ netname, &ctr_src.share.info2[i].info_2_str.uni_netname);
+ rpcstr_pull_unistr2_fstring(
+ remark, &ctr_src.share.info2[i].info_2_str.uni_remark);
+ rpcstr_pull_unistr2_fstring(
+ path, &ctr_src.share.info2[i].info_2_str.uni_path);
+
+ /* since we do not have NetShareGetInfo implemented in samba3 we
+ only can skip inside the enum-ctr_src */
+ if (argc == 1) {
+ char *one_share = talloc_strdup(mem_ctx, argv[0]);
+ if (!strequal(netname, one_share))
+ continue;
+ }
+
+ /* skip builtin and hidden shares
+ In particular, one might not want to mirror whole discs :) */
+ if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$"))
+ continue;
+
+ if (strequal(netname, "print$") || netname[1] == '$') {
+ d_printf("skipping [%s]: builtin/hidden share\n", netname);
+ continue;
+ }
+
+ if (opt_exclude && in_list(netname, (char *)opt_exclude, False)) {
+ printf("excluding [%s]\n", netname);
+ continue;
+ }
+
+ /* only work with file-shares */
+ if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
+ d_printf("skipping [%s]: not a file share.\n", netname);
+ continue;
+ }
+
+ if (!cli_tdis(cli))
+ return NT_STATUS_UNSUCCESSFUL;
+
+ printf("syncing [%s] files and directories %s ACLs, %s DOS Attributes %s\n",
+ netname,
+ opt_acls ? "including" : "without",
+ opt_attrs ? "including" : "without",
+ opt_timestamps ? "(preserving timestamps)" : "");
+
+
+ /* open share source */
+ nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
+ cli->desthost, netname, "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+ got_src_share = True;
+
+
+ /* open share destination */
+ nt_status = connect_to_service(&cli_share_dst, NULL,
+ dst, netname, "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+ got_dst_share = True;
+
+
+ /* now call the filesync */
+ pstrcpy(mask, "\\*");
+
+ if (!sync_files(mem_ctx, cli_share_src, cli_share_dst, mask, NULL)) {
+ d_printf("could not sync files for share: %s\n", netname);
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_src_share)
+ cli_shutdown(cli_share_src);
+
+ if (got_dst_share)
+ cli_shutdown(cli_share_dst);
+
+ return nt_status;
+
+}
+
+static int rpc_share_migrate_files(int argc, const char **argv)
+{
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SRVSVC, 0,
+ rpc_share_migrate_files_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
+ * from one server to another
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ *
+ **/
+static int rpc_share_migrate_all(int argc, const char **argv)
+{
+ int ret;
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
+ if (ret)
+ return ret;
+#if 0
+ ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_security_internals, argc, argv);
+ if (ret)
+ return ret;
+#endif
+ return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
+}
+
+
+/**
+ * 'net rpc share migrate' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+static int rpc_share_migrate(int argc, const char **argv)
+{
+
+ struct functable func[] = {
+ {"all", rpc_share_migrate_all},
+ {"files", rpc_share_migrate_files},
+ {"help", rpc_share_usage},
+/* {"security", rpc_share_migrate_security},*/
+ {"shares", rpc_share_migrate_shares},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, rpc_share_usage);
+}
+
+/**
* 'net rpc share' entrypoint.
* @param argc Standard main() style argc
* @param argv Standard main() style argv. Initial components are already
@@ -2503,6 +2985,7 @@ int net_rpc_share(int argc, const char **argv)
struct functable func[] = {
{"add", rpc_share_add},
{"delete", rpc_share_delete},
+ {"migrate", rpc_share_migrate},
{NULL, NULL}
};
@@ -3570,6 +4053,252 @@ static int rpc_vampire(int argc, const char **argv) {
return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
argc, argv);
}
+
+/**
+ * Migrate everything from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ *
+ * The order is important !
+ * To successfully add drivers the print-queues have to exist !
+ * Applying ACLs should be the last step, because you're easily locked out
+ *
+ **/
+static int rpc_printer_migrate_all(int argc, const char **argv)
+{
+ int ret;
+
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
+ if (ret)
+ return ret;
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
+
+}
+
+/**
+ * Migrate print-drivers from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_drivers(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_drivers_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate print-forms from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_forms(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_forms_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate printers from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_printers(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_printers_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate printer-ACLs from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_security(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_security_internals,
+ argc, argv);
+}
+
+/**
+ * Migrate printer-settings from a print-server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_migrate_settings(int argc, const char **argv)
+{
+ if (!opt_host) {
+ printf("no server to migrate\n");
+ return -1;
+ }
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_migrate_settings_internals,
+ argc, argv);
+}
+
+/**
+ * 'net rpc printer' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+
+int rpc_printer_migrate(int argc, const char **argv)
+{
+
+ /* ouch: when addriver and setdriver are called from within
+ rpc_printer_migrate_drivers_internals, the printer-queue already
+ *has* to exist */
+
+ struct functable func[] = {
+ {"all", rpc_printer_migrate_all},
+ {"drivers", rpc_printer_migrate_drivers},
+ {"forms", rpc_printer_migrate_forms},
+ {"help", rpc_printer_usage},
+ {"printers", rpc_printer_migrate_printers},
+ {"security", rpc_printer_migrate_security},
+ {"settings", rpc_printer_migrate_settings},
+ {NULL, NULL}
+ };
+
+ return net_run_function(argc, argv, func, rpc_printer_usage);
+}
+
+
+/**
+ * List printers on a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_list(int argc, const char **argv)
+{
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_list_internals,
+ argc, argv);
+}
+
+/**
+ * List printer-drivers on a remote RPC server
+ *
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_driver_list(int argc, const char **argv)
+{
+
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_driver_list_internals,
+ argc, argv);
+}
+
+/**
+ * Display rpc printer help page.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+int rpc_printer_usage(int argc, const char **argv)
+{
+ return net_help_printer(argc, argv);
+}
+
+/**
+ * 'net rpc printer' entrypoint.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ **/
+int net_rpc_printer(int argc, const char **argv)
+{
+ struct functable func[] = {
+ {"list", rpc_printer_list},
+ {"migrate", rpc_printer_migrate},
+ {"driver", rpc_printer_driver_list},
+ {NULL, NULL}
+ };
+
+ if (argc == 0)
+ return run_rpc_command(NULL, PI_SPOOLSS, 0,
+ rpc_printer_list_internals,
+ argc, argv);
+
+ return net_run_function(argc, argv, func, rpc_printer_usage);
+}
+
/****************************************************************************/
@@ -3589,7 +4318,8 @@ int net_rpc_usage(int argc, const char **argv)
d_printf(" net rpc user \t\t\tto add, delete and list users\n");
d_printf(" net rpc password <username> [<password>] -Uadmin_username%%admin_pass");
d_printf(" net rpc group \t\tto list groups\n");
- d_printf(" net rpc share \t\tto add, delete, and list shares\n");
+ d_printf(" net rpc share \t\tto add, delete, list and migrate shares\n");
+ d_printf(" net rpc printer \t\tto list and migrate printers\n");
d_printf(" net rpc file \t\t\tto list open files\n");
d_printf(" net rpc changetrustpw \tto change the trust account password\n");
d_printf(" net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
@@ -3659,6 +4389,7 @@ int net_rpc(int argc, const char **argv)
{"group", net_rpc_group},
{"share", net_rpc_share},
{"file", net_rpc_file},
+ {"printer", net_rpc_printer},
{"changetrustpw", net_rpc_changetrustpw},
{"trustdom", rpc_trustdom},
{"abortshutdown", rpc_shutdown_abort},
diff --git a/source/utils/net_rpc_printer.c b/source/utils/net_rpc_printer.c
new file mode 100644
index 00000000000..51f4df7b05a
--- /dev/null
+++ b/source/utils/net_rpc_printer.c
@@ -0,0 +1,2339 @@
+/*
+ Samba Unix/Linux SMB client library
+ Distributed SMB/CIFS Server Management Utility
+ Copyright (C) 2004 Guenther Deschner (gd@samba.org)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "includes.h"
+#include "../utils/net.h"
+
+struct table_node {
+ const char *long_archi;
+ const char *short_archi;
+ int version;
+};
+
+
+/* support itanium as well */
+static const struct table_node archi_table[]= {
+
+ {"Windows 4.0", "WIN40", 0 },
+ {"Windows NT x86", "W32X86", 2 },
+ {"Windows NT R4000", "W32MIPS", 2 },
+ {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
+ {"Windows NT PowerPC", "W32PPC", 2 },
+ {"Windows IA64", "IA64", 3 },
+ {NULL, "", -1 }
+};
+
+
+/**
+ * The display-functions for Security-Descriptors were taken from rpcclient
+ *
+ * They reside here for debugging purpose and should
+ * possibly be removed later on
+ *
+ **/
+/****************************************************************************
+convert a security permissions into a string
+****************************************************************************/
+char *get_sec_mask_str(uint32 type)
+{
+ static fstring typestr="";
+
+ typestr[0] = 0;
+
+ if (type & GENERIC_ALL_ACCESS)
+ fstrcat(typestr, "Generic all access ");
+ if (type & GENERIC_EXECUTE_ACCESS)
+ fstrcat(typestr, "Generic execute access ");
+ if (type & GENERIC_WRITE_ACCESS)
+ fstrcat(typestr, "Generic write access ");
+ if (type & GENERIC_READ_ACCESS)
+ fstrcat(typestr, "Generic read access ");
+ if (type & MAXIMUM_ALLOWED_ACCESS)
+ fstrcat(typestr, "MAXIMUM_ALLOWED_ACCESS ");
+ if (type & SYSTEM_SECURITY_ACCESS)
+ fstrcat(typestr, "SYSTEM_SECURITY_ACCESS ");
+ if (type & SYNCHRONIZE_ACCESS)
+ fstrcat(typestr, "SYNCHRONIZE_ACCESS ");
+ if (type & WRITE_OWNER_ACCESS)
+ fstrcat(typestr, "WRITE_OWNER_ACCESS ");
+ if (type & WRITE_DAC_ACCESS)
+ fstrcat(typestr, "WRITE_DAC_ACCESS ");
+ if (type & READ_CONTROL_ACCESS)
+ fstrcat(typestr, "READ_CONTROL_ACCESS ");
+ if (type & DELETE_ACCESS)
+ fstrcat(typestr, "DELETE_ACCESS ");
+
+ printf("\t\tSpecific bits: 0x%lx\n", (unsigned long)type&SPECIFIC_RIGHTS_MASK);
+
+ return typestr;
+}
+
+
+/****************************************************************************
+ display sec_ace structure
+ ****************************************************************************/
+void display_sec_ace(SEC_ACE *ace)
+{
+ fstring sid_str;
+
+ printf("\tACE\n\t\ttype: ");
+ switch (ace->type) {
+ case SEC_ACE_TYPE_ACCESS_ALLOWED:
+ printf("ACCESS ALLOWED");
+ break;
+ case SEC_ACE_TYPE_ACCESS_DENIED:
+ printf("ACCESS DENIED");
+ break;
+ case SEC_ACE_TYPE_SYSTEM_AUDIT:
+ printf("SYSTEM AUDIT");
+ break;
+ case SEC_ACE_TYPE_SYSTEM_ALARM:
+ printf("SYSTEM ALARM");
+ break;
+ default:
+ printf("????");
+ break;
+ }
+ printf(" (%d) flags: %d\n", ace->type, ace->flags);
+ printf("\t\tPermissions: 0x%x: %s\n", ace->info.mask, get_sec_mask_str(ace->info.mask));
+
+ sid_to_string(sid_str, &ace->trustee);
+ printf("\t\tSID: %s\n\n", sid_str);
+}
+
+
+/****************************************************************************
+ display sec_acl structure
+ ****************************************************************************/
+void display_sec_acl(SEC_ACL *sec_acl)
+{
+ int i;
+
+ printf("\tACL\tNum ACEs:\t%d\trevision:\t%x\n",
+ sec_acl->num_aces, sec_acl->revision);
+ printf("\t---\n");
+
+ if (sec_acl->size != 0 && sec_acl->num_aces != 0)
+ for (i = 0; i < sec_acl->num_aces; i++)
+ display_sec_ace(&sec_acl->ace[i]);
+
+}
+
+/****************************************************************************
+ display sec_desc structure
+ ****************************************************************************/
+void display_sec_desc(SEC_DESC *sec)
+{
+ fstring sid_str;
+
+ if (sec == NULL)
+ return;
+
+ if (sec->sacl) {
+ printf("SACL\n");
+ display_sec_acl(sec->sacl);
+ }
+
+ if (sec->dacl) {
+ printf("DACL\n");
+ display_sec_acl(sec->dacl);
+ }
+
+ if (sec->owner_sid) {
+ sid_to_string(sid_str, sec->owner_sid);
+ printf("\tOwner SID:\t%s\n", sid_str);
+ }
+
+ if (sec->grp_sid) {
+ sid_to_string(sid_str, sec->grp_sid);
+ printf("\tParent SID:\t%s\n", sid_str);
+ }
+}
+
+
+/**
+ * This display-printdriver-functions was borrowed from rpcclient/cmd_spoolss.c.
+ * It is here for debugging purpose and should be removed later on.
+ **/
+
+/****************************************************************************
+printer info level 3 display function
+****************************************************************************/
+static void display_print_driver_3(DRIVER_INFO_3 *i1)
+{
+ fstring name = "";
+ fstring architecture = "";
+ fstring driverpath = "";
+ fstring datafile = "";
+ fstring configfile = "";
+ fstring helpfile = "";
+ fstring dependentfiles = "";
+ fstring monitorname = "";
+ fstring defaultdatatype = "";
+
+ int length=0;
+ BOOL valid = True;
+
+ if (i1 == NULL)
+ return;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
+ rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
+ rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
+ rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+ rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
+ rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
+ rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
+
+ d_printf ("Printer Driver Info 3:\n");
+ d_printf ("\tVersion: [%x]\n", i1->version);
+ d_printf ("\tDriver Name: [%s]\n",name);
+ d_printf ("\tArchitecture: [%s]\n", architecture);
+ d_printf ("\tDriver Path: [%s]\n", driverpath);
+ d_printf ("\tDatafile: [%s]\n", datafile);
+ d_printf ("\tConfigfile: [%s]\n", configfile);
+ d_printf ("\tHelpfile: [%s]\n\n", helpfile);
+
+ while (valid) {
+ rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
+
+ length+=strlen(dependentfiles)+1;
+
+ if (strlen(dependentfiles) > 0) {
+ d_printf ("\tDependentfiles: [%s]\n", dependentfiles);
+ } else {
+ valid = False;
+ }
+ }
+
+ printf ("\n");
+
+ d_printf ("\tMonitorname: [%s]\n", monitorname);
+ d_printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
+
+ return;
+}
+
+
+static void display_reg_value(pstring subkey, REGISTRY_VALUE value)
+{
+ pstring text;
+
+ switch(value.type) {
+ case REG_DWORD:
+ d_printf("\t[%s:%s]: REG_DWORD: 0x%08x\n", subkey, value.valuename,
+ *((uint32 *) value.data_p));
+ break;
+
+ case REG_SZ:
+ rpcstr_pull(text, value.data_p, sizeof(text), value.size,
+ STR_TERMINATE);
+ d_printf("\t[%s:%s]: REG_SZ: %s\n", subkey, value.valuename, text);
+ break;
+
+ case REG_BINARY:
+ d_printf("\t[%s:%s]: REG_BINARY: unknown length value not displayed\n",
+ subkey, value.valuename);
+ break;
+
+ case REG_MULTI_SZ: {
+ uint16 *curstr = (uint16 *) value.data_p;
+ uint8 *start = value.data_p;
+ d_printf("\t[%s:%s]: REG_MULTI_SZ:\n", subkey, value.valuename);
+ while ((*curstr != 0) &&
+ ((uint8 *) curstr < start + value.size)) {
+ rpcstr_pull(text, curstr, sizeof(text), -1,
+ STR_TERMINATE);
+ d_printf("%s\n", text);
+ curstr += strlen(text) + 1;
+ }
+ }
+ break;
+
+ default:
+ d_printf("\t%s: unknown type %d\n", value.valuename, value.type);
+ }
+
+}
+
+
+/**
+ * Copies ACLs, DOS-attributes and timestamps from one
+ * file or directory from one connected share to another connected share
+ *
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A connected cli_state
+ * @param cli_share_dst A connected cli_state
+ * @param src_file The source file-name
+ * @param dst_file The destination file-name
+ * @param copy_acls Whether to copy acls
+ * @param copy_attrs Whether to copy DOS attributes
+ * @param copy_timestamps Whether to preserve timestamps
+ * @param is_file Whether this file is a file or a dir
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+net_copy_fileattr(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ char *src_name, char *dst_name,
+ BOOL copy_acls, BOOL copy_attrs,
+ BOOL copy_timestamps, BOOL is_file)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int fnum_src = 0;
+ int fnum_dst = 0;
+ SEC_DESC *sd = NULL;
+ uint16 attr;
+ time_t atime, ctime, mtime;
+
+
+ if (!copy_timestamps && !copy_acls && !copy_attrs)
+ return NT_STATUS_OK;
+
+
+ /* open file/dir on the originating server */
+
+ DEBUGADD(3,("opening %s %s on originating server\n",
+ is_file?"file":"dir", src_name));
+
+ fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
+ if (fnum_src == -1) {
+ DEBUGADD(0,("cannot open %s %s on originating server %s\n",
+ is_file?"file":"dir", src_name, cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+
+ if (copy_acls) {
+
+ /* get the security descriptor */
+ sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx);
+ if (!sd) {
+ DEBUG(0,("failed to get security descriptor: %s\n",
+ cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+ if (opt_verbose && DEBUGLEVEL >= 3)
+ display_sec_desc(sd);
+ }
+
+
+ if (copy_attrs || copy_timestamps) {
+
+ /* get file attributes */
+ if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL,
+ &ctime, &atime, &mtime)) {
+ DEBUG(0,("failed to get file-attrs: %s\n",
+ cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+ }
+
+
+ /* open the file/dir on the destination server */
+
+ fnum_dst = cli_nt_create(cli_share_dst, dst_name, WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS);
+ if (fnum_dst == -1) {
+ DEBUG(0,("failed to open %s on the destination server: %s: %s\n",
+ is_file?"file":"dir", dst_name, cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ if (copy_timestamps) {
+
+ /* set timestamps */
+ if (!cli_setattrE(cli_share_dst, fnum_dst, ctime, atime, mtime)) {
+ DEBUG(0,("failed to set file-attrs (timestamps): %s\n",
+ cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+ }
+
+ if (copy_acls) {
+
+ /* set acls */
+ if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) {
+ DEBUG(0,("could not set secdesc on %s: %s\n",
+ dst_name, cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+ }
+
+ if (copy_attrs) {
+
+ /* set attrs */
+ if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) {
+ DEBUG(0,("failed to set file-attrs: %s\n",
+ cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+ }
+
+
+ /* closing files */
+
+ if (!cli_close(cli_share_src, fnum_src)) {
+ d_printf("could not close %s on originating server: %s\n",
+ is_file?"file":"dir", cli_errstr(cli_share_src));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+ if (!cli_close(cli_share_dst, fnum_dst)) {
+ d_printf("could not close %s on destination server: %s\n",
+ is_file?"file":"dir", cli_errstr(cli_share_dst));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+
+ nt_status = NT_STATUS_OK;
+
+out:
+
+ /* cleaning up */
+ if (fnum_src)
+ cli_close(cli_share_src, fnum_src);
+
+ if (fnum_dst)
+ cli_close(cli_share_dst, fnum_dst);
+
+ return nt_status;
+}
+
+
+/**
+ * Copy a file or directory from a connected share to another connected share
+ *
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A connected cli_state
+ * @param cli_share_dst A connected cli_state
+ * @param src_file The source file-name
+ * @param dst_file The destination file-name
+ * @param copy_acls Whether to copy acls
+ * @param copy_attrs Whether to copy DOS attributes
+ * @param copy_timestamps Whether to preserve timestamps
+ * @param is_file Whether this file is a file or a dir
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ char *src_name, char *dst_name,
+ BOOL copy_acls, BOOL copy_attrs,
+ BOOL copy_timestamps, BOOL is_file)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int fnum_src = 0;
+ int fnum_dst = 0;
+ static int io_bufsize = 64512;
+ int read_size = io_bufsize;
+ char *data = NULL;
+ off_t start = 0;
+ off_t nread = 0;
+
+
+ if (!src_name || !dst_name)
+ goto out;
+
+ if (cli_share_dst == NULL || cli_share_dst == NULL)
+ goto out;
+
+
+ /* open on the originating server */
+ DEBUGADD(3,("opening %s %s on originating server\n",
+ is_file ? "file":"dir", src_name));
+ if (is_file)
+ fnum_src = cli_open(cli_share_src, src_name, O_RDONLY, DENY_NONE);
+ else
+ fnum_src = cli_nt_create(cli_share_src, src_name, READ_CONTROL_ACCESS);
+
+ if (fnum_src == -1) {
+ DEBUGADD(0,("cannot open file %s on originating server %s\n",
+ src_name, cli_errstr(cli_share_src)));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+
+ if (is_file) {
+
+ /* open file on the destination server */
+ DEBUGADD(3,("opening file %s on destination server\n", dst_name));
+ fnum_dst = cli_open(cli_share_dst, dst_name,
+ O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+
+ if (fnum_dst == -1) {
+ DEBUGADD(1,("cannot create file %s on destination server: %s\n",
+ dst_name, cli_errstr(cli_share_dst)));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ /* allocate memory */
+ if (!(data = (char *)malloc(read_size))) {
+ d_printf("malloc fail for size %d\n", read_size);
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ }
+
+
+ if (opt_verbose) {
+
+ d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] "
+ "%s ACLs and %s DOS Attributes %s\n",
+ cli_share_src->desthost, cli_share_src->share, src_name,
+ cli_share_dst->desthost, cli_share_dst->share, dst_name,
+ copy_acls ? "with" : "without",
+ copy_attrs ? "with" : "without",
+ copy_timestamps ? "(preserving timestamps)" : "" );
+ }
+
+
+ while (is_file) {
+
+ /* copying file */
+ int n, ret;
+ n = cli_read(cli_share_src, fnum_src, data, nread + start,
+ read_size);
+
+ if (n <= 0)
+ break;
+
+ ret = cli_write(cli_share_dst, fnum_dst, 0, data,
+ nread + start, n);
+
+ if (n != ret) {
+ d_printf("Error writing file: %s\n",
+ cli_errstr(cli_share_dst));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ nread += n;
+ }
+
+
+ if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) {
+
+ /* creating dir */
+ DEBUGADD(3,("creating dir %s on the destination server\n",
+ dst_name));
+
+ if (!cli_mkdir(cli_share_dst, dst_name)) {
+ DEBUG(0,("cannot create directory %s: %s\n",
+ dst_name, cli_errstr(cli_share_dst)));
+ nt_status = NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!cli_chkpath(cli_share_dst, dst_name)) {
+ d_printf("cannot check for directory %s: %s\n",
+ dst_name, cli_errstr(cli_share_dst));
+ goto out;
+ }
+ }
+
+
+ /* closing files */
+ if (!cli_close(cli_share_src, fnum_src)) {
+ d_printf("could not close file on originating server: %s\n",
+ cli_errstr(cli_share_src));
+ nt_status = cli_nt_error(cli_share_src);
+ goto out;
+ }
+
+ if (is_file && !cli_close(cli_share_dst, fnum_dst)) {
+ d_printf("could not close file on destination server: %s\n",
+ cli_errstr(cli_share_dst));
+ nt_status = cli_nt_error(cli_share_dst);
+ goto out;
+ }
+
+ /* possibly we have to copy some file-attributes / acls / sd */
+ nt_status = net_copy_fileattr(mem_ctx, cli_share_src, cli_share_dst,
+ src_name, dst_name, copy_acls,
+ copy_attrs, copy_timestamps, is_file);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto out;
+
+
+ nt_status = NT_STATUS_OK;
+
+out:
+
+ /* cleaning up */
+ if (fnum_src)
+ cli_close(cli_share_src, fnum_src);
+
+ if (fnum_dst)
+ cli_close(cli_share_dst, fnum_dst);
+
+ SAFE_FREE(data);
+
+ return nt_status;
+}
+
+
+/**
+ * Copy a driverfile from on connected share to another connected share
+ * This silently assumes that a driver-file is picked up from
+ *
+ * \\src_server\print$\{arch}\{version}\file
+ *
+ * and copied to
+ *
+ * \\dst_server\print$\{arch}\file
+ *
+ * to be added via setdriver-calls later.
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A cli_state connected to source print$-share
+ * @param cli_share_dst A cli_state connected to destination print$-share
+ * @param file The file-name to be copied
+ * @param short_archi The name of the driver-architecture (short form)
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ char *file, const char *short_archi) {
+
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ const char *p;
+ char *src_name;
+ char *dst_name;
+ fstring version;
+ fstring filename;
+ fstring tok;
+
+ /* scroll through the file until we have the part
+ beyond archi_table.short_archi */
+ p = file;
+ while (next_token(&p, tok, "\\", sizeof(tok))) {
+ if (strequal(tok, short_archi)) {
+ next_token(&p, version, "\\", sizeof(version));
+ next_token(&p, filename, "\\", sizeof(filename));
+ }
+ }
+
+ /* build source file name */
+ if (asprintf(&src_name, "\\%s\\%s\\%s", short_archi, version, filename) < 0 )
+ return NT_STATUS_NO_MEMORY;
+
+
+ /* create destination file name */
+ if (asprintf(&dst_name, "\\%s\\%s", short_archi, filename) < 0 )
+ return NT_STATUS_NO_MEMORY;
+
+
+ /* finally copy the file */
+ nt_status = net_copy_file(mem_ctx, cli_share_src, cli_share_dst,
+ src_name, dst_name, False, False, False, True);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto out;
+
+ nt_status = NT_STATUS_OK;
+
+out:
+ SAFE_FREE(src_name);
+ SAFE_FREE(dst_name);
+
+ return nt_status;
+}
+
+
+/**
+ * Check for existing Architecture directory on a given server
+ *
+ * @param cli_share A cli_state connected to a print$-share
+ * @param short_archi The Architecture for the print-driver
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+check_arch_dir(struct cli_state *cli_share, const char *short_archi)
+{
+
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ char *dir;
+
+ if (asprintf(&dir, "\\%s", short_archi) < 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ DEBUG(10,("creating print-driver dir for architecture: %s\n",
+ short_archi));
+
+ if (!cli_mkdir(cli_share, dir)) {
+ DEBUG(1,("cannot create directory %s: %s\n",
+ dir, cli_errstr(cli_share)));
+ nt_status = NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (!cli_chkpath(cli_share, dir)) {
+ d_printf("cannot check %s: %s\n",
+ dir, cli_errstr(cli_share));
+ goto out;
+ }
+
+ nt_status = NT_STATUS_OK;
+
+out:
+ SAFE_FREE(dir);
+ return nt_status;
+}
+
+
+/**
+ * Copy a print-driver (level 3) from one connected print$-share to another
+ * connected print$-share
+ *
+ * @param mem_ctx A talloc-context
+ * @param cli_share_src A cli_state connected to a print$-share
+ * @param cli_share_dst A cli_state connected to a print$-share
+ * @param short_archi The Architecture for the print-driver
+ * @param i1 The DRIVER_INFO_3-struct
+ *
+ * @return Normal NTSTATUS return.
+ **/
+static NTSTATUS
+copy_print_driver_3(TALLOC_CTX *mem_ctx,
+ struct cli_state *cli_share_src,
+ struct cli_state *cli_share_dst,
+ const char *short_archi, DRIVER_INFO_3 *i1)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int length = 0;
+ BOOL valid = True;
+
+ fstring name = "";
+ fstring driverpath = "";
+ fstring datafile = "";
+ fstring configfile = "";
+ fstring helpfile = "";
+ fstring dependentfiles = "";
+
+ if (i1 == NULL)
+ return nt_status;
+
+ rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+ rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
+ rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
+ rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+ rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
+
+
+ if (opt_verbose)
+ d_printf("copying driver: [%s], for architecture: [%s], version: [%d]\n",
+ name, short_archi, i1->version);
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ driverpath, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ datafile, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ configfile, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ nt_status = net_copy_driverfile(mem_ctx, cli_share_src, cli_share_dst,
+ helpfile, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ while (valid) {
+ rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
+ length+=strlen(dependentfiles)+1;
+ if (strlen(dependentfiles) > 0) {
+
+ nt_status = net_copy_driverfile(mem_ctx,
+ cli_share_src, cli_share_dst,
+ dependentfiles, short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+ } else {
+ valid = False;
+ }
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ * net_spoolss-functions
+ * =====================
+ *
+ * the net_spoolss-functions aim to simplify spoolss-client-functions
+ * required during the migration-process wrt buffer-sizes, returned
+ * error-codes, etc.
+ *
+ * this greatly reduces the complexitiy of the migrate-functions.
+ *
+ **/
+
+static BOOL
+net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ char *name, uint32 flags, uint32 level,
+ uint32 *num_printers, PRINTER_INFO_CTR *ctr)
+{
+
+ WERROR result;
+ uint32 needed;
+
+ /* enum printers */
+ result = cli_spoolss_enum_printers(
+ cli, mem_ctx, 0, &needed, name, flags,
+ level, num_printers, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_enum_printers(
+ cli, mem_ctx, needed, NULL, name, flags,
+ level, num_printers, ctr);
+
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot enum printers: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ const char *printername, const char *datatype,
+ uint32 access_required, const char *servername,
+ const char *username, POLICY_HND *hnd)
+{
+ WERROR result;
+
+ fstring servername2;
+ slprintf(servername2, sizeof(servername2)-1, "\\\\%s", cli->desthost);
+
+ DEBUG(10,("connecting to: %s as %s for %s and access: %x\n",
+ servername2, username, printername, access_required));
+
+ /* open printer */
+ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+ "", access_required,
+ servername2, username, hnd);
+
+ /* be more verbose */
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
+ d_printf("no access to printer [%s] on [%s] for user [%s] granted\n",
+ printername, servername2, username);
+ return False;
+ }
+
+ if (!W_ERROR_IS_OK(result)) {
+ d_printf("cannot open printer %s on server %s: %s\n",
+ printername, servername2, dos_errstr(result));
+ return False;
+ }
+
+ DEBUG(2,("got printer handle for printer: %s, server: %s\n",
+ printername, servername2));
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 level,
+ PRINTER_INFO_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* getprinter call */
+ result = cli_spoolss_getprinter(cli,
+ mem_ctx, 0, &needed, hnd, level, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_getprinter(cli,
+ mem_ctx, needed, NULL, hnd, level, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot get printer-info: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 level,
+ PRINTER_INFO_CTR *ctr)
+{
+ WERROR result;
+
+ /* setprinter call */
+ result = cli_spoolss_setprinter(cli, mem_ctx, hnd, level, ctr, 0);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot set printer-info: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, REGISTRY_VALUE *value)
+{
+ WERROR result;
+
+ /* setprinterdata call */
+ result = cli_spoolss_setprinterdata(cli, mem_ctx, hnd, value);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf ("unable to set printerdata: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, const char *keyname,
+ uint16 **keylist)
+{
+ WERROR result;
+ uint32 needed, len;
+
+ /* enumprinterkey call */
+ result = cli_spoolss_enumprinterkey(
+ cli, mem_ctx, 0, &needed, hnd, keyname, NULL, NULL);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
+ result = cli_spoolss_enumprinterkey(
+ cli, mem_ctx, needed, NULL, hnd, keyname, keylist,
+ &len);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("enumprinterkey failed: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 offered,
+ POLICY_HND *hnd, const char *keyname,
+ REGVAL_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* enumprinterdataex call */
+ result = cli_spoolss_enumprinterdataex(
+ cli, mem_ctx, 0, &needed, hnd, keyname, NULL);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_MORE_DATA))
+ result = cli_spoolss_enumprinterdataex(
+ cli, mem_ctx, needed, NULL, hnd, keyname, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("enumprinterdataex failed: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, char *keyname,
+ REGISTRY_VALUE *value)
+{
+ WERROR result;
+
+ /* setprinterdataex call */
+ result = cli_spoolss_setprinterdataex(cli, mem_ctx, hnd,
+ keyname, value);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("could not set printerdataex: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, int level, uint32 *num_forms,
+ FORM_1 **forms)
+
+{
+ WERROR result;
+ uint32 needed;
+
+ /* enumforms call */
+ result = cli_spoolss_enumforms(
+ cli, mem_ctx, 0, &needed, hnd, level, num_forms, forms);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_enumforms(
+ cli, mem_ctx, needed, NULL, hnd, level,
+ num_forms, forms);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("could not enum forms: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ uint32 level, const char *env,
+ uint32 *num_drivers,
+ PRINTER_DRIVER_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* enumprinterdrivers call */
+ result = cli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, 0, &needed, level,
+ env, num_drivers, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_enumprinterdrivers(
+ cli, mem_ctx, needed, NULL, level,
+ env, num_drivers, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot enum drivers: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_getprinterdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ POLICY_HND *hnd, uint32 level,
+ const char *env, int version,
+ PRINTER_DRIVER_CTR *ctr)
+{
+ WERROR result;
+ uint32 needed;
+
+ /* getprinterdriver call */
+ result = cli_spoolss_getprinterdriver(
+ cli, mem_ctx, 0, &needed, hnd, level,
+ env, version, ctr);
+
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_INSUFFICIENT_BUFFER))
+ result = cli_spoolss_getprinterdriver(
+ cli, mem_ctx, needed, NULL, hnd, level,
+ env, version, ctr);
+
+ if (!W_ERROR_IS_OK(result)) {
+ DEBUG(1,("cannot get driver (for architecture: %s): %s\n",
+ env, dos_errstr(result)));
+ if (W_ERROR_V(result) != W_ERROR_V(WERR_UNKNOWN_PRINTER_DRIVER)) {
+ printf("cannot get driver: %s\n", dos_errstr(result));
+ }
+ return False;
+ }
+
+ return True;
+}
+
+
+static BOOL
+net_spoolss_addprinterdriver(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, uint32 level,
+ PRINTER_DRIVER_CTR *ctr)
+{
+ WERROR result;
+
+ /* addprinterdriver call */
+ result = cli_spoolss_addprinterdriver(cli, mem_ctx, level, ctr);
+
+ /* be more verbose */
+ if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
+ printf("You are not allowed to add drivers\n");
+ return False;
+ }
+ if (!W_ERROR_IS_OK(result)) {
+ printf("cannot add driver: %s\n", dos_errstr(result));
+ return False;
+ }
+
+ return True;
+}
+
+/**
+ * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr
+ * for a single printer or for all printers depending on argc/argv
+ **/
+static BOOL
+get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int level, int argc, const char **argv,
+ uint32 *num_printers, PRINTER_INFO_CTR *ctr)
+{
+
+ char *sharename;
+ fstring servername;
+ POLICY_HND hnd;
+
+ /* no arguments given, enumerate all printers */
+ if (argc == 0) {
+
+ if (!net_spoolss_enum_printers(cli, mem_ctx, NULL,
+ PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED,
+ level, num_printers, ctr))
+ return False;
+
+ goto out;
+ }
+
+
+ /* argument given, get a single printer by name */
+ sharename = strdup(argv[0]);
+
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername,
+ cli->user_name, &hnd))
+ return False;
+
+ if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, ctr)) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+ return False;
+ }
+
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+
+ *num_printers = 1;
+
+out:
+ DEBUG(3,("got %d printers\n", *num_printers));
+
+ return True;
+
+}
+
+
+/**
+ * List print-queues (including local printers that are not shared)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i, num_printers;
+ uint32 level = 2;
+ pstring printername, sharename;
+ PRINTER_INFO_CTR ctr;
+
+ printf("listing printers\n");
+
+ if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr))
+ return nt_status;
+
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+
+ d_printf("printer %d: %s, shared as: %s\n",
+ i+1, printername, sharename);
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/**
+ * List printer-drivers from a server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i;
+ uint32 level = 3;
+ PRINTER_DRIVER_CTR drv_ctr_enum;
+ int d;
+
+ ZERO_STRUCT(drv_ctr_enum);
+
+
+ printf("listing printer-drivers\n");
+
+ for (i=0; archi_table[i].long_archi!=NULL; i++) {
+
+ int num_drivers;
+
+ /* enum remote drivers */
+ if (!net_spoolss_enumprinterdrivers(cli, mem_ctx, level,
+ archi_table[i].long_archi,
+ &num_drivers, &drv_ctr_enum)) {
+
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (num_drivers == 0) {
+ d_printf ("no drivers found on server for architecture: [%s].\n",
+ archi_table[i].long_archi);
+ continue;
+ }
+
+ d_printf("got %d printer-drivers for architecture: [%s]\n",
+ num_drivers, archi_table[i].long_archi);
+
+
+ /* do something for all drivers for architecture */
+ for (d = 0; d < num_drivers; d++) {
+ display_print_driver_3(&(drv_ctr_enum.info3[d]));
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ return nt_status;
+
+}
+
+
+/**
+ * Migrate Printer-ACLs from a source server to the destination server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ /* TODO: what now, info2 or info3 ?
+ convince jerry that we should add clientside setacls level 3 at least
+ */
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i = 0;
+ uint32 num_printers;
+ uint32 level = 2;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
+ struct cli_state *cli_dst = NULL;
+
+ ZERO_STRUCT(ctr_src);
+
+ DEBUG(3,("copying printer ACLs\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum source printers */
+ if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* we can reset NT_STATUS here because we do not
+ get any real NT_STATUS-codes anymore from now on */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ d_printf("migrating printer ACLs for: [%s] / [%s]\n",
+ printername, sharename);
+
+ /* according to msdn you have specify these access-rights
+ to see the security descriptor
+ - READ_CONTROL (DACL)
+ - ACCESS_SYSTEM_SECURITY (SACL)
+ */
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli_dst->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
+ goto done;
+
+ /* check for existing src printer */
+ if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, 3, &ctr_src))
+ goto done;
+
+
+ /* Copy Security Descriptor */
+
+ /* copy secdesc (info level 2) */
+ ctr_dst.printers_2->devmode = NULL;
+ ctr_dst.printers_2->secdesc = dup_sec_desc(mem_ctx, ctr_src.printers_3->secdesc);
+
+ if (opt_verbose)
+ display_sec_desc(ctr_dst.printers_2->secdesc);
+
+ if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &ctr_dst))
+ goto done;
+
+ DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
+
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+}
+
+
+/**
+ * Migrate printer-forms from a src server to the dst server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ WERROR result;
+ uint32 i, f;
+ uint32 num_printers;
+ uint32 level = 1;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_INFO_CTR ctr_enum, ctr_dst;
+ uint32 num_forms;
+ FORM_1 *forms;
+ struct cli_state *cli_dst = NULL;
+
+ ZERO_STRUCT(ctr_enum);
+
+ DEBUG(3,("copying forms\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum src printers */
+ if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* we can reset NT_STATUS here because we do not
+ get any real NT_STATUS-codes anymore from now on */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ d_printf("migrating printer forms for: [%s] / [%s]\n",
+ printername, sharename);
+
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst))
+ goto done;
+
+ /* finally migrate forms */
+ if (!net_spoolss_enumforms(cli, mem_ctx, &hnd_src, level, &num_forms, &forms))
+ goto done;
+
+ DEBUG(1,("got %d forms for printer\n", num_forms));
+
+
+ for (f = 0; f < num_forms; f++) {
+
+ FORM form;
+ fstring form_name;
+
+ /* only migrate FORM_PRINTER types, according to jerry
+ FORM_BUILTIN-types are hard-coded in samba */
+ if (forms[f].flag != FORM_PRINTER)
+ continue;
+
+ if (forms[f].name.buffer)
+ rpcstr_pull(form_name, forms[f].name.buffer,
+ sizeof(form_name), -1, STR_TERMINATE);
+
+ if (opt_verbose)
+ d_printf("\tmigrating form # %d [%s] of type [%d]\n",
+ f, form_name, forms[f].flag);
+
+ /* is there a more elegant way to do that ? */
+ form.flags = FORM_PRINTER;
+ form.size_x = forms[f].width;
+ form.size_y = forms[f].length;
+ form.left = forms[f].left;
+ form.top = forms[f].top;
+ form.right = forms[f].right;
+ form.bottom = forms[f].bottom;
+
+ init_unistr2(&form.name, form_name, UNI_STR_TERMINATE);
+
+ /* FIXME: there might be something wrong with samba's
+ builtin-forms */
+ result = cli_spoolss_addform(cli_dst, mem_ctx,
+ &hnd_dst, 1, &form);
+ if (!W_ERROR_IS_OK(result)) {
+ d_printf("\tAddForm form %d: [%s] refused.\n",
+ f, form_name);
+ continue;
+ }
+
+ DEBUGADD(1,("\tAddForm of [%s] succeeded\n", form_name));
+ }
+
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+
+}
+
+
+/**
+ * Migrate printer-drivers from a src server to the dst server
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i, p;
+ uint32 num_printers;
+ uint32 level = 3;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ BOOL got_src_driver_share = False;
+ BOOL got_dst_driver_share = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
+ PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
+ struct cli_state *cli_dst = NULL;
+ struct cli_state *cli_share_src = NULL;
+ struct cli_state *cli_share_dst = NULL;
+ fstring drivername = "";
+
+ ZERO_STRUCT(drv_ctr_src);
+ ZERO_STRUCT(drv_ctr_dst);
+ ZERO_STRUCT(info_ctr_enum);
+ ZERO_STRUCT(info_ctr_dst);
+
+
+ DEBUG(3,("copying printer-drivers\n"));
+
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* open print$-share on the src server */
+ nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
+ cli->desthost, "print$", "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ got_src_driver_share = True;
+
+
+ /* open print$-share on the dst server */
+ nt_status = connect_to_service(&cli_share_dst, &cli_dst->dest_ip,
+ cli_dst->desthost, "print$", "A:");
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+ got_dst_driver_share = True;
+
+
+ /* enum src printers */
+ if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (p = 0; p < num_printers; p++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, info_ctr_enum.printers_2[p].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, info_ctr_enum.printers_2[p].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* we can reset NT_STATUS here because we do not
+ get any real NT_STATUS-codes anymore from now on */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ d_printf("migrating printer driver for: [%s] / [%s]\n",
+ printername, sharename);
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst))
+ goto done;
+
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* in a first step call getdriver for each shared printer (per arch)
+ to get a list of all files that have to be copied */
+
+ for (i=0; archi_table[i].long_archi!=NULL; i++) {
+
+ /* getdriver src */
+ if (!net_spoolss_getprinterdriver(cli, mem_ctx, &hnd_src,
+ level, archi_table[i].long_archi,
+ archi_table[i].version, &drv_ctr_src))
+ continue;
+
+ rpcstr_pull(drivername, drv_ctr_src.info3->name.buffer,
+ sizeof(drivername), -1, STR_TERMINATE);
+
+ if (opt_verbose)
+ display_print_driver_3(drv_ctr_src.info3);
+
+
+ /* check arch dir */
+ nt_status = check_arch_dir(cli_share_dst, archi_table[i].short_archi);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+
+ /* copy driver-files */
+ nt_status = copy_print_driver_3(mem_ctx, cli_share_src, cli_share_dst,
+ archi_table[i].short_archi,
+ drv_ctr_src.info3);
+ if (!NT_STATUS_IS_OK(nt_status))
+ goto done;
+
+
+ /* adddriver dst */
+ if (!net_spoolss_addprinterdriver(cli_dst, mem_ctx, level, &drv_ctr_src)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUGADD(1,("Sucessfully added driver [%s] for printer [%s]\n",
+ drivername, printername));
+
+ }
+
+ /* setdriver dst */
+ init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
+
+ if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ DEBUGADD(1,("Sucessfully set driver %s for printer %s\n",
+ drivername, printername));
+
+ /* close dst */
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+
+ /* close src */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+
+ if (got_src_driver_share)
+ cli_shutdown(cli_share_src);
+
+ if (got_dst_driver_share)
+ cli_shutdown(cli_share_dst);
+
+ return nt_status;
+
+}
+
+
+/**
+ * Migrate printer-queues from a src to the dst server
+ * (requires a working "addprinter command" to be installed for the local smbd)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i = 0, num_printers;
+ uint32 level = 2;
+ PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
+ struct cli_state *cli_dst = NULL;
+ POLICY_HND hnd_dst, hnd_src;
+ pstring printername, sharename;
+ fstring servername;
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+
+ DEBUG(3,("copying printers\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum printers */
+ if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ /* we can reset NT_STATUS here because we do not
+ get any real NT_STATUS-codes anymore from now on */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ d_printf("migrating printer queue for: [%s] / [%s]\n",
+ printername, sharename);
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli->user_name, &hnd_dst)) {
+
+ DEBUG(1,("could not open printer: %s\n", sharename));
+ } else {
+ got_hnd_dst = True;
+ }
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
+ printf ("could not get printer, creating printer.\n");
+ } else {
+ DEBUG(1,("printer already exists: %s\n", sharename));
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+ continue;
+ }
+
+
+ /* now get again src printer ctr via getprinter,
+ we first need a handle for that */
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+ /* getprinter on the src server */
+ if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, level, &ctr_src))
+ goto done;
+
+
+ /* copy each src printer to a dst printer 1:1,
+ maybe some values have to be changed though */
+ d_printf("creating printer: %s\n", printername);
+ result = cli_spoolss_addprinterex (cli_dst, mem_ctx, level, &ctr_src);
+
+ if (W_ERROR_IS_OK(result))
+ d_printf ("printer [%s] successfully added.\n", printername);
+ else if (W_ERROR_V(result) == W_ERROR_V(WERR_PRINTER_ALREADY_EXISTS))
+ d_printf ("printer [%s] already exists.\n", printername);
+ else {
+ printf ("could not create printer\n");
+ goto done;
+ }
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+}
+
+
+/**
+ * Migrate Printer-Settings from a src server to the dst server
+ * (for this to work, printers and drivers already have to be migrated earlier)
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through.
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc Standard main() style argc
+ * @param argv Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv)
+{
+
+ /* FIXME: Here the nightmare begins */
+
+ WERROR result;
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ uint32 i = 0, p = 0, j = 0;
+ uint32 num_printers, val_needed, data_needed;
+ uint32 level = 2;
+ fstring servername = "";
+ pstring printername = "", sharename = "";
+ BOOL got_hnd_src = False;
+ BOOL got_hnd_dst = False;
+ BOOL got_dst_spoolss_pipe = False;
+ POLICY_HND hnd_src, hnd_dst;
+ PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish;
+ REGVAL_CTR reg_ctr;
+ struct cli_state *cli_dst = NULL;
+ char *devicename = NULL, *unc_name = NULL, *url = NULL;
+ fstring longname;
+
+ const char *keyname = NULL;
+ uint16 *keylist = NULL, *curkey;
+
+ ZERO_STRUCT(ctr_enum);
+
+ DEBUG(3,("copying printer settings\n"));
+
+ /* connect destination PI_SPOOLSS */
+ nt_status = connect_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+ if (!NT_STATUS_IS_OK(nt_status))
+ return nt_status;
+
+
+ /* enum src printers */
+ if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ if (!num_printers) {
+ printf ("no printers found on server.\n");
+ nt_status = NT_STATUS_OK;
+ goto done;
+ }
+
+
+ /* needed for dns-strings in regkeys */
+ get_mydnsfullname(longname);
+
+ /* do something for all printers */
+ for (i = 0; i < num_printers; i++) {
+
+ /* do some initialization */
+ rpcstr_pull(printername, ctr_enum.printers_2[i].printername.buffer,
+ sizeof(printername), -1, STR_TERMINATE);
+ rpcstr_pull(sharename, ctr_enum.printers_2[i].sharename.buffer,
+ sizeof(sharename), -1, STR_TERMINATE);
+ keyname = "";
+ /* we can reset NT_STATUS here because we do not
+ get any real NT_STATUS-codes anymore from now on */
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ d_printf("migrating printer settings for: [%s] / [%s]\n",
+ printername, sharename);
+
+
+ /* open src printer handle */
+ if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, "",
+ MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd_src))
+ goto done;
+
+ got_hnd_src = True;
+
+
+ /* open dst printer handle */
+ if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, "",
+ PRINTER_ALL_ACCESS, servername, cli_dst->user_name, &hnd_dst))
+ goto done;
+
+ got_hnd_dst = True;
+
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst,
+ level, &ctr_dst))
+ goto done;
+
+
+ /* STEP 1: COPY DEVICE-MODE and other
+ PRINTER_INFO_2-attributes
+ */
+
+ ctr_dst.printers_2 = &ctr_enum.printers_2[i];
+
+ /* why is the port always disconnected when the printer
+ is correctly installed (incl. driver ???) */
+ init_unistr( &ctr_dst.printers_2->portname, SAMBA_PRINTER_PORT_NAME);
+
+ /* check if printer is published */
+ if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
+
+ /* check for existing dst printer */
+ if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
+ goto done;
+
+ ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH;
+
+ /* ignore False from setprinter due to WERR_IO_PENDING */
+ net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
+
+ DEBUG(3,("republished printer\n"));
+ }
+
+ /* copy devmode (info level 2) */
+ ctr_dst.printers_2->devmode = talloc_memdup(mem_ctx,
+ ctr_enum.printers_2[i].devmode, sizeof(DEVICEMODE));
+
+ /* do not copy security descriptor (we have another command for that) */
+ ctr_dst.printers_2->secdesc = NULL;
+
+
+ /* devmode->devicename is possibly broken at the moment for all
+ strlen(longprinternames) > MAXDEVICENAME (that is 32 chars)
+ this fires up thousands of safe_strncpy-debug0-messages
+ on my test-servers
+ TODO: tell jerry, jra, etc. again.
+ */
+
+#if 0
+ if (asprintf(&devicename, "\\\\%s\\%s", longname, printername) < 0) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ init_unistr(&ctr_dst.printers_2->devmode->devicename, devicename);
+#endif
+ if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst,
+ level, &ctr_dst))
+ goto done;
+
+ DEBUGADD(1,("\tSetPrinter of DEVICEMODE succeeded\n"));
+
+
+
+ /* STEP 2: COPY REGISTRY VALUES */
+
+ /* please keep in mind that samba parse_spools gives horribly
+ crippled results when used to cli_spoolss_enumprinterdataex
+ a win2k3-server.
+ FIXME: IIRC I've seen it too on a win2k-server
+ */
+
+ /* enumerate data on src handle */
+ result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0,
+ &val_needed, &data_needed, NULL);
+
+ /* loop for all printerdata */
+ while (W_ERROR_IS_OK(result)) {
+
+ REGISTRY_VALUE value;
+
+ result = cli_spoolss_enumprinterdata(
+ cli, mem_ctx, &hnd_src, p++, val_needed,
+ data_needed, 0, 0, &value);
+
+ /* loop for all reg_keys */
+ if (W_ERROR_IS_OK(result)) {
+
+ /* display_value */
+ if (opt_verbose)
+ display_reg_value(NULL, value);
+
+ /* set_value */
+ if (!net_spoolss_setprinterdata(cli_dst, mem_ctx,
+ &hnd_dst, &value))
+ goto done;
+
+ DEBUGADD(1,("\tSetPrinterData of [%s] succeeded\n",
+ value.valuename));
+ }
+ }
+
+ /* STEP 3: COPY SUBKEY VALUES */
+
+ /* here we need to enum all printer_keys and then work
+ on the result with enum_printer_key_ex. nt4 does not
+ respond to enumprinterkey, win2k does, so continue
+ in case of an error */
+
+ if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, keyname, &keylist)) {
+ printf("got no key-data\n");
+ continue;
+ }
+
+
+ /* work on a list of printer keys
+ each key has to be enumerated to get all required
+ information. information is then set via setprinterdataex-calls */
+
+ if (keylist == NULL)
+ continue;
+
+ curkey = keylist;
+ while (*curkey != 0) {
+
+ pstring subkey;
+ rpcstr_pull(subkey, curkey, sizeof(subkey), -1, STR_TERMINATE);
+
+ curkey += strlen(subkey) + 1;
+
+ /* enumerate all src subkeys */
+ if (!net_spoolss_enumprinterdataex(cli, mem_ctx, 0,
+ &hnd_src, subkey,
+ &reg_ctr))
+ goto done;
+
+ for (j=0; j < reg_ctr.num_values; j++) {
+
+ REGISTRY_VALUE value;
+ UNISTR2 data;
+
+ /* although samba replies with sane data in most cases we
+ should try to avoid writing wrong registry data */
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME) ||
+ strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_PORTNAME)) {
+
+ /* although windows uses a multi-sz, we use a sz */
+ init_unistr2(&data, SAMBA_PRINTER_PORT_NAME, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_PORTNAME);
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_UNCNAME)) {
+
+ if (asprintf(&unc_name, "\\\\%s\\%s", longname, sharename) < 0) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ init_unistr2(&data, unc_name, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_UNCNAME);
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_URL)) {
+
+ continue;
+
+#if 0
+ /* FIXME: should we really do that ??? */
+ if (asprintf(&url, "http://%s:631/printers/%s", longname, sharename) < 0) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ init_unistr2(&data, url, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_URL);
+#endif
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SERVERNAME)) {
+
+ init_unistr2(&data, longname, UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_SERVERNAME);
+ }
+
+ if (strequal(reg_ctr.values[j]->valuename, SPOOL_REG_SHORTSERVERNAME)) {
+
+ init_unistr2(&data, global_myname(), UNI_STR_TERMINATE);
+ fstrcpy(value.valuename, SPOOL_REG_SHORTSERVERNAME);
+ }
+
+ value.type = REG_SZ;
+ value.size = data.uni_str_len * 2;
+ value.data_p = talloc_memdup(mem_ctx, data.buffer, value.size);
+
+ if (opt_verbose)
+ display_reg_value(subkey, value);
+
+ /* here we have to set all subkeys on the dst server */
+ if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst,
+ subkey, &value))
+ goto done;
+
+ } else {
+
+ if (opt_verbose)
+ display_reg_value(subkey, *(reg_ctr.values[j]));
+
+ /* here we have to set all subkeys on the dst server */
+ if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst,
+ subkey, reg_ctr.values[j]))
+ goto done;
+
+ }
+
+ DEBUGADD(1,("\tSetPrinterDataEx of key [%s\\%s] succeeded\n",
+ subkey, reg_ctr.values[j]->valuename));
+
+ }
+
+ regval_ctr_destroy(&reg_ctr);
+ }
+
+ safe_free(keylist);
+
+ /* close printer handles here */
+ if (got_hnd_src) {
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+ got_hnd_src = False;
+ }
+
+ if (got_hnd_dst) {
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+ got_hnd_dst = False;
+ }
+
+ }
+
+ nt_status = NT_STATUS_OK;
+
+done:
+ SAFE_FREE(devicename);
+ SAFE_FREE(url);
+ SAFE_FREE(unc_name);
+
+ if (got_hnd_src)
+ cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+
+ if (got_hnd_dst)
+ cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+
+ if (got_dst_spoolss_pipe) {
+ cli_nt_session_close(cli_dst);
+ cli_shutdown(cli_dst);
+ }
+ return nt_status;
+}
diff --git a/source/utils/smbcacls.c b/source/utils/smbcacls.c
index cb82ad831eb..4dc89aecb9d 100644
--- a/source/utils/smbcacls.c
+++ b/source/utils/smbcacls.c
@@ -761,11 +761,13 @@ static struct cli_state *connect_one(const char *share)
ctx=talloc_init("main");
- setlinebuf(stdout);
-
+ /* set default debug level to 0 regardless of what smb.conf sets */
+ setup_logging( "smbcacls", True );
+ DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
dbf = x_stderr;
+ x_setbuf( x_stderr, NULL );
- setup_logging(argv[0],True);
+ setlinebuf(stdout);
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();
diff --git a/source/utils/smbcquotas.c b/source/utils/smbcquotas.c
index 0bd87554209..81f7dd42bbc 100644
--- a/source/utils/smbcquotas.c
+++ b/source/utils/smbcquotas.c
@@ -236,8 +236,9 @@ static int do_quota(struct cli_state *cli, enum SMB_QUOTA_TYPE qtype, uint16 cmd
}
if (!cli_get_quota_handle(cli, &quota_fnum)) {
- d_printf("Failed to open \\%s %s.\n",
- FAKE_FILE_NAME_QUOTA,cli_errstr(cli));
+ d_printf("Quotas are not enabled on this share.\n");
+ d_printf("Failed to open %s %s.\n",
+ FAKE_FILE_NAME_QUOTA_WIN32,cli_errstr(cli));
return -1;
}
@@ -419,14 +420,15 @@ FSQFLAGS:QUOTA_ENABLED/DENY_DISK/LOG_SOFTLIMIT/LOG_HARD_LIMIT", "SETSTRING" },
ZERO_STRUCT(qt);
- setlinebuf(stdout);
-
+ /* set default debug level to 1 regardless of what smb.conf sets */
+ setup_logging( "smbcquotas", True );
+ DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
dbf = x_stderr;
+ x_setbuf( x_stderr, NULL );
- fault_setup(NULL);
-
- setup_logging(argv[0],True);
+ setlinebuf(stdout);
+ fault_setup(NULL);
lp_load(dyn_CONFIGFILE,True,False,False);
load_interfaces();