summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-12-02 13:33:07 +0000
committerGerald Carter <jerry@samba.org>2005-12-02 13:33:07 +0000
commit6c43e50ecd10fb085b4c3dbb83560c759980f917 (patch)
treef8429b14abcdeba9b4aa939e30c7d1f8c677f3e0
parent83d9e39f05693f1e42c889ddf183ac249df0e819 (diff)
downloadsamba-6c43e50ecd10fb085b4c3dbb83560c759980f917.tar.gz
samba-6c43e50ecd10fb085b4c3dbb83560c759980f917.tar.xz
samba-6c43e50ecd10fb085b4c3dbb83560c759980f917.zip
r12017: starting the sync up for 3.0.21. Gotten through r11915
so far. Jeremy, This is turning out ot be more changes that I anticipated and may end up being a full sync. But the changes appear sar or on a non-default code path.
-rw-r--r--WHATSNEW.txt350
-rw-r--r--examples/VFS/skel_opaque.c2
-rw-r--r--source/Makefile.in2
-rw-r--r--source/VERSION2
-rw-r--r--source/auth/auth_sam.c5
-rw-r--r--source/client/client.c5
-rw-r--r--source/client/smbspool.c14
-rw-r--r--source/configure.in40
-rw-r--r--source/include/includes.h9
-rw-r--r--source/include/libsmbclient.h7
-rw-r--r--source/include/rpc_eventlog.h10
-rw-r--r--source/include/rpc_samr.h18
-rw-r--r--source/lib/crc32.c2
-rw-r--r--source/lib/smbldap.c202
-rw-r--r--source/lib/snprintf.c23
-rw-r--r--source/lib/system.c54
-rw-r--r--source/libads/kerberos_verify.c6
-rw-r--r--source/libads/ldap.c13
-rw-r--r--source/nsswitch/winbind_nss_solaris.c4
-rw-r--r--source/nsswitch/winbindd.h3
-rw-r--r--source/nsswitch/winbindd_ads.c37
-rw-r--r--source/nsswitch/winbindd_cache.c13
-rw-r--r--source/nsswitch/winbindd_misc.c3
-rw-r--r--source/nsswitch/winbindd_pam.c2
-rw-r--r--source/nsswitch/winbindd_passdb.c12
-rw-r--r--source/nsswitch/winbindd_reconnect.c14
-rw-r--r--source/nsswitch/winbindd_rpc.c8
-rw-r--r--source/param/loadparm.c8
-rw-r--r--source/passdb/pdb_ldap.c2
-rw-r--r--source/passdb/pdb_nds.c54
-rw-r--r--source/rpc_client/cli_lsarpc.c2
-rw-r--r--source/rpc_parse/parse_eventlog.c2
-rw-r--r--source/rpc_parse/parse_samr.c26
-rw-r--r--source/rpc_server/srv_eventlog_lib.c107
-rw-r--r--source/rpc_server/srv_eventlog_nt.c235
-rw-r--r--source/rpc_server/srv_samr.c20
-rw-r--r--source/rpc_server/srv_samr_nt.c539
-rw-r--r--source/rpc_server/srv_util.c2
-rw-r--r--source/rpcclient/cmd_lsarpc.c2
-rw-r--r--source/rpcclient/cmd_samr.c15
-rwxr-xr-xsource/script/installman.sh17
-rw-r--r--source/script/mkproto.awk2
-rw-r--r--source/services/services_db.c72
-rw-r--r--source/smbd/dosmode.c2
-rw-r--r--source/smbd/filename.c18
-rw-r--r--source/smbd/session.c3
-rw-r--r--source/smbd/sesssetup.c33
-rw-r--r--source/utils/eventlogadm.c8
-rw-r--r--source/utils/net_lookup.c4
-rw-r--r--source/utils/smbget.c24
50 files changed, 1268 insertions, 789 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 91ed878e93f..479c86f9f40 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,19 +1,31 @@
- =================================
- Release Notes for Samba 3.0.21rc1
- Nov 12, 2005
- =================================
+ ==============================
+ Release Notes for Samba 3.0.21
+ Dec 3, 2005
+ ==============================
-This is a release candidate of the 3.0.21 code base and is provided
-for testing purposes only. While close to the final stable release,
-this snapshot is *not* intended for production servers.
+This is the latest stable release of Samba. This is the version
+that production Samba servers should be running for all current
+bug-fixes. Please read the following important changes in this
+release.
Common bugs fixed in 3.0.21rc1 include:
+ o Missing groups in a user's token when logging in via kerberos
+ o Incompatibilities with newer MS Windows hotfixes and
+ embedded OS platforms
o Portability and crash bugs.
o Performance issues in winbindd.
New features introduced in Samba 3.0.21rc1 include:
+ o Complete NTLMv2 support by consolidating authentication
+ mechanism used at the CIFS and RPC layers.
+ o The capability to manage Unix services using the Win32
+ Service Control API.
+ o The capability to view external Unix log files via the
+ Microsoft Event Viewer.
+ o New libmsrpc share library for application developers.
+ o Rewrite of CIFS oplock implementation.
o Performance Counter external daemon.
o Winbindd auto-detection query methods when communicating with
a domain controller.
@@ -30,15 +42,122 @@ smb.conf changes
-------------- ------
dfree cache time New
dfree command Per share
+ eventlog list New
+ iprint server New
+ map read only New
+ rename user script New
+ reset on zero vc New
+ svcctl list Renamed from 'enable svcctl'
-Changes since 3.0.21pre1
+Changes since 3.0.21rc1
------------------------
commits
-------
+o Jeremy Allison <jra@samba.org>
+ * Remove #define of close -> close_fn maxcor in libsmbclient.
+ * Return early if -1 returned from *BSD EA call (reported by
+ Timur).
+ * Name space cleanup by marking local functions static.
+ * Move samr enumeration cache from per handle basis to a shared
+ cache.
+ * BUG 3274: Fix invalid smbclient qpath_basic() queries against
+ OS/2 servers (based on patch from Guenter Kukkukk).
+ * Ensure default applies to new files (reported by Thomas
+ Neumann).
+
+
+o Rashid N. Achilov <shelton@granch.ru>
+ * Add better service description names to the svcctl code.
+
+
+o Timur Bakeyev <timur@com.bat.ru>
+ * BUG 3262: Improve FreeBSD DOS attribute error reporting.
+
+
+o Gerald (Jerry) Carter <jerry@samba.org>
+ * Add smbget to the list of tools built by default.
+ * Fix clearing of eventlog tdb files.
+ * Fix sequential reads in eventlog support.
+ * BUG 2718: Don't use qpathinfo_basic() call when remote server
+ is Win9x.
+ * Fix build issues with the Sun compiler.
+ * BUG 3156: Don't use find_service() when explicitly looking
+ for a printer.
+ * Fix nss_winbind_solaris.c build breakage on HP=UX.
+
+
+o Alex Deiter <tiamat@komi.mts.ru>
+ * BUG 3196: Patch to compile against the Sun LDAP client libs.
+ (not for AD support; just ldap support).
+
+
+o Guenther Deschner <gd@samba.org>
+ * Avoid an inifinite loop when retying to connect in smbspool.
+ * Memory leak fixes in the kerberos PAC parsing code.
+ * Improve NT_STATUS error messages returned from pam_winbind.
+ * Rename unknown samr group fields in samr structures with
+ the correct name.
+ * Cleanup redundant StartTLS code.
+ * Allow StartTLS support when connecting to Windows 2003 by
+ setting 'ldap ssl = start_tls'.
+
+
+o Volker Lendecke <vl@samba.org>
+ * Removed unused alternative_name cocde from winbindd.
+ * Protect against NULL alternative_name strings in winbindd.
+ * Define a default panic action with -DEVELOPER is defined.
+ * Add the capability ot reset smbd connections on a zero VC id.
+
+
+o Jim McDonough <jmcd@us.ibm.com>
+ * BUG 3187: Fix time zone offset in logon hours restrictions.
+
+
+o Lars Müller <lmuelle@samba.org>
+ * Only install smbsh manpage if smbwrapper has been successfully
+ built.
+
+
+o Tim Potter <tpot@samba.org>
+ * BUG 3260: Fix DYNEXP flags on HPUX.
+
+
+o Aruna Prabakar <aruna.prabakar@hp.com.
+ * Add checks to verify that the spooler is running on HP-UX when
+ reloading the printer name cache.
+
+
+o Darren Tucker <dtucker@zip.com.au>
+ o Crash fix for snprintf() code.
+
+
+o Rainer Weikusat <rainer.weikusat@sncag.com>
+ * Fix function name typo in skeleton VFS code.
+
+
+
+Changes since 3.0.20b
+---------------------
o Jeremy Allison <jra@samba.org>
+ * BUG 1828: Fixed SPNEGO issues with PocketPC clients.
+ * Added 'map readonly' parameter.
+ * BUG 3166: Fix crash in libsmbclient if the $HOME environment is
+ not defined.
+ * Maintain schannel client session keys in volatile
+ $(privatedir)/schannel_store.tdb.
+ * BUG 2769: Ensure we mangle filenames ending in a space
+ * Catch corner case of renaming a symlinked directory into
+ itself
+ * Ensure that smb.conf requests for hidden files are honored,
+ even when DOS attributes are stored in EA's
+ * Add new auth method "auth_script" for calling an external
+ program
+ * BUG 2152: Fix for mangled filenames when the client does
+ support long filenames
+ * Rewritten implementation of client and server DCE/RPC infrastructure
* BUG 3192: Adds a "dfree cache time" parameter.
* Fix acl evaluation bug found by Marc Cousin. Only evaluate
the S_IWGRP mask in the absence of a POSIX ACL.
@@ -83,6 +202,23 @@ o Alexander Bokovoy <ab@samba.org>
o Gerald (Jerry) Carter <jerry@samba.org>
+ * Eventlog and ServiceControl support.
+ * BUG 1051: store the directory path so we can send the full
+ name in the unlink call from smbclient.
+ * Use reference count strategy for keeping the registry tdb
+ open.
+ * Convert internal registry objects to new hierarchical talloc
+ * Allow the root user a free pass for access checks in the
+ registry and service control checks.
+ * Sanity checks in the privilege code to prevent empty SID
+ entries
+ * Add basic infrastructure for 'make test' when the socket
+ wrapper library is configured at compile time
+ * Convert profiles utility to use the current regfio interface
+ for reading and writing user profiles
+ * Remove netsamlogon_cache interface
+ * Ensure that print jobs are removed even when the cancel
+ command is received before the print cache has been updated
* Fix linking problem on Solaris when including ACL support.
* Give root a free pass to open the eventlog tdb files.
* Fix segfault in addprinter due to mixing talloc() and
@@ -110,6 +246,18 @@ o Gerald (Jerry) Carter <jerry@samba.org>
o Guenther Deschner <gd@samba.org>
+ * Fixed compile problems and warnings with newer OpenLDAP
+ and OpenSSL libs
+ * Fix bug when enumerating trusted domains via 'wbinfo -m'
+ * Parse the MS Kerberos PAC to obtain the user group
+ membership during logon.
+ * Add support for SeRestorePrivilege to allow a process to
+ change the ownership of a file to any arbitrary account
+ * Fix password history storage when using Novell eDirectory for
+ ldapsam storage
+ * Backport Kerberos PAC parsing from Samba 4 branch in order to
+ correctly create the NT User Token when logging into a Samba
+ member server
* Add small helper function to return a PAC_LOGON_INFO.
* Use LDAP bitwise matching rule when searching for groups
in ADS.
@@ -119,7 +267,18 @@ o Paul Green <paulg@samba.org>
* Update to the latest config.guess and config.sub files.
+o Deryck Hodge <deryck@samba.org>
+ * Allow control of syslog facility and level in audit vfs modules.
+
+
+o S Murthy Kambhampaty <smk_va@yahoo.com>
+ * Patches for Fedora RPM specfile and init script
+
+
o Volker Lendecke <vl@samba.org>
+ * New oplock implementation.
+ * Add assert() call if winbindd cannot locate the domain SID in
+ secrets.tdb on startup
* Fix an annoying timeout in winbindd when nmbd is not running.
* Speed up loading smb.conf for large numbers of share
definitions by adding an internal hashing of names to snums.
@@ -141,6 +300,10 @@ o Derrell Lipman <derrell@samba.org>
* Cleanup libmsrpc version numbers.
+o Jason Mader <jason@ncac.gwu.edu>
+ * Removed compiler various warnings.
+
+
o Alex Masterov <alex@infobit.ru>
* BUG 3218: Fix XATTR calls on *BSD systems.
@@ -149,189 +312,42 @@ o Jim McDonough <jmcd@us.ibm.com>
* Speed up string_to_sid by removing next_token calls and
unneeded strncmp() calls.
* Implement user rename for smbpasswd and LDAP backends.
+ * BUG 2961 (partial): Add rename support for user accounts to tdbsam
o Stefan Metzmacher <metze@samba.org>
+ * Fix setting of quotas on linux kernel with the struct
+ if_dqblk interface
+ * Enable sysquota interfact on Linux by default
* Use lp_socket_address() when binding to port 138/udp in nmbd.
o Brian Moran <bmoran@centeris.com>
+ * Eventlog and ServiceControl support.
+ * Added eventlogadm tool for writing Eventlog records.
* Fix typo when creating Eventlog source DLL registry paths.
* Add simple script to tail syslog and write records to
eventlog tdb.
-o Lars Müller <lmuelle@samba.org>
- * Only install smbsh manpage if smbwrapper has been successfully
- built.
-
-
o Ricky Nance <ricky.nance@gmail.com>
* Updates for the mklogon perl scripts.
o Chris Nicholls <skel@samba.org>
+ * New libmsrpc library (Google SoC Project).
* Fix libmsrpc build of on the Sun compiler by removing empty
structure declarations.
-o Marcin Porwit <mporwit@centeris.com>
- * Added basic Performance Counter daemon which can feed data
- for the Windows perfmon.exe tool.
-
-
-o Simo Sorce <idra@samba.org>
- * Update Debian packaging.
-
-
-
-Release Notes for older release follow:
-
- --------------------------------------------------
-
- ==================================
- Release Notes for Samba 3.0.21pre1
- Oct 18, 2005
- ==================================
-
-
-Common bugs fixed in 3.0.21pre1 include:
-
- o Missing groups in a user's token when logging in via kerberos
- o Incompatibilities with newer MS Windows hotfixes and
- embedded OS platforms
-
-New features introduced in Samba 3.0.21pre1 include:
-
- o Complete NTLMv2 support by consolidating authentication
- mechanism used at the CIFS and RPC layers.
- o The capability to manage Unix services using the Win32
- Service Control API.
- o The capability to view external Unix log files via the
- Microsoft Event Viewer.
- o New libmsrpc share library for application developers.
- o Rewrite of CIFS oplock implementation.
-
-
-######################################################################
-Changes
-#######
-
-smb.conf changes
-----------------
-
- Parameter Name Action
- -------------- ------
- eventlog list New
- iprint server New
- map read only New
- rename user script New
- svcctl list Renamed from 'enable svcctl'
-
-
-Changes since 3.0.20[a-b]
--------------------------
-
-commits
--------
-
-o Jeremy Allison <jra@samba.org>
- * BUG 1828: Fixed SPNEGO issues with PocketPC clients.
- * Added 'map readonly' parameter.
- * BUG 3166: Fix crash in libsmbclient if the $HOME environment is
- not defined.
- * Maintain schannel client session keys in volatile
- $(privatedir)/schannel_store.tdb.
- * BUG 2769: Ensure we mangle filenames ending in a space
- * Catch corner case of renaming a symlinked directory into
- itself
- * Ensure that smb.conf requests for hidden files are honored,
- even when DOS attributes are stored in EA's
- * Add new auth method "auth_script" for calling an external
- program
- * BUG 2152: Fix for mangled filenames when the client does
- support long filenames
- * Rewritten implementation of client and server DCE/RPC infrastructure
-
-
-o Gerald (Jerry) Carter <jerry@samba.org>
- * Eventlog and ServiceControl support.
- * BUG 1051: store the directory path so we can send the full
- name in the unlink call from smbclient.
- * Use reference count strategy for keeping the registry tdb
- open.
- * Convert internal registry objects to new hierarchical talloc
- * Allow the root user a free pass for access checks in the
- registry and service control checks.
- * Sanity checks in the privilege code to prevent empty SID
- entries
- * Add basic infrastructure for 'make test' when the socket
- wrapper library is configured at compile time
- * Convert profiles utility to use the current regfio interface
- for reading and writing user profiles
- * Remove netsamlogon_cache interface
- * Ensure that print jobs are removed even when the cancel
- command is received before the print cache has been updated
-
-
-o Guenther Deschner <gd@samba.org>
- * Fixed compile problems and warnings with newer OpenLDAP
- and OpenSSL libs
- * Fix bug when enumerating trusted domains via 'wbinfo -m'
- * Parse the MS Kerberos PAC to obtain the user group
- membership during logon.
- * Add support for SeRestorePrivilege to allow a process to
- change the ownership of a file to any arbitrary account
- * Fix password history storage when using Novell eDirectory for
- ldapsam storage
- * Backport Kerberos PAC parsing from Samba 4 branch in order to
- correctly create the NT User Token when logging into a Samba
- member server
-
-
-o Deryck Hodge <deryck@samba.org>
- * Allow control of syslog facility and level in audit vfs modules.
-
-
-o S Murthy Kambhampaty <smk_va@yahoo.com>
- * Patches for Fedora RPM specfile and init script
-
-
-o Volker Lendecke <vl@samba.org>
- * New oplock implementation.
- * Add assert() call if winbindd cannot locate the domain SID in
- secrets.tdb on startup
-
-
-o Jason Mader <jason@ncac.gwu.edu>
- * Removed compiler various warnings.
-
-
-o Jim McDonough <jmcd@us.ibm.com>
- * BUG 2961 (partial): Add rename support for user accounts to tdbsam
-
-
-o Stefan Metzmacher <metze@samba.org>
- * Fix setting of quotas on linux kernel with the struct
- if_dqblk interface
- * Enable sysquota interfact on Linux by default
-
-
-o Brian Moran <bmoran@centeris.com>
- * Eventlog and ServiceControl support.
- * Added eventlogadm tool for writing Eventlog records.
-
-
-o Chris Nicholls <skel@samba.org>
- * New libmsrpc library (Google SoC Project).
-
-
o James Peach <jpeach@sgi.com>
* Fix parsing error for smb ports parameter.
o Marcin Porwit <mporwit@centeris.com>
* Eventlog and ServiceControl support.
+ * Added basic Performance Counter daemon which can feed data
+ for the Windows perfmon.exe tool.
o Joel Smith <joel.j.smith@novell.com>
@@ -342,6 +358,12 @@ o Toomas Soome <Toomas.Soome@mls.ee>
* Implement host lookups in nss_winbind.so.1 on Solaris
+o Simo Sorce <idra@samba.org>
+ * Update Debian packaging.
+
+
+Release Notes for older release follow:
+
--------------------------------------------------
===============================
Release Notes for Samba 3.0.20b
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index e6b7d032fcf..e6af475da6e 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -524,7 +524,7 @@ static int skel_aio_fsync(struct vfs_handle_struct *handle, struct files_struct
static int skel_aio_suspend(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_AIOCB * const aiocb[], int n, const struct timespec *ts)
{
- return vfswrap_aioi_suspend(NULL, fsp, aiocb, n, ts);
+ return vfswrap_aio_suspend(NULL, fsp, aiocb, n, ts);
}
/* VFS operations structure */
diff --git a/source/Makefile.in b/source/Makefile.in
index 6a12b2e25e9..cca0715a3aa 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -128,7 +128,7 @@ PATH_FLAGS = $(PATH_FLAGS6) $(PASSWD_FLAGS)
SBIN_PROGS = bin/smbd@EXEEXT@ bin/nmbd@EXEEXT@ bin/swat@EXEEXT@ @EXTRA_SBIN_PROGS@
BIN_PROGS1 = bin/smbclient@EXEEXT@ bin/net@EXEEXT@ bin/smbspool@EXEEXT@ \
- bin/testparm@EXEEXT@ bin/smbstatus@EXEEXT@
+ bin/testparm@EXEEXT@ bin/smbstatus@EXEEXT@ bin/smbget@EXEEXT@
BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
bin/nmblookup@EXEEXT@ bin/pdbedit@EXEEXT@ bin/tdbdump@EXEEXT@ \
bin/tdbtool@EXEEXT@
diff --git a/source/VERSION b/source/VERSION
index c377386a9c4..9895f797c4d 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -51,7 +51,7 @@ SAMBA_VERSION_PRE_RELEASE=
# e.g. SAMBA_VERSION_RC_RELEASE=1 #
# -> "3.0.0rc1" #
########################################################
-SAMBA_VERSION_RC_RELEASE=1
+SAMBA_VERSION_RC_RELEASE=
########################################################
# To mark SVN snapshots this should be set to 'yes' #
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index c92cecdde59..558c181f704 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -88,7 +88,7 @@ static BOOL logon_hours_ok(SAM_ACCOUNT *sampass)
}
lasttime = (time_t)smb_last_time.tv_sec;
- utctime = localtime(&lasttime);
+ utctime = gmtime(&lasttime);
/* find the corresponding byte and bit */
bitpos = (utctime->tm_wday * 24 + utctime->tm_hour) % 168;
@@ -96,7 +96,8 @@ static BOOL logon_hours_ok(SAM_ACCOUNT *sampass)
if (! (hours[bitpos/8] & bitmask)) {
DEBUG(1,("logon_hours_ok: Account for user %s not allowed to logon at this time (%s).\n",
- pdb_get_username(sampass), asctime(utctime) ));
+ pdb_get_username(sampass),
+ asctime(localtime(&lasttime)) ));
return False;
}
diff --git a/source/client/client.c b/source/client/client.c
index f849738da0a..47a45b8a53b 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -288,9 +288,10 @@ static int do_cd(char *newdir)
if ( strequal(targetpath,"\\" ) )
return 0;
- /* use a trans2_qpathinfo to test directories for modern servers */
+ /* Use a trans2_qpathinfo to test directories for modern servers.
+ Except Win9x doesn't support the qpathinfo_basic() call..... */
- if ( targetcli->protocol >= PROTOCOL_LANMAN2 ) {
+ if ( targetcli->protocol > PROTOCOL_LANMAN2 && !targetcli->win95 ) {
if ( !cli_qpathinfo_basic( targetcli, targetpath, &sbuf, &attributes ) ) {
d_printf("cd %s: %s\n", dname, cli_errstr(targetcli));
pstrcpy(cur_dir,saved_dir);
diff --git a/source/client/smbspool.c b/source/client/smbspool.c
index da517297f71..aff241adeed 100644
--- a/source/client/smbspool.c
+++ b/source/client/smbspool.c
@@ -30,6 +30,7 @@
#define CC_MAX_FILE_PATH_LEN (sizeof(TICKET_CC_DIR)-1)+ CC_MAX_FILE_LEN+2
#define OVERWRITE 1
#define KRB5CCNAME "KRB5CCNAME"
+#define MAX_RETRY_CONNECT 3
/*
@@ -71,6 +72,7 @@ static int smb_print(struct cli_state *, char *, FILE *);
int status=0; /* Status of LPD job */
struct cli_state *cli; /* SMB interface */
char null_str[1];
+ int tries = 0;
null_str[0] = '\0';
@@ -229,17 +231,23 @@ static int smb_print(struct cli_state *, char *, FILE *);
{
if (getenv("CLASS") == NULL)
{
- fprintf(stderr, "ERROR: Unable to connect to CIFS host, will retry in 60 seconds...");
+ fprintf(stderr, "ERROR: Unable to connect to CIFS host, will retry in 60 seconds...\n");
sleep (60); /* should just waiting and retrying fix authentication ??? */
+ tries++;
}
else
{
- fprintf(stderr, "ERROR: Unable to connect to CIFS host, trying next printer...");
+ fprintf(stderr, "ERROR: Unable to connect to CIFS host, trying next printer...\n");
return (1);
}
}
}
- while (cli == NULL);
+ while ((cli == NULL) && (tries < MAX_RETRY_CONNECT));
+
+ if (cli == NULL) {
+ fprintf(stderr, "ERROR: Unable to connect to CIFS host after (tried %d times)\n", tries);
+ return (1);
+ }
/*
* Now that we are connected to the server, ignore SIGTERM so that we
diff --git a/source/configure.in b/source/configure.in
index eb1974ccf7a..296673e4b53 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -1480,10 +1480,10 @@ if test "$enable_shared" = "yes"; then
fi
if test "$host_cpu" = "ia64"; then
SHLIBEXT="so"
- DYNEXP="-Wl,-E,+b /usr/local/lib/hpux32:/usr/lib/hpux32"
+ DYNEXP="-Wl,-E,+b/usr/local/lib/hpux32:/usr/lib/hpux32"
else
SHLIBEXT="sl"
- DYNEXP="-Wl,-E,+b /usr/local/lib:/usr/lib"
+ DYNEXP="-Wl,-E,+b/usr/local/lib:/usr/lib"
fi
AC_DEFINE(STAT_ST_BLOCKSIZE,8192,[The size of a block])
AC_DEFINE(POSIX_ACL_NEEDS_MASK,1,[Does a POSIX ACL need a mask element])
@@ -2796,8 +2796,6 @@ if test x"$with_ldap_support" != x"no"; then
# now see if we can find the ldap libs in standard paths
AC_CHECK_LIB_EXT(ldap, LDAP_LIBS, ldap_init)
- AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS)
-
########################################################
# If we have LDAP, does it's rebind procedure take 2 or 3 arguments?
# Check found in pam_ldap 145.
@@ -2816,9 +2814,7 @@ if test x"$with_ldap_support" != x"no"; then
AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $smb_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc])
- AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS)
-
- if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then
+ if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes"; then
AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED"
default_static_modules="$default_static_modules pdb_ldap idmap_ldap";
@@ -2870,6 +2866,36 @@ if test x"$with_ldap_support" != x"yes"; then
with_ads_support=no
fi
+AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS)
+
+if test x"$ac_cv_func_ext_ldap_initialize" != x"yes"; then
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(Active Directory Support requires ldap_initialize)
+ fi
+ AC_MSG_WARN(Active Directory Support requires ldap_initialize)
+ with_ads_support=no
+fi
+
+AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS)
+
+if test x"$ac_cv_func_ext_ldap_domain2hostlist" != x"yes"; then
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(Active Directory Support requires ldap_domain2hostlist)
+ fi
+ AC_MSG_WARN(Active Directory Support requires ldap_domain2hostlist)
+ with_ads_support=no
+fi
+
+AC_CHECK_FUNC_EXT(ldap_add_result_entry,$LDAP_LIBS)
+
+if test x"$ac_cv_func_ext_ldap_add_result_entry" != x"yes"; then
+ if test x"$with_ads_support" = x"yes"; then
+ AC_MSG_ERROR(Active Directory Support requires ldap_add_result_entry)
+ fi
+ AC_MSG_WARN(Active Directory Support requires ldap_add_result_entry)
+ with_ads_support=no
+fi
+
if test x"$with_ads_support" != x"no"; then
# Do no harm to the values of CFLAGS and LIBS while testing for
diff --git a/source/include/includes.h b/source/include/includes.h
index 626124523e5..cde199eed8b 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -458,10 +458,19 @@
#if HAVE_LBER_H
#include <lber.h>
+#ifndef LBER_USE_DER
+#define LBER_USE_DER 0x01
+#endif
#endif
#if HAVE_LDAP_H
#include <ldap.h>
+#ifndef LDAP_CONST
+#define LDAP_CONST const
+#endif
+#ifndef LDAP_OPT_SUCCESS
+#define LDAP_OPT_SUCCESS 0
+#endif
#else
#undef HAVE_LDAP
#endif
diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h
index 46896d68e48..6d3a0cda09d 100644
--- a/source/include/libsmbclient.h
+++ b/source/include/libsmbclient.h
@@ -339,13 +339,6 @@ typedef int (*smbc_remove_cached_srv_fn)(SMBCCTX * c, SMBCSRV *srv);
typedef int (*smbc_purge_cached_fn) (SMBCCTX * c);
-/* close was renamed to close_fn, because close is often a macro.
- * Allow backward compatability where this is not the case */
-#ifndef close
-#define close close_fn
-#endif
-
-
/**@ingroup structure
* Structure that contains a client context information
* This structure is know as SMBCCTX
diff --git a/source/include/rpc_eventlog.h b/source/include/rpc_eventlog.h
index 67e03edbc6e..5bede97d1c9 100644
--- a/source/include/rpc_eventlog.h
+++ b/source/include/rpc_eventlog.h
@@ -57,6 +57,16 @@
#define ELOG_SYS "System"
#define ELOG_SEC "Security"
+typedef struct elog_tdb {
+ struct elog_tdb *prev, *next;
+ char *name;
+ TDB_CONTEXT *tdb;
+ int ref_count;
+} ELOG_TDB;
+
+#define ELOG_TDB_CTX(x) ((x)->tdb)
+
+
#define EVENTLOG_DATABASE_VERSION_V1 1
/***********************************/
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index 6067587654e..f19de2ef4fc 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -126,7 +126,7 @@ SamrTestPrivateFunctionsUser
#define SAMR_UNKNOWN_2b 0x2b
#define SAMR_GET_USRDOM_PWINFO 0x2c
#define SAMR_REMOVE_SID_FOREIGN_DOMAIN 0x2d
-#define SAMR_UNKNOWN_2E 0x2e /* looks like an alias for SAMR_QUERY_DOMAIN_INFO */
+#define SAMR_QUERY_DOMAIN_INFO2 0x2e /* looks like an alias for SAMR_QUERY_DOMAIN_INFO */
#define SAMR_UNKNOWN_2f 0x2f
#define SAMR_QUERY_DISPINFO3 0x30 /* Alias for SAMR_QUERY_DISPINFO
with info level 3 */
@@ -1064,7 +1064,7 @@ typedef struct samr_group_info1
{
UNIHDR hdr_acct_name;
- uint32 unknown_1; /* 0x0000 0003 - number of group members? */
+ uint32 group_attr; /* 0x0000 0003 - group attribute */
uint32 num_members; /* 0x0000 0001 - number of group members? */
UNIHDR hdr_acct_desc;
@@ -1084,7 +1084,7 @@ typedef struct samr_group_info2
typedef struct samr_group_info3
{
- uint32 unknown_1; /* 0x0000 0003 - number of group members? */
+ uint32 group_attr; /* 0x0000 0003 - group attribute */
} GROUP_INFO3;
@@ -1813,23 +1813,23 @@ typedef struct sid_info_3
} DOM_SID3;
-/* SAMR_Q_UNKNOWN_2E */
-typedef struct q_samr_unknown_2e_info
+/* SAMR_Q_QUERY_DOMAIN_INFO2 */
+typedef struct q_samr_query_domain_info2
{
POLICY_HND domain_pol; /* policy handle */
uint16 switch_value;
-} SAMR_Q_UNKNOWN_2E;
+} SAMR_Q_QUERY_DOMAIN_INFO2;
-/* SAMR_R_UNKNOWN_2E */
-typedef struct r_samr_unknown_2e_info
+/* SAMR_R_QUERY_DOMAIN_INFO2 */
+typedef struct r_samr_query_domain_info2
{
uint32 ptr_0;
uint16 switch_value;
SAM_UNK_CTR *ctr;
NTSTATUS status; /* return status */
-} SAMR_R_UNKNOWN_2E;
+} SAMR_R_QUERY_DOMAIN_INFO2;
/* SAMR_Q_SET_DOMAIN_INFO */
typedef struct q_samr_set_domain_info
diff --git a/source/lib/crc32.c b/source/lib/crc32.c
index c6a13fada12..7522ab7c811 100644
--- a/source/lib/crc32.c
+++ b/source/lib/crc32.c
@@ -42,7 +42,7 @@
#include "includes.h"
-const uint32 crc32_tab[] = {
+static const uint32 crc32_tab[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c
index f08a67a22c8..a3ebe72df21 100644
--- a/source/lib/smbldap.c
+++ b/source/lib/smbldap.c
@@ -523,24 +523,56 @@ static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state)
t->smbldap_state = smbldap_state;
}
-/*******************************************************************
- open a connection to the ldap server.
-******************************************************************/
-static int smbldap_open_connection (struct smbldap_state *ldap_state)
+/********************************************************************
+ start TLS on an existing LDAP connection
+*******************************************************************/
+
+int smb_ldap_start_tls(LDAP *ldap_struct, int version)
+{
+ int rc;
+
+ if (lp_ldap_ssl() != LDAP_SSL_START_TLS) {
+ return LDAP_SUCCESS;
+ }
+
+#ifdef LDAP_OPT_X_TLS
+ if (version != LDAP_VERSION3) {
+ DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ if ((rc = ldap_start_tls_s (ldap_struct, NULL, NULL)) != LDAP_SUCCESS) {
+ DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
+ ldap_err2string(rc)));
+ return rc;
+ }
+
+ DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
+ return LDAP_SUCCESS;
+#else
+ DEBUG(0,("StartTLS not supported by LDAP client libraries!\n"));
+ return LDAP_OPERATIONS_ERROR;
+#endif
+}
+/********************************************************************
+ setup a connection to the LDAP server based on a uri
+*******************************************************************/
+
+int smb_ldap_setup_conn(LDAP **ldap_struct, const char *uri)
{
- int rc = LDAP_SUCCESS;
- int version;
- BOOL ldap_v3 = False;
- LDAP **ldap_struct = &ldap_state->ldap_struct;
+ int rc;
+ DEBUG(10, ("smb_ldap_setup_connection: %s\n", uri));
+
#ifdef HAVE_LDAP_INITIALIZE
- DEBUG(10, ("smbldap_open_connection: %s\n", ldap_state->uri));
- if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) {
+ rc = ldap_initialize(ldap_struct, uri);
+ if (rc) {
DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc)));
- return rc;
}
+
+ return rc;
#else
/* Parse the string manually */
@@ -549,15 +581,15 @@ static int smbldap_open_connection (struct smbldap_state *ldap_state)
int port = 0;
fstring protocol;
fstring host;
- const char *p = ldap_state->uri;
SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254);
-
+
+
/* skip leading "URL:" (if any) */
- if ( strnequal( p, "URL:", 4 ) ) {
- p += 4;
+ if ( strnequal( uri, "URL:", 4 ) ) {
+ uri += 4;
}
- sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
+ sscanf(uri, "%10[^:]://%254[^:/]:%d", protocol, host, &port);
if (port == 0) {
if (strequal(protocol, "ldap")) {
@@ -586,10 +618,88 @@ static int smbldap_open_connection (struct smbldap_state *ldap_state)
#else
DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n"));
return LDAP_OPERATIONS_ERROR;
-#endif
+#endif /* LDAP_OPT_X_TLS */
}
+
+ }
+#endif /* HAVE_LDAP_INITIALIZE */
+ return LDAP_SUCCESS;
+}
+
+/********************************************************************
+ try to upgrade to Version 3 LDAP if not already, in either case return current
+ version
+ *******************************************************************/
+
+int smb_ldap_upgrade_conn(LDAP *ldap_struct, int *new_version)
+{
+ int version;
+ int rc;
+
+ /* assume the worst */
+ *new_version = LDAP_VERSION2;
+
+ rc = ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (rc) {
+ return rc;
+ }
+
+ if (version == LDAP_VERSION3) {
+ *new_version = LDAP_VERSION3;
+ return LDAP_SUCCESS;
+ }
+
+ /* try upgrade */
+ version = LDAP_VERSION3;
+ rc = ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+ if (rc) {
+ return rc;
+ }
+
+ *new_version = LDAP_VERSION3;
+ return LDAP_SUCCESS;
+}
+
+/*******************************************************************
+ open a connection to the ldap server (just until the bind)
+ ******************************************************************/
+
+int smb_ldap_setup_full_conn(LDAP *ldap_struct, const char *uri)
+{
+ int rc, version;
+
+ rc = smb_ldap_setup_conn(&ldap_struct, uri);
+ if (rc) {
+ return rc;
+ }
+
+ rc = smb_ldap_upgrade_conn(ldap_struct, &version);
+ if (rc) {
+ return rc;
+ }
+
+ rc = smb_ldap_start_tls(ldap_struct, version);
+ if (rc) {
+ return rc;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+/*******************************************************************
+ open a connection to the ldap server.
+******************************************************************/
+static int smbldap_open_connection (struct smbldap_state *ldap_state)
+
+{
+ int rc = LDAP_SUCCESS;
+ int version;
+ LDAP **ldap_struct = &ldap_state->ldap_struct;
+
+ rc = smb_ldap_setup_conn(ldap_struct, ldap_state->uri);
+ if (rc) {
+ return rc;
}
-#endif
/* Store the LDAP pointer in a lookup list */
@@ -597,45 +707,22 @@ static int smbldap_open_connection (struct smbldap_state *ldap_state)
/* Upgrade to LDAPv3 if possible */
- if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS)
- {
- if (version != LDAP_VERSION3)
- {
- version = LDAP_VERSION3;
- if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
- ldap_v3 = True;
- }
- } else {
- ldap_v3 = True;
- }
+ rc = smb_ldap_upgrade_conn(*ldap_struct, &version);
+ if (rc) {
+ return rc;
}
- if (lp_ldap_ssl() == LDAP_SSL_START_TLS) {
-#ifdef LDAP_OPT_X_TLS
- if (ldap_v3) {
- if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS)
- {
- DEBUG(0,("Failed to issue the StartTLS instruction: %s\n",
- ldap_err2string(rc)));
- return rc;
- }
- DEBUG (3, ("StartTLS issued: using a TLS connection\n"));
- } else {
-
- DEBUG(0, ("Need LDAPv3 for Start TLS\n"));
- return LDAP_OPERATIONS_ERROR;
- }
-#else
- DEBUG(0,("smbldap_open_connection: StartTLS not supported by LDAP client libraries!\n"));
- return LDAP_OPERATIONS_ERROR;
-#endif
- }
+ /* Start TLS if required */
+ rc = smb_ldap_start_tls(*ldap_struct, version);
+ if (rc) {
+ return rc;
+ }
+
DEBUG(2, ("smbldap_open_connection: connection opened\n"));
return rc;
}
-
/*******************************************************************
a rebind function for authenticated referrals
This version takes a void* that we can shove useful stuff in :-)
@@ -690,9 +777,18 @@ static int rebindproc_connect_with_state (LDAP *ldap_struct,
{
struct smbldap_state *ldap_state = arg;
int rc;
- DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n",
- ldap_state->bind_dn));
-
+ int version;
+
+ DEBUG(5,("rebindproc_connect_with_state: Rebinding to %s as \"%s\"\n",
+ url, ldap_state->bind_dn));
+
+ /* call START_TLS again (ldaps:// is handled by the OpenLDAP library
+ * itself) before rebinding to another LDAP server to avoid to expose
+ * our credentials. At least *try* to secure the connection - Guenther */
+
+ smb_ldap_upgrade_conn(ldap_struct, &version);
+ smb_ldap_start_tls(ldap_struct, version);
+
/** @TODO Should we be doing something to check what servers we rebind to?
Could we get a referral to a machine that we don't want to give our
username and password to? */
diff --git a/source/lib/snprintf.c b/source/lib/snprintf.c
index 633517def28..a3e4b06d47f 100644
--- a/source/lib/snprintf.c
+++ b/source/lib/snprintf.c
@@ -89,6 +89,12 @@
*
* Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
* if the C library has some snprintf functions already.
+ *
+ * Darren Tucker (dtucker@zip.com.au)
+ * Fix bug allowing read overruns of the source string with "%.*s"
+ * Usually harmless unless the read runs outside the process' allocation
+ * (eg if your malloc does guard pages) in which case it will segfault.
+ * From OpenSSH. Also added test for same.
**************************************************************/
#ifndef NO_CONFIG_H
@@ -479,7 +485,7 @@ static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
value = "<NULL>";
}
- for (strln = 0; value[strln]; ++strln); /* strlen */
+ for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
padlen = min - strln;
if (padlen < 0)
padlen = 0;
@@ -892,6 +898,7 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
{
char buf1[1024];
char buf2[1024];
+ char *buf3;
char *fp_fmt[] = {
"%1.1f",
"%-1.5f",
@@ -1001,6 +1008,20 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...)
}
}
+#define BUFSZ 2048
+
+ if ((buf3 = malloc(BUFSZ)) == NULL) {
+ fail++;
+ } else {
+ num++;
+ memset(buf3, 'a', BUFSZ);
+ snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3);
+ if (strcmp(buf1, "a") != 0) {
+ printf("length limit buf1 '%s' expected 'a'\n", buf1);
+ fail++;
+ }
+ }
+
printf ("%d tests failed out of %d.\n", fail, num);
printf("seeing how many digits we support\n");
diff --git a/source/lib/system.c b/source/lib/system.c
index c59fe5c34d9..e9c13e6d079 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -1385,14 +1385,17 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si
* the returned value to the size of the buffer, so we have to check
* that the buffer is large enough to fit the returned value.
*/
- retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
-
- if(retval > size) {
- errno = ERANGE;
- return -1;
+ if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
+ if(retval > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
+ return retval;
}
- return extattr_get_file(path, attrnamespace, attrname, value, size);
+ DEBUG(10,("sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)));
+ return -1;
#elif defined(HAVE_ATTR_GET)
int retval, flags = 0;
int valuelength = (int)size;
@@ -1420,14 +1423,17 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
- retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
-
- if(retval > size) {
- errno = ERANGE;
- return -1;
+ if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
+ if(retval > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
+ return retval;
}
-
- return extattr_get_link(path, attrnamespace, attrname, value, size);
+
+ DEBUG(10,("sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)));
+ return -1;
#elif defined(HAVE_ATTR_GET)
int retval, flags = ATTR_DONTFOLLOW;
int valuelength = (int)size;
@@ -1455,14 +1461,17 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
- retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
-
- if(retval > size) {
- errno = ERANGE;
- return -1;
+ if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
+ if(retval > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
+ return retval;
}
-
- return extattr_get_fd(filedes, attrnamespace, attrname, value, size);
+
+ DEBUG(10,("sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno)));
+ return -1;
#elif defined(HAVE_ATTR_GETF)
int retval, flags = 0;
int valuelength = (int)size;
@@ -1554,7 +1563,7 @@ static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size
errno = ERANGE;
return -1;
}
- /* Shift the results back, so we can prepend prefixes */
+ /* Shift results back, so we can prepend prefixes */
buf = memmove(list + len, list, list_size);
for(i = 0; i < list_size; i += len + 1) {
@@ -1784,6 +1793,7 @@ int sys_setxattr (const char *path, const char *name, const void *value, size_t
errno = ENOATTR;
return -1;
}
+ /* Ignore other errors */
}
else {
/* CREATE attribute, that already exists */
@@ -1829,6 +1839,7 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t
errno = ENOATTR;
return -1;
}
+ /* Ignore other errors */
}
else {
/* CREATE attribute, that already exists */
@@ -1875,6 +1886,7 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size
errno = ENOATTR;
return -1;
}
+ /* Ignore other errors */
}
else {
/* CREATE attribute, that already exists */
diff --git a/source/libads/kerberos_verify.c b/source/libads/kerberos_verify.c
index f21577d0802..220bf14e32c 100644
--- a/source/libads/kerberos_verify.c
+++ b/source/libads/kerberos_verify.c
@@ -400,9 +400,9 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
file_save("/tmp/ticket.dat", ticket->data, ticket->length);
#endif
- /* continue when no PAC is retrieved
- (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set,
- or Kerberos tickets encryped using a DES key) - Guenther */
+ /* continue when no PAC is retrieved or we couldn't decode the PAC
+ (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set, or
+ Kerberos tickets encrypted using a DES key) - Guenther */
got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt);
if (!got_auth_data) {
diff --git a/source/libads/ldap.c b/source/libads/ldap.c
index bf402b3499e..e4cfc456a21 100644
--- a/source/libads/ldap.c
+++ b/source/libads/ldap.c
@@ -292,6 +292,11 @@ got_connection:
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
+ status = ADS_ERROR(smb_ldap_start_tls(ads->ld, version));
+ if (!ADS_ERR_OK(status)) {
+ return status;
+ }
+
if (!ads->auth.user_name) {
/* have to use the userPrincipalName value here and
not servicePrincipalName; found by Guenther Deschner @ Sernet */
@@ -577,8 +582,10 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
status = ads_do_paged_search(ads, bind_path, scope, expr, attrs, res,
&count, &cookie);
- if (!ADS_ERR_OK(status)) return status;
+ if (!ADS_ERR_OK(status))
+ return status;
+#ifdef HAVE_LDAP_ADD_RESULT_ENTRY
while (cookie) {
void *res2 = NULL;
ADS_STATUS status2;
@@ -598,6 +605,10 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path,
/* note that we do not free res2, as the memory is now
part of the main returned list */
}
+#else
+ DEBUG(0, ("no ldap_add_result_entry() support in LDAP libs!\n"));
+ status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+#endif
return status;
}
diff --git a/source/nsswitch/winbind_nss_solaris.c b/source/nsswitch/winbind_nss_solaris.c
index 64b8b734f17..8076c043e04 100644
--- a/source/nsswitch/winbind_nss_solaris.c
+++ b/source/nsswitch/winbind_nss_solaris.c
@@ -340,6 +340,7 @@ _nss_winbind_group_constr (const char* db_name,
/*****************************************************************
hosts and ipnodes backend
*****************************************************************/
+#if defined(SUNOS5) /* not compatible with HP-UX */
/* this parser is shared between get*byname and get*byaddr, as key type
in request is stored in different locations, I had to provide the
@@ -627,4 +628,5 @@ _nss_winbind_hosts_constr(dummy1, dummy2, dummy3)
sizeof (host_ops) / sizeof (host_ops[0])));
}
-#endif /* SUN_NSS */
+#endif /* defined(SUNOS5) */
+#endif /* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 3adf7717d6d..00a02330559 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -275,9 +275,6 @@ struct winbindd_methods {
char ***names,
char ***alt_names,
DOM_SID **dom_sids);
-
- /* setup the list of alternate names for the domain, if any */
- NTSTATUS (*alternate_name)(struct winbindd_domain *domain);
};
/* Used to glue a policy handle and cli_state together */
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index 32bc641b6a6..ac24b35229c 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -933,42 +933,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
return result;
}
-/* find alternate names list for the domain - for ADS this is the
- netbios name */
-static NTSTATUS alternate_name(struct winbindd_domain *domain)
-{
- ADS_STRUCT *ads;
- ADS_STATUS rc;
- TALLOC_CTX *ctx;
- const char *workgroup;
-
- DEBUG(3,("ads: alternate_name\n"));
-
- ads = ads_cached_connection(domain);
-
- if (!ads) {
- domain->last_status = NT_STATUS_SERVER_DISABLED;
- return NT_STATUS_UNSUCCESSFUL;
- }
-
- if (!(ctx = talloc_init("alternate_name"))) {
- return NT_STATUS_NO_MEMORY;
- }
-
- rc = ads_workgroup_name(ads, ctx, &workgroup);
-
- if (ADS_ERR_OK(rc)) {
- fstrcpy(domain->name, workgroup);
- fstrcpy(domain->alt_name, ads->config.realm);
- strupper_m(domain->alt_name);
- strupper_m(domain->name);
- }
-
- talloc_destroy(ctx);
-
- return ads_ntstatus(rc);
-}
-
/* the ADS backend methods are exposed via this structure */
struct winbindd_methods ads_methods = {
True,
@@ -983,7 +947,6 @@ struct winbindd_methods ads_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- alternate_name
};
#endif
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index 83ded01d4ea..2d03e452ad6 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -1401,18 +1401,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
names, alt_names, dom_sids);
}
-/* find the alternate names for the domain, if any */
-static NTSTATUS alternate_name(struct winbindd_domain *domain)
-{
- get_cache(domain);
-
- DEBUG(10,("alternate_name: [Cached] - doing backend query for info for domain %s\n",
- domain->name ));
-
- /* we don't cache this call */
- return domain->backend->alternate_name(domain);
-}
-
/* Invalidate cached user and group lists coherently */
static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
@@ -1467,7 +1455,6 @@ struct winbindd_methods cache_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- alternate_name
};
static BOOL init_wcache(void)
diff --git a/source/nsswitch/winbindd_misc.c b/source/nsswitch/winbindd_misc.c
index 4afc525b301..ec8bacc4745 100644
--- a/source/nsswitch/winbindd_misc.c
+++ b/source/nsswitch/winbindd_misc.c
@@ -134,7 +134,8 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
for (i=1; i<num_domains; i++)
extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
extra_data,
- names[i], alt_names[i],
+ names[i],
+ alt_names[i] ? alt_names[i] : names[i],
sid_string_static(&sids[i]));
/* This is a bit excessive, but the extra data sooner or later will be
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index 4582eced0e5..e683f397b66 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -797,7 +797,7 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
done:
state->response.data.auth.nt_status = NT_STATUS_V(result);
fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
- fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
+ fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
state->response.data.auth.pam_error = nt_status_to_pam(result);
DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2,
diff --git a/source/nsswitch/winbindd_passdb.c b/source/nsswitch/winbindd_passdb.c
index 238e80f31b1..c32aa01a38a 100644
--- a/source/nsswitch/winbindd_passdb.c
+++ b/source/nsswitch/winbindd_passdb.c
@@ -378,17 +378,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
return nt_status;
}
-/* find alternate names list for the domain
- * should we look for netbios aliases??
- SSS */
-static NTSTATUS alternate_name(struct winbindd_domain *domain)
-{
- DEBUG(3,("pdb: alternate_name\n"));
-
- return NT_STATUS_OK;
-}
-
-
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods passdb_methods = {
False,
@@ -403,5 +392,4 @@ struct winbindd_methods passdb_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- alternate_name
};
diff --git a/source/nsswitch/winbindd_reconnect.c b/source/nsswitch/winbindd_reconnect.c
index 1a90717db31..77df9c1513c 100644
--- a/source/nsswitch/winbindd_reconnect.c
+++ b/source/nsswitch/winbindd_reconnect.c
@@ -242,19 +242,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
return result;
}
-static NTSTATUS alternate_name(struct winbindd_domain *domain)
-{
- NTSTATUS result;
-
- result = msrpc_methods.alternate_name(domain);
-
- if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))
- result = msrpc_methods.alternate_name(domain);
-
- return result;
-}
-
-
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods reconnect_methods = {
False,
@@ -269,5 +256,4 @@ struct winbindd_methods reconnect_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- alternate_name
};
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 63e24877008..6179189e309 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -883,13 +883,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
return result;
}
-/* find alternate names list for the domain - none for rpc */
-static NTSTATUS alternate_name(struct winbindd_domain *domain)
-{
- return NT_STATUS_OK;
-}
-
-
/* the rpc backend methods are exposed via this structure */
struct winbindd_methods msrpc_methods = {
False,
@@ -904,5 +897,4 @@ struct winbindd_methods msrpc_methods = {
lookup_groupmem,
sequence_number,
trusted_domains,
- alternate_name
};
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index d2d739fa726..86a5353dca7 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -145,7 +145,6 @@ typedef struct
char *szNetbiosName;
char **szNetbiosAliases;
char *szNetbiosScope;
- char *szDomainOtherSIDs;
char *szNameResolveOrder;
char *szPanicAction;
char *szAddUserScript;
@@ -302,6 +301,7 @@ typedef struct
int name_cache_timeout;
int client_signing;
int server_signing;
+ BOOL bResetOnZeroVC;
param_opt_struct *param_opt;
}
global;
@@ -952,6 +952,7 @@ static struct parm_struct parm_table[] = {
{"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED},
{"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED},
{"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED},
+ {"reset on zero vc", P_BOOL, P_GLOBAL, &Globals.bResetOnZeroVC, NULL, NULL, FLAG_ADVANCED},
{"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"defer sharing violations", P_BOOL, P_GLOBAL, &Globals.bDeferSharingViolations, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL},
@@ -1425,6 +1426,9 @@ static void init_globals(void)
slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION,
DEFAULT_MINOR_VERSION);
string_set(&Globals.szAnnounceVersion, s);
+#ifdef DEVELOPER
+ string_set(&Globals.szPanicAction, "/bin/sleep 999999999");
+#endif
pstrcpy(user_socket_options, DEFAULT_SOCKET_OPTIONS);
@@ -1520,6 +1524,7 @@ static void init_globals(void)
Globals.bUseMmap = True;
#endif
Globals.bUnixExtensions = True;
+ Globals.bResetOnZeroVC = False;
/* hostname lookups can be very expensive and are broken on
a large number of sites (tridge) */
@@ -1807,6 +1812,7 @@ FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
+FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy)
FN_GLOBAL_BOOL(lp_wins_support, &Globals.bWINSsupport)
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 92ef5133258..8a9730c3c8a 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -3415,7 +3415,7 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
ldap_get_option(ldap_state->smbldap_state->ldap_struct,
LDAP_OPT_ERROR_STRING,&ld_error);
- DEBUG(0, ("ldapsam_get_account_policy_from_ldap: Could not set account policy "
+ DEBUG(0, ("ldapsam_get_account_policy_from_ldap: Could not get account policy "
"for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
ld_error?ld_error:"unknown"));
SAFE_FREE(ld_error);
diff --git a/source/passdb/pdb_nds.c b/source/passdb/pdb_nds.c
index 5de80a827fa..c6d644827c7 100644
--- a/source/passdb/pdb_nds.c
+++ b/source/passdb/pdb_nds.c
@@ -762,11 +762,7 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
const char **attr_list;
size_t pwd_len;
char clear_text_pw[512];
- const char *p = NULL;
LDAP *ld = NULL;
- int ldap_port = 0;
- char protocol[12];
- char ldap_server[256];
const char *username = pdb_get_username(sam_acct);
BOOL got_clear_text_pw = False;
@@ -809,53 +805,13 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
DEBUG(5,("pdb_nds_update_login_attempts: using random password %s\n", clear_text_pw));
}
- /* Parse the location string */
- p = ldap_state->location;
-
- /* skip leading "URL:" (if any) */
- if ( strnequal( p, "URL:", 4 ) ) {
- p += 4;
- }
-
- sscanf(p, "%10[^:]://%254[^:/]:%d", protocol, ldap_server, &ldap_port);
-
- if (ldap_port == 0) {
- if (strequal(protocol, "ldap")) {
- ldap_port = LDAP_PORT;
- } else if (strequal(protocol, "ldaps")) {
- ldap_port = LDAPS_PORT;
- } else {
- DEBUG(0, ("unrecognised protocol (%s)!\n", protocol));
- }
- }
-
- ld = ldap_init(ldap_server, ldap_port);
-
- if(ld != NULL) {
- int version;
-
- /* LDAP version 3 required for ldap_sasl */
- if (ldap_get_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
- if (version != LDAP_VERSION3) {
- version = LDAP_VERSION3;
- if (ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
- DEBUG(4, ("pdb_nds_update_login_attempts: Set protocol version to LDAP_VERSION3\n"));
- }
- }
- }
-
- /* Turn on ssl if required */
- if(strequal(protocol, "ldaps")) {
- int tls = LDAP_OPT_X_TLS_HARD;
- if (ldap_set_option (ld, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) {
- DEBUG(1, ("pdb_nds_update_login_attempts: Failed to setup a TLS session\n"));
- } else {
- DEBUG(4, ("pdb_nds_update_login_attempts: Activated TLS on session\n"));
- }
+ if((success != True) || (got_clear_text_pw == True)) {
+
+ rc = smb_ldap_setup_full_conn(ld, ldap_state->location);
+ if (rc) {
+ return NT_STATUS_INVALID_CONNECTION;
}
- }
- if((success != True) || (got_clear_text_pw == True)) {
/* Attempt simple bind with real or bogus password */
rc = ldap_simple_bind_s(ld, dn, clear_text_pw);
if (rc == LDAP_SUCCESS) {
diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c
index c64de2b8e88..aa1cb95fda1 100644
--- a/source/rpc_client/cli_lsarpc.c
+++ b/source/rpc_client/cli_lsarpc.c
@@ -1264,7 +1264,7 @@ NTSTATUS rpccli_lsa_open_trusted_domain(struct rpc_pipe_client *cli, TALLOC_CTX
NTSTATUS rpccli_lsa_query_trusted_domain_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol,
- uint16 info_class, DOM_SID *dom_sid,
+ uint16 info_class,
LSA_TRUSTED_DOMAIN_INFO **info)
{
prs_struct qbuf, rbuf;
diff --git a/source/rpc_parse/parse_eventlog.c b/source/rpc_parse/parse_eventlog.c
index 0f0b02748b3..5e28a4aba5d 100644
--- a/source/rpc_parse/parse_eventlog.c
+++ b/source/rpc_parse/parse_eventlog.c
@@ -294,7 +294,7 @@ BOOL eventlog_io_r_read_eventlog(const char *desc,
while(entry != NULL && record_written < record_total)
{
- DEBUG(10, ("eventlog_io_r_read_eventlog: writing record [%d] out of [%d].\n", record_written, record_total));
+ DEBUG(11, ("eventlog_io_r_read_eventlog: writing record [%d] out of [%d].\n", record_written, record_total));
/* Encode the actual eventlog record record */
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index dfe80a65e27..2ba99fff495 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -2141,7 +2141,7 @@ void init_samr_group_info1(GROUP_INFO1 * gr1,
{
DEBUG(5, ("init_samr_group_info1\n"));
- gr1->unknown_1 = 0x3;
+ gr1->group_attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT); /* why not | SE_GROUP_ENABLED ? */
gr1->num_members = num_members;
init_unistr2(&gr1->uni_acct_name, acct_name, UNI_FLAGS_NONE);
@@ -2174,7 +2174,7 @@ BOOL samr_io_group_info1(const char *desc, GROUP_INFO1 * gr1,
if(!smb_io_unihdr("hdr_acct_name", &gr1->hdr_acct_name, ps, depth))
return False;
- if(!prs_uint32("unknown_1", ps, depth, &gr1->unknown_1))
+ if(!prs_uint32("group_attr", ps, depth, &gr1->group_attr))
return False;
if(!prs_uint32("num_members", ps, depth, &gr1->num_members))
return False;
@@ -2238,7 +2238,7 @@ void init_samr_group_info3(GROUP_INFO3 *gr3)
{
DEBUG(5, ("init_samr_group_info3\n"));
- gr3->unknown_1 = 0x3;
+ gr3->group_attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT); /* why not | SE_GROUP_ENABLED ? */
}
/*******************************************************************
@@ -2256,7 +2256,7 @@ BOOL samr_io_group_info3(const char *desc, GROUP_INFO3 *gr3, prs_struct *ps, int
if(!prs_align(ps))
return False;
- if(!prs_uint32("unknown_1", ps, depth, &gr3->unknown_1))
+ if(!prs_uint32("group_attr", ps, depth, &gr3->group_attr))
return False;
return True;
@@ -7143,10 +7143,10 @@ BOOL samr_io_r_chgpasswd_user(const char *desc, SAMR_R_CHGPASSWD_USER * r_u,
reads or writes a structure.
********************************************************************/
-void init_samr_q_unknown_2e(SAMR_Q_UNKNOWN_2E *q_u,
+void init_samr_q_query_domain_info2(SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
POLICY_HND *domain_pol, uint16 switch_value)
{
- DEBUG(5, ("init_samr_q_unknown_2e\n"));
+ DEBUG(5, ("init_samr_q_query_domain_info2\n"));
q_u->domain_pol = *domain_pol;
q_u->switch_value = switch_value;
@@ -7156,13 +7156,13 @@ void init_samr_q_unknown_2e(SAMR_Q_UNKNOWN_2E *q_u,
reads or writes a structure.
********************************************************************/
-BOOL samr_io_q_unknown_2e(const char *desc, SAMR_Q_UNKNOWN_2E *q_u,
+BOOL samr_io_q_query_domain_info2(const char *desc, SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
prs_struct *ps, int depth)
{
if (q_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_q_unknown_2e");
+ prs_debug(ps, depth, desc, "samr_io_q_query_domain_info2");
depth++;
if(!prs_align(ps))
@@ -7181,11 +7181,11 @@ BOOL samr_io_q_unknown_2e(const char *desc, SAMR_Q_UNKNOWN_2E *q_u,
inits a SAMR_R_QUERY_DOMAIN_INFO structure.
********************************************************************/
-void init_samr_r_samr_unknown_2e(SAMR_R_UNKNOWN_2E * r_u,
+void init_samr_r_samr_query_domain_info2(SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
uint16 switch_value, SAM_UNK_CTR * ctr,
NTSTATUS status)
{
- DEBUG(5, ("init_samr_r_samr_unknown_2e\n"));
+ DEBUG(5, ("init_samr_r_samr_query_domain_info2\n"));
r_u->ptr_0 = 0;
r_u->switch_value = 0;
@@ -7202,13 +7202,13 @@ void init_samr_r_samr_unknown_2e(SAMR_R_UNKNOWN_2E * r_u,
reads or writes a structure.
********************************************************************/
-BOOL samr_io_r_samr_unknown_2e(const char *desc, SAMR_R_UNKNOWN_2E * r_u,
+BOOL samr_io_r_samr_query_domain_info2(const char *desc, SAMR_R_QUERY_DOMAIN_INFO2 * r_u,
prs_struct *ps, int depth)
{
if (r_u == NULL)
return False;
- prs_debug(ps, depth, desc, "samr_io_r_samr_unknown_2e");
+ prs_debug(ps, depth, desc, "samr_io_r_samr_query_domain_info2");
depth++;
if(!prs_align(ps))
@@ -7253,7 +7253,7 @@ BOOL samr_io_r_samr_unknown_2e(const char *desc, SAMR_R_UNKNOWN_2E * r_u,
return False;
break;
default:
- DEBUG(0, ("samr_io_r_samr_unknown_2e: unknown switch level 0x%x\n",
+ DEBUG(0, ("samr_io_r_samr_query_domain_info2: unknown switch level 0x%x\n",
r_u->switch_value));
r_u->status = NT_STATUS_INVALID_INFO_CLASS;
return False;
diff --git a/source/rpc_server/srv_eventlog_lib.c b/source/rpc_server/srv_eventlog_lib.c
index b21c2a2529f..ec5edf2f347 100644
--- a/source/rpc_server/srv_eventlog_lib.c
+++ b/source/rpc_server/srv_eventlog_lib.c
@@ -24,14 +24,7 @@
/* maintain a list of open eventlog tdbs with reference counts */
-struct elog_open_tdb {
- struct elog_open_tdb *prev, *next;
- char *name;
- TDB_CONTEXT *tdb;
- int ref_count;
-};
-
-static struct elog_open_tdb *open_elog_list;
+static ELOG_TDB *open_elog_list;
/********************************************************************
Init an Eventlog TDB, and return it. If null, something bad
@@ -317,14 +310,14 @@ BOOL can_write_to_eventlog( TDB_CONTEXT * tdb, int32 needed )
/*******************************************************************
*******************************************************************/
-TDB_CONTEXT *elog_open_tdb( char *logname )
+ELOG_TDB *elog_open_tdb( char *logname, BOOL force_clear )
{
- TDB_CONTEXT *tdb;
+ TDB_CONTEXT *tdb = NULL;
uint32 vers_id;
- struct elog_open_tdb *ptr;
+ ELOG_TDB *ptr;
char *tdbfilename;
pstring tdbpath;
- struct elog_open_tdb *tdb_node;
+ ELOG_TDB *tdb_node = NULL;
char *eventlogdir;
/* first see if we have an open context */
@@ -332,7 +325,19 @@ TDB_CONTEXT *elog_open_tdb( char *logname )
for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
if ( strequal( ptr->name, logname ) ) {
ptr->ref_count++;
- return ptr->tdb;
+
+ /* trick to alow clearing of the eventlog tdb.
+ The force_clear flag should imply that someone
+ has done a force close. So make sure the tdb
+ is NULL. If this is a normal open, then just
+ return the existing reference */
+
+ if ( force_clear ) {
+ SMB_ASSERT( ptr->tdb == NULL );
+ break;
+ }
+ else
+ return ptr;
}
}
@@ -348,27 +353,41 @@ TDB_CONTEXT *elog_open_tdb( char *logname )
pstrcpy( tdbpath, tdbfilename );
SAFE_FREE( tdbfilename );
- DEBUG(7,("elog_open_tdb: Opening %s...\n", tdbpath ));
+ DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
+ tdbpath, force_clear?"True":"False" ));
+
+ /* the tdb wasn't already open or this is a forced clear open */
- tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
- if ( tdb ) {
- vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
+ if ( !force_clear ) {
- if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
- DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
- vers_id, tdbpath));
- tdb_close( tdb );
- tdb = elog_init_tdb( tdbpath );
+ tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, O_RDWR , 0 );
+ if ( tdb ) {
+ vers_id = tdb_fetch_int32( tdb, EVT_VERSION );
+
+ if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
+ DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
+ vers_id, tdbpath));
+ tdb_close( tdb );
+ tdb = elog_init_tdb( tdbpath );
+ }
}
}
- else {
+
+ if ( !tdb )
tdb = elog_init_tdb( tdbpath );
- }
/* if we got a valid context, then add it to the list */
if ( tdb ) {
- if ( !(tdb_node = TALLOC_ZERO_P( NULL, struct elog_open_tdb )) ) {
+ /* on a forced clear, just reset the tdb context if we already
+ have an open entry in the list */
+
+ if ( ptr ) {
+ ptr->tdb = tdb;
+ return ptr;
+ }
+
+ if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
tdb_close( tdb );
return NULL;
@@ -381,42 +400,34 @@ TDB_CONTEXT *elog_open_tdb( char *logname )
DLIST_ADD( open_elog_list, tdb_node );
}
- return tdb;
+ return tdb_node;
}
/*******************************************************************
Wrapper to handle reference counts to the tdb
*******************************************************************/
-int elog_close_tdb( TDB_CONTEXT *tdb )
+int elog_close_tdb( ELOG_TDB *etdb, BOOL force_close )
{
- struct elog_open_tdb *ptr;
+ TDB_CONTEXT *tdb;
- if ( !tdb )
+ if ( !etdb )
return 0;
- /* See if we can just decrement the ref_count.
- Just compare pointer values (not names ) */
-
- for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
- if ( tdb == ptr->tdb ) {
- ptr->ref_count--;
- break;
- }
- }
+ etdb->ref_count--;
- /* if we have a NULL pointer; it means we are trying to
- close a tdb not in the list of open eventlogs */
-
- SMB_ASSERT( ptr != NULL );
- if ( !ptr )
+ SMB_ASSERT( etdb->ref_count >= 0 );
+
+ if ( etdb->ref_count == 0 ) {
+ tdb = etdb->tdb;
+ DLIST_REMOVE( open_elog_list, etdb );
+ TALLOC_FREE( etdb );
return tdb_close( tdb );
+ }
- SMB_ASSERT( ptr->ref_count >= 0 );
-
- if ( ptr->ref_count == 0 ) {
- DLIST_REMOVE( open_elog_list, ptr );
- TALLOC_FREE( ptr );
+ if ( force_close ) {
+ tdb = etdb->tdb;
+ etdb->tdb = NULL;
return tdb_close( tdb );
}
diff --git a/source/rpc_server/srv_eventlog_nt.c b/source/rpc_server/srv_eventlog_nt.c
index 6413221031c..658928b9270 100644
--- a/source/rpc_server/srv_eventlog_nt.c
+++ b/source/rpc_server/srv_eventlog_nt.c
@@ -27,7 +27,8 @@
typedef struct {
char *logname;
- TDB_CONTEXT *tdb;
+ ELOG_TDB *etdb;
+ uint32 current_record;
uint32 num_records;
uint32 oldest_entry;
uint32 flags;
@@ -41,8 +42,8 @@ static void free_eventlog_info( void *ptr )
{
EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr;
- if ( elog->tdb )
- elog_close_tdb( elog->tdb );
+ if ( elog->etdb )
+ elog_close_tdb( elog->etdb, False );
TALLOC_FREE( elog );
}
@@ -131,6 +132,45 @@ static BOOL elog_validate_logname( const char *name )
}
/********************************************************************
+********************************************************************/
+
+static BOOL get_num_records_hook( EVENTLOG_INFO * info )
+{
+ int next_record;
+ int oldest_record;
+
+ if ( !info->etdb ) {
+ DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
+ return False;
+ }
+
+ /* lock the tdb since we have to get 2 records */
+
+ tdb_lock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
+ next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
+ oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
+ tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
+
+ DEBUG( 8,
+ ( "Oldest Record %d; Next Record %d\n", oldest_record,
+ next_record ) );
+
+ info->num_records = ( next_record - oldest_record );
+ info->oldest_entry = oldest_record;
+
+ return True;
+}
+
+/********************************************************************
+ ********************************************************************/
+
+static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info )
+{
+ /* it's the same thing */
+ return get_num_records_hook( info );
+}
+
+/********************************************************************
********************************************************************/
static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hnd )
@@ -153,10 +193,10 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
in a single process */
become_root();
- elog->tdb = elog_open_tdb( elog->logname );
+ elog->etdb = elog_open_tdb( elog->logname, False );
unbecome_root();
- if ( !elog->tdb ) {
+ if ( !elog->etdb ) {
/* according to MSDN, if the logfile cannot be found, we should
default to the "Application" log */
@@ -173,11 +213,11 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
}
become_root();
- elog->tdb = elog_open_tdb( elog->logname );
+ elog->etdb = elog_open_tdb( elog->logname, False );
unbecome_root();
}
- if ( !elog->tdb ) {
+ if ( !elog->etdb ) {
TALLOC_FREE( elog );
return NT_STATUS_ACCESS_DENIED; /* ??? */
}
@@ -186,7 +226,7 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
/* now do the access check. Close the tdb if we fail here */
if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
- elog_close_tdb( elog->tdb );
+ elog_close_tdb( elog->etdb, False );
TALLOC_FREE( elog );
return NT_STATUS_ACCESS_DENIED;
}
@@ -199,6 +239,15 @@ static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hn
return NT_STATUS_NO_MEMORY;
}
+ /* set the initial current_record pointer */
+
+ if ( !get_oldest_entry_hook( elog ) ) {
+ DEBUG(3,("elog_open: Successfully opened eventlog but can't "
+ "get any information on internal records!\n"));
+ }
+
+ elog->current_record = elog->oldest_entry;
+
return NT_STATUS_OK;
}
@@ -219,12 +268,12 @@ static NTSTATUS elog_close( pipes_struct *p, POLICY_HND *hnd )
static int elog_size( EVENTLOG_INFO *info )
{
- if ( !info || !info->tdb ) {
+ if ( !info || !info->etdb ) {
DEBUG(0,("elog_size: Invalid info* structure!\n"));
return 0;
}
- return elog_tdb_size( info->tdb, NULL, NULL );
+ return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
}
/********************************************************************
@@ -348,7 +397,7 @@ static BOOL sync_eventlog_params( EVENTLOG_INFO *info )
DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
- if ( !info->tdb ) {
+ if ( !info->etdb ) {
DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
return False;
}
@@ -391,38 +440,8 @@ static BOOL sync_eventlog_params( EVENTLOG_INFO *info )
regkey_close_internal( keyinfo );
- tdb_store_int32( info->tdb, EVT_MAXSIZE, uiMaxSize );
- tdb_store_int32( info->tdb, EVT_RETENTION, uiRetention );
-
- return True;
-}
-
-/********************************************************************
-********************************************************************/
-
-static BOOL get_num_records_hook( EVENTLOG_INFO * info )
-{
- int next_record;
- int oldest_record;
-
- if ( !info->tdb ) {
- DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
- return False;
- }
-
- /* lock the tdb since we have to get 2 records */
-
- tdb_lock_bystring( info->tdb, EVT_NEXT_RECORD, 1 );
- next_record = tdb_fetch_int32( info->tdb, EVT_NEXT_RECORD);
- oldest_record = tdb_fetch_int32( info->tdb, EVT_OLDEST_ENTRY);
- tdb_unlock_bystring( info->tdb, EVT_NEXT_RECORD);
-
- DEBUG( 8,
- ( "Oldest Record %d; Next Record %d\n", oldest_record,
- next_record ) );
-
- info->num_records = ( next_record - oldest_record );
- info->oldest_entry = oldest_record;
+ tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
+ tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
return True;
}
@@ -430,15 +449,6 @@ static BOOL get_num_records_hook( EVENTLOG_INFO * info )
/********************************************************************
********************************************************************/
-static BOOL get_oldest_entry_hook( EVENTLOG_INFO * info )
-{
- /* it's the same thing */
- return get_num_records_hook( info );
-}
-
-/********************************************************************
- ********************************************************************/
-
static Eventlog_entry *read_package_entry( prs_struct * ps,
EVENTLOG_Q_READ_EVENTLOG * q_u,
EVENTLOG_R_READ_EVENTLOG * r_u,
@@ -600,7 +610,7 @@ NTSTATUS _eventlog_open_eventlog( pipes_struct * p,
DEBUG(10,("_eventlog_open_eventlog: Size [%d]\n", elog_size( info )));
sync_eventlog_params( info );
- prune_eventlog( info->tdb );
+ prune_eventlog( ELOG_TDB_CTX(info->etdb) );
return NT_STATUS_OK;
}
@@ -624,20 +634,26 @@ NTSTATUS _eventlog_clear_eventlog( pipes_struct * p,
rpcstr_pull( backup_file_name, q_u->backupfile.string->buffer,
sizeof( backup_file_name ),
q_u->backupfile.string->uni_str_len * 2, 0 );
+
+ DEBUG(8,( "_eventlog_clear_eventlog: Using [%s] as the backup "
+ "file name for log [%s].",
+ backup_file_name, info->logname ) );
}
- DEBUG( 8,
- ( "_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
- backup_file_name, info->logname ) );
+ /* check for WRITE access to the file */
-#if 0
- /* close the current one, reinit */
+ if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
+ return NT_STATUS_ACCESS_DENIED;
- tdb_close( info->tdb );
+ /* Force a close and reopen */
- if ( !(info->tdb = elog_init_tdb( ttdb[i].tdbfname )) )
+ elog_close_tdb( info->etdb, True );
+ become_root();
+ info->etdb = elog_open_tdb( info->logname, True );
+ unbecome_root();
+
+ if ( !info->etdb )
return NT_STATUS_ACCESS_DENIED;
-#endif
return NT_STATUS_OK;
}
@@ -661,71 +677,86 @@ NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
{
EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
Eventlog_entry entry, *ee_new;
-
uint32 num_records_read = 0;
prs_struct *ps;
int bytes_left, record_number;
- TDB_CONTEXT *tdb;
+ uint32 elog_read_type, elog_read_dir;
info->flags = q_u->flags;
ps = &p->out_data.rdata;
bytes_left = q_u->max_read_size;
- tdb = info->tdb;
- if ( !tdb ) {
+
+ if ( !info->etdb )
return NT_STATUS_ACCESS_DENIED;
+
+ /* check for valid flags. Can't use the sequential and seek flags together */
+
+ elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
+ elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
+
+ if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ)
+ || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) )
+ {
+ DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags));
+ return NT_STATUS_INVALID_PARAMETER;
}
- /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */
+ /* a sequential read should ignore the offset */
- record_number = q_u->offset;
+ if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ )
+ record_number = info->current_record;
+ else
+ record_number = q_u->offset;
while ( bytes_left > 0 ) {
- if ( get_eventlog_record
- ( ps, tdb, record_number, &entry ) ) {
- DEBUG( 8,
- ( "Retrieved record %d\n", record_number ) );
+
+ /* assume that when the record fetch fails, that we are done */
+
+ if ( !get_eventlog_record ( ps, ELOG_TDB_CTX(info->etdb), record_number, &entry ) )
+ break;
+
+ DEBUG( 8, ( "Retrieved record %d\n", record_number ) );
- /* Now see if there is enough room to add */
- ee_new = read_package_entry( ps, q_u, r_u,&entry );
- if ( !ee_new )
- return NT_STATUS_NO_MEMORY;
-
- if ( r_u->num_bytes_in_resp + ee_new->record.length >
- q_u->max_read_size ) {
- r_u->bytes_in_next_record =
- ee_new->record.length;
-
- /* response would be too big to fit in client-size buffer */
+ /* Now see if there is enough room to add */
+
+ if ( !(ee_new = read_package_entry( ps, q_u, r_u,&entry )) )
+ return NT_STATUS_NO_MEMORY;
+
+ if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) {
+ r_u->bytes_in_next_record = ee_new->record.length;
+
+ /* response would be too big to fit in client-size buffer */
- bytes_left = 0;
- break;
- }
+ bytes_left = 0;
+ break;
+ }
- add_record_to_resp( r_u, ee_new );
- bytes_left -= ee_new->record.length;
- ZERO_STRUCT( entry );
- num_records_read =
- r_u->num_records - num_records_read;
+ add_record_to_resp( r_u, ee_new );
+ bytes_left -= ee_new->record.length;
+ ZERO_STRUCT( entry );
+ num_records_read = r_u->num_records - num_records_read;
- DEBUG( 10,
- ( "_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n",
- num_records_read, r_u->num_records,
- r_u->num_bytes_in_resp,
- q_u->max_read_size ) );
- } else {
- DEBUG( 8, ( "get_eventlog_record returned NULL\n" ) );
- return NT_STATUS_NO_MEMORY; /* wrong error - but return one anyway */
- }
-
+ DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total "
+ "of [%d] records using [%d] bytes out of a max of [%d].\n",
+ num_records_read, r_u->num_records,
+ r_u->num_bytes_in_resp,
+ q_u->max_read_size ) );
if ( info->flags & EVENTLOG_FORWARDS_READ )
record_number++;
else
record_number--;
+
+ /* update the eventlog record pointer */
+
+ info->current_record = record_number;
}
-
- return NT_STATUS_OK;
+
+ /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to
+ say when there are no more records */
+
+ return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL);
}
/********************************************************************
diff --git a/source/rpc_server/srv_samr.c b/source/rpc_server/srv_samr.c
index ffb7882e110..cbfad5688e1 100644
--- a/source/rpc_server/srv_samr.c
+++ b/source/rpc_server/srv_samr.c
@@ -1374,13 +1374,13 @@ static BOOL api_samr_remove_sid_foreign_domain(pipes_struct *p)
}
/*******************************************************************
- api_samr_query_dom_info
+ api_samr_query_dom_info2
********************************************************************/
-static BOOL api_samr_unknown_2e(pipes_struct *p)
+static BOOL api_samr_query_domain_info2(pipes_struct *p)
{
- SAMR_Q_UNKNOWN_2E q_u;
- SAMR_R_UNKNOWN_2E r_u;
+ SAMR_Q_QUERY_DOMAIN_INFO2 q_u;
+ SAMR_R_QUERY_DOMAIN_INFO2 r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
@@ -1388,16 +1388,16 @@ static BOOL api_samr_unknown_2e(pipes_struct *p)
ZERO_STRUCT(r_u);
/* grab the samr unknown 8 command */
- if(!samr_io_q_unknown_2e("", &q_u, data, 0)) {
- DEBUG(0,("api_samr_unknown_2e: unable to unmarshall SAMR_Q_UNKNOWN_2E.\n"));
+ if(!samr_io_q_query_domain_info2("", &q_u, data, 0)) {
+ DEBUG(0,("api_samr_query_domain_info2: unable to unmarshall SAMR_Q_QUERY_DOMAIN_INFO2.\n"));
return False;
}
- r_u.status = _samr_unknown_2e(p, &q_u, &r_u);
+ r_u.status = _samr_query_domain_info2(p, &q_u, &r_u);
/* store the response in the SMB stream */
- if(!samr_io_r_samr_unknown_2e("", &r_u, rdata, 0)) {
- DEBUG(0,("api_samr_unknown_2e: unable to marshall SAMR_R_UNKNOWN_2E.\n"));
+ if(!samr_io_r_samr_query_domain_info2("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_samr_query_domain_info2: unable to marshall SAMR_R_QUERY_DOMAIN_INFO2.\n"));
return False;
}
@@ -1490,7 +1490,7 @@ static struct api_struct api_samr_cmds [] =
{"SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_query_sec_obj },
{"SAMR_SET_SEC_OBJECT" , SAMR_SET_SEC_OBJECT , api_samr_set_sec_obj },
{"SAMR_GET_USRDOM_PWINFO" , SAMR_GET_USRDOM_PWINFO, api_samr_get_usrdom_pwinfo},
- {"SAMR_UNKNOWN_2E" , SAMR_UNKNOWN_2E , api_samr_unknown_2e },
+ {"SAMR_QUERY_DOMAIN_INFO2", SAMR_QUERY_DOMAIN_INFO2, api_samr_query_domain_info2},
{"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info },
{"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 }
};
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index 71272a9a98b..4d44f8312b3 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -40,11 +40,12 @@
SA_RIGHT_USER_CHANGE_PASSWORD | \
SA_RIGHT_USER_SET_LOC_COM )
-extern rid_name domain_group_rids[];
-extern rid_name domain_alias_rids[];
-extern rid_name builtin_alias_rids[];
+#define DISP_INFO_CACHE_TIMEOUT 10
typedef struct disp_info {
+ struct disp_info *next, *prev;
+ TALLOC_CTX *mem_ctx;
+ DOM_SID sid; /* identify which domain this is. */
struct pdb_search *users; /* querydispinfo 1 and 4 */
struct pdb_search *machines; /* querydispinfo 2 */
struct pdb_search *groups; /* querydispinfo 3 and 5, enumgroups */
@@ -53,8 +54,15 @@ typedef struct disp_info {
uint16 enum_acb_mask;
struct pdb_search *enum_users; /* enumusers with a mask */
+
+ smb_event_id_t di_cache_timeout_event; /* cache idle timeout handler. */
} DISP_INFO;
+/* We keep a static list of these by SID as modern clients close down
+ all resources between each request in a complete enumeration. */
+
+static DISP_INFO *disp_info_list;
+
struct samr_info {
/* for use by the \PIPE\samr policy */
DOM_SID sid;
@@ -62,8 +70,7 @@ struct samr_info {
uint32 acc_granted;
uint16 acb_mask;
BOOL only_machines;
- DISP_INFO disp_info;
-
+ DISP_INFO *disp_info;
TALLOC_CTX *mem_ctx;
};
@@ -215,6 +222,39 @@ static NTSTATUS access_check_samr_function(uint32 acc_granted, uint32 acc_requir
return NT_STATUS_ACCESS_DENIED;
}
+/*******************************************************************
+ Fetch or create a dispinfo struct.
+********************************************************************/
+
+static DISP_INFO *get_samr_dispinfo_by_sid(DOM_SID *psid, const char *sid_str)
+{
+ TALLOC_CTX *mem_ctx;
+ DISP_INFO *dpi;
+
+ for (dpi = disp_info_list; dpi; dpi = dpi->next) {
+ if (sid_equal(psid, &dpi->sid)) {
+ return dpi;
+ }
+ }
+
+ /* This struct is never free'd - I'm using talloc so we
+ can get a list out of smbd using smbcontrol. There will
+ be one of these per SID we're authorative for. JRA. */
+
+ mem_ctx = talloc_init("DISP_INFO for domain sid %s", sid_str);
+
+ if ((dpi = TALLOC_ZERO_P(mem_ctx, DISP_INFO)) == NULL)
+ return NULL;
+
+ dpi->mem_ctx = mem_ctx;
+ if (psid) {
+ sid_copy( &dpi->sid, psid);
+ }
+
+ DLIST_ADD(disp_info_list, dpi);
+
+ return dpi;
+}
/*******************************************************************
Create a samr_info struct.
@@ -244,42 +284,156 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
DEBUG(10,("get_samr_info_by_sid: created new info for NULL sid.\n"));
}
info->mem_ctx = mem_ctx;
+
+ info->disp_info = get_samr_dispinfo_by_sid(psid, sid_str);
+
+ if (!info->disp_info) {
+ talloc_destroy(mem_ctx);
+ return NULL;
+ }
+
return info;
}
/*******************************************************************
- Function to free the per handle data.
+ Function to free the per SID data.
********************************************************************/
+static void free_samr_cache(DISP_INFO *disp_info, const char *sid_str)
+{
+ DEBUG(10,("free_samr_cache: deleting cache for SID %s\n", sid_str));
+
+ /* We need to become root here because the paged search might have to
+ * tell the LDAP server we're not interested in the rest anymore. */
+
+ become_root();
+
+ if (disp_info->users) {
+ DEBUG(10,("free_samr_cache: deleting users cache\n"));
+ pdb_search_destroy(disp_info->users);
+ disp_info->users = NULL;
+ }
+ if (disp_info->machines) {
+ DEBUG(10,("free_samr_cache: deleting machines cache\n"));
+ pdb_search_destroy(disp_info->machines);
+ disp_info->machines = NULL;
+ }
+ if (disp_info->groups) {
+ DEBUG(10,("free_samr_cache: deleting groups cache\n"));
+ pdb_search_destroy(disp_info->groups);
+ disp_info->groups = NULL;
+ }
+ if (disp_info->aliases) {
+ DEBUG(10,("free_samr_cache: deleting aliases cache\n"));
+ pdb_search_destroy(disp_info->aliases);
+ disp_info->aliases = NULL;
+ }
+ if (disp_info->builtins) {
+ DEBUG(10,("free_samr_cache: deleting builtins cache\n"));
+ pdb_search_destroy(disp_info->builtins);
+ disp_info->builtins = NULL;
+ }
+ if (disp_info->enum_users) {
+ DEBUG(10,("free_samr_cache: deleting enum_users cache\n"));
+ pdb_search_destroy(disp_info->enum_users);
+ disp_info->enum_users = NULL;
+ }
+ disp_info->enum_acb_mask = 0;
+
+ unbecome_root();
+}
+
/*******************************************************************
Function to free the per handle data.
********************************************************************/
-static void free_samr_db(struct samr_info *info)
-{
- pdb_search_destroy(info->disp_info.users);
- info->disp_info.users = NULL;
- pdb_search_destroy(info->disp_info.machines);
- info->disp_info.machines = NULL;
- pdb_search_destroy(info->disp_info.groups);
- info->disp_info.groups = NULL;
- pdb_search_destroy(info->disp_info.aliases);
- info->disp_info.aliases = NULL;
- pdb_search_destroy(info->disp_info.builtins);
- info->disp_info.builtins = NULL;
- pdb_search_destroy(info->disp_info.enum_users);
- info->disp_info.enum_users = NULL;
-}
-
static void free_samr_info(void *ptr)
{
struct samr_info *info=(struct samr_info *) ptr;
- free_samr_db(info);
+ /* Only free the dispinfo cache if no one bothered to set up
+ a timeout. */
+
+ if (info->disp_info && info->disp_info->di_cache_timeout_event == (smb_event_id_t)0) {
+ fstring sid_str;
+ sid_to_string(sid_str, &info->disp_info->sid);
+ free_samr_cache(info->disp_info, sid_str);
+ }
+
talloc_destroy(info->mem_ctx);
}
/*******************************************************************
+ Idle event handler. Throw away the disp info cache.
+ ********************************************************************/
+
+static void disp_info_cache_idle_timeout_handler(void **private_data,
+ time_t *ev_interval,
+ time_t ev_now)
+{
+ fstring sid_str;
+ DISP_INFO *disp_info = (DISP_INFO *)(*private_data);
+
+ sid_to_string(sid_str, &disp_info->sid);
+
+ free_samr_cache(disp_info, sid_str);
+
+ /* Remove the event. */
+ smb_unregister_idle_event(disp_info->di_cache_timeout_event);
+ disp_info->di_cache_timeout_event = (smb_event_id_t)0;
+
+ DEBUG(10,("disp_info_cache_idle_timeout_handler: caching timed out for SID %s at %u\n",
+ sid_str, (unsigned int)ev_now));
+}
+
+/*******************************************************************
+ Setup cache removal idle event handler.
+ ********************************************************************/
+
+static void set_disp_info_cache_timeout(DISP_INFO *disp_info, time_t secs_fromnow)
+{
+ fstring sid_str;
+
+ sid_to_string(sid_str, &disp_info->sid);
+
+ /* Remove any pending timeout and update. */
+
+ if (disp_info->di_cache_timeout_event) {
+ smb_unregister_idle_event(disp_info->di_cache_timeout_event);
+ disp_info->di_cache_timeout_event = (smb_event_id_t)0;
+ }
+
+ DEBUG(10,("set_disp_info_cache_timeout: caching enumeration for SID %s for %u seconds\n",
+ sid_str, (unsigned int)secs_fromnow ));
+
+ disp_info->di_cache_timeout_event =
+ smb_register_idle_event(disp_info_cache_idle_timeout_handler,
+ disp_info,
+ secs_fromnow);
+}
+
+/*******************************************************************
+ Force flush any cache. We do this on any samr_set_xxx call.
+ We must also remove the timeout handler.
+ ********************************************************************/
+
+static void force_flush_samr_cache(DISP_INFO *disp_info)
+{
+ if (disp_info) {
+ fstring sid_str;
+
+ sid_to_string(sid_str, &disp_info->sid);
+ if (disp_info->di_cache_timeout_event) {
+ smb_unregister_idle_event(disp_info->di_cache_timeout_event);
+ disp_info->di_cache_timeout_event = (smb_event_id_t)0;
+ DEBUG(10,("force_flush_samr_cache: clearing idle event for SID %s\n",
+ sid_str));
+ }
+ free_samr_cache(disp_info, sid_str);
+ }
+}
+
+/*******************************************************************
Ensure password info is never given out. Paranioa... JRA.
********************************************************************/
@@ -298,24 +452,36 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
static uint32 count_sam_users(struct disp_info *info, uint16 acct_flags)
{
struct samr_displayentry *entry;
- if (info->users == NULL)
+ if (info->users == NULL) {
info->users = pdb_search_users(acct_flags);
- if (info->users == NULL)
- return 0;
+ if (info->users == NULL) {
+ return 0;
+ }
+ }
/* Fetch the last possible entry, thus trigger an enumeration */
pdb_search_entries(info->users, 0xffffffff, 1, &entry);
+
+ /* Ensure we cache this enumeration. */
+ set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT);
+
return info->users->num_entries;
}
static uint32 count_sam_groups(struct disp_info *info)
{
struct samr_displayentry *entry;
- if (info->groups == NULL)
+ if (info->groups == NULL) {
info->groups = pdb_search_groups();
- if (info->groups == NULL)
- return 0;
+ if (info->groups == NULL) {
+ return 0;
+ }
+ }
/* Fetch the last possible entry, thus trigger an enumeration */
pdb_search_entries(info->groups, 0xffffffff, 1, &entry);
+
+ /* Ensure we cache this enumeration. */
+ set_disp_info_cache_timeout(info, DISP_INFO_CACHE_TIMEOUT);
+
return info->groups->num_entries;
}
@@ -431,12 +597,12 @@ NTSTATUS _samr_set_sec_obj(pipes_struct *p, SAMR_Q_SET_SEC_OBJ *q_u, SAMR_R_SET_
return NT_STATUS_NOT_IMPLEMENTED;
}
-
/*******************************************************************
********************************************************************/
static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol,
- DOM_SID *sid, uint32 *acc_granted)
+ DOM_SID *sid, uint32 *acc_granted,
+ DISP_INFO **ppdisp_info)
{
struct samr_info *info = NULL;
@@ -449,6 +615,10 @@ static BOOL get_lsa_policy_samr_sid( pipes_struct *p, POLICY_HND *pol,
*sid = info->sid;
*acc_granted = info->acc_granted;
+ if (ppdisp_info) {
+ *ppdisp_info = info->disp_info;
+ }
+
return True;
}
@@ -467,42 +637,35 @@ NTSTATUS _samr_query_sec_obj(pipes_struct *p, SAMR_Q_QUERY_SEC_OBJ *q_u, SAMR_R_
r_u->status = NT_STATUS_OK;
/* Get the SID. */
- if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &pol_sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
-
-
DEBUG(10,("_samr_query_sec_obj: querying security on SID: %s\n", sid_to_string(str_sid, &pol_sid)));
/* Check what typ of SID is beeing queried (e.g Domain SID, User SID, Group SID) */
/* To query the security of the SAM it self an invalid SID with S-0-0 is passed to this function */
- if (pol_sid.sid_rev_num == 0)
- {
+ if (pol_sid.sid_rev_num == 0) {
DEBUG(5,("_samr_query_sec_obj: querying security on SAM\n"));
r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0);
- }
- else if (sid_equal(&pol_sid,get_global_sam_sid())) /* check if it is our domain SID */
-
- {
+ } else if (sid_equal(&pol_sid,get_global_sam_sid())) {
+ /* check if it is our domain SID */
DEBUG(5,("_samr_query_sec_obj: querying security on Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0);
- }
- else if (sid_equal(&pol_sid,&global_sid_Builtin)) /* check if it is the Builtin Domain */
- {
+ } else if (sid_equal(&pol_sid,&global_sid_Builtin)) {
+ /* check if it is the Builtin Domain */
/* TODO: Builtin probably needs a different SD with restricted write access*/
DEBUG(5,("_samr_query_sec_obj: querying security on Builtin Domain with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0);
- }
- else if (sid_check_is_in_our_domain(&pol_sid) ||
- sid_check_is_in_builtin(&pol_sid))
- {
+ } else if (sid_check_is_in_our_domain(&pol_sid) ||
+ sid_check_is_in_builtin(&pol_sid)) {
/* TODO: different SDs have to be generated for aliases groups and users.
Currently all three get a default user SD */
DEBUG(10,("_samr_query_sec_obj: querying security on Object with SID: %s\n", sid_to_string(str_sid, &pol_sid)));
r_u->status = make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &pol_sid, SAMR_USR_RIGHTS_WRITE_PW);
+ } else {
+ return NT_STATUS_OBJECT_TYPE_MISMATCH;
}
- else return NT_STATUS_OBJECT_TYPE_MISMATCH;
if ((r_u->buf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -594,21 +757,32 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
become_root();
- if ((info->disp_info.enum_users != NULL) &&
- (info->disp_info.enum_acb_mask != q_u->acb_mask)) {
- pdb_search_destroy(info->disp_info.enum_users);
- info->disp_info.enum_users = NULL;
+
+ /* AS ROOT !!!! */
+
+ if ((info->disp_info->enum_users != NULL) &&
+ (info->disp_info->enum_acb_mask != q_u->acb_mask)) {
+ pdb_search_destroy(info->disp_info->enum_users);
+ info->disp_info->enum_users = NULL;
}
- if (info->disp_info.enum_users == NULL) {
- info->disp_info.enum_users = pdb_search_users(q_u->acb_mask);
- info->disp_info.enum_acb_mask = q_u->acb_mask;
+ if (info->disp_info->enum_users == NULL) {
+ info->disp_info->enum_users = pdb_search_users(q_u->acb_mask);
+ info->disp_info->enum_acb_mask = q_u->acb_mask;
}
- if (info->disp_info.enum_users == NULL)
+
+ if (info->disp_info->enum_users == NULL) {
+ /* END AS ROOT !!!! */
+ unbecome_root();
return NT_STATUS_ACCESS_DENIED;
- num_account = pdb_search_entries(info->disp_info.enum_users,
+ }
+
+ num_account = pdb_search_entries(info->disp_info->enum_users,
enum_context, max_entries,
&entries);
+
+ /* END AS ROOT !!!! */
+
unbecome_root();
if (num_account == 0) {
@@ -625,8 +799,14 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
if (!NT_STATUS_IS_OK(r_u->status))
return r_u->status;
- if (max_entries <= num_account)
+ if (max_entries <= num_account) {
r_u->status = STATUS_MORE_ENTRIES;
+ } else {
+ r_u->status = NT_STATUS_OK;
+ }
+
+ /* Ensure we cache this enumeration. */
+ set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT);
DEBUG(5, ("_samr_enum_dom_users: %d\n", __LINE__));
@@ -705,18 +885,23 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM
/* the domain group array is being allocated in the function below */
become_root();
- if (info->disp_info.groups == NULL)
- info->disp_info.groups = pdb_search_groups();
- unbecome_root();
- if (info->disp_info.groups == NULL)
- return NT_STATUS_ACCESS_DENIED;
+ if (info->disp_info->groups == NULL) {
+ info->disp_info->groups = pdb_search_groups();
- become_root();
- num_groups = pdb_search_entries(info->disp_info.groups, q_u->start_idx,
+ if (info->disp_info->groups == NULL) {
+ unbecome_root();
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ num_groups = pdb_search_entries(info->disp_info->groups, q_u->start_idx,
MAX_SAM_ENTRIES, &groups);
unbecome_root();
+ /* Ensure we cache this enumeration. */
+ set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT);
+
make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name,
num_groups, groups);
@@ -752,26 +937,30 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S
sid_string_static(&info->sid)));
if (sid_check_is_domain(&info->sid))
- search = &info->disp_info.aliases;
+ search = &info->disp_info->aliases;
if (sid_check_is_builtin(&info->sid))
- search = &info->disp_info.builtins;
+ search = &info->disp_info->builtins;
if (search == NULL)
return NT_STATUS_INVALID_HANDLE;
become_root();
- if (*search == NULL)
- *search = pdb_search_aliases(&info->sid);
- unbecome_root();
- if (*search == NULL)
- return NT_STATUS_ACCESS_DENIED;
+ if (*search == NULL) {
+ *search = pdb_search_aliases(&info->sid);
+ if (*search == NULL) {
+ unbecome_root();
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
- become_root();
num_aliases = pdb_search_entries(*search, q_u->start_idx,
MAX_SAM_ENTRIES, &aliases);
unbecome_root();
+ /* Ensure we cache this enumeration. */
+ set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT);
+
make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name,
num_aliases, aliases);
@@ -872,38 +1061,68 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
become_root();
+ /* THe following done as ROOT. Don't return without unbecome_root(). */
+
switch (q_u->switch_level) {
case 0x1:
case 0x4:
- if (info->disp_info.users == NULL)
- info->disp_info.users = pdb_search_users(ACB_NORMAL);
- if (info->disp_info.users == NULL)
- return NT_STATUS_ACCESS_DENIED;
- num_account = pdb_search_entries(info->disp_info.users,
+ if (info->disp_info->users == NULL) {
+ info->disp_info->users = pdb_search_users(ACB_NORMAL);
+ if (info->disp_info->users == NULL) {
+ unbecome_root();
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ DEBUG(10,("samr_reply_query_dispinfo: starting user enumeration at index %u\n",
+ (unsigned int)enum_context ));
+ } else {
+ DEBUG(10,("samr_reply_query_dispinfo: using cached user enumeration at index %u\n",
+ (unsigned int)enum_context ));
+ }
+
+ num_account = pdb_search_entries(info->disp_info->users,
enum_context, max_entries,
&entries);
break;
case 0x2:
- if (info->disp_info.machines == NULL)
- info->disp_info.machines =
+ if (info->disp_info->machines == NULL) {
+ info->disp_info->machines =
pdb_search_users(ACB_WSTRUST|ACB_SVRTRUST);
- if (info->disp_info.machines == NULL)
- return NT_STATUS_ACCESS_DENIED;
- num_account = pdb_search_entries(info->disp_info.machines,
+ if (info->disp_info->machines == NULL) {
+ unbecome_root();
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ DEBUG(10,("samr_reply_query_dispinfo: starting machine enumeration at index %u\n",
+ (unsigned int)enum_context ));
+ } else {
+ DEBUG(10,("samr_reply_query_dispinfo: using cached machine enumeration at index %u\n",
+ (unsigned int)enum_context ));
+ }
+
+ num_account = pdb_search_entries(info->disp_info->machines,
enum_context, max_entries,
&entries);
break;
case 0x3:
case 0x5:
- if (info->disp_info.groups == NULL)
- info->disp_info.groups = pdb_search_groups();
- if (info->disp_info.groups == NULL)
- return NT_STATUS_ACCESS_DENIED;
- num_account = pdb_search_entries(info->disp_info.groups,
+ if (info->disp_info->groups == NULL) {
+ info->disp_info->groups = pdb_search_groups();
+ if (info->disp_info->groups == NULL) {
+ unbecome_root();
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ DEBUG(10,("samr_reply_query_dispinfo: starting group enumeration at index %u\n",
+ (unsigned int)enum_context ));
+ } else {
+ DEBUG(10,("samr_reply_query_dispinfo: using cached group enumeration at index %u\n",
+ (unsigned int)enum_context ));
+ }
+
+ num_account = pdb_search_entries(info->disp_info->groups,
enum_context, max_entries,
&entries);
break;
default:
+ unbecome_root();
smb_panic("info class changed");
break;
}
@@ -947,10 +1166,14 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
/* calculate the total size */
total_data_size=num_account*struct_size;
- if (num_account)
+ if (num_account) {
r_u->status = STATUS_MORE_ENTRIES;
- else
+ } else {
r_u->status = NT_STATUS_OK;
+ }
+
+ /* Ensure we cache this enumeration. */
+ set_disp_info_cache_timeout(info->disp_info, DISP_INFO_CACHE_TIMEOUT);
DEBUG(5, ("_samr_query_dispinfo: %d\n", __LINE__));
@@ -978,7 +1201,7 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM
DEBUG(5,("_samr_query_aliasinfo: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_LOOKUP_INFO, "_samr_query_aliasinfo"))) {
return r_u->status;
@@ -1096,7 +1319,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
ZERO_ARRAY(rid);
ZERO_ARRAY(type);
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted)) {
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted, NULL)) {
init_samr_r_lookup_names(p->mem_ctx, r_u, 0, NULL, NULL, NT_STATUS_OBJECT_TYPE_MISMATCH);
return r_u->status;
}
@@ -1255,7 +1478,7 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK
DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &pol_sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
if (num_rids > 1000) {
@@ -1317,7 +1540,7 @@ NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USE
/* find the domain policy handle and get domain SID / access bits in the domain policy. */
- if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted) )
+ if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted, NULL) )
return NT_STATUS_INVALID_HANDLE;
nt_status = access_check_samr_function( acc_granted,
@@ -1712,7 +1935,7 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_USER_GET_GROUPS, "_samr_query_usergroups"))) {
@@ -1766,7 +1989,7 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
continue;
gids = TALLOC_REALLOC_ARRAY(p->mem_ctx, gids, DOM_GID, num_gids+1);
- gids[num_gids].attr=7;
+ gids[num_gids].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED);
gids[num_gids].g_rid = rid;
num_gids += 1;
}
@@ -1858,9 +2081,9 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
/* AS ROOT !!! */
- num_users=count_sam_users(&info->disp_info,
+ num_users=count_sam_users(info->disp_info,
ACB_NORMAL);
- num_groups=count_sam_groups(&info->disp_info);
+ num_groups=count_sam_groups(info->disp_info);
pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
u_logout = account_policy_temp;
@@ -1993,9 +2216,10 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS;
BOOL can_add_account = False;
SE_PRIV se_rights;
+ DISP_INFO *disp_info = NULL;
/* Get the domain SID stored in the domain policy */
- if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_USER, "_samr_create_user"))) {
@@ -2141,6 +2365,9 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ /* After a "set" ensure we have no cached display info. */
+ force_flush_samr_cache(info->disp_info);
+
r_u->user_rid=pdb_get_user_rid(sam_pass);
r_u->access_granted = acc_granted;
@@ -2424,7 +2651,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
/* find the domain policy and get the SID / access bits stored in the domain policy */
- if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted) )
+ if ( !get_lsa_policy_samr_sid(p, &domain_pol, &sid, &acc_granted, NULL) )
return NT_STATUS_INVALID_HANDLE;
status = access_check_samr_function(acc_granted,
@@ -2819,13 +3046,14 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
BOOL ret;
BOOL has_enough_rights = False;
uint32 acb_info;
+ DISP_INFO *disp_info = NULL;
DEBUG(5, ("_samr_set_userinfo: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
/* observed when joining an XP client to a Samba domain */
@@ -2941,6 +3169,10 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
/* ================ END SeMachineAccountPrivilege BLOCK ================ */
+ if (NT_STATUS_IS_OK(r_u->status)) {
+ force_flush_samr_cache(disp_info);
+ }
+
return r_u->status;
}
@@ -2960,13 +3192,14 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
BOOL ret;
BOOL has_enough_rights = False;
uint32 acb_info;
+ DISP_INFO *disp_info = NULL;
DEBUG(5, ("samr_reply_set_userinfo2: %d\n", __LINE__));
r_u->status = NT_STATUS_OK;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, pol, &sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
/* observed when joining XP client to Samba domain */
@@ -3047,6 +3280,10 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
/* ================ END SeMachineAccountPrivilege BLOCK ================ */
+ if (NT_STATUS_IS_OK(r_u->status)) {
+ force_flush_samr_cache(disp_info);
+ }
+
return r_u->status;
}
@@ -3130,7 +3367,7 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
uint32 acc_granted;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status =
@@ -3242,7 +3479,7 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_
NTSTATUS result;
/* find the policy handle. open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_GET_MEMBERS, "_samr_query_groupmem"))) {
@@ -3291,10 +3528,10 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
SE_PRIV se_rights;
BOOL can_add_accounts;
BOOL ret;
-
+ DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_ADD_MEMBER, "_samr_add_aliasmem"))) {
@@ -3318,6 +3555,10 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
/******** END SeAddUsers BLOCK *********/
+ if (ret) {
+ force_flush_samr_cache(disp_info);
+ }
+
return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
}
@@ -3332,9 +3573,10 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
SE_PRIV se_rights;
BOOL can_add_accounts;
BOOL ret;
+ DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_REMOVE_MEMBER, "_samr_del_aliasmem"))) {
@@ -3359,6 +3601,10 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
/******** END SeAddUsers BLOCK *********/
+ if (ret) {
+ force_flush_samr_cache(disp_info);
+ }
+
return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
}
@@ -3382,9 +3628,10 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
+ DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_ADD_MEMBER, "_samr_add_groupmem"))) {
@@ -3470,6 +3717,9 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
}
passwd_free(&pwd);
+
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3488,6 +3738,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
uint32 acc_granted;
SE_PRIV se_rights;
BOOL can_add_accounts;
+ DISP_INFO *disp_info = NULL;
/*
* delete the group member named q_u->rid
@@ -3496,7 +3747,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
*/
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_REMOVE_MEMBER, "_samr_del_groupmem"))) {
@@ -3555,6 +3806,9 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
}
pdb_free_sam(&sam_pass);
+
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3590,11 +3844,12 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
uint32 acc_granted;
BOOL can_add_accounts;
BOOL ret;
+ DISP_INFO *disp_info = NULL;
DEBUG(5, ("_samr_delete_dom_user: %d\n", __LINE__));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->user_pol, &user_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_user"))) {
@@ -3651,6 +3906,8 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM
if (!close_policy_hnd(p, &q_u->user_pol))
return NT_STATUS_OBJECT_NAME_INVALID;
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3671,11 +3928,12 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
SE_PRIV se_rights;
BOOL can_add_accounts;
BOOL ret;
+ DISP_INFO *disp_info = NULL;
DEBUG(5, ("samr_delete_dom_group: %d\n", __LINE__));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->group_pol, &group_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_group"))) {
@@ -3734,6 +3992,8 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
if (!close_policy_hnd(p, &q_u->group_pol))
return NT_STATUS_OBJECT_NAME_INVALID;
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3748,11 +4008,12 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
SE_PRIV se_rights;
BOOL can_add_accounts;
BOOL ret;
+ DISP_INFO *disp_info = NULL;
DEBUG(5, ("_samr_delete_dom_alias: %d\n", __LINE__));
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &alias_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS, "_samr_delete_dom_alias"))) {
@@ -3788,6 +4049,8 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S
if (!close_policy_hnd(p, &q_u->alias_pol))
return NT_STATUS_OBJECT_NAME_INVALID;
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3808,9 +4071,10 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
SE_PRIV se_rights;
BOOL can_add_accounts;
NTSTATUS result;
+ DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_GROUP, "_samr_create_dom_group"))) {
@@ -3879,6 +4143,8 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
if (!create_policy_hnd(p, &r_u->pol, free_samr_info, (void *)info))
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3897,9 +4163,10 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
NTSTATUS result;
SE_PRIV se_rights;
BOOL can_add_accounts;
+ DISP_INFO *disp_info = NULL;
/* Find the policy handle. Open a policy on it. */
- if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_ALIAS, "_samr_create_alias"))) {
@@ -3951,6 +4218,8 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
if (!create_policy_hnd(p, &r_u->alias_pol, free_samr_info, (void *)info))
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ force_flush_samr_cache(disp_info);
+
return NT_STATUS_OK;
}
@@ -3972,7 +4241,7 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM
uint32 acc_granted;
BOOL ret;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_LOOKUP_INFO, "_samr_query_groupinfo"))) {
@@ -4029,8 +4298,9 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
uint32 acc_granted;
BOOL ret;
BOOL can_mod_accounts;
+ DISP_INFO *disp_info = NULL;
- if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &group_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_GROUP_SET_INFO, "_samr_set_groupinfo"))) {
@@ -4067,6 +4337,10 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
/******** End SeAddUsers BLOCK *********/
+ if (ret) {
+ force_flush_samr_cache(disp_info);
+ }
+
return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
}
@@ -4084,8 +4358,9 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
uint32 acc_granted;
BOOL ret;
BOOL can_mod_accounts;
+ DISP_INFO *disp_info = NULL;
- if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->alias_pol, &group_sid, &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, SA_RIGHT_ALIAS_SET_INFO, "_samr_set_aliasinfo"))) {
@@ -4120,6 +4395,10 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_
/******** End SeAddUsers BLOCK *********/
+ if (ret) {
+ force_flush_samr_cache(disp_info);
+ }
+
return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
}
@@ -4163,7 +4442,7 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G
BOOL ret;
SE_PRIV se_rights;
- if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid, &acc_granted))
+ if (!get_lsa_policy_samr_sid(p, &q_u->domain_pol, &sid, &acc_granted, NULL))
return NT_STATUS_INVALID_HANDLE;
status = access_check_samr_function(acc_granted,
@@ -4226,7 +4505,8 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
DOM_SID delete_sid, domain_sid;
uint32 acc_granted;
NTSTATUS result;
-
+ DISP_INFO *disp_info = NULL;
+
sid_copy( &delete_sid, &q_u->sid.sid );
DEBUG(5,("_samr_remove_sid_foreign_domain: removing SID [%s]\n",
@@ -4235,7 +4515,7 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
/* Find the policy handle. Open a policy on it. */
if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &domain_sid,
- &acc_granted))
+ &acc_granted, &disp_info))
return NT_STATUS_INVALID_HANDLE;
result = access_check_samr_function(acc_granted, STD_RIGHT_DELETE_ACCESS,
@@ -4270,6 +4550,7 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
return NT_STATUS_OK;
}
+ force_flush_samr_cache(disp_info);
result = NT_STATUS_OK;
@@ -4277,10 +4558,12 @@ NTSTATUS _samr_remove_sid_foreign_domain(pipes_struct *p,
}
/*******************************************************************
- _samr_unknown_2e
+ _samr_query_domain_info2
********************************************************************/
-NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOWN_2E *r_u)
+NTSTATUS _samr_query_domain_info2(pipes_struct *p,
+ SAMR_Q_QUERY_DOMAIN_INFO2 *q_u,
+ SAMR_R_QUERY_DOMAIN_INFO2 *r_u)
{
struct samr_info *info = NULL;
SAM_UNK_CTR *ctr;
@@ -4309,7 +4592,7 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
r_u->status = NT_STATUS_OK;
- DEBUG(5,("_samr_unknown_2e: %d\n", __LINE__));
+ DEBUG(5,("_samr_query_domain_info2: %d\n", __LINE__));
/* find the policy handle. open a policy on it. */
if (!find_policy_by_hnd(p, &q_u->domain_pol, (void **)&info))
@@ -4340,13 +4623,11 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
break;
case 0x02:
become_root();
- num_users = count_sam_users(&info->disp_info,
+ num_users = count_sam_users(info->disp_info,
ACB_NORMAL);
- num_groups = count_sam_groups(&info->disp_info);
+ num_groups = count_sam_groups(info->disp_info);
unbecome_root();
- free_samr_db(info);
-
pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
u_logout = account_policy_temp;
@@ -4410,9 +4691,9 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
return NT_STATUS_INVALID_INFO_CLASS;
}
- init_samr_r_samr_unknown_2e(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
+ init_samr_r_samr_query_domain_info2(r_u, q_u->switch_value, ctr, NT_STATUS_OK);
- DEBUG(5,("_samr_unknown_2e: %d\n", __LINE__));
+ DEBUG(5,("_samr_query_domain_info2: %d\n", __LINE__));
return r_u->status;
}
diff --git a/source/rpc_server/srv_util.c b/source/rpc_server/srv_util.c
index 79d5d06d23a..3666d474787 100644
--- a/source/rpc_server/srv_util.c
+++ b/source/rpc_server/srv_util.c
@@ -102,7 +102,7 @@ NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) {
if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) {
sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid));
- gids[*numgroups].attr=7;
+ gids[*numgroups].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED);
(*numgroups)++;
}
}
diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c
index 2cc1ffcca0f..5a0ba054833 100644
--- a/source/rpcclient/cmd_lsarpc.c
+++ b/source/rpcclient/cmd_lsarpc.c
@@ -934,7 +934,7 @@ static NTSTATUS cmd_lsa_query_trustdominfo(struct rpc_pipe_client *cli,
goto done;
result = rpccli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol,
- info_class, &dom_sid, &info);
+ info_class, &info);
if (!NT_STATUS_IS_OK(result))
goto done;
diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c
index 665fe342265..6ff2bce8518 100644
--- a/source/rpcclient/cmd_samr.c
+++ b/source/rpcclient/cmd_samr.c
@@ -404,13 +404,22 @@ static void display_group_info1(GROUP_INFO1 *info1)
printf("\tGroup Name:\t%s\n", temp);
unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1);
printf("\tDescription:\t%s\n", temp);
- printf("\tunk1:%d\n", info1->unknown_1);
+ printf("\tGroup Attribute:%d\n", info1->group_attr);
printf("\tNum Members:%d\n", info1->num_members);
}
/****************************************************************************
display group info
****************************************************************************/
+static void display_group_info3(GROUP_INFO3 *info3)
+{
+ printf("\tGroup Attribute:%d\n", info3->group_attr);
+}
+
+
+/****************************************************************************
+ display group info
+ ****************************************************************************/
static void display_group_info4(GROUP_INFO4 *info4)
{
fstring desc;
@@ -429,6 +438,10 @@ static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
display_group_info1(&ctr->group.info1);
break;
}
+ case 3: {
+ display_group_info3(&ctr->group.info3);
+ break;
+ }
case 4: {
display_group_info4(&ctr->group.info4);
break;
diff --git a/source/script/installman.sh b/source/script/installman.sh
index 6278012635f..3bbca1a8aa5 100755
--- a/source/script/installman.sh
+++ b/source/script/installman.sh
@@ -18,6 +18,10 @@ if test ! -d $SRCDIR../docs/manpages; then
exit 0
fi
+# Get the configured feature set
+test -f "${SRCDIR}/config.log" && \
+ eval $( grep "^[[:alnum:]]*=.*" "${SRCDIR}/config.log")
+
for lang in $langs; do
if [ "X$lang" = XC ]; then
echo Installing default man pages in $MANDIR/
@@ -40,13 +44,20 @@ for lang in $langs; do
for sect in 1 5 7 8 ; do
for m in $langdir/man$sect ; do
for s in $SRCDIR../docs/manpages/$lang/*$sect; do
- FNAME=$m/`basename $s`
-
+ MP_BASENAME=${s##*/}
+
+ # Check if this man page if required by the configured feature set
+ case "${MP_BASENAME}" in
+ smbsh.1) test -z "${SMBWRAPPER}" && continue ;;
+ *) ;;
+ esac
+
+ FNAME="$m/${MP_BASENAME}"
+
# Test for writability. Involves
# blowing away existing files.
if (rm -f $FNAME && touch $FNAME); then
- rm $FNAME
if [ "x$GROFF" = x ] ; then
cp $s $m # Copy raw nroff
else
diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk
index 73a1c2b3f0a..a0f3096c842 100644
--- a/source/script/mkproto.awk
+++ b/source/script/mkproto.awk
@@ -136,7 +136,7 @@ END {
gotstart = 1;
}
- if( $0 ~ /^NODE_STATUS_STRUCT|SMB_STRUCT_DIR/ ) {
+ if( $0 ~ /^NODE_STATUS_STRUCT|SMB_STRUCT_DIR|ELOG_TDB/ ) {
gotstart = 1;
}
diff --git a/source/services/services_db.c b/source/services/services_db.c
index 5c87225f573..c75cb38c48b 100644
--- a/source/services/services_db.c
+++ b/source/services/services_db.c
@@ -35,43 +35,51 @@ struct service_display_info {
};
struct service_display_info builtin_svcs[] = {
- { "Spooler", "smbd", "Print Spooler",
- "Internal service for spooling files to print devices" },
- { "NETLOGON", "smbd", "Net Logon",
- "File service providing access to policy and profile data" },
- { "RemoteRegistry", "smbd", "Remote Registry Service",
- "Internal service providing remote access to the Samba registry" },
- { "WINS", "nmbd", "Windows Internet Name Service (WINS)",
- "Internal service providing a NetBIOS point-to-point name server" },
+ { "Spooler", "smbd", "Print Spooler", "Internal service for spooling files to print devices" },
+ { "NETLOGON", "smbd", "Net Logon", "File service providing access to policy and profile data" },
+ { "RemoteRegistry", "smbd", "Remote Registry Service", "Internal service providing remote access to "
+ "the Samba registry" },
+ { "WINS", "nmbd", "Windows Internet Name Service (WINS)", "Internal service providing a "
+ "NetBIOS point-to-point name server" },
{ NULL, NULL, NULL, NULL }
};
struct service_display_info common_unix_svcs[] = {
- { "cups", NULL, "Common Unix Printing System", NULL },
- { "postfix", NULL, "Internet Mail Service", NULL },
- { "sendmail", NULL, "Internet Mail Service", NULL },
- { "portmap", NULL, "TCP Port to RPC PortMapper", NULL },
- { "xinetd", NULL, "Internet Meta-Daemon", NULL },
- { "inet", NULL, "Internet Meta-Daemon", NULL },
- { "xntpd", NULL, "Network Time Service", NULL },
- { "ntpd", NULL, "Network Time Service", NULL },
- { "lpd", NULL, "BSD Print Spooler", NULL },
- { "nfsserver", NULL, "Network File Service", NULL },
- { "cron", NULL, "Scheduling Service", NULL },
- { "at", NULL, "Scheduling Service", NULL },
- { "nscd", NULL, "Name Service Cache Daemon", NULL },
- { "slapd", NULL, "LDAP Directory Service", NULL },
- { "ldap", NULL, "LDAP DIrectory Service", NULL },
- { "ypbind", NULL, "NIS Directory Service", NULL },
- { "courier-imap", NULL, "IMAP4 Mail Service", NULL },
- { "courier-pop3", NULL, "POP3 Mail Service", NULL },
- { "named", NULL, "Domain Name Service", NULL },
- { "bind", NULL, "Domain Name Service", NULL },
- { "httpd", NULL, "HTTP Server", NULL },
- { "apache", NULL, "HTTP Server", NULL },
- { "autofs", NULL, "Automounter", NULL },
- { "squid", NULL, "Web Cache Proxy ", NULL },
+ { "cups", NULL, "Common Unix Printing System","Provides unified printing support for all operating systems" },
+ { "postfix", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" },
+ { "sendmail", NULL, "Internet Mail Service", "Provides support for sending and receiving electonic mail" },
+ { "portmap", NULL, "TCP Port to RPC PortMapper",NULL },
+ { "xinetd", NULL, "Internet Meta-Daemon", NULL },
+ { "inet", NULL, "Internet Meta-Daemon", NULL },
+ { "xntpd", NULL, "Network Time Service", NULL },
+ { "ntpd", NULL, "Network Time Service", NULL },
+ { "lpd", NULL, "BSD Print Spooler", NULL },
+ { "nfsserver", NULL, "Network File Service", NULL },
+ { "cron", NULL, "Scheduling Service", NULL },
+ { "at", NULL, "Scheduling Service", NULL },
+ { "nscd", NULL, "Name Service Cache Daemon", NULL },
+ { "slapd", NULL, "LDAP Directory Service", NULL },
+ { "ldap", NULL, "LDAP DIrectory Service", NULL },
+ { "ypbind", NULL, "NIS Directory Service", NULL },
+ { "courier-imap", NULL, "IMAP4 Mail Service", NULL },
+ { "courier-pop3", NULL, "POP3 Mail Service", NULL },
+ { "named", NULL, "Domain Name Service", NULL },
+ { "bind", NULL, "Domain Name Service", NULL },
+ { "httpd", NULL, "HTTP Server", NULL },
+ { "apache", NULL, "HTTP Server", "Provides s highly scalable and flexible web server "
+ "capable of implementing various protocols incluing "
+ "but not limited to HTTP" },
+ { "autofs", NULL, "Automounter", NULL },
+ { "squid", NULL, "Web Cache Proxy ", NULL },
{ "perfcountd", NULL, "Performance Monitoring Daemon", NULL },
+ { "pgsql", NULL, "PgSQL Database Server", "Provides service for SQL database from Postgresql.org" },
+ { "arpwatch", NULL, "ARP Tables watcher", "Provides service for monitoring ARP tables for changes" },
+ { "dhcpd", NULL, "DHCP Server", "Provides service for dynamic host configuration and IP assignment" },
+ { "nwserv", NULL, "NetWare Server Emulator", "Provides service for emulating Novell NetWare 3.12 server" },
+ { "proftpd", NULL, "Professional FTP Server", "Provides high configurable service for FTP connection and "
+ "file transferring" },
+ { "ssh2", NULL, "SSH Secure Shell", "Provides service for secure connection for remote administration" },
+ { "sshd", NULL, "SSH Secure Shell", "Provides service for secure connection for remote administration" },
{ NULL, NULL, NULL, NULL }
};
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index fec148b8e63..532c79043a2 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -126,7 +126,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL c
Change a unix mode to a dos mode.
****************************************************************************/
-uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
+static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf)
{
int result = 0;
enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn));
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index b389b9c1ae7..2ee8ba1e4ff 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -150,9 +150,6 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
pstrcpy(saved_last_component, name);
}
- if (!conn->case_preserve || (mangle_is_8_3(name, False, SNUM(conn)) && !conn->short_case_preserve))
- strnorm(name, lp_defaultcase(SNUM(conn)));
-
start = name;
pstrcpy(orig_path, name);
@@ -301,16 +298,17 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
return(False);
}
- /*
+ /*
* Just the last part of the name doesn't exist.
- * We may need to strupper() or strlower() it in case
- * this conversion is being used for file creation
- * purposes. If the filename is of mixed case then
- * don't normalise it.
+ * We need to strupper() or strlower() it as
+ * this conversion may be used for file creation
+ * purposes. Fix inspired by Thomas Neumann <t.neumann@iku-ag.de>.
*/
-
- if (!conn->case_preserve && (!strhasupper(start) || !strhaslower(start)))
+ if (!conn->case_preserve ||
+ (mangle_is_8_3(start, False, SNUM(conn)) &&
+ !conn->short_case_preserve)) {
strnorm(start, lp_defaultcase(SNUM(conn)));
+ }
/*
* check on the mangled stack to see if we can recover the
diff --git a/source/smbd/session.c b/source/smbd/session.c
index 9a9a0d90b24..27f760a088e 100644
--- a/source/smbd/session.c
+++ b/source/smbd/session.c
@@ -198,7 +198,8 @@ void session_yield(user_struct *vuser)
tdb_delete(tdb, key);
}
-static BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *), void *state)
+BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
+ void *state)
{
if (!session_init()) {
DEBUG(3, ("No tdb opened\n"));
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index 2c967601678..a22a575c762 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -168,6 +168,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(NT_STATUS_NO_MEMORY);
if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
+ talloc_destroy(mem_ctx);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -177,6 +178,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (!NT_STATUS_IS_OK(ret)) {
DEBUG(1,("Failed to verify incoming ticket!\n"));
+ talloc_destroy(mem_ctx);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -188,6 +190,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
SAFE_FREE(client);
+ talloc_destroy(mem_ctx);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -206,6 +209,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
SAFE_FREE(client);
+ talloc_destroy(mem_ctx);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
}
@@ -283,6 +287,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
SAFE_FREE(client);
data_blob_free(&ap_rep);
data_blob_free(&session_key);
+ talloc_destroy(mem_ctx);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
}
@@ -302,6 +307,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
passwd_free(&pw);
+ talloc_destroy(mem_ctx);
return ERROR_NT(ret);
}
@@ -314,6 +320,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
data_blob_free(&ap_rep);
data_blob_free(&session_key);
passwd_free(&pw);
+ talloc_destroy(mem_ctx);
return ERROR_NT(ret);
}
@@ -737,6 +744,29 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
a new session setup with VC==0 is ignored.
****************************************************************************/
+static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *p)
+{
+ struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
+ const char *ip = (const char *)p;
+
+ if (!process_exists(pid_to_procid(sessionid->pid))) {
+ return 0;
+ }
+
+ if (sessionid->pid == sys_getpid()) {
+ return 0;
+ }
+
+ if (strcmp(ip, sessionid->ip_addr) != 0) {
+ return 0;
+ }
+
+ message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
+ NULL, 0, True);
+ return 0;
+}
+
static void setup_new_vc_session(void)
{
DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
@@ -744,6 +774,9 @@ static void setup_new_vc_session(void)
conn_close_all();
invalidate_all_vuids();
#endif
+ if (lp_reset_on_zero_vc()) {
+ session_traverse(shutdown_other_smbds, client_addr());
+ }
}
/****************************************************************************
diff --git a/source/utils/eventlogadm.c b/source/utils/eventlogadm.c
index 31e853b61f4..1d60d6b7ea8 100644
--- a/source/utils/eventlogadm.c
+++ b/source/utils/eventlogadm.c
@@ -79,7 +79,7 @@ int DoWriteCommand( int argc, char **argv, BOOL debugflag, char *exename )
{
FILE *f1;
char *argfname;
- TDB_CONTEXT *elog_tdb;
+ ELOG_TDB *etdb;
/* fixed constants are bad bad bad */
pstring linein;
@@ -100,7 +100,7 @@ int DoWriteCommand( int argc, char **argv, BOOL debugflag, char *exename )
argfname = argv[0];
- if ( !( elog_tdb = elog_open_tdb( argfname ) ) ) {
+ if ( !( etdb = elog_open_tdb( argfname, False ) ) ) {
printf( "can't open the eventlog TDB (%s)\n", argfname );
return -1;
}
@@ -130,7 +130,7 @@ int DoWriteCommand( int argc, char **argv, BOOL debugflag, char *exename )
/* printf("Writing to the event log\n"); */
- rcnum = write_eventlog_tdb( elog_tdb, &ee );
+ rcnum = write_eventlog_tdb( ELOG_TDB_CTX(etdb), &ee );
if ( !rcnum ) {
printf( "Can't write to the event log\n" );
} else {
@@ -146,7 +146,7 @@ int DoWriteCommand( int argc, char **argv, BOOL debugflag, char *exename )
}
}
- tdb_close( elog_tdb );
+ elog_close_tdb( etdb , False );
return 0;
}
diff --git a/source/utils/net_lookup.c b/source/utils/net_lookup.c
index 3a6781f7621..cd62245600d 100644
--- a/source/utils/net_lookup.c
+++ b/source/utils/net_lookup.c
@@ -85,7 +85,7 @@ static void print_ldap_srvlist(char *srvlist)
static int net_lookup_ldap(int argc, const char **argv)
{
-#ifdef HAVE_LDAP
+#ifdef HAVE_ADS
char *srvlist;
const char *domain;
int rc;
@@ -127,7 +127,7 @@ static int net_lookup_ldap(int argc, const char **argv)
}
return -1;
#endif
- DEBUG(1,("No LDAP support\n"));
+ DEBUG(1,("No ADS support\n"));
return -1;
}
diff --git a/source/utils/smbget.c b/source/utils/smbget.c
index e8069802ca9..eab5e5ac02f 100644
--- a/source/utils/smbget.c
+++ b/source/utils/smbget.c
@@ -28,6 +28,10 @@
int columns = 0;
+static int _resume, _recursive, debuglevel;
+static char *outputfile;
+
+
time_t total_start_time = 0;
off_t total_bytes = 0;
@@ -507,16 +511,13 @@ int readrcfile(const char *name, const struct poptOption long_options[])
int main(int argc, const char **argv)
{
- int resume = 0, recursive = 0;
int c = 0;
- int debuglevel = 0;
const char *file = NULL;
char *rcfile = NULL;
- char *outputfile = NULL;
struct poptOption long_options[] = {
{"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" },
- {"resume", 'r', POPT_ARG_NONE, &resume, 0, "Automatically resume aborted files" },
- {"recursive", 'R', POPT_ARG_NONE, &recursive, 0, "Recursively download files" },
+ {"resume", 'r', POPT_ARG_NONE, &_resume, 0, "Automatically resume aborted files" },
+ {"recursive", 'R', POPT_ARG_NONE, &_recursive, 0, "Recursively download files" },
{"username", 'u', POPT_ARG_STRING, &username, 'u', "Username to use" },
{"password", 'p', POPT_ARG_STRING, &password, 'p', "Password to use" },
{"workgroup", 'w', POPT_ARG_STRING, &workgroup, 'w', "Workgroup to use (optional)" },
@@ -537,7 +538,8 @@ int main(int argc, const char **argv)
/* only read rcfile if it exists */
asprintf(&rcfile, "%s/.smbgetrc", getenv("HOME"));
- if(access(rcfile, F_OK) == 0) readrcfile(rcfile, long_options);
+ if(access(rcfile, F_OK) == 0)
+ readrcfile(rcfile, long_options);
free(rcfile);
#ifdef SIGWINCH
@@ -559,7 +561,7 @@ int main(int argc, const char **argv)
}
}
- if((send_stdout || outputfile) && recursive) {
+ if((send_stdout || outputfile) && _recursive) {
fprintf(stderr, "The -o or -O and -R options can not be used together.\n");
return 1;
}
@@ -578,9 +580,11 @@ int main(int argc, const char **argv)
total_start_time = time(NULL);
- while((file = poptGetArg(pc))) {
- if(!recursive) return smb_download_file(file, "", recursive, resume, outputfile);
- else return smb_download_dir(file, "", resume);
+ while ( (file = poptGetArg(pc)) ) {
+ if (!_recursive)
+ return smb_download_file(file, "", _recursive, _resume, outputfile);
+ else
+ return smb_download_dir(file, "", _resume);
}
clean_exit();