summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2004-04-04 13:23:11 +0000
committerGerald Carter <jerry@samba.org>2004-04-04 13:23:11 +0000
commit44449419559cae0176e1bd4755a3a6a0e3a6ae13 (patch)
tree2e9777ff4b7681a8b93e2365849b1d075b742119
parent211fcde5103a2eeaa5c4a71040f49d3400c1491e (diff)
downloadsamba-44449419559cae0176e1bd4755a3a6a0e3a6ae13.tar.gz
r15: syncing for 3.0.3pre2
-rw-r--r--WHATSNEW.txt97
-rw-r--r--examples/pdb/README2
-rw-r--r--packaging/RedHat/samba.spec.tmpl4
-rw-r--r--source/Makefile.in16
-rw-r--r--source/VERSION4
-rw-r--r--source/auth/auth_ntlmssp.c20
-rw-r--r--source/auth/auth_sam.c3
-rw-r--r--source/auth/auth_util.c167
-rw-r--r--source/bin/.cvsignore7
-rw-r--r--source/client/client.c8
-rwxr-xr-xsource/client/mount.cifs.c47
-rw-r--r--source/configure.in3
-rw-r--r--source/include/ads.h3
-rw-r--r--source/include/auth.h24
-rw-r--r--source/include/rpc_netlogon.h20
-rwxr-xr-xsource/include/rpc_spoolss.h2
-rw-r--r--source/include/smb.h14
-rw-r--r--source/lib/afs.c361
-rw-r--r--source/lib/charcnv.c18
-rw-r--r--source/lib/debug.c7
-rw-r--r--source/lib/popt_common.c2
-rw-r--r--source/lib/substitute.c5
-rw-r--r--source/lib/talloc.c18
-rw-r--r--source/lib/username.c5
-rw-r--r--source/lib/util.c2
-rw-r--r--source/lib/util_sock.c2
-rw-r--r--source/libads/ads_struct.c19
-rw-r--r--source/libads/kerberos.c39
-rw-r--r--source/libads/krb5_setpw.c2
-rw-r--r--source/libsmb/cliconnect.c35
-rw-r--r--source/libsmb/clientgen.c2
-rw-r--r--source/libsmb/clifile.c254
-rw-r--r--source/libsmb/ntlm_check.c74
-rw-r--r--source/libsmb/ntlmssp.c15
-rw-r--r--source/libsmb/samlogon_cache.c4
-rw-r--r--source/libsmb/smb_signing.c119
-rw-r--r--source/libsmb/smbencrypt.c10
-rw-r--r--source/msdfs/msdfs.c12
-rw-r--r--source/nsswitch/wbinfo.c78
-rw-r--r--source/nsswitch/winbindd.h6
-rw-r--r--source/nsswitch/winbindd_ads.c30
-rw-r--r--source/nsswitch/winbindd_cache.c8
-rw-r--r--source/nsswitch/winbindd_nss.h1
-rw-r--r--source/nsswitch/winbindd_pam.c35
-rw-r--r--source/nsswitch/winbindd_rpc.c6
-rw-r--r--source/nsswitch/winbindd_wins.c5
-rw-r--r--source/param/loadparm.c34
-rw-r--r--source/passdb/lookup_sid.c2
-rw-r--r--source/passdb/passdb.c2
-rw-r--r--source/passdb/pdb_ldap.c24
-rw-r--r--source/printing/nt_printing.c8
-rwxr-xr-xsource/python/setup.py3
-rw-r--r--source/rpc_client/cli_netlogon.c49
-rw-r--r--source/rpc_client/cli_pipe.c4
-rw-r--r--source/rpc_parse/parse_net.c84
-rw-r--r--source/rpc_parse/parse_spoolss.c2
-rw-r--r--source/rpc_server/srv_srvsvc_nt.c8
-rw-r--r--source/rpc_server/srv_util.c6
-rw-r--r--source/rpcclient/cmd_netlogon.c26
-rw-r--r--source/smbd/dir.c4
-rw-r--r--source/smbd/dosmode.c395
-rw-r--r--source/smbd/fake_file.c8
-rw-r--r--source/smbd/fileio.c5
-rw-r--r--source/smbd/negprot.c6
-rw-r--r--source/smbd/nttrans.c23
-rw-r--r--source/smbd/open.c80
-rw-r--r--source/smbd/password.c6
-rw-r--r--source/smbd/posix_acls.c4
-rw-r--r--source/smbd/reply.c102
-rw-r--r--source/smbd/server.c11
-rw-r--r--source/smbd/sesssetup.c20
-rw-r--r--source/smbd/trans2.c347
-rw-r--r--source/tdb/spinlock.c28
-rw-r--r--source/tdb/tdb.c45
-rw-r--r--source/tdb/tdb.h35
-rw-r--r--source/torture/torture.c107
-rw-r--r--source/utils/ntlm_auth.c4
77 files changed, 2405 insertions, 692 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 517c94e1fc1..92e7c71f9a7 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,6 +1,6 @@
=================================
- Release Notes for Samba 3.0.3pre1
- March 19, 2004
+ Release Notes for Samba 3.0.3pre2
+ XXXX XX, 2004
=================================
This is a preview release of the Samba 3.0.3 code base and is
@@ -14,28 +14,91 @@ exact updates.
Common bugs fixed in this preview release include:
- o Crash bugs and change notify issues in Samba's
+ o <FILL IN>
+
+
+######################################################################
+Changes
+#######
+
+commits
+-------
+
+o Jeremy Allison <jra@samba.org>
+
+
+o Andrew Bartlet <abartlet@samba.org>
+
+
+o Alexander Bokovoy <ab@samba.org>
+
+
+o Gerald Carter <jerry@samba.org>
+ * BUG 417, 1128: Ensure that the current_user_info is set
+ constistenly so that %[UuGg] is expanded correctly.
+ * BUG 1195: Fix crash in winbindd when the ADS server is
+ unavailable.
+ * BUG 1185: Set reconnect time to be the same as the
+ 'winbind cache time'.
+
+
+o Volker Lendecke <vl@samba.org>
+ * Implement wbinfo -k: Have winbind generate an AFS token after
+ authenticating the user
+
+
+o Herb Lewis <herb@samba.org>
+
+
+o Jim McDonough <jmcd@us.ibm.com>
+
+
+o Tim Potter <tpot@samba.org>
+
+
+o Simo Source <idra@samba.org>
+
+
+o Richard Sharpe <rsharpe@samba.org>
+
+
+o Andrew Tridgell <tridge@samba.org>
+
+
+o Jelmer Vernooij <jelmer@samba.org>
+
+
+
+Changes for older versions follow below:
+
+ --------------------------------------------------
+
+ =================================
+ Release Notes for Samba 3.0.3pre1
+ March 19, 2004
+ =================================
+
+
+Common bugs fixed in this preview release include:
+
+ o Crash bugs and change notify issues in Samba's
printing code.
- o Honoring secondary group membership on domain
+ o Honoring secondary group membership on domain
member servers.
o TDB scalability issue surrounding the TDB_CLEAR_IF_FIRST
flag.
-
+
New features introduced in this preview release include:
- o Improved support for i18n character sets.
- o Support for account lockout policy based on
+ o Improved support for i18n character sets.
+ o Support for account lockout policy based on
bad password attempts.
- o Improved support for long password changes (>14
+ o Improved support for long password changes (>14
characters) and strong password enforcement.
- o Continued work on support Windows aliases (i.e.
+ o Continued work on support Windows aliases (i.e.
nested groups).
-
-######################################################################
-Changes
-#######
Changes since 3.0.2a
--------------------
smb.conf changes
@@ -127,7 +190,7 @@ o Alexander Bokovoy <ab@samba.org>
o Gerald (Jerry) Carter <jerry@samba.org>
- * Fix 'make installmodules' bug on True64.
+ * BUG 850: Fix 'make installmodules' bug on True64.
* BUG 66: mark 'only user' deprecated.
* Remove corrupt tdb and shutdown (only for printing tdbs,
connections, sessionid & locking).
@@ -308,8 +371,6 @@ o Shiro Yamada <shiro@miraclelinux.com>
* BUG 1129: install image files for SWAT.
-Changes for older versions follow below:
-
--------------------------------------------------
==============================
@@ -338,10 +399,6 @@ these accounts and reset the password hashes to a string of X's.
******************* Attention! Achtung! Kree! *********************
-######################################################################
-Changes
-#######
-
Changes since 3.0.2
-------------------
diff --git a/examples/pdb/README b/examples/pdb/README
index c18e128e782..ab1baed2366 100644
--- a/examples/pdb/README
+++ b/examples/pdb/README
@@ -1,7 +1,7 @@
README for Samba Password Database (PDB) examples
====================================================
Jelmer Vernooij <jelmer@nl.linux.org>
-Stefan (metze) Metzmacher <metze@metzemix.de>
+Stefan (metze) Metzmacher <metze@samba.org>
The pdb_test.c file in this directory contains a very basic example of
a pdb plugin. It just prints the name of the function that is executed using
diff --git a/packaging/RedHat/samba.spec.tmpl b/packaging/RedHat/samba.spec.tmpl
index 70d51e34437..2e1a9cbaf98 100644
--- a/packaging/RedHat/samba.spec.tmpl
+++ b/packaging/RedHat/samba.spec.tmpl
@@ -160,10 +160,6 @@ make DESTDIR=$RPM_BUILD_ROOT \
installman installswat installdat installmodules
cd ..
-## work around a temporary bug in the installswat script
-## copy the images
-mv docs/htmldocs/images $RPM_BUILD_ROOT/%{prefix}/share/swat/help
-
## don't duplicate the docs. These are installed with SWAT
rm -rf docs/htmldocs
rm -rf docs/manpages
diff --git a/source/Makefile.in b/source/Makefile.in
index 843e843a1ef..0c096217698 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -319,6 +319,7 @@ VFS_NETATALK_OBJ = modules/vfs_netatalk.o
VFS_DEFAULT_QUOTA_OBJ = modules/vfs_default_quota.o
VFS_READONLY_OBJ = modules/vfs_readonly.o modules/getdate.o
VFS_CAP_OBJ = modules/vfs_cap.o
+VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o
PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o
@@ -635,10 +636,10 @@ WINBINDD_OBJ = \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
$(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \
$(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
- $(DCUTIL_OBJ) $(IDMAP_OBJ) lib/dummyroot.o
+ $(DCUTIL_OBJ) $(IDMAP_OBJ) lib/dummyroot.o lib/afs.o
WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
- $(UBIQX_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
+ $(UBIQX_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) lib/afs.o
WINBIND_NSS_OBJ = nsswitch/wb_common.o lib/replace1.o @WINBIND_NSS_EXTRA_OBJS@
@@ -1171,9 +1172,14 @@ bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.@PICSUFFIX@)
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.@PICSUFFIX@) \
@SONAMEFLAG@`basename $@`
+bin/expand_msdfs.@SHLIBEXT@: $(VFS_EXPAND_MSDFS_OBJ:.o=.@PICSUFFIX@)
+ @echo "Building plugin $@"
+ @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_EXPAND_MSDFS_OBJ:.o=.@PICSUFFIX@) \
+ @SONAMEFLAG@`basename $@`
+
bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
@echo Linking $@
- @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@
+ @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@ -lcrypto
bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
$(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
@@ -1284,7 +1290,7 @@ python_ext: $(PYTHON_PICOBJS)
fi
PYTHON_OBJS="$(PYTHON_PICOBJS)" \
PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS) $(FLAGS)" \
- LIBS="$(LIBS) $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS)" \
+ LIBS="$(LDFLAGS) $(LIBS) $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS)" \
$(PYTHON) python/setup.py build
python_install: $(PYTHON_PICOBJS)
@@ -1294,7 +1300,7 @@ python_install: $(PYTHON_PICOBJS)
fi
PYTHON_OBJS="$(PYTHON_PICOBJS)" \
PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS)" \
- LIBS="$(LIBS)" \
+ LIBS="$(LDFLAGS) $(LIBS)" \
$(PYTHON) python/setup.py install
python_clean:
diff --git a/source/VERSION b/source/VERSION
index b777e5bcee3..00ec36133b0 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -41,7 +41,7 @@ SAMBA_VERSION_REVISION=
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=1
+SAMBA_VERSION_PRE_RELEASE=2
########################################################
# For 'rc' releases the version will be #
@@ -93,7 +93,7 @@ SAMBA_VERSION_TEST_RELEASE=
# e.g. SAMBA_VERSION_IS_CVS_SNAPSHOT=yes #
# -> "CVS 3.0.0rc2" #
########################################################
-SAMBA_VERSION_IS_CVS_SNAPSHOT=
+SAMBA_VERSION_IS_CVS_SNAPSHOT=yes
########################################################
# This can be set by vendors if they want... #
diff --git a/source/auth/auth_ntlmssp.c b/source/auth/auth_ntlmssp.c
index a5ce101e5e7..498a7b1a39a 100644
--- a/source/auth/auth_ntlmssp.c
+++ b/source/auth/auth_ntlmssp.c
@@ -78,21 +78,9 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state,
static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key)
{
AUTH_NTLMSSP_STATE *auth_ntlmssp_state = ntlmssp_state->auth_context;
- uint32 auth_flags = AUTH_FLAG_NONE;
auth_usersupplied_info *user_info = NULL;
- DATA_BLOB plaintext_password = data_blob(NULL, 0);
NTSTATUS nt_status;
- if (auth_ntlmssp_state->ntlmssp_state->lm_resp.length) {
- auth_flags |= AUTH_FLAG_LM_RESP;
- }
-
- if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length == 24) {
- auth_flags |= AUTH_FLAG_NTLM_RESP;
- } else if (auth_ntlmssp_state->ntlmssp_state->nt_resp.length > 24) {
- auth_flags |= AUTH_FLAG_NTLMv2_RESP;
- }
-
/* the client has given us its machine name (which we otherwise would not get on port 445).
we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
@@ -108,10 +96,10 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
auth_ntlmssp_state->ntlmssp_state->user,
auth_ntlmssp_state->ntlmssp_state->domain,
auth_ntlmssp_state->ntlmssp_state->workstation,
- auth_ntlmssp_state->ntlmssp_state->lm_resp,
- auth_ntlmssp_state->ntlmssp_state->nt_resp,
- plaintext_password,
- auth_flags, True);
+ auth_ntlmssp_state->ntlmssp_state->lm_resp.data ? &auth_ntlmssp_state->ntlmssp_state->lm_resp : NULL,
+ auth_ntlmssp_state->ntlmssp_state->nt_resp.data ? &auth_ntlmssp_state->ntlmssp_state->nt_resp : NULL,
+ NULL, NULL, NULL,
+ True);
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index b35cc78d6b2..5efc51b21ae 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -57,7 +57,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
nt_pw = pdb_get_nt_passwd(sampass);
return ntlm_password_check(mem_ctx, &auth_context->challenge,
- &user_info->lm_resp, &user_info->nt_resp,
+ &user_info->lm_resp, &user_info->nt_resp,
+ &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd,
username,
user_info->smb_name.str,
user_info->client_domain.str,
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index f62cc2fb9e0..9df58739837 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -124,9 +124,10 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
const char *client_domain,
const char *domain,
const char *wksta_name,
- DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
- DATA_BLOB plaintext,
- uint32 auth_flags, BOOL encrypted)
+ DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
+ DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
+ DATA_BLOB *plaintext,
+ BOOL encrypted)
{
DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
@@ -183,12 +184,19 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
- (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length);
- (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length);
- (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length);
+ if (lm_pwd)
+ (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
+ if (nt_pwd)
+ (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
+ if (lm_interactive_pwd)
+ (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
+ if (nt_interactive_pwd)
+ (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
+
+ if (plaintext)
+ (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
(*user_info)->encrypted = encrypted;
- (*user_info)->auth_flags = auth_flags;
DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
@@ -203,9 +211,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
const char *smb_name,
const char *client_domain,
const char *wksta_name,
- DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
- DATA_BLOB plaintext,
- uint32 ntlmssp_flags, BOOL encrypted)
+ DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
+ DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
+ DATA_BLOB *plaintext,
+ BOOL encrypted)
{
const char *domain;
fstring internal_username;
@@ -233,8 +242,10 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
/* we know that it is a trusted domain (and we are allowing them) or it is our domain */
return make_user_info(user_info, smb_name, internal_username,
- client_domain, domain, wksta_name, lm_pwd, nt_pwd,
- plaintext, ntlmssp_flags, encrypted);
+ client_domain, domain, wksta_name,
+ lm_pwd, nt_pwd,
+ lm_interactive_pwd, nt_interactive_pwd,
+ plaintext, encrypted);
}
/****************************************************************************
@@ -253,23 +264,14 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
NTSTATUS nt_status;
DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
- DATA_BLOB plaintext_blob = data_blob(NULL, 0);
- uint32 auth_flags = AUTH_FLAG_NONE;
-
- if (lm_pwd_len)
- auth_flags |= AUTH_FLAG_LM_RESP;
- if (nt_pwd_len == 24) {
- auth_flags |= AUTH_FLAG_NTLM_RESP;
- } else if (nt_pwd_len != 0) {
- auth_flags |= AUTH_FLAG_NTLMv2_RESP;
- }
nt_status = make_user_info_map(user_info,
- smb_name, client_domain,
- wksta_name,
- lm_blob, nt_blob,
- plaintext_blob,
- auth_flags, True);
+ smb_name, client_domain,
+ wksta_name,
+ lm_pwd_len ? &lm_blob : NULL,
+ nt_pwd_len ? &nt_blob : NULL,
+ NULL, NULL, NULL,
+ True);
ret = NT_STATUS_IS_OK(nt_status) ? True : False;
@@ -297,7 +299,6 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
unsigned char local_lm_response[24];
unsigned char local_nt_response[24];
unsigned char key[16];
- uint32 auth_flags = AUTH_FLAG_NONE;
ZERO_STRUCT(key);
memcpy(key, dc_sess_key, 8);
@@ -316,8 +317,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
dump_data(100, nt_pwd, sizeof(nt_pwd));
#endif
- SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
- SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
+ if (lm_interactive_pwd)
+ SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
+
+ if (nt_interactive_pwd)
+ SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
#ifdef DEBUG_PASSWORD
DEBUG(100,("decrypt of lm owf password:"));
@@ -327,37 +331,51 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
dump_data(100, nt_pwd, sizeof(nt_pwd));
#endif
- SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
- SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
+ if (lm_interactive_pwd)
+ SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
+
+ if (nt_interactive_pwd)
+ SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
/* Password info paranoia */
- ZERO_STRUCT(lm_pwd);
- ZERO_STRUCT(nt_pwd);
ZERO_STRUCT(key);
{
BOOL ret;
NTSTATUS nt_status;
- DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
- DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
- DATA_BLOB plaintext_blob = data_blob(NULL, 0);
+ DATA_BLOB local_lm_blob;
+ DATA_BLOB local_nt_blob;
- if (lm_interactive_pwd)
- auth_flags |= AUTH_FLAG_LM_RESP;
- if (nt_interactive_pwd)
- auth_flags |= AUTH_FLAG_NTLM_RESP;
+ DATA_BLOB lm_interactive_blob;
+ DATA_BLOB nt_interactive_blob;
+
+ if (lm_interactive_pwd) {
+ local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
+ lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd));
+ ZERO_STRUCT(lm_pwd);
+ }
+
+ if (nt_interactive_pwd) {
+ local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
+ nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd));
+ ZERO_STRUCT(nt_pwd);
+ }
nt_status = make_user_info_map(user_info,
smb_name, client_domain,
wksta_name,
- local_lm_blob,
- local_nt_blob,
- plaintext_blob,
- auth_flags, True);
-
+ lm_interactive_pwd ? &local_lm_blob : NULL,
+ nt_interactive_pwd ? &local_nt_blob : NULL,
+ lm_interactive_pwd ? &lm_interactive_blob : NULL,
+ nt_interactive_pwd ? &nt_interactive_blob : NULL,
+ NULL,
+ True);
+
ret = NT_STATUS_IS_OK(nt_status) ? True : False;
data_blob_free(&local_lm_blob);
data_blob_free(&local_nt_blob);
+ data_blob_free(&lm_interactive_blob);
+ data_blob_free(&nt_interactive_blob);
return ret;
}
}
@@ -377,7 +395,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
DATA_BLOB local_lm_blob;
DATA_BLOB local_nt_blob;
NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
- uint32 auth_flags = AUTH_FLAG_NONE;
/*
* Not encrypted - do so.
@@ -400,7 +417,6 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
case insensitive */
local_nt_blob = data_blob(NULL, 0);
- auth_flags = (AUTH_FLAG_PLAINTEXT | AUTH_FLAG_LM_RESP);
} else {
local_lm_blob = data_blob(NULL, 0);
local_nt_blob = data_blob(NULL, 0);
@@ -409,10 +425,11 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
ret = make_user_info_map(user_info, smb_name,
client_domain,
get_remote_machine_name(),
- local_lm_blob,
- local_nt_blob,
- plaintext_password,
- auth_flags, False);
+ local_lm_blob.data ? &local_lm_blob : NULL,
+ local_nt_blob.data ? &local_nt_blob : NULL,
+ NULL, NULL,
+ plaintext_password.data ? &plaintext_password : NULL,
+ False);
data_blob_free(&local_lm_blob);
return NT_STATUS_IS_OK(ret) ? True : False;
@@ -427,27 +444,13 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
const char *client_domain,
DATA_BLOB lm_resp, DATA_BLOB nt_resp)
{
- uint32 auth_flags = AUTH_FLAG_NONE;
-
- DATA_BLOB no_plaintext_blob = data_blob(NULL, 0);
-
- if (lm_resp.length == 24) {
- auth_flags |= AUTH_FLAG_LM_RESP;
- }
- if (nt_resp.length == 0) {
- } else if (nt_resp.length == 24) {
- auth_flags |= AUTH_FLAG_NTLM_RESP;
- } else {
- auth_flags |= AUTH_FLAG_NTLMv2_RESP;
- }
-
return make_user_info_map(user_info, smb_name,
- client_domain,
- get_remote_machine_name(),
- lm_resp,
- nt_resp,
- no_plaintext_blob,
- auth_flags, True);
+ client_domain,
+ get_remote_machine_name(),
+ lm_resp.data ? &lm_resp : NULL,
+ nt_resp.data ? &nt_resp : NULL,
+ NULL, NULL, NULL,
+ True);
}
/****************************************************************************
@@ -456,19 +459,16 @@ NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
BOOL make_user_info_guest(auth_usersupplied_info **user_info)
{
- DATA_BLOB lm_blob = data_blob(NULL, 0);
- DATA_BLOB nt_blob = data_blob(NULL, 0);
- DATA_BLOB plaintext_blob = data_blob(NULL, 0);
- uint32 auth_flags = AUTH_FLAG_NONE;
NTSTATUS nt_status;
nt_status = make_user_info(user_info,
- "","",
- "","",
- "",
- nt_blob, lm_blob,
- plaintext_blob,
- auth_flags, True);
+ "","",
+ "","",
+ "",
+ NULL, NULL,
+ NULL, NULL,
+ NULL,
+ True);
return NT_STATUS_IS_OK(nt_status) ? True : False;
}
@@ -1307,7 +1307,8 @@ void free_user_info(auth_usersupplied_info **user_info)
SAFE_FREE((*user_info)->wksta_name.str);
data_blob_free(&(*user_info)->lm_resp);
data_blob_free(&(*user_info)->nt_resp);
- SAFE_FREE((*user_info)->interactive_password);
+ data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
+ data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
data_blob_clear_free(&(*user_info)->plaintext_password);
ZERO_STRUCT(**user_info);
}
diff --git a/source/bin/.cvsignore b/source/bin/.cvsignore
index 09aba16017c..fd5d9372e4e 100644
--- a/source/bin/.cvsignore
+++ b/source/bin/.cvsignore
@@ -5,6 +5,7 @@ debug2html
editreg
locktest
locktest2
+log2pcap
make_printerdef
make_smbcodepage
make_unicodemap
@@ -27,7 +28,9 @@ smbcontrol
smbcquotas
smbd
smbfilter
+smbget
smbgroupedit
+smbiconv
smbmnt
smbmount
smbpasswd
@@ -37,19 +40,17 @@ smbstatus
smbtorture
smbtree
smbumount
-smbiconv
swat
-tdbdump
t_push_ucs2
t_snprintf
t_strcmp
t_stringoverflow
talloctort
tdbbackup
+tdbdump
testparm
testprns
vfstest
-log2pcap
wbinfo
winbindd
wrepld
diff --git a/source/client/client.c b/source/client/client.c
index 214b7872979..1da35fcc439 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -2853,6 +2853,7 @@ static int do_message_op(void)
int main(int argc,char *argv[])
{
extern BOOL AllowDebugChange;
+ extern BOOL override_logfile;
pstring base_directory;
int opt;
pstring query_host;
@@ -2989,11 +2990,14 @@ static int do_message_op(void)
/* save the workgroup...
- FIXME!! do we need to do tyhis for other options as well
+ FIXME!! do we need to do this for other options as well
(or maybe a generic way to keep lp_load() from overwriting
everything)? */
- fstrcpy( new_workgroup, lp_workgroup() );
+ fstrcpy( new_workgroup, lp_workgroup() );
+
+ if ( override_logfile )
+ setup_logging( lp_logfile(), False );
if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index 504de9e629d..a2f9ebf45ca 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -38,7 +38,7 @@
#include <fcntl.h>
#define MOUNT_CIFS_VERSION_MAJOR "1"
-#define MOUNT_CIFS_VERSION_MINOR "1"
+#define MOUNT_CIFS_VERSION_MINOR "2"
#ifndef MOUNT_CIFS_VENDOR_SUFFIX
#define MOUNT_CIFS_VENDOR_SUFFIX ""
@@ -117,19 +117,20 @@ static int open_cred_file(char * file_name)
/* eat leading white space */
for(i=0;i<4096;i++) {
- if(line_buf[i] == '\0')
- break;
- else if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
+ if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
break;
+ /* if whitespace - skip past it */
line_buf++;
}
-
if (strncasecmp("username",line_buf,8) == 0) {
temp_val = strchr(line_buf + i,'=');
if(temp_val) {
/* go past equals sign */
temp_val++;
- length = strlen(temp_val);
+ for(length = 0;length<4087;length++) {
+ if(temp_val[length] == '\n')
+ break;
+ }
if(length > 4086) {
printf("cifs.mount failed due to malformed username in credentials file");
memset(line_buf,0,4096);
@@ -150,7 +151,10 @@ static int open_cred_file(char * file_name)
if(temp_val) {
/* go past equals sign */
temp_val++;
- length = strlen(temp_val);
+ for(length = 0;length<65;length++) {
+ if(temp_val[length] == '\n')
+ break;
+ }
if(length > 64) {
printf("cifs.mount failed: password in credentials file too long\n");
memset(line_buf,0, 4096);
@@ -161,9 +165,11 @@ static int open_cred_file(char * file_name)
} else {
if(mountpassword == NULL) {
mountpassword = calloc(65,1);
- }
+ } else
+ memset(mountpassword,0,64);
if(mountpassword) {
- strncpy(mountpassword,temp_val,64);
+ /* BB add handling for commas in password here */
+ strncpy(mountpassword,temp_val,length);
got_password = 1;
}
}
@@ -841,11 +847,32 @@ int main(int argc, char ** argv)
mountent.mnt_fsname = share_name;
mountent.mnt_dir = mountpoint;
mountent.mnt_type = "cifs";
- mountent.mnt_opts = "";
+ mountent.mnt_opts = malloc(200);
+ if(mountent.mnt_opts) {
+ memset(mountent.mnt_opts,0,200);
+ if(flags & MS_RDONLY)
+ strcat(mountent.mnt_opts,"ro");
+ else
+ strcat(mountent.mnt_opts,"rw");
+ if(flags & MS_MANDLOCK)
+ strcat(mountent.mnt_opts,",mand");
+ else
+ strcat(mountent.mnt_opts,",nomand");
+ if(flags & MS_NOEXEC)
+ strcat(mountent.mnt_opts,",noexec");
+ if(flags & MS_NOSUID)
+ strcat(mountent.mnt_opts,",nosuid");
+ if(flags & MS_NODEV)
+ strcat(mountent.mnt_opts,",nodev");
+ if(flags & MS_SYNCHRONOUS)
+ strcat(mountent.mnt_opts,",synch");
+ }
mountent.mnt_freq = 0;
mountent.mnt_passno = 0;
rc = addmntent(pmntfile,&mountent);
endmntent(pmntfile);
+ if(mountent.mnt_opts)
+ free(mountent.mnt_opts);
} else {
printf("could not update mount table\n");
}
diff --git a/source/configure.in b/source/configure.in
index f92ea2d0806..59b1d062f63 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -360,7 +360,7 @@ dnl These have to be built static:
default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
dnl These are preferably build shared, and static if dlopen() is not available
-default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap charset_CP850 charset_CP437"
+default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs charset_CP850 charset_CP437"
if test "x$developer" = xyes; then
default_static_modules="$default_static_modules rpc_echo"
@@ -4371,6 +4371,7 @@ SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), "bin/fake_perms.$SHLIBEXT", V
SMB_MODULE(vfs_default_quota, \$(VFS_DEFAULT_QUOTA_OBJ), "bin/default_quota.$SHLIBEXT", VFS)
SMB_MODULE(vfs_readonly, \$(VFS_READONLY_OBJ), "bin/readonly.$SHLIBEXT", VFS)
SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS)
+SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT", VFS)
SMB_SUBSYSTEM(VFS,smbd/vfs.o)
AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules])
diff --git a/source/include/ads.h b/source/include/ads.h
index 65a5ade556d..4daa65e796d 100644
--- a/source/include/ads.h
+++ b/source/include/ads.h
@@ -10,6 +10,8 @@ typedef struct {
time_t last_attempt; /* last attempt to reconnect */
int ldap_port;
+ int is_mine; /* do I own this structure's memory? */
+
/* info needed to find the server */
struct {
char *realm;
@@ -27,6 +29,7 @@ typedef struct {
char *kdc_server;
unsigned flags;
int time_offset;
+ time_t expire;
} auth;
/* info derived from the servers config */
diff --git a/source/include/auth.h b/source/include/auth.h
index ecf4d539d8c..8f52512e6a0 100644
--- a/source/include/auth.h
+++ b/source/include/auth.h
@@ -27,37 +27,17 @@ typedef struct normal_string
char *str;
} AUTH_STR;
-/* AUTH_UNISTR - unicode string or buffer */
-typedef struct unicode_string
-{
- int len;
- uchar *unistr;
-} AUTH_UNISTR;
-
-typedef struct interactive_password
-{
- OWF_INFO lm_owf; /* LM OWF Password */
- OWF_INFO nt_owf; /* NT OWF Password */
-} auth_interactive_password;
-
-#define AUTH_FLAG_NONE 0x000000
-#define AUTH_FLAG_PLAINTEXT 0x000001
-#define AUTH_FLAG_LM_RESP 0x000002
-#define AUTH_FLAG_NTLM_RESP 0x000004
-#define AUTH_FLAG_NTLMv2_RESP 0x000008
-
typedef struct auth_usersupplied_info
{
DATA_BLOB lm_resp;
DATA_BLOB nt_resp;
- auth_interactive_password * interactive_password;
+ DATA_BLOB lm_interactive_pwd;
+ DATA_BLOB nt_interactive_pwd;
DATA_BLOB plaintext_password;
BOOL encrypted;
- uint32 auth_flags;
-
AUTH_STR client_domain; /* domain name string */
AUTH_STR domain; /* domain name after mapping */
AUTH_STR internal_username; /* username after mapping */
diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h
index 74e3a50ee4a..a5b93b0238a 100644
--- a/source/include/rpc_netlogon.h
+++ b/source/include/rpc_netlogon.h
@@ -33,6 +33,7 @@
#define NET_SRVPWSET 0x06
#define NET_SAM_DELTAS 0x07
#define NET_LOGON_CTRL 0x0c
+#define NET_GETDCNAME 0x0d
#define NET_AUTH2 0x0f
#define NET_LOGON_CTRL2 0x0e
#define NET_SAM_SYNC 0x10
@@ -298,6 +299,25 @@ typedef struct net_r_logon_ctrl2_info
} NET_R_LOGON_CTRL2;
+/* NET_Q_GETDCNAME - Ask a DC for a trusted DC name */
+
+typedef struct net_q_getdcname
+{
+ uint32 ptr_logon_server;
+ UNISTR2 uni_logon_server;
+ uint32 ptr_domainname;
+ UNISTR2 uni_domainname;
+} NET_Q_GETDCNAME;
+
+/* NET_R_GETDCNAME - Ask a DC for a trusted DC name */
+
+typedef struct net_r_getdcname
+{
+ uint32 ptr_dcname;
+ UNISTR2 uni_dcname;
+ NTSTATUS status;
+} NET_R_GETDCNAME;
+
/* NET_Q_TRUST_DOM_LIST - LSA Query Trusted Domains */
typedef struct net_q_trust_dom_info
{
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index f96b4fa96ab..d9fc0c6a6ab 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -375,7 +375,7 @@ PRINTER_MESSAGE_INFO;
#define PRINTER_ATTRIBUTE_SAMBA (PRINTER_ATTRIBUTE_RAW_ONLY|\
PRINTER_ATTRIBUTE_SHARED|\
- PRINTER_ATTRIBUTE_NETWORK)
+ PRINTER_ATTRIBUTE_LOCAL)
#define NO_PRIORITY 0
#define MAX_PRIORITY 99
diff --git a/source/include/smb.h b/source/include/smb.h
index 6c2f74e3b9e..3ee6f01d34d 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -1649,7 +1649,7 @@ struct ip_service {
typedef struct smb_sign_info {
void (*sign_outgoing_message)(char *outbuf, struct smb_sign_info *si);
- BOOL (*check_incoming_message)(char *inbuf, struct smb_sign_info *si);
+ BOOL (*check_incoming_message)(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok);
void (*free_signing_context)(struct smb_sign_info *si);
void *signing_context;
@@ -1657,6 +1657,18 @@ typedef struct smb_sign_info {
BOOL allow_smb_signing;
BOOL doing_signing;
BOOL mandatory_signing;
+ BOOL seen_valid; /* Have I ever seen a validly signed packet? */
} smb_sign_info;
+struct ea_struct {
+ uint8 flags;
+ char *name;
+ DATA_BLOB value;
+};
+
+/* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */
+#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
+/* EA to use for DOS attributes */
+#define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
+
#endif /* _SMB_H */
diff --git a/source/lib/afs.c b/source/lib/afs.c
index 789afcdd837..ce972ec27b7 100644
--- a/source/lib/afs.c
+++ b/source/lib/afs.c
@@ -43,6 +43,130 @@ struct ClearToken {
uint32 EndTimestamp;
};
+static char *afs_encode_token(const char *cell, const DATA_BLOB ticket,
+ const struct ClearToken *ct)
+{
+ char *base64_ticket;
+ char *result;
+
+ DATA_BLOB key = data_blob(ct->HandShakeKey, 8);
+ char *base64_key;
+
+ base64_ticket = base64_encode_data_blob(ticket);
+ if (base64_ticket == NULL)
+ return NULL;
+
+ base64_key = base64_encode_data_blob(key);
+ if (base64_key == NULL) {
+ free(base64_ticket);
+ return NULL;
+ }
+
+ asprintf(&result, "%s\n%u\n%s\n%u\n%u\n%u\n%s\n", cell,
+ ct->AuthHandle, base64_key, ct->ViceId, ct->BeginTimestamp,
+ ct->EndTimestamp, base64_ticket);
+
+ DEBUG(10, ("Got ticket string:\n%s\n", result));
+
+ free(base64_ticket);
+ free(base64_key);
+
+ return result;
+}
+
+static BOOL afs_decode_token(const char *string, char **cell,
+ DATA_BLOB *ticket, struct ClearToken *ct)
+{
+ DATA_BLOB blob;
+ struct ClearToken result_ct;
+
+ char *s = strdup(string);
+
+ char *t;
+
+ if ((t = strtok(s, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ *cell = strdup(t);
+
+ if ((t = strtok(NULL, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ if (sscanf(t, "%u", &result_ct.AuthHandle) != 1) {
+ DEBUG(10, ("sscanf AuthHandle failed\n"));
+ return False;
+ }
+
+ if ((t = strtok(NULL, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ blob = base64_decode_data_blob(t);
+
+ if ( (blob.data == NULL) ||
+ (blob.length != sizeof(result_ct.HandShakeKey) )) {
+ DEBUG(10, ("invalid key: %x/%d\n", (uint32)blob.data,
+ blob.length));
+ return False;
+ }
+
+ memcpy(result_ct.HandShakeKey, blob.data, blob.length);
+
+ data_blob_free(&blob);
+
+ if ((t = strtok(NULL, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ if (sscanf(t, "%u", &result_ct.ViceId) != 1) {
+ DEBUG(10, ("sscanf ViceId failed\n"));
+ return False;
+ }
+
+ if ((t = strtok(NULL, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ if (sscanf(t, "%u", &result_ct.BeginTimestamp) != 1) {
+ DEBUG(10, ("sscanf BeginTimestamp failed\n"));
+ return False;
+ }
+
+ if ((t = strtok(NULL, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ if (sscanf(t, "%u", &result_ct.EndTimestamp) != 1) {
+ DEBUG(10, ("sscanf EndTimestamp failed\n"));
+ return False;
+ }
+
+ if ((t = strtok(NULL, "\n")) == NULL) {
+ DEBUG(10, ("strtok failed\n"));
+ return False;
+ }
+
+ blob = base64_decode_data_blob(t);
+
+ if (blob.data == NULL) {
+ DEBUG(10, ("Could not get ticket\n"));
+ return False;
+ }
+
+ *ticket = blob;
+ *ct = result_ct;
+
+ return True;
+}
+
/*
Put an AFS token into the Kernel so that it can authenticate against
the AFS server. This assumes correct local uid settings.
@@ -53,9 +177,9 @@ struct ClearToken {
to avoid.
*/
-static BOOL afs_settoken(const char *username, const char *cell,
+static BOOL afs_settoken(const char *cell,
const struct ClearToken *ctok,
- char *v4tkt_data, int v4tkt_length)
+ DATA_BLOB ticket)
{
int ret;
struct {
@@ -67,10 +191,10 @@ static BOOL afs_settoken(const char *username, const char *cell,
char *p = buf;
int tmp;
- memcpy(p, &v4tkt_length, sizeof(uint32));
+ memcpy(p, &ticket.length, sizeof(uint32));
p += sizeof(uint32);
- memcpy(p, v4tkt_data, v4tkt_length);
- p += v4tkt_length;
+ memcpy(p, ticket.data, ticket.length);
+ p += ticket.length;
tmp = sizeof(struct ClearToken);
memcpy(p, &tmp, sizeof(uint32));
@@ -109,90 +233,69 @@ static BOOL afs_settoken(const char *username, const char *cell,
return (ret == 0);
}
-/*
- This routine takes a radical approach completely defeating the
- Kerberos idea of security and using AFS simply as an intelligent
- file backend. Samba has persuaded itself somehow that the user is
- actually correctly identified and then we create a ticket that the
- AFS server hopefully accepts using its KeyFile that the admin has
- kindly stored to our secrets.tdb.
-
- Thanks to the book "Network Security -- PRIVATE Communication in a
- PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner
- Kerberos 4 tickets are not really hard to construct.
-
- For the comments "Alice" is the User to be auth'ed, and "Bob" is the
- AFS server. */
-
-BOOL afs_login(connection_struct *conn)
+BOOL afs_settoken_str(const char *token_string)
{
- fstring ticket;
- char *p = ticket;
- uint32 len;
- struct afs_key key;
- pstring afs_username;
- char *cell;
-
+ DATA_BLOB ticket;
struct ClearToken ct;
+ BOOL result;
+ char *cell;
- uint32 now; /* I assume time() returns 32 bit */
+ if (!afs_decode_token(token_string, &cell, &ticket, &ct))
+ return False;
- des_key_schedule key_schedule;
+ if (geteuid() != 0)
+ ct.ViceId = getuid();
- pstrcpy(afs_username, lp_afs_username_map());
- standard_sub_conn(conn, afs_username, sizeof(afs_username));
+ result = afs_settoken(cell, &ct, ticket);
- /* The pts command always generates completely lower-case user
- * names. */
- strlower_m(afs_username);
+ SAFE_FREE(cell);
+ data_blob_free(&ticket);
- cell = strchr(afs_username, '@');
-
- if (cell == NULL) {
- DEBUG(1, ("AFS username doesn't contain a @, "
- "could not find cell\n"));
- return False;
+ return result;
}
- *cell = '\0';
- cell += 1;
+/* Create a ClearToken and an encrypted ticket. ClearToken has not yet the
+ * ViceId set, this should be set by the caller. */
- DEBUG(10, ("Trying to log into AFS for user %s@%s\n",
- afs_username, cell));
+static BOOL afs_createtoken(const char *username, const char *cell,
+ DATA_BLOB *ticket, struct ClearToken *ct)
+{
+ fstring clear_ticket;
+ char *p = clear_ticket;
+ uint32 len;
+ uint32 now;
+
+ struct afs_key key;
+ des_key_schedule key_schedule;
if (!secrets_init())
return False;
if (!secrets_fetch_afs_key(cell, &key)) {
- DEBUG(5, ("Could not fetch AFS service key\n"));
+ DEBUG(1, ("Could not fetch AFS service key\n"));
return False;
}
- ct.AuthHandle = key.kvno;
+ ct->AuthHandle = key.kvno;
/* Build the ticket. This is going to be encrypted, so in our
way we fill in ct while we still have the unencrypted
form. */
- p = ticket;
+ p = clear_ticket;
/* The byte-order */
*p = 1;
p += 1;
/* "Alice", the client username */
- strncpy(p, afs_username, sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ strncpy(p, username, sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
p += strlen(p)+1;
- strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ strncpy(p, "", sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
p += strlen(p)+1;
- strncpy(p, cell, sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ strncpy(p, cell, sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
p += strlen(p)+1;
- /* This assumes that we have setresuid and set the real uid as well as
- the effective uid in set_effective_uid(). */
- ct.ViceId = getuid();
- DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId));
-
/* Alice's network layer address. At least Openafs-1.2.10
ignores this, so we fill in a dummy value here. */
SIVAL(p, 0, 0);
@@ -203,7 +306,7 @@ BOOL afs_login(connection_struct *conn)
/* Our client code needs the the key in the clear, it does not
know the server-key ... */
- memcpy(ct.HandShakeKey, p, 8);
+ memcpy(ct->HandShakeKey, p, 8);
p += 8;
@@ -216,37 +319,151 @@ BOOL afs_login(connection_struct *conn)
/* Ticket creation time */
now = time(NULL);
SIVAL(p, 0, now);
- ct.BeginTimestamp = now;
+ ct->BeginTimestamp = now;
- ct.EndTimestamp = now + (255*60*5);
- if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1) {
- ct.BeginTimestamp += 1; /* Lifetime must be even */
+ ct->EndTimestamp = now + (255*60*5);
+ if (((ct->EndTimestamp - ct->BeginTimestamp) & 1) == 1) {
+ ct->BeginTimestamp += 1; /* Lifetime must be even */
}
p += 4;
/* And here comes Bob's name and instance, in this case the
AFS server. */
- strncpy(p, "afs", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ strncpy(p, "afs", sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
p += strlen(p)+1;
- strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
+ strncpy(p, "", sizeof(clear_ticket)-PTR_DIFF(p,clear_ticket)-1);
p += strlen(p)+1;
/* And zero-pad to a multiple of 8 bytes */
- len = PTR_DIFF(p, ticket);
+ len = PTR_DIFF(p, clear_ticket);
if (len & 7) {
uint32 extra_space = 8-(len & 7);
memset(p, 0, extra_space);
p+=extra_space;
}
- len = PTR_DIFF(p, ticket);
+ len = PTR_DIFF(p, clear_ticket);
des_key_sched((const_des_cblock *)key.key, key_schedule);
- des_pcbc_encrypt(ticket, ticket,
+ des_pcbc_encrypt(clear_ticket, clear_ticket,
len, key_schedule, (C_Block *)key.key, 1);
ZERO_STRUCT(key);
- return afs_settoken(afs_username, cell, &ct, ticket, len);
+ *ticket = data_blob(clear_ticket, len);
+
+ return True;
+}
+
+char *afs_createtoken_str(const char *username, const char *cell)
+{
+ DATA_BLOB ticket;
+ struct ClearToken ct;
+ char *result;
+
+ if (!afs_createtoken(username, cell, &ticket, &ct))
+ return NULL;
+
+ result = afs_encode_token(cell, ticket, &ct);
+
+ data_blob_free(&ticket);
+
+ return result;
+}
+
+/*
+ This routine takes a radical approach completely bypassing the
+ Kerberos idea of security and using AFS simply as an intelligent
+ file backend. Samba has persuaded itself somehow that the user is
+ actually correctly identified and then we create a ticket that the
+ AFS server hopefully accepts using its KeyFile that the admin has
+ kindly stored to our secrets.tdb.
+
+ Thanks to the book "Network Security -- PRIVATE Communication in a
+ PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner
+ Kerberos 4 tickets are not really hard to construct.
+
+ For the comments "Alice" is the User to be auth'ed, and "Bob" is the
+ AFS server. */
+
+BOOL afs_login(connection_struct *conn)
+{
+ DATA_BLOB ticket;
+ pstring afs_username;
+ char *cell;
+ BOOL result;
+
+ struct ClearToken ct;
+
+ pstrcpy(afs_username, lp_afs_username_map());
+ standard_sub_conn(conn, afs_username, sizeof(afs_username));
+
+ /* The pts command always generates completely lower-case user
+ * names. */
+ strlower_m(afs_username);
+
+ cell = strchr(afs_username, '@');
+
+ if (cell == NULL) {
+ DEBUG(1, ("AFS username doesn't contain a @, "
+ "could not find cell\n"));
+ return False;
+ }
+
+ *cell = '\0';
+ cell += 1;
+
+ DEBUG(10, ("Trying to log into AFS for user %s@%s\n",
+ afs_username, cell));
+
+ if (!afs_createtoken(afs_username, cell, &ticket, &ct))
+ return False;
+
+ /* For which Unix-UID do we want to set the token? */
+ ct.ViceId = getuid();
+
+ {
+ char *str, *new_cell;
+ DATA_BLOB test_ticket;
+ struct ClearToken test_ct;
+
+ hex_encode(ct.HandShakeKey, sizeof(ct.HandShakeKey), &str);
+ DEBUG(10, ("Key: %s\n", str));
+ free(str);
+
+ str = afs_encode_token(cell, ticket, &ct);
+
+ if (!afs_decode_token(str, &new_cell, &test_ticket,
+ &test_ct)) {
+ DEBUG(0, ("Could not decode token"));
+ goto decode_failed;
+ }
+
+ if (strcmp(cell, new_cell) != 0) {
+ DEBUG(0, ("cell changed\n"));
+ }
+
+ if ((ticket.length != test_ticket.length) ||
+ (memcmp(ticket.data, test_ticket.data,
+ ticket.length) != 0)) {
+ DEBUG(0, ("Ticket changed\n"));
+ }
+
+ if (memcmp(&ct, &test_ct, sizeof(ct)) != 0) {
+ DEBUG(0, ("ClearToken changed\n"));
+ }
+
+ data_blob_free(&test_ticket);
+
+ decode_failed:
+ SAFE_FREE(str);
+ SAFE_FREE(new_cell);
+ }
+
+ result = afs_settoken(cell, &ct, ticket);
+
+ data_blob_free(&ticket);
+
+ return result;
}
#else
@@ -256,4 +473,14 @@ BOOL afs_login(connection_struct *conn)
return True;
}
+BOOL afs_settoken_str(const char *token_string)
+{
+ return False;
+}
+
+char *afs_createtoken_str(const char *username, const char *cell)
+{
+ return False;
+}
+
#endif /* WITH_FAKE_KASERVER */
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index 11b1448f1eb..b9791931a35 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -130,9 +130,21 @@ void init_iconv(void)
conv_handles[c1][c2] = smb_iconv_open(n2,n1);
if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
- DEBUG(0,("Conversion from %s to %s not supported\n",
+ DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
charset_name((charset_t)c1), charset_name((charset_t)c2)));
- conv_handles[c1][c2] = NULL;
+ if (c1 != CH_UCS2) {
+ n1 = "ASCII";
+ }
+ if (c2 != CH_UCS2) {
+ n2 = "ASCII";
+ }
+ DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
+ n1, n2 ));
+ conv_handles[c1][c2] = smb_iconv_open(n2,n1);
+ if (!conv_handles[c1][c2]) {
+ DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
+ smb_panic("init_iconv: conv_handle initialization failed.");
+ }
}
}
}
@@ -477,8 +489,6 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
if (!conv_silent)
DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
- if (allow_bad_conv)
- goto use_as_is;
return (size_t)-1;
}
diff --git a/source/lib/debug.c b/source/lib/debug.c
index 0050761e9a8..1a926053bb0 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -84,6 +84,13 @@ BOOL debug_warn_unknown_class = True;
BOOL debug_auto_add_unknown_class = True;
BOOL AllowDebugChange = True;
+/*
+ used to check if the user specified a
+ logfile on the command line
+*/
+BOOL override_logfile;
+
+
/*
* This is to allow assignment to DEBUGLEVEL before the debug
* system has been initialised.
diff --git a/source/lib/popt_common.c b/source/lib/popt_common.c
index 9a5a1120225..6c35213d43a 100644
--- a/source/lib/popt_common.c
+++ b/source/lib/popt_common.c
@@ -35,6 +35,7 @@
extern pstring user_socket_options;
extern BOOL AllowDebugChange;
+extern BOOL override_logfile;
struct user_auth_info cmdline_auth_info;
@@ -95,6 +96,7 @@ static void popt_common_callback(poptContext con,
if (arg) {
pstr_sprintf(logfile, "%s/log.%s", arg, pname);
lp_set_logfile(logfile);
+ override_logfile = True;
}
break;
diff --git a/source/lib/substitute.c b/source/lib/substitute.c
index 5dec9808101..fed11c22982 100644
--- a/source/lib/substitute.c
+++ b/source/lib/substitute.c
@@ -116,6 +116,11 @@ void sub_set_smb_name(const char *name)
alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1);
}
+char* sub_get_smb_name( void )
+{
+ return smb_user_name;
+}
+
/*******************************************************************
Setup the strings used by substitutions. Called per packet. Ensure
%U name is set correctly also.
diff --git a/source/lib/talloc.c b/source/lib/talloc.c
index 485dc28f31d..093a221fd3d 100644
--- a/source/lib/talloc.c
+++ b/source/lib/talloc.c
@@ -276,6 +276,24 @@ char *talloc_strdup(TALLOC_CTX *t, const char *p)
return NULL;
}
+/** strdup_upper with a talloc */
+char *talloc_strdup_upper(TALLOC_CTX *t, const char *p)
+{
+ char *r;
+ if (p) {
+ char *q = strdup_upper(p);
+ if (q) {
+ r = talloc_strdup(t, q);
+ SAFE_FREE(q);
+ return r;
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
/** strdup_w with a talloc */
smb_ucs2_t *talloc_strdup_w(TALLOC_CTX *t, const smb_ucs2_t *p)
{
diff --git a/source/lib/username.c b/source/lib/username.c
index 40327f81687..ac5530b5c71 100644
--- a/source/lib/username.c
+++ b/source/lib/username.c
@@ -283,6 +283,11 @@ struct passwd *Get_Pwnam(const char *user)
fstring user2;
struct passwd *ret;
+ if ( *user == '\0' ) {
+ DEBUG(10,("Get_Pwnam: empty username!\n"));
+ return NULL;
+ }
+
fstrcpy(user2, user);
DEBUG(5,("Finding user %s\n", user));
diff --git a/source/lib/util.c b/source/lib/util.c
index 10d224baabf..3f57048a00b 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -1411,7 +1411,7 @@ void smb_panic2(const char *why, BOOL decrement_pid_count )
for (i = 0; i < backtrace_size; i++)
DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
- SAFE_FREE(backtrace_strings);
+ /* Leak the backtrace_strings, rather than risk what free() might do */
}
#elif HAVE_LIBEXC
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index 19fb41f6ca3..845aaa4b13a 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -596,7 +596,7 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
}
/* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(buffer)) {
+ if (!srv_check_sign_mac(buffer, True)) {
DEBUG(0, ("receive_smb: SMB Signature verification failed on incoming packet!\n"));
if (smb_read_error == 0)
smb_read_error = READ_BAD_SIG;
diff --git a/source/libads/ads_struct.c b/source/libads/ads_struct.c
index 9774968e121..92f37093f46 100644
--- a/source/libads/ads_struct.c
+++ b/source/libads/ads_struct.c
@@ -102,13 +102,10 @@ ADS_STRUCT *ads_init(const char *realm,
ads->server.foreign = 1;
}
- return ads;
-}
+ /* the caller will own the memory by default */
+ ads->is_mine = 1;
-/* a simpler ads_init() interface using all defaults */
-ADS_STRUCT *ads_init_simple(void)
-{
- return ads_init(NULL, NULL, NULL);
+ return ads;
}
/*
@@ -117,6 +114,9 @@ ADS_STRUCT *ads_init_simple(void)
void ads_destroy(ADS_STRUCT **ads)
{
if (ads && *ads) {
+ BOOL is_mine;
+
+ is_mine = (*ads)->is_mine;
#if HAVE_LDAP
if ((*ads)->ld) ldap_unbind((*ads)->ld);
#endif
@@ -133,8 +133,11 @@ void ads_destroy(ADS_STRUCT **ads)
SAFE_FREE((*ads)->config.realm);
SAFE_FREE((*ads)->config.bind_path);
SAFE_FREE((*ads)->config.ldap_server_name);
-
+
+
ZERO_STRUCTP(*ads);
- SAFE_FREE(*ads);
+
+ if ( is_mine )
+ SAFE_FREE(*ads);
}
}
diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c
index bef2febaefd..70f6f3386c7 100644
--- a/source/libads/kerberos.c
+++ b/source/libads/kerberos.c
@@ -54,7 +54,7 @@ kerb_prompter(krb5_context ctx, void *data,
simulate a kinit, putting the tgt in the default cache location
remus@snapserver.com
*/
-int kerberos_kinit_password(const char *principal, const char *password, int time_offset)
+int kerberos_kinit_password(const char *principal, const char *password, int time_offset, time_t *expire_time)
{
krb5_context ctx;
krb5_error_code code = 0;
@@ -102,6 +102,9 @@ int kerberos_kinit_password(const char *principal, const char *password, int tim
return code;
}
+ if (expire_time)
+ *expire_time = (time_t) my_creds.times.endtime;
+
krb5_cc_close(ctx, cc);
krb5_free_cred_contents(ctx, &my_creds);
krb5_free_principal(ctx, me);
@@ -126,7 +129,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
return KRB5_LIBOS_CANTREADPWD;
}
- ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset);
+ ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset, &ads->auth.expire);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
@@ -136,5 +139,37 @@ int ads_kinit_password(ADS_STRUCT *ads)
return ret;
}
+int ads_kdestroy(const char *cc_name)
+{
+ krb5_error_code code;
+ krb5_context ctx;
+ krb5_ccache cc;
+
+ if ((code = krb5_init_context (&ctx))) {
+ DEBUG(3, ("ads_kdestroy: kdb5_init_context rc=%d\n", code));
+ return code;
+ }
+
+ if (!cc_name) {
+ if ((code = krb5_cc_default(ctx, &cc))) {
+ krb5_free_context(ctx);
+ return code;
+ }
+ } else {
+ if ((code = krb5_cc_resolve(ctx, cc_name, &cc))) {
+ DEBUG(3, ("ads_kdestroy: krb5_cc_resolve rc=%d\n",
+ code));
+ krb5_free_context(ctx);
+ return code;
+ }
+ }
+
+ if ((code = krb5_cc_destroy (ctx, cc))) {
+ DEBUG(3, ("ads_kdestroy: krb5_cc_destroy rc=%d\n", code));
+ }
+
+ krb5_free_context (ctx);
+ return code;
+}
#endif
diff --git a/source/libads/krb5_setpw.c b/source/libads/krb5_setpw.c
index 9cf15221a8d..16d3df83e93 100644
--- a/source/libads/krb5_setpw.c
+++ b/source/libads/krb5_setpw.c
@@ -642,7 +642,7 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
{
int ret;
- if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset))) {
+ if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL))) {
DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index e75a361e259..cdf58c5b913 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -325,7 +325,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
session_key = data_blob(NULL, 16);
SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
}
- cli_simple_set_signing(cli, session_key, nt_response, 0);
+ cli_simple_set_signing(cli, session_key, nt_response);
} else {
/* pre-encrypted password supplied. Only used for
security=server, can't do
@@ -358,7 +358,9 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user,
memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
}
p += clistr_push(cli, p, user, -1, STR_TERMINATE);
- p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
+
+ /* Upper case here might help some NTLMv2 implementations */
+ p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
cli_setup_bcc(cli, p);
@@ -521,7 +523,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *
file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
#endif
- cli_simple_set_signing(cli, session_key_krb5, null_blob, 0);
+ cli_simple_set_signing(cli, session_key_krb5, null_blob);
blob2 = cli_session_setup_blob(cli, negTokenTarg);
@@ -588,7 +590,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
/* now send that blob on its way */
if (!cli_session_setup_blob_send(cli, msg1)) {
- DEBUG(3, ("Failed to send NTLMSSP/SPENGO blob to server!\n"));
+ DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
nt_status = NT_STATUS_UNSUCCESSFUL;
} else {
data_blob_free(&msg1);
@@ -643,13 +645,16 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
cli_set_session_key(cli, ntlmssp_state->session_key);
- /* Using NTLMSSP session setup, signing on the net only starts
- * after a successful authentication and the session key has
- * been determined, but with a sequence number of 2. This
- * assumes that NTLMSSP needs exactly 2 roundtrips, for any
- * other SPNEGO mechanism it needs adapting. */
-
- cli_simple_set_signing(cli, key, null_blob, 2);
+ if (cli_simple_set_signing(cli, key, null_blob)) {
+
+ /* 'resign' the last message, so we get the right sequence numbers
+ for checking the first reply from the server */
+ cli_calculate_sign_mac(cli);
+
+ if (!cli_check_sign_mac(cli, True)) {
+ nt_status = NT_STATUS_ACCESS_DENIED;
+ }
+ }
}
/* we have a reference conter on ntlmssp_state, if we are signing
@@ -718,7 +723,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
int ret;
use_in_memory_ccache();
- ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */);
+ ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL);
if (ret){
DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
@@ -817,7 +822,7 @@ BOOL cli_session_setup(struct cli_state *cli,
if (cli->capabilities & CAP_EXTENDED_SECURITY) {
ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
if (!ADS_ERR_OK(status)) {
- DEBUG(3, ("SPENGO login failed: %s\n", ads_errstr(status)));
+ DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
return False;
}
return True;
@@ -871,7 +876,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) {
if (!lp_client_lanman_auth()) {
- DEBUG(1, ("Server requested LANMAN password but 'client use lanman auth'"
+ DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
" is disabled\n"));
return False;
}
@@ -1088,6 +1093,8 @@ BOOL cli_negprot(struct cli_state *cli)
}
cli->sign_info.negotiated_smb_signing = True;
cli->sign_info.mandatory_signing = True;
+ } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
+ cli->sign_info.negotiated_smb_signing = True;
}
} else if (cli->protocol >= PROTOCOL_LANMAN1) {
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 8542eea064d..66edc3ce38b 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -117,7 +117,7 @@ BOOL cli_receive_smb(struct cli_state *cli)
return ret;
}
- if (!cli_check_sign_mac(cli)) {
+ if (!cli_check_sign_mac(cli, True)) {
DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
cli->smb_rw_error = READ_BAD_SIG;
close(cli->fd);
diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c
index a3fa811e29f..bf7923ec788 100644
--- a/source/libsmb/clifile.c
+++ b/source/libsmb/clifile.c
@@ -1161,3 +1161,257 @@ NTSTATUS cli_raw_ioctl(struct cli_state *cli, int fnum, uint32 code, DATA_BLOB *
return NT_STATUS_OK;
}
+
+/*********************************************************
+ Set an extended attribute utility fn.
+*********************************************************/
+
+static BOOL cli_set_ea(struct cli_state *cli, uint16 setup, char *param, unsigned int param_len,
+ const char *ea_name, const char *ea_val, size_t ea_len)
+{
+ unsigned int data_len = 0;
+ char *data = NULL;
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ size_t ea_namelen = strlen(ea_name);
+
+ data_len = 4 + 4 + ea_namelen + 1 + ea_len;
+ data = malloc(data_len);
+ if (!data) {
+ return False;
+ }
+ p = data;
+ SIVAL(p,0,data_len);
+ p += 4;
+ SCVAL(p, 0, 0); /* EA flags. */
+ SCVAL(p, 1, ea_namelen);
+ SSVAL(p, 2, ea_len);
+ memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
+ memcpy(p+4+ea_namelen+1, ea_val, ea_len);
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 2, /* param, length, max */
+ data, data_len, cli->max_xmit /* data, length, max */
+ )) {
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &param_len,
+ &rdata, &data_len)) {
+ return False;
+ }
+
+ SAFE_FREE(data);
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+
+ return True;
+}
+
+/*********************************************************
+ Set an extended attribute on a pathname.
+*********************************************************/
+
+BOOL cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
+{
+ uint16 setup = TRANSACT2_SETPATHINFO;
+ unsigned int param_len = 0;
+ char param[sizeof(pstring)+6];
+ size_t srclen = 2*(strlen(path)+1);
+ char *p;
+
+ memset(param, 0, sizeof(param));
+ SSVAL(param,0,SMB_INFO_SET_EA);
+ p = &param[6];
+
+ p += clistr_push(cli, p, path, MIN(srclen, sizeof(param)-6), STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ return cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
+}
+
+/*********************************************************
+ Set an extended attribute on an fnum.
+*********************************************************/
+
+BOOL cli_set_ea_fnum(struct cli_state *cli, int fnum, const char *ea_name, const char *ea_val, size_t ea_len)
+{
+ char param[6];
+ uint16 setup = TRANSACT2_SETFILEINFO;
+
+ memset(param, 0, 6);
+ SSVAL(param,0,fnum);
+ SSVAL(param,2,SMB_INFO_SET_EA);
+
+ return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
+}
+
+/*********************************************************
+ Get an extended attribute list tility fn.
+*********************************************************/
+
+static BOOL cli_get_ea_list(struct cli_state *cli,
+ uint16 setup, char *param, unsigned int param_len,
+ TALLOC_CTX *ctx,
+ size_t *pnum_eas,
+ struct ea_struct **pea_list)
+{
+ unsigned int data_len = 0;
+ unsigned int rparam_len, rdata_len;
+ char *rparam=NULL, *rdata=NULL;
+ char *p;
+ size_t ea_size;
+ size_t num_eas;
+ BOOL ret = False;
+ struct ea_struct *ea_list;
+
+ *pnum_eas = 0;
+ *pea_list = NULL;
+
+ if (!cli_send_trans(cli, SMBtrans2,
+ NULL, /* Name */
+ -1, 0, /* fid, flags */
+ &setup, 1, 0, /* setup, length, max */
+ param, param_len, 10, /* param, length, max */
+ NULL, data_len, cli->max_xmit /* data, length, max */
+ )) {
+ return False;
+ }
+
+ if (!cli_receive_trans(cli, SMBtrans2,
+ &rparam, &rparam_len,
+ &rdata, &rdata_len)) {
+ return False;
+ }
+
+ if (!rdata || rdata_len < 4) {
+ goto out;
+ }
+
+ ea_size = (size_t)IVAL(rdata,0);
+ if (ea_size > rdata_len) {
+ goto out;
+ }
+
+ if (ea_size == 0) {
+ /* No EA's present. */
+ ret = True;
+ goto out;
+ }
+
+ p = rdata + 4;
+ ea_size -= 4;
+
+ /* Validate the EA list and count it. */
+ for (num_eas = 0; ea_size >= 4; num_eas++) {
+ unsigned int ea_namelen = CVAL(p,1);
+ unsigned int ea_valuelen = SVAL(p,2);
+ if (ea_namelen == 0) {
+ goto out;
+ }
+ if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
+ goto out;
+ }
+ ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
+ p += 4 + ea_namelen + 1 + ea_valuelen;
+ }
+
+ if (num_eas == 0) {
+ ret = True;
+ goto out;
+ }
+
+ *pnum_eas = num_eas;
+ if (!pea_list) {
+ /* Caller only wants number of EA's. */
+ ret = True;
+ goto out;
+ }
+
+ ea_list = (struct ea_struct *)talloc(ctx, num_eas*sizeof(struct ea_struct));
+ if (!ea_list) {
+ goto out;
+ }
+
+ ea_size = (size_t)IVAL(rdata,0);
+ p = rdata + 4;
+
+ for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
+ struct ea_struct *ea = &ea_list[num_eas];
+ fstring unix_ea_name;
+ unsigned int ea_namelen = CVAL(p,1);
+ unsigned int ea_valuelen = SVAL(p,2);
+
+ ea->flags = CVAL(p,0);
+ unix_ea_name[0] = '\0';
+ pull_ascii_fstring(unix_ea_name, p + 4);
+ ea->name = talloc_strdup(ctx, unix_ea_name);
+ /* Ensure the value is null terminated (in case it's a string). */
+ ea->value = data_blob_talloc(ctx, NULL, ea_valuelen + 1);
+ if (!ea->value.data) {
+ goto out;
+ }
+ if (ea_valuelen) {
+ memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
+ }
+ ea->value.data[ea_valuelen] = 0;
+ ea->value.length--;
+ p += 4 + ea_namelen + 1 + ea_valuelen;
+ }
+
+ *pea_list = ea_list;
+ ret = True;
+
+ out :
+
+ SAFE_FREE(rdata);
+ SAFE_FREE(rparam);
+ return ret;
+}
+
+/*********************************************************
+ Get an extended attribute list from a pathname.
+*********************************************************/
+
+BOOL cli_get_ea_list_path(struct cli_state *cli, const char *path,
+ TALLOC_CTX *ctx,
+ size_t *pnum_eas,
+ struct ea_struct **pea_list)
+{
+ uint16 setup = TRANSACT2_QPATHINFO;
+ unsigned int param_len = 0;
+ char param[sizeof(pstring)+6];
+ char *p;
+
+ p = param;
+ memset(p, 0, 6);
+ SSVAL(p, 0, SMB_INFO_QUERY_ALL_EAS);
+ p += 6;
+ p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
+ param_len = PTR_DIFF(p, param);
+
+ return cli_get_ea_list(cli, setup, param, param_len, ctx, pnum_eas, pea_list);
+}
+
+/*********************************************************
+ Get an extended attribute list from an fnum.
+*********************************************************/
+
+BOOL cli_get_ea_list_fnum(struct cli_state *cli, int fnum,
+ TALLOC_CTX *ctx,
+ size_t *pnum_eas,
+ struct ea_struct **pea_list)
+{
+ uint16 setup = TRANSACT2_QFILEINFO;
+ char param[6];
+
+ memset(param, 0, 6);
+ SSVAL(param,0,fnum);
+ SSVAL(param,2,SMB_INFO_SET_EA);
+
+ return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
+}
diff --git a/source/libsmb/ntlm_check.c b/source/libsmb/ntlm_check.c
index 362b640f913..a7764f9e986 100644
--- a/source/libsmb/ntlm_check.c
+++ b/source/libsmb/ntlm_check.c
@@ -85,6 +85,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response,
const uchar *part_passwd,
const DATA_BLOB *sec_blob,
const char *user, const char *domain,
+ BOOL upper_case_domain, /* should the domain be transformed into upper case? */
DATA_BLOB *user_sess_key)
{
/* Finish the encryption of part_passwd. */
@@ -122,7 +123,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response,
memcpy(client_response, ntv2_response->data, sizeof(client_response));
- if (!ntv2_owf_gen(part_passwd, user, domain, kr)) {
+ if (!ntv2_owf_gen(part_passwd, user, domain, upper_case_domain, kr)) {
return False;
}
@@ -169,6 +170,8 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
const DATA_BLOB *challenge,
const DATA_BLOB *lm_response,
const DATA_BLOB *nt_response,
+ const DATA_BLOB *lm_interactive_pwd,
+ const DATA_BLOB *nt_interactive_pwd,
const char *username,
const char *client_username,
const char *client_domain,
@@ -182,6 +185,47 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
username));
}
+ if (nt_interactive_pwd && nt_interactive_pwd->length && nt_pw) {
+ if (nt_interactive_pwd->length != 16) {
+ DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_pwd->length,
+ username));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ if (memcmp(nt_interactive_pwd->data, nt_pw, 16) == 0) {
+ if (user_sess_key) {
+ *user_sess_key = data_blob(NULL, 16);
+ SMBsesskeygen_ntv1(nt_pw, NULL, user_sess_key->data);
+ }
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(3,("ntlm_password_check: Interactive logon: NT password check failed for user %s\n",
+ username));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ } else if (lm_interactive_pwd && lm_interactive_pwd->length && lm_pw) {
+ if (lm_interactive_pwd->length != 16) {
+ DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_pwd->length,
+ username));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ if (!lp_lanman_auth()) {
+ DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n",
+ username));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+
+ if (memcmp(lm_interactive_pwd->data, lm_pw, 16) == 0) {
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n",
+ username));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
+ }
+
/* Check for cleartext netlogon. Used by Exchange 5.5. */
if (challenge->length == sizeof(zeros) &&
(memcmp(challenge->data, zeros, challenge->length) == 0 )) {
@@ -235,13 +279,24 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
if (nt_response->length >= 24 && nt_pw) {
if (nt_response->length > 24) {
/* We have the NT MD4 hash challenge available - see if we can
- use it (ie. does it exist in the smbpasswd file).
+ use it
*/
DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain));
if (smb_pwd_check_ntlmv2( nt_response,
nt_pw, challenge,
- client_username,
+ client_username,
+ client_domain,
+ False,
+ user_sess_key)) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain));
+ if (smb_pwd_check_ntlmv2( nt_response,
+ nt_pw, challenge,
+ client_username,
client_domain,
+ True,
user_sess_key)) {
return NT_STATUS_OK;
}
@@ -251,6 +306,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
nt_pw, challenge,
client_username,
"",
+ False,
user_sess_key)) {
return NT_STATUS_OK;
} else {
@@ -334,6 +390,17 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
nt_pw, challenge,
client_username,
client_domain,
+ False,
+ NULL)) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain));
+ if (smb_pwd_check_ntlmv2( lm_response,
+ nt_pw, challenge,
+ client_username,
+ client_domain,
+ True,
NULL)) {
return NT_STATUS_OK;
}
@@ -343,6 +410,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx,
nt_pw, challenge,
client_username,
"",
+ False,
NULL)) {
return NT_STATUS_OK;
}
diff --git a/source/libsmb/ntlmssp.c b/source/libsmb/ntlmssp.c
index 60523ddf9d0..ddc2e0325fd 100644
--- a/source/libsmb/ntlmssp.c
+++ b/source/libsmb/ntlmssp.c
@@ -168,7 +168,9 @@ NTSTATUS ntlmssp_set_password(NTLMSSP_STATE *ntlmssp_state, const char *password
*/
NTSTATUS ntlmssp_set_domain(NTLMSSP_STATE *ntlmssp_state, const char *domain)
{
- ntlmssp_state->domain = talloc_strdup(ntlmssp_state->mem_ctx, domain);
+ /* Possibly make our NTLMv2 client more robust by always having
+ an uppercase domain */
+ ntlmssp_state->domain = talloc_strdup_upper(ntlmssp_state->mem_ctx, domain);
if (!ntlmssp_state->domain) {
return NT_STATUS_NO_MEMORY;
}
@@ -1020,16 +1022,19 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
/* Key exchange encryptes a new client-generated session key with
the password-derived key */
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+ /* Make up a new session key */
uint8 client_session_key[16];
-
- generate_random_buffer(client_session_key, sizeof(client_session_key), False);
+ generate_random_buffer(client_session_key, sizeof(client_session_key), False);
+
+ /* Encrypt the new session key with the old one */
encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
-
SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
+ dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
+
+ /* Mark the new session key as the 'real' session key */
data_blob_free(&session_key);
session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key));
- dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
}
/* this generates the actual auth packet */
diff --git a/source/libsmb/samlogon_cache.c b/source/libsmb/samlogon_cache.c
index 72c10007bf4..4cd642c4e35 100644
--- a/source/libsmb/samlogon_cache.c
+++ b/source/libsmb/samlogon_cache.c
@@ -157,7 +157,7 @@ BOOL netsamlogon_cache_store(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user)
free the user_info struct (malloc()'d memory)
***********************************************************************/
-NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, DOM_SID *user_sid)
+NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
{
NET_USER_INFO_3 *user = NULL;
TDB_DATA data, key;
@@ -218,7 +218,7 @@ NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, DOM_SID *user_sid)
return user;
}
-BOOL netsamlogon_cache_have(DOM_SID *user_sid)
+BOOL netsamlogon_cache_have(const DOM_SID *user_sid)
{
TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
NET_USER_INFO_3 *user = NULL;
diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c
index 9010dbf5cb2..7130453c0c9 100644
--- a/source/libsmb/smb_signing.c
+++ b/source/libsmb/smb_signing.c
@@ -150,7 +150,7 @@ static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
SMB signing - NULL implementation - check a MAC sent by server.
************************************************************/
-static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
{
return True;
}
@@ -197,25 +197,39 @@ static void free_signing_context(struct smb_sign_info *si)
}
-static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq)
+static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq, BOOL must_be_ok)
{
- if (good && !si->doing_signing) {
- si->doing_signing = True;
- }
+ if (good) {
- if (!good) {
- if (si->doing_signing) {
- struct smb_basic_signing_context *data = si->signing_context;
+ if (!si->doing_signing) {
+ si->doing_signing = True;
+ }
+
+ if (!si->seen_valid) {
+ si->seen_valid = True;
+ }
- /* W2K sends a bad first signature but the sign engine is on.... JRA. */
- if (data->send_seq_num > 1)
- DEBUG(1, ("signing_good: SMB signature check failed on seq %u!\n",
- (unsigned int)seq ));
+ } else {
+ if (!si->mandatory_signing && !si->seen_valid) {
- return False;
- } else {
- DEBUG(3, ("signing_good: Peer did not sign reply correctly\n"));
+ if (!must_be_ok) {
+ return True;
+ }
+ /* Non-mandatory signing - just turn off if this is the first bad packet.. */
+ DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and peer\n"
+ "isn't sending correct signatures. Turning off.\n"));
+ si->negotiated_smb_signing = False;
+ si->allow_smb_signing = False;
+ si->doing_signing = False;
free_signing_context(si);
+ return True;
+ } else if (!must_be_ok) {
+ /* This packet is known to be unsigned */
+ return True;
+ } else {
+ /* Mandatory signing or bad packet after signing started - fail and disconnect. */
+ if (seq)
+ DEBUG(0, ("signing_good: BAD SIG: seq %u\n", (unsigned int)seq));
return False;
}
}
@@ -323,7 +337,7 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
SMB signing - Client implementation - check a MAC sent by server.
************************************************************/
-static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
{
BOOL good;
uint32 reply_seq_number;
@@ -381,7 +395,7 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
DEBUG(10, ("client_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number));
dump_data(10, (const char *)server_sent_mac, 8);
}
- return signing_good(inbuf, si, good, saved_seq);
+ return signing_good(inbuf, si, good, saved_seq, must_be_ok);
}
/***********************************************************
@@ -415,7 +429,7 @@ static void simple_free_signing_context(struct smb_sign_info *si)
BOOL cli_simple_set_signing(struct cli_state *cli,
const DATA_BLOB user_session_key,
- const DATA_BLOB response, int initial_send_seq_num)
+ const DATA_BLOB response)
{
struct smb_basic_signing_context *data;
@@ -453,7 +467,7 @@ BOOL cli_simple_set_signing(struct cli_state *cli,
dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
/* Initialise the sequence number */
- data->send_seq_num = initial_send_seq_num;
+ data->send_seq_num = 0;
/* Initialise the list of outstanding packets */
data->outstanding_packet_list = NULL;
@@ -535,7 +549,7 @@ static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
SMB signing - TEMP implementation - check a MAC sent by server.
************************************************************/
-static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL foo)
{
return True;
}
@@ -597,9 +611,9 @@ void cli_calculate_sign_mac(struct cli_state *cli)
* which had a bad checksum, True otherwise.
*/
-BOOL cli_check_sign_mac(struct cli_state *cli)
+BOOL cli_check_sign_mac(struct cli_state *cli, BOOL must_be_ok)
{
- if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info)) {
+ if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info, must_be_ok)) {
free_signing_context(&cli->sign_info);
return False;
}
@@ -688,7 +702,7 @@ static BOOL is_oplock_break(char *inbuf)
SMB signing - Server implementation - check a MAC sent by server.
************************************************************/
-static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si)
+static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si, BOOL must_be_ok)
{
BOOL good;
struct smb_basic_signing_context *data = si->signing_context;
@@ -762,25 +776,7 @@ We were expecting seq %u\n", reply_seq_number, saved_seq ));
dump_data(10, (const char *)server_sent_mac, 8);
}
- if (!signing_good(inbuf, si, good, saved_seq)) {
- if (!si->mandatory_signing && (data->send_seq_num < 3)){
- /* Non-mandatory signing - just turn off if this is the first bad packet.. */
- DEBUG(5, ("srv_check_incoming_message: signing negotiated but not required and client \
-isn't sending correct signatures. Turning off.\n"));
- si->negotiated_smb_signing = False;
- si->allow_smb_signing = False;
- si->doing_signing = False;
- free_signing_context(si);
- return True;
- } else {
- /* Mandatory signing or bad packet after signing started - fail and disconnect. */
- if (saved_seq)
- DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u\n", (unsigned int)saved_seq));
- return False;
- }
- } else {
- return True;
- }
+ return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
}
/***********************************************************
@@ -813,13 +809,13 @@ BOOL srv_oplock_set_signing(BOOL onoff)
Called to validate an incoming packet from the client.
************************************************************/
-BOOL srv_check_sign_mac(char *inbuf)
+BOOL srv_check_sign_mac(char *inbuf, BOOL must_be_ok)
{
/* Check if it's a session keepalive. */
if(CVAL(inbuf,0) == SMBkeepalive)
return True;
- return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info);
+ return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
}
/***********************************************************
@@ -907,6 +903,41 @@ BOOL srv_is_signing_active(void)
return srv_sign_info.doing_signing;
}
+
+/***********************************************************
+ Returns whether signing is negotiated. We can't use it unless it was
+ in the negprot.
+************************************************************/
+
+BOOL srv_is_signing_negotiated(void)
+{
+ return srv_sign_info.negotiated_smb_signing;
+}
+
+/***********************************************************
+ Returns whether signing is actually happening
+************************************************************/
+
+BOOL srv_signing_started(void)
+{
+ struct smb_basic_signing_context *data;
+
+ if (!srv_sign_info.doing_signing) {
+ return False;
+ }
+
+ data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
+ if (!data)
+ return False;
+
+ if (data->send_seq_num == 0) {
+ return False;
+ }
+
+ return True;
+}
+
+
/***********************************************************
Tell server code we are in a multiple trans reply state.
************************************************************/
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index c5acedae51c..270a659e57f 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -127,7 +127,9 @@ void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
/* Does both the NTLMv2 owfs of a user's password */
BOOL ntv2_owf_gen(const uchar owf[16],
- const char *user_in, const char *domain_in, uchar kr_buf[16])
+ const char *user_in, const char *domain_in,
+ BOOL upper_case_domain, /* Transform the domain into UPPER case */
+ uchar kr_buf[16])
{
smb_ucs2_t *user;
smb_ucs2_t *domain;
@@ -150,7 +152,9 @@ BOOL ntv2_owf_gen(const uchar owf[16],
}
strupper_w(user);
- strupper_w(domain);
+
+ if (upper_case_domain)
+ strupper_w(domain);
SMB_ASSERT(user_byte_len >= 2);
SMB_ASSERT(domain_byte_len >= 2);
@@ -426,7 +430,7 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
the username and domain.
This prevents username swapping during the auth exchange
*/
- if (!ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash)) {
+ if (!ntv2_owf_gen(nt_hash, user, domain, True, ntlm_v2_hash)) {
return False;
}
diff --git a/source/msdfs/msdfs.c b/source/msdfs/msdfs.c
index 2df5fcf4f5a..2ac7bda1754 100644
--- a/source/msdfs/msdfs.c
+++ b/source/msdfs/msdfs.c
@@ -481,6 +481,12 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn,
return False;
}
+ if (!lp_msdfs_root(snum)) {
+ DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n",
+ dp.servicename, pathname));
+ goto out;
+ }
+
/*
* Self referrals are tested with a anonymous IPC connection and
* a GET_DFS_REFERRAL call to \\server\share. (which means dp.reqpath[0] points
@@ -496,12 +502,6 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn,
if (!create_conn_struct(conn, snum, conn_path))
return False;
- if (!lp_msdfs_root(SNUM(conn))) {
- DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n",
- dp.servicename, pathname));
- goto out;
- }
-
if (*lp_msdfs_proxy(snum) != '\0') {
struct referral* ref;
jucn->referral_count = 1;
diff --git a/source/nsswitch/wbinfo.c b/source/nsswitch/wbinfo.c
index 772332ee592..2cea4130adc 100644
--- a/source/nsswitch/wbinfo.c
+++ b/source/nsswitch/wbinfo.c
@@ -594,6 +594,64 @@ static BOOL wbinfo_auth_crap(char *username)
return result == NSS_STATUS_SUCCESS;
}
+/* Authenticate a user with a plaintext password and set a token */
+
+static BOOL wbinfo_klog(char *username)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ NSS_STATUS result;
+ char *p;
+
+ /* Send off request */
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ p = strchr(username, '%');
+
+ if (p) {
+ *p = 0;
+ fstrcpy(request.data.auth.user, username);
+ fstrcpy(request.data.auth.pass, p + 1);
+ *p = '%';
+ } else {
+ fstrcpy(request.data.auth.user, username);
+ fstrcpy(request.data.auth.pass, getpass("Password: "));
+ }
+
+ request.flags |= WBFLAG_PAM_AFS_TOKEN;
+
+ result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response);
+
+ /* Display response */
+
+ d_printf("plaintext password authentication %s\n",
+ (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
+
+ if (response.data.auth.nt_status)
+ d_printf("error code was %s (0x%x)\nerror messsage was: %s\n",
+ response.data.auth.nt_status_string,
+ response.data.auth.nt_status,
+ response.data.auth.error_string);
+
+ if (result != NSS_STATUS_SUCCESS)
+ return False;
+
+ if (response.extra_data == NULL) {
+ d_printf("Did not get token data\n");
+ return False;
+ }
+
+ if (!afs_settoken_str((char *)response.extra_data)) {
+ d_printf("Could not set token\n");
+ return False;
+ }
+
+ d_printf("Successfully created AFS token\n");
+ return True;
+}
+
/******************************************************************
create a winbindd user
******************************************************************/
@@ -846,18 +904,19 @@ static BOOL print_domain_groups(const char *domain)
static BOOL wbinfo_set_auth_user(char *username)
{
- char *password;
+ const char *password;
+ char *p;
fstring user, domain;
/* Separate into user and password */
parse_wbinfo_domain_user(username, domain, user);
- password = strchr(user, '%');
+ p = strchr(user, '%');
- if (password) {
- *password = 0;
- password++;
+ if (p != NULL) {
+ *p = 0;
+ password = p+1;
} else {
char *thepass = getpass("Password: ");
if (thepass) {
@@ -1000,6 +1059,9 @@ int main(int argc, char **argv)
{ "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL },
{ "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
{ "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
+#ifdef WITH_FAKE_KASERVER
+ { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
+#endif
POPT_COMMON_VERSION
POPT_TABLEEND
};
@@ -1159,6 +1221,12 @@ int main(int argc, char **argv)
goto done;
break;
}
+ case 'k':
+ if (!wbinfo_klog(string_arg)) {
+ d_printf("Could not klog user\n");
+ goto done;
+ }
+ break;
case 'c':
if ( !wbinfo_create_user(string_arg) ) {
d_printf("Could not create user account\n");
diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h
index 7c8e6256e15..0087d58195d 100644
--- a/source/nsswitch/winbindd.h
+++ b/source/nsswitch/winbindd.h
@@ -162,7 +162,7 @@ struct winbindd_methods {
/* lookup user info for a given SID */
NTSTATUS (*query_user)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
WINBIND_USERINFO *user_info);
/* lookup all groups that a user is a member of. The backend
@@ -170,13 +170,13 @@ struct winbindd_methods {
function */
NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
uint32 *num_groups, DOM_SID ***user_gids);
/* find all members of the group with the specified group_rid */
NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *group_sid,
+ const DOM_SID *group_sid,
uint32 *num_names,
DOM_SID ***sid_mem, char ***names,
uint32 **name_types);
diff --git a/source/nsswitch/winbindd_ads.c b/source/nsswitch/winbindd_ads.c
index e6b857f4061..cd8b8e0e246 100644
--- a/source/nsswitch/winbindd_ads.c
+++ b/source/nsswitch/winbindd_ads.c
@@ -5,6 +5,7 @@
Copyright (C) Andrew Tridgell 2001
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
+ Copyright (C) Gerald (Jerry) Carter 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -39,7 +40,22 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
ADS_STATUS status;
if (domain->private) {
- return (ADS_STRUCT *)domain->private;
+ ads = (ADS_STRUCT *)domain->private;
+
+ /* check for a valid structure */
+
+ DEBUG(7, ("Current tickets expire at %d\n, time is now %d\n",
+ (uint32) ads->auth.expire, (uint32) time(NULL)));
+ if ( ads->config.realm && (ads->auth.expire > time(NULL))) {
+ return ads;
+ }
+ else {
+ /* we own this ADS_STRUCT so make sure it goes away */
+ ads->is_mine = True;
+ ads_destroy( &ads );
+ ads_kdestroy("MEMORY:winbind_ccache");
+ domain->private = NULL;
+ }
}
/* we don't want this to affect the users ccache */
@@ -79,6 +95,12 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
return NULL;
}
+ /* set the flag that says we don't own the memory even
+ though we do so that ads_destroy() won't destroy the
+ structure we pass back by reference */
+
+ ads->is_mine = False;
+
domain->private = (void *)ads;
return ads;
}
@@ -390,7 +412,7 @@ failed:
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
+ const DOM_SID *sid,
WINBIND_USERINFO *info)
{
ADS_STRUCT *ads = NULL;
@@ -561,7 +583,7 @@ done:
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
+ const DOM_SID *sid,
uint32 *num_groups, DOM_SID ***user_gids)
{
ADS_STRUCT *ads = NULL;
@@ -659,7 +681,7 @@ done:
*/
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *group_sid, uint32 *num_names,
+ const DOM_SID *group_sid, uint32 *num_names,
DOM_SID ***sid_mem, char ***names,
uint32 **name_types)
{
diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c
index 91834e476fc..73918d74f7d 100644
--- a/source/nsswitch/winbindd_cache.c
+++ b/source/nsswitch/winbindd_cache.c
@@ -339,10 +339,12 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
get_cache( domain );
+#if 0 /* JERRY -- disable as the default cache time is now 5 minutes */
/* trying to reconnect is expensive, don't do it too often */
if (domain->sequence_number == DOM_SEQUENCE_NONE) {
cache_time *= 8;
}
+#endif
time_diff = t - domain->last_seq_check;
@@ -1039,7 +1041,7 @@ do_query:
/* Lookup user information from a rid */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
WINBIND_USERINFO *info)
{
struct winbind_cache *cache = get_cache(domain);
@@ -1102,7 +1104,7 @@ do_query:
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
uint32 *num_groups, DOM_SID ***user_gids)
{
struct winbind_cache *cache = get_cache(domain);
@@ -1185,7 +1187,7 @@ skip_save:
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *group_sid, uint32 *num_names,
+ const DOM_SID *group_sid, uint32 *num_names,
DOM_SID ***sid_mem, char ***names,
uint32 **name_types)
{
diff --git a/source/nsswitch/winbindd_nss.h b/source/nsswitch/winbindd_nss.h
index 0d110b8afa8..c8fe5c826c1 100644
--- a/source/nsswitch/winbindd_nss.h
+++ b/source/nsswitch/winbindd_nss.h
@@ -156,6 +156,7 @@ typedef struct winbindd_gr {
#define WBFLAG_QUERY_ONLY 0x0020
#define WBFLAG_ALLOCATE_RID 0x0040
#define WBFLAG_PAM_UNIX_NAME 0x0080
+#define WBFLAG_PAM_AFS_TOKEN 0x0100
/* Winbind request structure */
diff --git a/source/nsswitch/winbindd_pam.c b/source/nsswitch/winbindd_pam.c
index 37b2a9f21b7..1d232edfe31 100644
--- a/source/nsswitch/winbindd_pam.c
+++ b/source/nsswitch/winbindd_pam.c
@@ -211,6 +211,41 @@ done:
state->response.data.auth.nt_status_string,
state->response.data.auth.pam_error));
+ if ( NT_STATUS_IS_OK(result) &&
+ (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) {
+
+ char *afsname = strdup(lp_afs_username_map());
+ char *cell;
+
+ if (afsname == NULL) goto no_token;
+
+ afsname = realloc_string_sub(afsname, "%D", name_domain);
+ afsname = realloc_string_sub(afsname, "%u", name_user);
+ afsname = realloc_string_sub(afsname, "%U", name_user);
+
+ if (afsname == NULL) goto no_token;
+
+ strlower_m(afsname);
+
+ cell = strchr(afsname, '@');
+
+ if (cell == NULL) goto no_token;
+
+ *cell = '\0';
+ cell += 1;
+
+ /* Append an AFS token string */
+ state->response.extra_data =
+ afs_createtoken_str(afsname, cell);
+
+ if (state->response.extra_data != NULL)
+ state->response.length +=
+ strlen(state->response.extra_data)+1;
+
+ no_token:
+ SAFE_FREE(afsname);
+ }
+
if (mem_ctx)
talloc_destroy(mem_ctx);
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index d4428a2f59c..25d5f64df67 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -366,7 +366,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
/* Lookup user information from a rid or username. */
static NTSTATUS query_user(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
WINBIND_USERINFO *user_info)
{
CLI_POLICY_HND *hnd = NULL;
@@ -465,7 +465,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
/* Lookup groups a user is a member of. I wish Unix had a call like this! */
static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *user_sid,
+ const DOM_SID *user_sid,
uint32 *num_groups, DOM_SID ***user_grpsids)
{
CLI_POLICY_HND *hnd;
@@ -571,7 +571,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
/* Lookup group membership given a rid. */
static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- DOM_SID *group_sid, uint32 *num_names,
+ const DOM_SID *group_sid, uint32 *num_names,
DOM_SID ***sid_mem, char ***names,
uint32 **name_types)
{
diff --git a/source/nsswitch/winbindd_wins.c b/source/nsswitch/winbindd_wins.c
index bc982d00443..a1eef159c0a 100644
--- a/source/nsswitch/winbindd_wins.c
+++ b/source/nsswitch/winbindd_wins.c
@@ -201,7 +201,10 @@ enum winbindd_result winbindd_wins_byname(struct winbindd_cli_state *state)
}
if (i != 0) {
/* Clear out the newline character */
- response[strlen(response)-1] = ' ';
+ /* But only if there is something in there,
+ otherwise we clobber something in the stack */
+ if (strlen(response))
+ response[strlen(response)-1] = ' ';
}
fstrcat(response,addr);
fstrcat(response,"\t");
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index af26697476a..6b09faf7bf9 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -280,7 +280,6 @@ typedef struct
BOOL bDebugPid;
BOOL bDebugUid;
BOOL bHostMSDfs;
- BOOL bUnicode;
BOOL bUseMmap;
BOOL bHostnameLookups;
BOOL bUnixExtensions;
@@ -380,6 +379,7 @@ typedef struct
BOOL bMap_system;
BOOL bMap_hidden;
BOOL bMap_archive;
+ BOOL bStoreDosAttributes;
BOOL bLocking;
BOOL bStrictLocking;
BOOL bPosixLocking;
@@ -413,6 +413,7 @@ typedef struct
BOOL bProfileAcls;
BOOL bMap_acl_inherit;
BOOL bAfs_Share;
+ BOOL bEASupport;
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
@@ -501,6 +502,7 @@ static service sDefault = {
False, /* bMap_system */
False, /* bMap_hidden */
True, /* bMap_archive */
+ False, /* bStoreDosAttributes */
True, /* bLocking */
True, /* bStrictLocking */
True, /* bPosixLocking */
@@ -534,6 +536,7 @@ static service sDefault = {
False, /* bProfileAcls */
False, /* bMap_acl_inherit */
False, /* bAfs_Share */
+ False, /* bEASupport */
NULL, /* Parametric options */
@@ -880,13 +883,13 @@ static struct parm_struct parm_table[] = {
{"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED},
{"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED},
{"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_ADVANCED},
- {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_ADVANCED},
{"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, FLAG_ADVANCED},
{"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},
{"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
+ {"ea support", P_BOOL, P_LOCAL, &sDefault.bEASupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED},
{"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED},
@@ -993,6 +996,7 @@ static struct parm_struct parm_table[] = {
{"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED },
{"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED},
+ {"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{N_("Domain Options"), P_SEP, P_SEPARATOR},
@@ -1420,7 +1424,6 @@ static void init_globals(void)
Globals.bPamPasswordChange = False;
Globals.bPasswdChatDebug = False;
Globals.iPasswdChatTimeout = 2; /* 2 second default. */
- Globals.bUnicode = True; /* Do unicode on the wire by default */
Globals.bNTPipeSupport = True; /* Do NT pipes by default. */
Globals.bNTStatusSupport = True; /* Use NT status by default. */
Globals.bStatCache = True; /* use stat cache by default */
@@ -1735,7 +1738,6 @@ FN_GLOBAL_BOOL(lp_pam_password_change, &Globals.bPamPasswordChange)
FN_GLOBAL_BOOL(lp_unix_password_sync, &Globals.bUnixPasswdSync)
FN_GLOBAL_BOOL(lp_passwd_chat_debug, &Globals.bPasswdChatDebug)
FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout)
-FN_GLOBAL_BOOL(lp_unicode, &Globals.bUnicode)
FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport)
FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport)
FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache)
@@ -1845,6 +1847,7 @@ FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
+FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
FN_LOCAL_BOOL(lp_locking, bLocking)
FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)
@@ -1872,6 +1875,7 @@ FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
+FN_LOCAL_BOOL(lp_ea_support, bEASupport)
FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile)
FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit)
@@ -2657,7 +2661,16 @@ static void add_to_file_list(const char *fname, const char *subfname)
BOOL lp_file_list_changed(void)
{
struct file_lists *f = file_lists;
- DEBUG(6, ("lp_file_list_changed()\n"));
+ char *username;
+
+ DEBUG(6, ("lp_file_list_changed()\n"));
+
+ /* get the username for substituion -- preference to the current_user_info */
+ if ( strlen( current_user_info.smb_name ) != 0 )
+ username = current_user_info.smb_name;
+ else
+ username = sub_get_smb_name();
+
while (f) {
pstring n2;
@@ -3806,9 +3819,18 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
pstring n2;
BOOL bRetval;
param_opt_struct *data, *pdata;
+ char *username;
pstrcpy(n2, pszFname);
- standard_sub_basic(current_user_info.smb_name, n2,sizeof(n2));
+
+ /* get the username for substituion -- preference to the current_user_info */
+
+ if ( strlen( current_user_info.smb_name ) != 0 )
+ username = current_user_info.smb_name;
+ else
+ username = sub_get_smb_name();
+
+ standard_sub_basic( username, n2,sizeof(n2) );
add_to_file_list(pszFname, n2);
diff --git a/source/passdb/lookup_sid.c b/source/passdb/lookup_sid.c
index 83d2cd28ac6..842db8de5dc 100644
--- a/source/passdb/lookup_sid.c
+++ b/source/passdb/lookup_sid.c
@@ -66,7 +66,7 @@ BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_N
Tries local lookup first - for local sids, then tries winbind.
*****************************************************************/
-BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
+BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
{
if (!name_type)
return False;
diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c
index 7c9376e045a..04e41b79707 100644
--- a/source/passdb/passdb.c
+++ b/source/passdb/passdb.c
@@ -704,7 +704,7 @@ BOOL fallback_pdb_rid_is_user(uint32 rid)
Convert a rid into a name. Used in the lookup SID rpc.
********************************************************************/
-BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use)
+BOOL local_lookup_sid(const DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use)
{
uint32 rid;
SAM_ACCOUNT *sam_account = NULL;
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 2141f2a3f1c..689c7010418 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -407,7 +407,7 @@ static time_t ldapsam_get_entry_timestamp(
strptime(temp, "%Y%m%d%H%M%SZ", &tm);
tzset();
- return (mktime(&tm) - timezone);
+ return timegm(&tm);
}
/**********************************************************************
@@ -539,28 +539,6 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
return False;
}
-
-#if 0 /* JERRY -- not used anymore */
- /*
- * If so configured, try and get the values from LDAP
- */
-
- if (lp_ldap_trust_ids() && (get_unix_attributes(ldap_state, sampass, entry, &gid)))
- {
- if (pdb_get_init_flags(sampass,PDB_GROUPSID) == PDB_DEFAULT)
- {
- GROUP_MAP map;
- /* call the mapping code here */
- if(pdb_getgrgid(&map, gid)) {
- pdb_set_group_sid(sampass, &map.sid, PDB_SET);
- }
- else {
- pdb_set_group_sid_from_rid(sampass, pdb_gid_to_group_rid(gid), PDB_SET);
- }
- }
- }
-#endif
-
if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) {
/* leave as default */
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index a0649d0a0b7..449b0e83edc 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -992,7 +992,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
fsp = open_file_shared(conn, filepath, &stat_buf,
SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* Old file not found, so by definition new file is in fact newer */
DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
@@ -1021,7 +1021,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
fsp = open_file_shared(conn, filepath, &stat_buf,
SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* New file not found, this shouldn't occur if the caller did its job */
DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
@@ -1137,7 +1137,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
fsp = open_file_shared(conn, driverpath, &st,
SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
driverpath, errno));
@@ -3292,7 +3292,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sh
info.parameters);
/* Samba has to have shared raw drivers. */
- info.attributes |= PRINTER_ATTRIBUTE_SAMBA;
+ info.attributes = PRINTER_ATTRIBUTE_SAMBA;
/* Restore the stripped strings. */
slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
diff --git a/source/python/setup.py b/source/python/setup.py
index a9f220f195a..4a4f6ad3f81 100755
--- a/source/python/setup.py
+++ b/source/python/setup.py
@@ -57,6 +57,9 @@ for lib in string.split(samba_libs):
if lib[0:2] == "-L":
library_dirs.append(lib[2:])
continue
+ if lib[0:2] == "-W":
+ # Skip linker flags
+ continue
print "Unknown entry '%s' in $LIBS variable passed to setup.py" % lib
sys.exit(1)
diff --git a/source/rpc_client/cli_netlogon.c b/source/rpc_client/cli_netlogon.c
index 70ac4603034..f6d88a19501 100644
--- a/source/rpc_client/cli_netlogon.c
+++ b/source/rpc_client/cli_netlogon.c
@@ -331,6 +331,55 @@ NTSTATUS cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
+/* GetDCName */
+
+NTSTATUS cli_netlogon_getdcname(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ const char *domainname, fstring dcname)
+{
+ prs_struct qbuf, rbuf;
+ NET_Q_GETDCNAME q;
+ NET_R_GETDCNAME r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ /* Initialise parse structures */
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+ /* Initialise input parameters */
+
+ init_net_q_getdcname(&q, cli->srv_name_slash, domainname);
+
+ /* Marshall data and send request */
+
+ if (!net_io_q_getdcname("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, NET_GETDCNAME, &qbuf, &rbuf)) {
+ result = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* Unmarshall response */
+
+ if (!net_io_r_getdcname("", &r, &rbuf, 0)) {
+ result = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ result = r.status;
+
+ if (NT_STATUS_IS_OK(result))
+ rpcstr_pull_unistr2_fstring(dcname, &r.uni_dcname);
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
/****************************************************************************
Generate the next creds to use.
****************************************************************************/
diff --git a/source/rpc_client/cli_pipe.c b/source/rpc_client/cli_pipe.c
index 82a4b21754e..df0d37a4631 100644
--- a/source/rpc_client/cli_pipe.c
+++ b/source/rpc_client/cli_pipe.c
@@ -1221,8 +1221,6 @@ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *
static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
{
- int i = 0;
-
# if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
if ( hdr_ba->addr.len <= 0)
return False;
@@ -1455,6 +1453,7 @@ BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx)
DEBUG(0,("cli_nt_session_open: pipe hnd state failed. Error was %s\n",
cli_errstr(cli)));
cli_close(cli, cli->nt_pipe_fnum);
+ cli->nt_pipe_fnum = 0;
return False;
}
}
@@ -1465,6 +1464,7 @@ BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx)
DEBUG(2,("cli_nt_session_open: rpc bind to %s failed\n",
get_pipe_name_from_index(pipe_idx)));
cli_close(cli, cli->nt_pipe_fnum);
+ cli->nt_pipe_fnum = 0;
return False;
}
diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c
index 90cd348f5a8..a98738b51f0 100644
--- a/source/rpc_parse/parse_net.c
+++ b/source/rpc_parse/parse_net.c
@@ -425,6 +425,90 @@ BOOL net_io_r_logon_ctrl(const char *desc, NET_R_LOGON_CTRL *r_l, prs_struct *ps
}
/*******************************************************************
+ Inits an NET_R_GETDCNAME structure.
+********************************************************************/
+void init_net_q_getdcname(NET_Q_GETDCNAME *r_t, const char *logon_server,
+ const char *domainname)
+{
+ DEBUG(5,("init_r_getdcname\n"));
+
+ r_t->ptr_logon_server = (logon_server != NULL);
+ init_unistr2(&r_t->uni_logon_server, logon_server, UNI_STR_TERMINATE);
+ r_t->ptr_domainname = (domainname != NULL);
+ init_unistr2(&r_t->uni_domainname, domainname, UNI_STR_TERMINATE);
+}
+
+/*******************************************************************
+ Reads or writes an NET_Q_GETDCNAME structure.
+********************************************************************/
+
+BOOL net_io_q_getdcname(const char *desc, NET_Q_GETDCNAME *r_t, prs_struct *ps,
+ int depth)
+{
+ if (r_t == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "net_io_q_getdcname");
+ depth++;
+
+ if (!prs_uint32("ptr_logon_server", ps, depth, &r_t->ptr_logon_server))
+ return False;
+
+ if (!smb_io_unistr2("logon_server", &r_t->uni_logon_server,
+ r_t->ptr_logon_server, ps, depth))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("ptr_domainname", ps, depth, &r_t->ptr_domainname))
+ return False;
+
+ if (!smb_io_unistr2("domainname", &r_t->uni_domainname,
+ r_t->ptr_domainname, ps, depth))
+ return False;
+
+ return True;
+}
+
+
+/*******************************************************************
+ Inits an NET_R_GETDCNAME structure.
+********************************************************************/
+void init_net_r_getdcname(NET_R_GETDCNAME *r_t, const char *dcname)
+{
+ DEBUG(5,("init_r_getdcname\n"));
+
+ init_unistr2(&r_t->uni_dcname, dcname, UNI_STR_TERMINATE);
+}
+
+/*******************************************************************
+ Reads or writes an NET_R_GETDCNAME structure.
+********************************************************************/
+
+BOOL net_io_r_getdcname(const char *desc, NET_R_GETDCNAME *r_t, prs_struct *ps,
+ int depth)
+{
+ if (r_t == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "net_io_r_getdcname");
+ depth++;
+
+ if (!prs_uint32("ptr_dcname", ps, depth, &r_t->ptr_dcname))
+ return False;
+
+ if (!smb_io_unistr2("dcname", &r_t->uni_dcname,
+ r_t->ptr_dcname, ps, depth))
+ return False;
+
+ if (!prs_ntstatus("status", ps, depth, &r_t->status))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
Inits an NET_R_TRUST_DOM_LIST structure.
********************************************************************/
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index 75813167676..ae087c7f774 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -2561,7 +2561,7 @@ BOOL smb_io_printer_info_2(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2
return False;
/* parse the sec_desc */
- if (has_secdesc) {
+ if (info->secdesc) {
if (!prs_set_offset(ps, sd_offset))
return False;
if (!smb_io_relsecdesc("secdesc", buffer, depth, &info->secdesc))
diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c
index 40d3a43bef9..77b9be99660 100644
--- a/source/rpc_server/srv_srvsvc_nt.c
+++ b/source/rpc_server/srv_srvsvc_nt.c
@@ -1887,13 +1887,13 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
unix_convert(filename, conn, NULL, &bad_path, &st);
fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDONLY),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* Perhaps it is a directory */
if (errno == EISDIR)
fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
if (!fsp) {
DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
@@ -1991,13 +1991,13 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
unix_convert(filename, conn, NULL, &bad_path, &st);
fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDWR),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* Perhaps it is a directory */
if (errno == EISDIR)
fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
if (!fsp) {
DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));
diff --git a/source/rpc_server/srv_util.c b/source/rpc_server/srv_util.c
index 504e6a83c00..5bb8db4e062 100644
--- a/source/rpc_server/srv_util.c
+++ b/source/rpc_server/srv_util.c
@@ -149,7 +149,11 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui
for (i=0;i<num_groups;i++) {
- if (!get_group_from_gid(groups[i], &map)) {
+ become_root();
+ ret = get_group_from_gid(groups[i], &map);
+ unbecome_root();
+
+ if ( !ret ) {
DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i]));
continue;
}
diff --git a/source/rpcclient/cmd_netlogon.c b/source/rpcclient/cmd_netlogon.c
index a48b59bf6a3..9e281fefce4 100644
--- a/source/rpcclient/cmd_netlogon.c
+++ b/source/rpcclient/cmd_netlogon.c
@@ -45,6 +45,31 @@ static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli,
return result;
}
+static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx, int argc,
+ const char **argv)
+{
+ fstring dcname;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s domainname\n", argv[0]);
+ return NT_STATUS_OK;
+ }
+
+ result = cli_netlogon_getdcname(cli, mem_ctx, argv[1], dcname);
+
+ if (!NT_STATUS_IS_OK(result))
+ goto done;
+
+ /* Display results */
+
+ printf("%s\n", dcname);
+
+ done:
+ return result;
+}
+
static NTSTATUS cmd_netlogon_logon_ctrl(struct cli_state *cli,
TALLOC_CTX *mem_ctx, int argc,
const char **argv)
@@ -309,6 +334,7 @@ struct cmd_set netlogon_commands[] = {
{ "NETLOGON" },
{ "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, "Logon Control 2", "" },
+ { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, "Get trusted DC name", "" },
{ "logonctrl", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl, NULL, PI_NETLOGON, "Logon Control", "" },
{ "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, PI_NETLOGON, "Sam Synchronisation", "" },
{ "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, PI_NETLOGON, "Query Sam Deltas", "" },
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index bbd79e16597..06ef23ab8cd 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -707,7 +707,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
if(S_ISDIR(pst->st_mode))
fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- unix_mode(conn,aRONLY|aDIR, name), &smb_action);
+ &smb_action);
else
fsp = open_file_stat(conn, name, pst);
@@ -763,7 +763,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
return True;
else
fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp)
return False;
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index fb72a2eafc8..d7dc63bb2fd 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -21,8 +21,8 @@
#include "includes.h"
/****************************************************************************
- change a dos mode to a unix mode
- base permission for files:
+ Change a dos mode to a unix mode.
+ Base permission for files:
if inheriting
apply read/write bits from parent directory.
else
@@ -35,92 +35,91 @@
Then apply create mask,
then add force bits.
}
- base permission for directories:
+ Base permission for directories:
dos directory is represented in unix by unix's dir bit and the exec bit
if !inheriting {
Then apply create mask,
then add force bits.
}
****************************************************************************/
-mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname)
+
+mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname)
{
- mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
- mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */
-
- if ( !IS_DOS_READONLY(dosmode) )
- result |= (S_IWUSR | S_IWGRP | S_IWOTH);
-
- if (fname && lp_inherit_perms(SNUM(conn))) {
- char *dname;
- SMB_STRUCT_STAT sbuf;
-
- dname = parent_dirname(fname);
- DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname));
- if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) {
- DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno)));
- return(0); /* *** shouldn't happen! *** */
- }
-
- /* Save for later - but explicitly remove setuid bit for safety. */
- dir_mode = sbuf.st_mode & ~S_ISUID;
- DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
- /* Clear "result" */
- result = 0;
- }
-
- if (IS_DOS_DIR(dosmode)) {
- /* We never make directories read only for the owner as under DOS a user
- can always create a file in a read-only directory. */
- result |= (S_IFDIR | S_IWUSR);
-
- if (dir_mode) {
- /* Inherit mode of parent directory. */
- result |= dir_mode;
- } else {
- /* Provisionally add all 'x' bits */
- result |= (S_IXUSR | S_IXGRP | S_IXOTH);
-
- /* Apply directory mask */
- result &= lp_dir_mask(SNUM(conn));
- /* Add in force bits */
- result |= lp_force_dir_mode(SNUM(conn));
- }
- } else {
- if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
- result |= S_IXUSR;
-
- if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
- result |= S_IXGRP;
+ mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
+ mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */
+
+ if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
+ result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+ }
+
+ if (fname && lp_inherit_perms(SNUM(conn))) {
+ char *dname;
+ SMB_STRUCT_STAT sbuf;
+
+ dname = parent_dirname(fname);
+ DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname));
+ if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) {
+ DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno)));
+ return(0); /* *** shouldn't happen! *** */
+ }
+
+ /* Save for later - but explicitly remove setuid bit for safety. */
+ dir_mode = sbuf.st_mode & ~S_ISUID;
+ DEBUG(2,("unix_mode(%s) inherit mode %o\n",fname,(int)dir_mode));
+ /* Clear "result" */
+ result = 0;
+ }
+
+ if (IS_DOS_DIR(dosmode)) {
+ /* We never make directories read only for the owner as under DOS a user
+ can always create a file in a read-only directory. */
+ result |= (S_IFDIR | S_IWUSR);
+
+ if (dir_mode) {
+ /* Inherit mode of parent directory. */
+ result |= dir_mode;
+ } else {
+ /* Provisionally add all 'x' bits */
+ result |= (S_IXUSR | S_IXGRP | S_IXOTH);
+
+ /* Apply directory mask */
+ result &= lp_dir_mask(SNUM(conn));
+ /* Add in force bits */
+ result |= lp_force_dir_mode(SNUM(conn));
+ }
+ } else {
+ if (lp_map_archive(SNUM(conn)) && IS_DOS_ARCHIVE(dosmode))
+ result |= S_IXUSR;
+
+ if (lp_map_system(SNUM(conn)) && IS_DOS_SYSTEM(dosmode))
+ result |= S_IXGRP;
- if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
- result |= S_IXOTH;
-
- if (dir_mode) {
- /* Inherit 666 component of parent directory mode */
- result |= dir_mode
- & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
- } else {
- /* Apply mode mask */
- result &= lp_create_mask(SNUM(conn));
- /* Add in force bits */
- result |= lp_force_create_mode(SNUM(conn));
- }
- }
-
- DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
- return(result);
-}
+ if (lp_map_hidden(SNUM(conn)) && IS_DOS_HIDDEN(dosmode))
+ result |= S_IXOTH;
+
+ if (dir_mode) {
+ /* Inherit 666 component of parent directory mode */
+ result |= dir_mode & (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
+ } else {
+ /* Apply mode mask */
+ result &= lp_create_mask(SNUM(conn));
+ /* Add in force bits */
+ result |= lp_force_create_mode(SNUM(conn));
+ }
+ }
+ DEBUG(3,("unix_mode(%s) returning 0%o\n",fname,(int)result ));
+ return(result);
+}
/****************************************************************************
- change a unix mode to a dos mode
+ Change a unix mode to a dos mode.
****************************************************************************/
-uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
+
+uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf)
{
int result = 0;
- DEBUG(8,("dos_mode: %s\n", path));
-
if ((sbuf->st_mode & S_IWUSR) == 0)
result |= aRONLY;
@@ -149,9 +148,142 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
#endif
#endif
+ DEBUG(8,("dos_mode_from_sbuf returning "));
+
+ if (result & aHIDDEN) DEBUG(8, ("h"));
+ if (result & aRONLY ) DEBUG(8, ("r"));
+ if (result & aSYSTEM) DEBUG(8, ("s"));
+ if (result & aDIR ) DEBUG(8, ("d"));
+ if (result & aARCH ) DEBUG(8, ("a"));
+
+ DEBUG(8,("\n"));
+ return result;
+}
+
+/****************************************************************************
+ Get DOS attributes from an EA.
+****************************************************************************/
+
+static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
+{
+ ssize_t sizeret;
+ fstring attrstr;
+ unsigned int dosattr;
+
+ if (!lp_store_dos_attributes(SNUM(conn))) {
+ return False;
+ }
+
+ *pattr = 0;
+
+ sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
+ if (sizeret == -1) {
+#if defined(ENOTSUP) && defined(ENOATTR)
+ if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) {
+ DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
+ path, strerror(errno) ));
+ }
+#endif
+ return False;
+ }
+ /* Null terminate string. */
+ attrstr[sizeret] = 0;
+ DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
+
+ if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
+ sscanf(attrstr, "%x", &dosattr) != 1) {
+ DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
+ return False;
+ }
+
+ if (S_ISDIR(sbuf->st_mode)) {
+ dosattr |= aDIR;
+ }
+ *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
+
+ DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
+
+ if (dosattr & aHIDDEN) DEBUG(8, ("h"));
+ if (dosattr & aRONLY ) DEBUG(8, ("r"));
+ if (dosattr & aSYSTEM) DEBUG(8, ("s"));
+ if (dosattr & aDIR ) DEBUG(8, ("d"));
+ if (dosattr & aARCH ) DEBUG(8, ("a"));
+
+ DEBUG(8,("\n"));
+
+ return True;
+}
+
+/****************************************************************************
+ Set DOS attributes in an EA.
+****************************************************************************/
+
+static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
+{
+ fstring attrstr;
+ files_struct *fsp = NULL;
+ BOOL ret = False;
+
+ snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
+ if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
+ if((errno != EPERM) && (errno != EACCES)) {
+ return False;
+ }
+
+ /* We want DOS semantics, ie allow non owner with write permission to change the
+ bits on a file. Just like file_utime below.
+ */
+
+ /* Check if we have write access. */
+ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
+ return False;
+
+ /*
+ * We need to open the file with write access whilst
+ * still in our current user context. This ensures we
+ * are not violating security in doing the setxattr.
+ */
+
+ fsp = open_file_fchmod(conn,path,sbuf);
+ if (!fsp)
+ return ret;
+ become_root();
+ if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
+ ret = True;
+ }
+ unbecome_root();
+ close_file_fchmod(fsp);
+ return ret;
+ }
+ DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
+ return True;
+}
+
+/****************************************************************************
+ Change a unix mode to a dos mode.
+****************************************************************************/
+
+uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
+{
+ uint32 result = 0;
+
+ DEBUG(8,("dos_mode: %s\n", path));
+
+ if (!VALID_STAT(*sbuf)) {
+ return 0;
+ }
+
+ /* Get the DOS attributes from an EA by preference. */
+ if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
+ return result;
+ }
+
+ result = dos_mode_from_sbuf(conn, sbuf);
+
+ /* Now do any modifications that depend on the path name. */
/* hide files with a name starting with a . */
if (lp_hide_dot_files(SNUM(conn))) {
- char *p = strrchr_m(path,'/');
+ const char *p = strrchr_m(path,'/');
if (p)
p++;
else
@@ -181,10 +313,10 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
}
/*******************************************************************
-chmod a file - but preserve some bits
+ chmod a file - but preserve some bits.
********************************************************************/
-int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st)
+int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st)
{
SMB_STRUCT_STAT st1;
int mask=0;
@@ -192,6 +324,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST
mode_t unixmode;
int ret = -1;
+ DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
if (!st) {
st = &st1;
if (SMB_VFS_STAT(conn,fname,st))
@@ -208,6 +341,11 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST
if (dos_mode(conn,fname,st) == dosmode)
return(0);
+ /* Store the DOS attributes in an EA by preference. */
+ if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
+ return 0;
+ }
+
unixmode = unix_mode(conn,dosmode,fname);
/* preserve the s bits */
@@ -275,70 +413,71 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST
return( ret );
}
-
/*******************************************************************
-Wrapper around dos_utime that possibly allows DOS semantics rather
-than POSIX.
+ Wrapper around dos_utime that possibly allows DOS semantics rather
+ than POSIX.
*******************************************************************/
+
int file_utime(connection_struct *conn, char *fname, struct utimbuf *times)
{
- extern struct current_user current_user;
- SMB_STRUCT_STAT sb;
- int ret = -1;
-
- errno = 0;
-
- if(SMB_VFS_UTIME(conn,fname, times) == 0)
- return 0;
-
- if((errno != EPERM) && (errno != EACCES))
- return -1;
-
- if(!lp_dos_filetimes(SNUM(conn)))
- return -1;
-
- /* We have permission (given by the Samba admin) to
- break POSIX semantics and allow a user to change
- the time on a file they don't own but can write to
- (as DOS does).
- */
-
- if(SMB_VFS_STAT(conn,fname,&sb) != 0)
- return -1;
-
- /* Check if we have write access. */
- if (CAN_WRITE(conn)) {
- if (((sb.st_mode & S_IWOTH) ||
- conn->admin_user ||
- ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
- ((sb.st_mode & S_IWGRP) &&
- in_group(sb.st_gid,current_user.gid,
- current_user.ngroups,current_user.groups)))) {
- /* We are allowed to become root and change the filetime. */
- become_root();
- ret = SMB_VFS_UTIME(conn,fname, times);
- unbecome_root();
- }
- }
-
- return ret;
+ extern struct current_user current_user;
+ SMB_STRUCT_STAT sb;
+ int ret = -1;
+
+ errno = 0;
+
+ if(SMB_VFS_UTIME(conn,fname, times) == 0)
+ return 0;
+
+ if((errno != EPERM) && (errno != EACCES))
+ return -1;
+
+ if(!lp_dos_filetimes(SNUM(conn)))
+ return -1;
+
+ /* We have permission (given by the Samba admin) to
+ break POSIX semantics and allow a user to change
+ the time on a file they don't own but can write to
+ (as DOS does).
+ */
+
+ if(SMB_VFS_STAT(conn,fname,&sb) != 0)
+ return -1;
+
+ /* Check if we have write access. */
+ if (CAN_WRITE(conn)) {
+ if (((sb.st_mode & S_IWOTH) || conn->admin_user ||
+ ((sb.st_mode & S_IWUSR) && current_user.uid==sb.st_uid) ||
+ ((sb.st_mode & S_IWGRP) &&
+ in_group(sb.st_gid,current_user.gid,
+ current_user.ngroups,current_user.groups)))) {
+ /* We are allowed to become root and change the filetime. */
+ become_root();
+ ret = SMB_VFS_UTIME(conn,fname, times);
+ unbecome_root();
+ }
+ }
+
+ return ret;
}
/*******************************************************************
-Change a filetime - possibly allowing DOS semantics.
+ Change a filetime - possibly allowing DOS semantics.
*******************************************************************/
+
BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime)
{
- struct utimbuf times;
+ struct utimbuf times;
- if (null_mtime(mtime)) return(True);
+ if (null_mtime(mtime))
+ return(True);
- times.modtime = times.actime = mtime;
+ times.modtime = times.actime = mtime;
- if (file_utime(conn, fname, &times)) {
- DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
- return False;
- }
+ if (file_utime(conn, fname, &times)) {
+ DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
+ return False;
+ }
- return(True);
+ return(True);
}
diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c
index 86d78e039a1..5ccb548ba5b 100644
--- a/source/smbd/fake_file.c
+++ b/source/smbd/fake_file.c
@@ -26,7 +26,7 @@
files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname,
SMB_STRUCT_STAT *psbuf,
uint32 desired_access,
- int share_mode,int ofun, mode_t mode,int oplock_request,
+ int share_mode,int ofun, uint32 new_dos_attr, int oplock_request,
int *Access,int *action)
{
extern struct current_user current_user;
@@ -35,7 +35,7 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect
if (fake_file_type == 0) {
return open_file_shared1(conn,fname,psbuf,desired_access,
- share_mode,ofun,mode,
+ share_mode,ofun,new_dos_attr,
oplock_request,Access,action);
}
@@ -51,8 +51,8 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect
if(!fsp)
return NULL;
- DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
- fname, fsp->fnum, share_mode, ofun, (int)mode, oplock_request ));
+ DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n",
+ fname, fsp->fnum, share_mode, ofun, oplock_request ));
if (!check_name(fname,conn)) {
file_free(fsp);
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index 3462a3b9fa5..c2fb6e34566 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -176,8 +176,9 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) {
int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
fsp->size = (SMB_BIG_UINT)st.st_size;
- if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode))
- file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
+ if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) {
+ file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
+ }
/*
* If this is the first write and we have an exclusive oplock then setup
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index 96961368fb1..1843c174bb5 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -251,7 +251,7 @@ static int reply_nt1(char *inbuf, char *outbuf)
capabilities |= CAP_EXTENDED_SECURITY;
}
- capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
+ capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
if (lp_unix_extensions()) {
capabilities |= CAP_UNIX;
@@ -266,10 +266,6 @@ static int reply_nt1(char *inbuf, char *outbuf)
if (lp_readraw() && lp_writeraw())
capabilities |= CAP_RAW_MODE;
- /* allow for disabling unicode */
- if (lp_unicode())
- capabilities |= CAP_UNICODE;
-
if (lp_nt_status_support())
capabilities |= CAP_STATUS32;
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 21b6db8b469..c9cc44627db 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -586,11 +586,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
- int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
/* Breakout the oplock request bits so we can set the
reply bits separately. */
int oplock_request = 0;
- mode_t unixmode;
int fmode=0,rmode=0;
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
@@ -766,8 +764,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -781,7 +777,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
restore_case_semantics(file_attributes);
@@ -811,14 +807,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
fsp = open_file_shared1(conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun,file_attributes,oplock_request,
&rmode,&smb_action);
} else {
/* to open a fake_file --metze */
fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun,file_attributes, oplock_request,
&rmode,&smb_action);
}
@@ -857,7 +853,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
restore_case_semantics(file_attributes);
@@ -1134,7 +1130,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
char *data = *ppdata;
/* Breakout the oplock request bits so we can set the reply bits separately. */
int oplock_request = 0;
- mode_t unixmode;
int fmode=0,rmode=0;
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
@@ -1154,7 +1149,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
- int smb_attr;
time_t c_time;
NTSTATUS status;
@@ -1192,7 +1186,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
create_options = IVAL(params,32);
sd_len = IVAL(params,36);
root_dir_fid = (uint16)IVAL(params,4);
- smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
if (create_options & FILE_OPEN_BY_FILE_ID) {
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
@@ -1297,8 +1290,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -1318,7 +1309,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* CreateDirectory() call.
*/
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
restore_case_semantics(file_attributes);
@@ -1332,7 +1323,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
*/
fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
- smb_open_mode,smb_ofun,unixmode,
+ smb_open_mode,smb_ofun,file_attributes,
oplock_request,&rmode,&smb_action);
if (!fsp) {
@@ -1350,7 +1341,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
restore_case_semantics(file_attributes);
diff --git a/source/smbd/open.c b/source/smbd/open.c
index e688f8de485..8ab5dab6ac9 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -741,20 +741,10 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
}
-static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode,
- mode_t new_mode, mode_t *returned_mode)
+static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode,
+ mode_t existing_mode, mode_t new_mode, mode_t *returned_mode)
{
- uint32 old_dos_mode, new_dos_mode;
uint32 noarch_old_dos_mode, noarch_new_dos_mode;
- SMB_STRUCT_STAT sbuf;
-
- ZERO_STRUCT(sbuf);
-
- sbuf.st_mode = existing_mode;
- old_dos_mode = dos_mode(conn, path, &sbuf);
-
- sbuf.st_mode = new_mode;
- new_dos_mode = dos_mode(conn, path, &sbuf);
noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE);
noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE);
@@ -770,11 +760,11 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex
old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode ));
/* If we're mapping SYSTEM and HIDDEN ensure they match. */
- if (lp_map_system(SNUM(conn))) {
+ if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM))
return False;
}
- if (lp_map_hidden(SNUM(conn))) {
+ if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN))
return False;
}
@@ -786,10 +776,10 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex
****************************************************************************/
files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
- int share_mode,int ofun, mode_t mode,int oplock_request,
+ int share_mode,int ofun, uint32 new_dos_mode, int oplock_request,
int *Access,int *action)
{
- return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode,
+ return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode,
oplock_request, Access, action);
}
@@ -799,8 +789,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
uint32 desired_access,
- int share_mode,int ofun, mode_t mode,int oplock_request,
- int *Access,int *action)
+ int share_mode,int ofun, uint32 new_dos_mode,
+ int oplock_request,
+ int *Access,int *paction)
{
int flags=0;
int flags2=0;
@@ -819,6 +810,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
int open_mode=0;
uint16 port = 0;
mode_t new_mode = (mode_t)0;
+ int action;
+ uint32 existing_dos_mode = 0;
+ /* We add aARCH to this as this mode is only used if the file is created new. */
+ mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname);
if (conn->printer) {
/* printers are handled completely differently. Most of the passed parameters are
@@ -826,7 +821,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
if (Access)
*Access = DOS_OPEN_WRONLY;
if (action)
- *action = FILE_WAS_CREATED;
+ *paction = FILE_WAS_CREATED;
return print_fsp_open(conn, fname);
}
@@ -834,14 +829,19 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
if(!fsp)
return NULL;
- DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
- fname, share_mode, ofun, (int)mode, oplock_request ));
+ DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
+ fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request ));
if (!check_name(fname,conn)) {
file_free(fsp);
return NULL;
}
+ new_dos_mode &= SAMBA_ATTRIBUTES_MASK;
+ if (file_existed) {
+ existing_dos_mode = dos_mode(conn, fname, psbuf);
+ }
+
/* ignore any oplock requests if oplocks are disabled */
if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) {
oplock_request = 0;
@@ -882,9 +882,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
/* We only care about matching attributes on file exists and truncate. */
if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) {
- if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) {
- DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n",
- fname, (int)psbuf->st_mode, (int)mode ));
+ if (!open_match_attributes(conn, fname, existing_dos_mode, new_dos_mode,
+ psbuf->st_mode, mode, &new_mode)) {
+ DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n",
+ fname, existing_dos_mode, new_dos_mode,
+ (int)psbuf->st_mode, (int)mode ));
file_free(fsp);
errno = EACCES;
return NULL;
@@ -928,7 +930,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
#endif /* O_SYNC */
if (flags != O_RDONLY && file_existed &&
- (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) {
+ (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) {
if (!fcbopen) {
DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n",
fname, !CAN_WRITE(conn) ? "share" : "file" ));
@@ -1119,16 +1121,19 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode ));
- if (Access)
+ if (Access) {
(*Access) = open_mode;
+ }
- if (action) {
- if (file_existed && !(flags2 & O_TRUNC))
- *action = FILE_WAS_OPENED;
- if (!file_existed)
- *action = FILE_WAS_CREATED;
- if (file_existed && (flags2 & O_TRUNC))
- *action = FILE_WAS_OVERWRITTEN;
+ if (file_existed && !(flags2 & O_TRUNC))
+ action = FILE_WAS_OPENED;
+ if (file_existed && (flags2 & O_TRUNC))
+ action = FILE_WAS_OVERWRITTEN;
+ if (!file_existed)
+ action = FILE_WAS_CREATED;
+
+ if (paction) {
+ *paction = action;
}
/*
@@ -1163,6 +1168,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
}
}
+ if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) {
+ /* Files should be initially set as archive */
+ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
+ file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL);
+ }
+ }
+
/*
* Take care of inherited ACLs on created files - if default ACL not
* selected.
@@ -1256,7 +1268,7 @@ int close_file_fchmod(files_struct *fsp)
****************************************************************************/
files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf,
- uint32 desired_access, int share_mode, int smb_ofun, mode_t unixmode, int *action)
+ uint32 desired_access, int share_mode, int smb_ofun, int *action)
{
extern struct current_user current_user;
BOOL got_stat = False;
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 10c6aadb1fc..ef5d0a97ac7 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -269,10 +269,14 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
vuser->homes_snum = -1;
}
- if (lp_server_signing() && !vuser->guest && !srv_is_signing_active()) {
+ if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) {
/* Try and turn on server signing on the first non-guest sessionsetup. */
srv_set_signing(vuser->session_key, response_blob);
}
+
+ /* fill in the current_user_info struct */
+ set_current_user_info( &vuser->user );
+
return vuser->vuid;
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 8033c694f5d..620e123e14d 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -57,8 +57,6 @@ typedef struct canon_ace {
* +------+------+-------------+---------------------+-------------+--------------------+
*/
-#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
-
#define PAI_VERSION_OFFSET 0
#define PAI_FLAG_OFFSET 1
#define PAI_NUM_ENTRIES_OFFSET 2
@@ -3183,7 +3181,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
the mask bits, not the real group bits, for a file with an ACL.
****************************************************************************/
-int get_acl_group_bits( connection_struct *conn, char *fname, mode_t *mode )
+int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
{
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index f5c4f25e408..ac239c7e042 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -61,6 +61,10 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
while (IS_DIRECTORY_SEP(*s)) {
s++;
}
+ if ((s[0] == '.') && (s[1] == '\0')) {
+ ret = NT_STATUS_OBJECT_NAME_INVALID;
+ break;
+ }
if ((d != destname) && (*s != '\0')) {
/* We only care about non-leading or trailing '/' or '\\' */
*d++ = '/';
@@ -84,7 +88,8 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
}
/* Are we at the start ? Can't go back further if so. */
if (d == destname) {
- return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ break;
}
/* Go back one level... */
/* We know this is safe as '/' cannot be part of a mb sequence. */
@@ -95,7 +100,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
d--;
}
s += 3;
- } else if ((s[0] == '.') && IS_DIRECTORY_SEP(s[1])) {
+ } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
/*
* No mb char starts with '.' so we're safe checking the directory separator here.
@@ -105,11 +110,14 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
if (s == srcname) {
ret = NT_STATUS_OBJECT_NAME_INVALID;
+ break;
} else {
- if (s[2] == '\0') {
- return NT_STATUS_INVALID_PARAMETER;
+ if (s[1] != '\0' && s[2] == '\0') {
+ ret = NT_STATUS_INVALID_PARAMETER;
+ break;
}
ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ break;
}
s++;
} else {
@@ -128,6 +136,7 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
break;
default:
DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
+ *d = '\0';
return NT_STATUS_INVALID_PARAMETER;
}
}
@@ -678,8 +687,9 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
else
mode &= ~aDIR;
- if (check_name(fname,conn))
- ok = (file_chmod(conn,fname,mode,NULL) == 0);
+ if (check_name(fname,conn)) {
+ ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
+ }
} else {
ok = True;
}
@@ -1008,12 +1018,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int share_mode;
SMB_OFF_T size = 0;
time_t mtime=0;
- mode_t unixmode;
int rmode=0;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+ uint16 dos_attr = SVAL(inbuf,smb_vwv1);
NTSTATUS status;
START_PROFILE(SMBopen);
@@ -1029,10 +1039,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,aARCH,fname);
-
fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- unixmode, oplock_request,&rmode,NULL);
+ (uint32)dos_attr, oplock_request,&rmode,NULL);
if (!fsp) {
END_PROFILE(SMBopen);
@@ -1089,7 +1097,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
- mode_t unixmode;
SMB_OFF_T size=0;
int fmode=0,mtime=0,rmode=0;
SMB_STRUCT_STAT sbuf;
@@ -1121,9 +1128,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
- fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
+ fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
oplock_request, &rmode,&smb_action);
if (!fsp) {
@@ -1215,7 +1220,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int com;
int outsize = 0;
int createmode;
- mode_t unixmode;
int ofun = 0;
BOOL bad_path = False;
files_struct *fsp;
@@ -1240,8 +1244,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
if (createmode & aVOLID)
DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
- unixmode = unix_mode(conn,createmode,fname);
-
if(com == SMBmknew) {
/* We should fail if file exists. */
ofun = FILE_CREATE_IF_NOT_EXIST;
@@ -1252,7 +1254,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* Open file in dos compatibility share mode. */
fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- ofun, unixmode, oplock_request, NULL, NULL);
+ ofun, (uint32)createmode, oplock_request, NULL, NULL);
if (!fsp) {
END_PROFILE(SMBcreate);
@@ -1269,7 +1271,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
DEBUG( 2, ( "new file %s\n", fname ) );
- DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
+ DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
END_PROFILE(SMBcreate);
return(outsize);
@@ -1283,8 +1285,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
{
pstring fname;
int outsize = 0;
- int createmode;
- mode_t unixmode;
+ int createattr;
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
@@ -1292,23 +1293,26 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SMB_STRUCT_STAT sbuf;
char *p, *s;
NTSTATUS status;
+ unsigned int namelen;
START_PROFILE(SMBctemp);
- createmode = SVAL(inbuf,smb_vwv0);
+ createattr = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
return ERROR_NT(status);
}
- pstrcat(fname,"\\TMXXXXXX");
+ if (*fname) {
+ pstrcat(fname,"/TMXXXXXX");
+ } else {
+ pstrcat(fname,"TMXXXXXX");
+ }
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,createmode,fname);
-
tmpfd = smb_mkstemp(fname);
if (tmpfd == -1) {
END_PROFILE(SMBctemp);
@@ -1322,7 +1326,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
fsp = open_file_shared(conn,fname,&sbuf,
SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
- unixmode, oplock_request, NULL, NULL);
+ (uint32)createattr, oplock_request, NULL, NULL);
/* close fd from smb_mkstemp() */
close(tmpfd);
@@ -1343,10 +1347,13 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
s++;
p = smb_buf(outbuf);
+#if 0
+ /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
+ thing in the byte section. JRA */
SSVALS(p, 0, -1); /* what is this? not in spec */
- SSVAL(p, 2, strlen(s));
- p += 4;
- p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
+#endif
+ namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
+ p += namelen;
outsize = set_message_end(outbuf, p);
if (oplock_request && lp_fake_oplocks(SNUM(conn)))
@@ -1356,8 +1363,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
DEBUG( 2, ( "created temp file %s\n", fname ) );
- DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
- fname, fsp->fd, createmode, (int)unixmode ) );
+ DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
+ fname, fsp->fd, sbuf.st_mode ) );
END_PROFILE(SMBctemp);
return(outsize);
@@ -1384,7 +1391,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT
unix_ERR_code = 0;
fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp) {
NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
@@ -1449,7 +1456,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO
unix_ERR_code = 0;
fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp) {
NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
@@ -1568,13 +1575,14 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
if (sys_direntry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
- continue;
+ break;
}
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
error = can_delete(fname,conn,dirtype,bad_path);
- if (!NT_STATUS_IS_OK(error))
+ if (!NT_STATUS_IS_OK(error)) {
continue;
+ }
if (SMB_VFS_UNLINK(conn,fname) == 0)
count++;
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
@@ -3401,6 +3409,9 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
if (*p2 == '?') {
*p2 = *p;
p2++;
+ } else if (*p2 == '*') {
+ pstrcpy(p2, p);
+ break;
} else {
p2++;
}
@@ -3414,6 +3425,9 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
if (*p2 == '?') {
*p2 = *p;
p2++;
+ } else if (*p2 == '*') {
+ pstrcpy(p2, p);
+ break;
} else {
p2++;
}
@@ -3830,7 +3844,7 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
if (sysdir_entry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
- continue;
+ break;
}
error = NT_STATUS_ACCESS_DENIED;
@@ -3853,6 +3867,14 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
continue;
}
+ if (strcsequal(fname,destname)) {
+ rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
+ DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
+ count++;
+ error = NT_STATUS_OK;
+ continue;
+ }
+
if (!replace_if_exists &&
vfs_file_exist(conn,destname, NULL)) {
DEBUG(6,("file_exist %s\n", destname));
@@ -3949,7 +3971,8 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
pstring dest;
-
+ uint32 dosattrs;
+
*err_ret = 0;
pstrcpy(dest,dest1);
@@ -3967,7 +3990,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
return(False);
fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
if (!fsp1)
return(False);
@@ -3975,11 +3998,12 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
if (!target_is_directory && count)
ofun = FILE_EXISTS_OPEN;
+ dosattrs = dos_mode(conn, src, &src_sbuf);
if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
ZERO_STRUCTP(&sbuf2);
fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
- ofun,src_sbuf.st_mode,0,&Access,&action);
+ ofun,dosattrs,0,&Access,&action);
if (!fsp2) {
close_file(fsp1,False);
diff --git a/source/smbd/server.c b/source/smbd/server.c
index 1de33739b24..53d07fd905c 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -249,7 +249,10 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
/* ready to listen */
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,user_socket_options);
-
+
+ /* Set server socket to non-blocking for the accept. */
+ set_blocking(s,False);
+
if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
DEBUG(0,("listen: %s\n",strerror(errno)));
close(s);
@@ -286,6 +289,9 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,user_socket_options);
+ /* Set server socket to non-blocking for the accept. */
+ set_blocking(s,False);
+
if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
DEBUG(0,("open_sockets_smbd: listen: %s\n",
strerror(errno)));
@@ -378,6 +384,9 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
continue;
}
+ /* Ensure child is set to blocking mode */
+ set_blocking(smbd_server_fd(),True);
+
if (smbd_server_fd() != -1 && interactive)
return True;
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index d91aa947286..b8777be6971 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -282,6 +282,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (sess_vuid == -1) {
ret = NT_STATUS_LOGON_FAILURE;
} else {
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
+
set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
@@ -291,14 +294,14 @@ static int reply_spnego_kerberos(connection_struct *conn,
SSVAL(outbuf, smb_uid, sess_vuid);
- if (!server_info->guest) {
+ if (!server_info->guest && !srv_signing_started()) {
/* We need to start the signing engine
* here but a W2K client sends the old
* "BSRSPYL " signature instead of the
* correct one. Subsequent packets will
* be correct.
*/
- srv_check_sign_mac(inbuf);
+ srv_check_sign_mac(inbuf, False);
}
}
@@ -355,6 +358,9 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
nt_status = NT_STATUS_LOGON_FAILURE;
} else {
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
+
set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
@@ -364,14 +370,15 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
SSVAL(outbuf,smb_uid,sess_vuid);
- if (!server_info->guest) {
+ if (!server_info->guest && !srv_signing_started()) {
/* We need to start the signing engine
* here but a W2K client sends the old
* "BSRSPYL " signature instead of the
* correct one. Subsequent packets will
* be correct.
*/
- srv_check_sign_mac(inbuf);
+
+ srv_check_sign_mac(inbuf, False);
}
}
}
@@ -911,7 +918,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- if (!server_info->guest && !srv_check_sign_mac(inbuf)) {
+ /* current_user_info is changed on new vuid */
+ reload_services( True );
+
+ if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
exit_server("reply_sesssetup_and_X: bad smb signature");
}
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 2f164dafa28..a88722edde5 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -50,6 +50,325 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
}
/****************************************************************************
+ Utility functions for dealing with extended attributes.
+****************************************************************************/
+
+static const char *prohibited_ea_names[] = {
+ SAMBA_POSIX_INHERITANCE_EA_NAME,
+ SAMBA_XATTR_DOS_ATTRIB,
+ NULL
+};
+
+/****************************************************************************
+ Refuse to allow clients to overwrite our private xattrs.
+****************************************************************************/
+
+static BOOL samba_private_attr_name(const char *unix_ea_name)
+{
+ int i;
+
+ for (i = 0; prohibited_ea_names[i]; i++) {
+ if (strequal( prohibited_ea_names[i], unix_ea_name))
+ return True;
+ }
+ return False;
+}
+
+struct ea_list {
+ struct ea_list *next, *prev;
+ struct ea_struct ea;
+};
+
+/****************************************************************************
+ Get one EA value. Fill in a struct ea_struct.
+****************************************************************************/
+
+static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
+ const char *fname, char *ea_name, struct ea_struct *pea)
+{
+ /* Get the value of this xattr. Max size is 64k. */
+ size_t attr_size = 256;
+ char *val = NULL;
+ ssize_t sizeret;
+
+ again:
+
+ val = talloc_realloc(mem_ctx, val, attr_size);
+ if (!val) {
+ return False;
+ }
+
+ if (fsp && fsp->fd != -1) {
+ sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
+ } else {
+ sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
+ }
+
+ if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
+ attr_size = 65536;
+ goto again;
+ }
+
+ if (sizeret == -1) {
+ return False;
+ }
+
+ DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
+ dump_data(10, val, sizeret);
+
+ pea->flags = 0;
+ if (strnequal(ea_name, "user.", 5)) {
+ pea->name = &ea_name[5];
+ } else {
+ pea->name = ea_name;
+ }
+ pea->value.data = val;
+ pea->value.length = (size_t)sizeret;
+ return True;
+}
+
+/****************************************************************************
+ Return a linked list of the total EA's. Plus a guess as to the total size
+ (NB. The is not the total size on the wire - we need to convert to DOS
+ codepage for that).
+****************************************************************************/
+
+static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
+{
+ /* Get a list of all xattrs. Max namesize is 64k. */
+ size_t ea_namelist_size = 1024;
+ char *ea_namelist;
+ char *p;
+ ssize_t sizeret;
+ int i;
+ struct ea_list *ea_list_head = NULL;
+
+ if (pea_total_len) {
+ *pea_total_len = 0;
+ }
+
+ if (!lp_ea_support(SNUM(conn))) {
+ return NULL;
+ }
+
+ for (i = 0, ea_namelist = talloc(mem_ctx, ea_namelist_size); i < 6;
+ ea_namelist = talloc_realloc(mem_ctx, ea_namelist, ea_namelist_size), i++) {
+ if (fsp && fsp->fd != -1) {
+ sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
+ } else {
+ sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
+ }
+
+ if (sizeret == -1 && errno == ERANGE) {
+ ea_namelist_size *= 2;
+ } else {
+ break;
+ }
+ }
+
+ if (sizeret == -1)
+ return NULL;
+
+ DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
+
+ if (sizeret) {
+ for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
+ struct ea_list *listp, *tmp;
+
+ if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
+ continue;
+
+ listp = talloc(mem_ctx, sizeof(struct ea_list));
+ if (!listp)
+ return NULL;
+
+ if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
+ return NULL;
+ }
+
+ if (pea_total_len) {
+ *pea_total_len += 4 + strlen(p) + 1 + listp->ea.value.length;
+ }
+ DLIST_ADD_END(ea_list_head, listp, tmp);
+ }
+ }
+
+ /* Add on 4 for total length. */
+ if (pea_total_len) {
+ *pea_total_len += 4;
+ }
+ return ea_list_head;
+}
+
+/****************************************************************************
+ Fill a qfilepathinfo buffer with EA's.
+****************************************************************************/
+
+static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
+ connection_struct *conn, files_struct *fsp, const char *fname)
+{
+ unsigned int ret_data_size = 4;
+ char *p = pdata;
+ size_t total_ea_len;
+ TALLOC_CTX *mem_ctx = talloc_init("fill_ea_buffer");
+ struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
+
+ SMB_ASSERT(total_data_size >= 4);
+
+ SIVAL(pdata,0,0);
+ if (!mem_ctx) {
+ return 4;
+ }
+
+ if (!ea_list) {
+ talloc_destroy(mem_ctx);
+ return 4;
+ }
+
+ if (total_ea_len > total_data_size) {
+ talloc_destroy(mem_ctx);
+ return 4;
+ }
+
+ total_data_size -= 4;
+ for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
+ size_t dos_namelen;
+ fstring dos_ea_name;
+ push_ascii_fstring(dos_ea_name, ea_list->ea.name);
+ dos_namelen = strlen(dos_ea_name);
+ if (dos_namelen > 255 || dos_namelen == 0) {
+ break;
+ }
+ if (ea_list->ea.value.length > 65535) {
+ break;
+ }
+ if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
+ break;
+ }
+
+ /* We know we have room. */
+ SCVAL(p,0,ea_list->ea.flags);
+ SCVAL(p,1,dos_namelen);
+ SSVAL(p,2,ea_list->ea.value.length);
+ fstrcpy(p+4, dos_ea_name);
+ memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
+
+ total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
+ p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
+ }
+
+ ret_data_size = PTR_DIFF(p, pdata);
+ talloc_destroy(mem_ctx);
+ SIVAL(pdata,0,ret_data_size);
+ return ret_data_size;
+}
+
+static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
+{
+ size_t total_ea_len = 0;
+ TALLOC_CTX *mem_ctx = talloc_init("estimate_ea_size");
+
+ (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
+ talloc_destroy(mem_ctx);
+ return total_ea_len;
+}
+
+/****************************************************************************
+ Set or delete an extended attribute.
+****************************************************************************/
+
+static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
+ char *pdata, int total_data)
+{
+ unsigned int namelen;
+ unsigned int ealen;
+ int ret;
+ fstring unix_ea_name;
+
+ if (!lp_ea_support(SNUM(conn))) {
+ return NT_STATUS_EAS_NOT_SUPPORTED;
+ }
+
+ if (total_data < 8) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (IVAL(pdata,0) > total_data) {
+ DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ pdata += 4;
+ namelen = CVAL(pdata,1);
+ ealen = SVAL(pdata,2);
+ pdata += 4;
+ if (total_data < 8 + namelen + 1 + ealen) {
+ DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
+ (unsigned int)total_data, namelen, ealen));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (pdata[namelen] != '\0') {
+ DEBUG(10,("set_ea: ea name not null terminated\n"));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
+ pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
+ pdata += (namelen + 1);
+
+ DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
+ if (ealen) {
+ DEBUG(10,("set_ea: data :\n"));
+ dump_data(10, pdata, ealen);
+ }
+
+ if (samba_private_attr_name(unix_ea_name)) {
+ DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (ealen == 0) {
+ /* Remove the attribute. */
+ if (fsp && (fsp->fd != -1)) {
+ DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
+ unix_ea_name, fsp->fsp_name));
+ ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
+ } else {
+ DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
+ unix_ea_name, fname));
+ ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
+ }
+#ifdef ENOATTR
+ /* Removing a non existent attribute always succeeds. */
+ DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
+ if (ret == -1 && errno == ENOATTR) {
+ ret = 0;
+ }
+#endif
+ } else {
+ if (fsp && (fsp->fd != -1)) {
+ DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
+ unix_ea_name, fsp->fsp_name));
+ ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
+ } else {
+ DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
+ unix_ea_name, fname));
+ ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
+ }
+ }
+
+ if (ret == -1) {
+ if (errno == ENOTSUP) {
+ return NT_STATUS_EAS_NOT_SUPPORTED;
+ }
+ return map_nt_error_from_unix(errno);
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
Send the required number of replies back.
We assume all fields other than the data fields are
set correctly for the type of call.
@@ -220,7 +539,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
int32 open_size;
char *pname;
pstring fname;
- mode_t unixmode;
SMB_OFF_T size=0;
int fmode=0,mtime=0,rmode;
SMB_INO_T inode = 0;
@@ -268,9 +586,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
- unixmode = unix_mode(conn,open_attr | aARCH, fname);
-
- fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
+ fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
oplock_request, &rmode,&smb_action);
if (!fsp) {
@@ -2048,8 +2364,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
break;
case SMB_INFO_QUERY_ALL_EAS:
- data_size = 4;
- SIVAL(pdata,0,0); /* ea size */
+ /* We have data_size bytes to put EA's into. */
+ data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
break;
case SMB_FILE_BASIC_INFORMATION:
@@ -2095,8 +2411,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
case SMB_FILE_EA_INFORMATION:
case SMB_QUERY_FILE_EA_INFO:
+ {
+ unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
data_size = 4;
+ SIVAL(pdata,0,ea_size);
break;
+ }
/* Get the 8.3 name - used if NT SMB was negotiated. */
case SMB_QUERY_FILE_ALT_NAME_INFO:
@@ -2703,7 +3023,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
}
case SMB_INFO_SET_EA:
- return(ERROR_DOS(ERRDOS,ERReasnotsupported));
+ status = set_ea(conn, fsp, fname, pdata, total_data);
+ if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
+ return ERROR_NT(status);
+ break;
/* XXXX um, i don't think this is right.
it's also not in the cifs6.txt spec.
@@ -2808,7 +3131,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL,
+ 0, &access_mode, &action);
if (new_fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadpath));
@@ -3203,8 +3527,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
- if(file_chmod(conn, fname, dosmode, NULL)) {
- DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
+ if(file_set_dosmode(conn, fname, dosmode, NULL)) {
+ DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
}
@@ -3234,7 +3558,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
new_fsp = open_file_shared(conn, fname, &sbuf,
SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL,
+ 0, &access_mode, &action);
if (new_fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadpath));
diff --git a/source/tdb/spinlock.c b/source/tdb/spinlock.c
index 3b3ebefded3..24c4371decc 100644
--- a/source/tdb/spinlock.c
+++ b/source/tdb/spinlock.c
@@ -1,21 +1,27 @@
/*
Unix SMB/CIFS implementation.
- Samba database functions
+
+ trivial database library
+
Copyright (C) Anton Blanchard 2001
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if HAVE_CONFIG_H
#include <config.h>
diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c
index 7b10cfb3777..cda9fc24750 100644
--- a/source/tdb/tdb.c
+++ b/source/tdb/tdb.c
@@ -1,24 +1,29 @@
/*
Unix SMB/CIFS implementation.
- Samba database functions
- Copyright (C) Andrew Tridgell 1999-2000
- Copyright (C) Luke Kenneth Casson Leighton 2000
+
+ trivial database library
+
+ Copyright (C) Andrew Tridgell 1999-2004
Copyright (C) Paul `Rusty' Russell 2000
Copyright (C) Jeremy Allison 2000-2003
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -1299,7 +1304,7 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock,
if fn is NULL then it is not called
a non-zero return value from fn() indicates that the traversal should stop
*/
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state)
+int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *private)
{
TDB_DATA key, dbuf;
struct list_struct rec;
@@ -1337,7 +1342,7 @@ int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state)
ret = -1;
goto out;
}
- if (fn && fn(tdb, key, dbuf, state)) {
+ if (fn && fn(tdb, key, dbuf, private)) {
/* They want us to terminate traversal */
ret = count;
if (unlock_record(tdb, tl.off) != 0) {
@@ -1486,9 +1491,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
/* first try in-place update, on modify or replace. */
if (tdb_update_hash(tdb, key, hash, dbuf) == 0)
goto out;
- if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST)
+ if (tdb->ecode == TDB_ERR_NOEXIST &&
+ flag == TDB_MODIFY) {
+ /* if the record doesn't exist and we are in TDB_MODIFY mode then
+ we should fail the store */
goto fail;
}
+ }
/* reset the error code potentially set by the tdb_update() */
tdb->ecode = TDB_SUCCESS;
@@ -1510,9 +1519,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
if (dbuf.dsize)
memcpy(p+key.dsize, dbuf.dptr, dbuf.dsize);
- /* now we're into insert / modify / replace of a record which
- * we know could not be optimised by an in-place store (for
- * various reasons). */
+ /* we have to allocate some space */
if (!(rec_ptr = tdb_allocate(tdb, key.dsize + dbuf.dsize, &rec)))
goto fail;
diff --git a/source/tdb/tdb.h b/source/tdb/tdb.h
index 6f3b1ff7562..eb120a8cecd 100644
--- a/source/tdb/tdb.h
+++ b/source/tdb/tdb.h
@@ -3,22 +3,28 @@
/*
Unix SMB/CIFS implementation.
- Samba database functions
- Copyright (C) Andrew Tridgell 1999
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ trivial database library
- This program is distributed in the hope that it will be useful,
+ Copyright (C) Andrew Tridgell 1999-2004
+
+ ** NOTE! The following LGPL license applies to the tdb
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __cplusplus
@@ -44,7 +50,8 @@ extern "C" {
/* error codes */
enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
- TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT };
+ TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
+ TDB_ERR_NOEXIST};
#ifndef u32
#define u32 unsigned
@@ -119,7 +126,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf);
int tdb_close(TDB_CONTEXT *tdb);
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
-int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state);
+int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *);
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]);
void tdb_unlockkeys(TDB_CONTEXT *tdb);
diff --git a/source/torture/torture.c b/source/torture/torture.c
index 07d568e8795..17a2ee00a8d 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -4310,8 +4310,114 @@ BOOL torture_chkpath_test(int dummy)
return ret;
}
+static BOOL run_eatest(int dummy)
+{
+ static struct cli_state *cli;
+ const char *fname = "\\eatest.txt";
+ BOOL correct = True;
+ int fnum, i;
+ size_t num_eas;
+ struct ea_struct *ea_list = NULL;
+ TALLOC_CTX *mem_ctx = talloc_init("eatest");
+
+ printf("starting eatest\n");
+
+ if (!torture_open_connection(&cli)) {
+ return False;
+ }
+
+ cli_unlink(cli, fname);
+ fnum = cli_nt_create_full(cli, fname, 0,
+ FIRST_DESIRED_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
+ FILE_SHARE_NONE, FILE_OVERWRITE_IF,
+ 0x4044, 0);
+
+ if (fnum == -1) {
+ printf("open failed - %s\n", cli_errstr(cli));
+ return False;
+ }
+
+ for (i = 0; i < 10; i++) {
+ fstring ea_name, ea_val;
+
+ slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
+ memset(ea_val, (char)i+1, i+1);
+ if (!cli_set_ea_fnum(cli, fnum, ea_name, ea_val, i+1)) {
+ printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+ return False;
+ }
+ }
+
+ cli_close(cli, fnum);
+ for (i = 0; i < 10; i++) {
+ fstring ea_name, ea_val;
+
+ slprintf(ea_name, sizeof(ea_name), "EA_%d", i+10);
+ memset(ea_val, (char)i+1, i+1);
+ if (!cli_set_ea_path(cli, fname, ea_name, ea_val, i+1)) {
+ printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+ return False;
+ }
+ }
+
+ if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) {
+ printf("ea_get list failed - %s\n", cli_errstr(cli));
+ correct = False;
+ }
+
+ printf("num_eas = %d\n", num_eas);
+
+ if (num_eas != 20) {
+ printf("Should be 20 EA's stored... failing.\n");
+ correct = False;
+ }
+
+ for (i = 0; i < num_eas; i++) {
+ printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
+ dump_data(0, ea_list[i].value.data, ea_list[i].value.length);
+ }
+ /* Setting EA's to zero length deletes them. Test this */
+ printf("Now deleting all EA's....\n");
+
+ for (i = 0; i < 20; i++) {
+ fstring ea_name;
+ slprintf(ea_name, sizeof(ea_name), "EA_%d", i);
+ if (!cli_set_ea_path(cli, fname, ea_name, "", 0)) {
+ printf("ea_set of name %s failed - %s\n", ea_name, cli_errstr(cli));
+ return False;
+ }
+ }
+
+ if (!cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)) {
+ printf("ea_get list failed - %s\n", cli_errstr(cli));
+ correct = False;
+ }
+ printf("num_eas = %d\n", num_eas);
+ for (i = 0; i < num_eas; i++) {
+ printf("%d: ea_name = %s. Val = ", i, ea_list[i].name);
+ dump_data(0, ea_list[i].value.data, ea_list[i].value.length);
+ }
+
+ if (num_eas != 0) {
+ printf("deleting EA's failed.\n");
+ correct = False;
+ }
+
+ /* Try and delete a non existant EA. */
+ if (!cli_set_ea_path(cli, fname, "foo", "", 0)) {
+ printf("deleting non-existant EA 'foo' should succeed. %s\n", cli_errstr(cli));
+ correct = False;
+ }
+
+ talloc_destroy(mem_ctx);
+ if (!torture_close_connection(cli)) {
+ correct = False;
+ }
+
+ return correct;
+}
static BOOL run_dirtest1(int dummy)
{
@@ -4650,6 +4756,7 @@ static struct {
{"IOCTL", torture_ioctl_test, 0},
{"CHKPATH", torture_chkpath_test, 0},
{"FDSESS", run_fdsesstest, 0},
+ { "EATEST", run_eatest, 0},
{NULL, NULL, 0}};
diff --git a/source/utils/ntlm_auth.c b/source/utils/ntlm_auth.c
index ec0f4041769..e33bca363bf 100644
--- a/source/utils/ntlm_auth.c
+++ b/source/utils/ntlm_auth.c
@@ -366,6 +366,7 @@ static NTSTATUS local_pw_check(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *n
&ntlmssp_state->chal,
&ntlmssp_state->lm_resp,
&ntlmssp_state->nt_resp,
+ NULL, NULL,
ntlmssp_state->user,
ntlmssp_state->user,
ntlmssp_state->domain,
@@ -1111,7 +1112,8 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
- if ((retval = kerberos_kinit_password(user, opt_password, 0))) {
+ if ((retval = kerberos_kinit_password(user, opt_password,
+ 0, NULL))) {
DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
x_fprintf(x_stdout, "NA\n");
return True;