summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2005-03-11 10:52:54 +0000
committerGerald Carter <jerry@samba.org>2005-03-11 10:52:54 +0000
commit061a07f6b476428c622618d83a5a1e54c5f05fe5 (patch)
tree5e926c06e720253210687391b68aa82f553c9ad3
parent6c30768e14f5639328e06a73940f133f9078b90e (diff)
downloadsamba-061a07f6b476428c622618d83a5a1e54c5f05fe5.tar.gz
r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
-rw-r--r--examples/LDAP/samba.schema.at.IBM-DS33
-rw-r--r--examples/LDAP/samba.schema.oc.IBM-DS12
-rw-r--r--examples/pdb/mysql/mysql.dump2
-rw-r--r--source/Makefile.in32
-rw-r--r--source/VERSION4
-rw-r--r--source/auth/auth_sam.c8
-rw-r--r--source/auth/auth_util.c1
-rw-r--r--source/client/client.c40
-rw-r--r--source/client/clitar.c6
-rwxr-xr-xsource/client/mount.cifs.c25
-rw-r--r--source/configure.in18
-rw-r--r--source/groupdb/mapping.c2
-rw-r--r--source/include/libsmb_internal.h76
-rw-r--r--source/include/libsmbclient.h88
-rw-r--r--source/include/local.h3
-rw-r--r--source/include/msdfs.h8
-rw-r--r--source/include/passdb.h6
-rw-r--r--source/include/printing.h2
-rw-r--r--source/include/privileges.h2
-rw-r--r--source/include/rpc_lsa.h19
-rw-r--r--source/include/rpc_samr.h8
-rw-r--r--source/include/smb.h5
-rw-r--r--source/include/smb_macros.h2
-rw-r--r--source/include/smbldap.h25
-rw-r--r--source/include/trans2.h25
-rw-r--r--source/lib/privileges.c116
-rw-r--r--source/lib/util_pw.c14
-rw-r--r--source/libsmb/cliconnect.c7
-rw-r--r--source/libsmb/clidfs.c66
-rw-r--r--source/libsmb/clientgen.c1
-rw-r--r--source/libsmb/clilist.c49
-rw-r--r--source/libsmb/libsmb_cache.c55
-rw-r--r--source/libsmb/libsmbclient.c1575
-rw-r--r--source/locking/brlock.c9
-rw-r--r--source/locking/posix.c8
-rw-r--r--source/nmbd/nmbd_winsproxy.c11
-rw-r--r--source/nsswitch/winbindd_passdb.c2
-rw-r--r--source/nsswitch/winbindd_rpc.c37
-rw-r--r--source/param/loadparm.c12
-rw-r--r--source/passdb/pdb_interface.c36
-rw-r--r--source/passdb/pdb_ldap.c146
-rw-r--r--source/passdb/pdb_pgsql.c15
-rw-r--r--source/passdb/pdb_sql.c84
-rw-r--r--source/printing/nt_printing.c55
-rw-r--r--source/printing/pcap.c2
-rw-r--r--source/printing/print_svid.c2
-rw-r--r--source/printing/printing.c115
-rw-r--r--source/rpc_client/cli_lsarpc.c12
-rw-r--r--source/rpc_client/cli_samr.c48
-rw-r--r--source/rpc_parse/parse_lsa.c43
-rw-r--r--source/rpc_parse/parse_samr.c60
-rw-r--r--source/rpc_server/srv_lsa.c40
-rw-r--r--source/rpc_server/srv_lsa_nt.c44
-rw-r--r--source/rpc_server/srv_samr_nt.c2
-rw-r--r--source/rpc_server/srv_samr_util.c15
-rw-r--r--source/rpc_server/srv_spoolss_nt.c32
-rw-r--r--source/rpcclient/cmd_lsarpc.c10
-rw-r--r--source/sam/idmap_ldap.c11
-rw-r--r--source/sam/idmap_rid.c6
-rw-r--r--source/smbd/close.c4
-rw-r--r--source/smbd/dir.c20
-rw-r--r--source/smbd/fileio.c6
-rw-r--r--source/smbd/files.c63
-rw-r--r--source/smbd/nttrans.c14
-rw-r--r--source/smbd/open.c11
-rw-r--r--source/smbd/posix_acls.c16
-rw-r--r--source/smbd/reply.c29
-rw-r--r--source/smbd/service.c16
-rw-r--r--source/smbd/trans2.c136
-rw-r--r--source/torture/torture.c9
-rw-r--r--source/utils/net_help.c2
-rw-r--r--source/utils/net_rpc.c155
-rw-r--r--source/utils/net_rpc_rights.c2
73 files changed, 2570 insertions, 1105 deletions
diff --git a/examples/LDAP/samba.schema.at.IBM-DS b/examples/LDAP/samba.schema.at.IBM-DS
index b2c3c875dc8..f14d8e164df 100644
--- a/examples/LDAP/samba.schema.at.IBM-DS
+++ b/examples/LDAP/samba.schema.at.IBM-DS
@@ -1,8 +1,10 @@
## Samba 3.0 schema for IBM Directory Server 5.1 - object classes only
attributetypes=( 1.3.6.1.4.1.7165.2.1.24 NAME 'sambaLMPassword' DESC 'LanManager Password' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+IBMAttributetypes=( 1.3.6.1.4.1.7165.2.1.24 DBNAME( 'sambaLMPassword' 'sambaLMPassword' ) ACCESS-CLASS critical )
attributetypes=( 1.3.6.1.4.1.7165.2.1.25 NAME 'sambaNTPassword' DESC 'MD4 hash of the unicode password'EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} SINGLE-VALUE )
+IBMAttributetypes=( 1.3.6.1.4.1.7165.2.1.25 DBNAME( 'sambaNTPassword' 'sambaNTPassword' ) ACCESS-CLASS critical )
attributetypes=( 1.3.6.1.4.1.7165.2.1.26 NAME 'sambaAcctFlags' DESC 'Account Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{16} SINGLE-VALUE )
@@ -44,4 +46,33 @@ attributetypes=( 1.3.6.1.4.1.7165.2.1.39 NAME 'sambaNextRid' DESC 'Next NT rid t
attributetypes=( 1.3.6.1.4.1.7165.2.1.40 NAME 'sambaAlgorithmicRidBase' DESC 'Base at which the samba RID generation algorithm should operate' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
-attributetypes=( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial' DESC '' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} )
+attributetypes=( 1.3.6.1.4.1.7165.2.1.41 NAME 'sambaShareName' DESC 'Share Name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.42 NAME 'sambaOptionName' DESC 'Option Name' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.43 NAME 'sambaBoolOption' DESC 'A boolean option' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.44 NAME 'sambaIntegerOption' DESC 'An integer option' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.45 NAME 'sambaStringOption' DESC 'A string option' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.46 NAME 'sambaStringListOption' DESC 'A string list option' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial' DESC 'munged dial' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.48 NAME 'sambaBadPasswordCount' DESC 'Bad password attempt count' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.49 NAME 'sambaBadPasswordTime' DESC 'Time of the last bad password attempt' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.51 NAME 'sambaSIDList' DESC 'Security ID List' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{64} )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.53 NAME 'sambaTrustFlags' DESC 'Trust Password Flags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.54 NAME 'sambaPasswordHistory' DESC 'Concatenated MD4 hashes of the unicode passwords used on this account' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} )
+IBMAttributetypes=( 1.3.6.1.4.1.7165.2.1.54 DBNAME( 'sambaPasswordHistory' 'sambaPasswordHistory' ) ACCESS-CLASS critical )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.55 NAME 'sambaLogonHours' DESC 'Logon Hours' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{42} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.56 NAME 'sambaAccountPolicyName' DESC 'Account Policy Name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+
+attributetypes=( 1.3.6.1.4.1.7165.2.1.57 NAME 'sambaAccountPolicyValue' DESC 'Account Policy Value' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
diff --git a/examples/LDAP/samba.schema.oc.IBM-DS b/examples/LDAP/samba.schema.oc.IBM-DS
index 86e1dee0aca..2b00a5e8c64 100644
--- a/examples/LDAP/samba.schema.oc.IBM-DS
+++ b/examples/LDAP/samba.schema.oc.IBM-DS
@@ -1,8 +1,8 @@
## Samba 3.0 schema for IBM Directory Server 5.1 - object classes only
-objectclasses=( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY DESC 'Samba 3.0 Auxilary SAM Account' MUST ( uid $ sambaSID ) MAY ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $ sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $ displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $ sambaProfilePath $ description $ sambaUserWorkstations $ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial ))
+objectclasses=( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY DESC 'Samba 3.0 Auxilary SAM Account' MUST ( uid $ sambaSID ) MAY ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $ sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $ displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $ sambaProfilePath $ description $ sambaUserWorkstations $ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial $ sambaBadPasswordCount $ sambaBadPasswordTime $ sambaPasswordHistory $ sambaLogonHours))
-objectclasses=( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY DESC 'Samba Group Mapping' MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY ( displayName $ description ))
+objectclasses=( 1.3.6.1.4.1.7165.2.2.4 NAME 'sambaGroupMapping' SUP top AUXILIARY DESC 'Samba Group Mapping' MUST ( gidNumber $ sambaSID $ sambaGroupType ) MAY ( displayName $ description $ sambaSIDList ))
objectclasses=( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL DESC 'Samba Domain Information' MUST ( sambaDomainName $ sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $ sambaAlgorithmicRidBase ) )
@@ -12,4 +12,12 @@ objectclasses=( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIAR
objectclasses=( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL DESC 'Structural Class for a SID' MUST ( sambaSID ) )
+objectclasses=( 1.3.6.1.4.1.7165.2.2.10 NAME 'sambaConfig' SUP top AUXILIARY DESC 'Samba Configuration Section' MAY ( description ) )
+objectclasses=( 1.3.6.1.4.1.7165.2.2.11 NAME 'sambaShare' SUP top STRUCTURAL DESC 'Samba Share Section' MUST ( sambaShareName ) MAY ( description ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURAL DESC 'Samba Configuration Option' MUST ( sambaOptionName ) MAY ( sambaBoolOption $ sambaIntegerOption $ sambaStringOption $ sambaStringListoption $ description ) )
+
+objectclasses=( 1.3.6.1.4.1.7165.2.2.14 NAME 'sambaTrustPassword' SUP top STRUCTURAL DESC 'Samba Trust Password' MUST ( sambaDomainName $ sambaNTPassword $ sambaTrustFlags ) MAY ( sambaSID $ sambaPwdLastSet ))
+
+objectclasses=( 1.3.6.1.4.1.7165.2.2.15 NAME 'sambaAccountPolicy' SUP top STRUCTURAL DESC 'Samba Account Policy' MUST ( sambaAccountPolicyName $ sambaAccountPolicyValue ) MAY ( description ) )
diff --git a/examples/pdb/mysql/mysql.dump b/examples/pdb/mysql/mysql.dump
index 89013521543..72018ce5a70 100644
--- a/examples/pdb/mysql/mysql.dump
+++ b/examples/pdb/mysql/mysql.dump
@@ -31,7 +31,7 @@ CREATE TABLE user (
logon_divs int(9),
hours_len int(9),
unknown_5 int(9),
- unknown_6 int(9),
+ unknown_6 int(9) default "1260",
bad_password_count int(9),
logon_count int(9)
);
diff --git a/source/Makefile.in b/source/Makefile.in
index eb39dbf88bf..fda2bd3d93a 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -173,8 +173,6 @@ SNPRINTF_OBJ = lib/snprintf.o
WBCOMMON_OBJ = nsswitch/wb_common.o
-DUMMYROOT_OBJ = lib/dummyroot.o
-
AFS_OBJ = lib/afs.o
AFS_SETTOKEN_OBJ = lib/afs_settoken.o
@@ -208,7 +206,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \
lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o
-LIB_NONSMBD_OBJ = $(LIB_OBJ) lib/dummysmbd.o
+LIB_NONSMBD_OBJ = $(LIB_OBJ) lib/dummyroot.o lib/dummysmbd.o
READLINE_OBJ = lib/readline.o
@@ -420,7 +418,7 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \
- $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
+ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \
wrepld/partners.o
@@ -436,20 +434,20 @@ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \
$(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \
$(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \
$(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ) \
- $(PASSCHANGE_OBJ) $(DUMMYROOT_OBJ)
+ $(PASSCHANGE_OBJ)
SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
$(PARAM_OBJ) $(LIB_NONSMBD_OBJ)
STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
- $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(DUMMYROOT_OBJ) $(ERRORMAP_OBJ)
+ $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ)
SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
$(SECRETS_OBJ) $(LIBSAMBA_OBJ) \
- $(PRINTBASE_OBJ) $(DUMMYROOT_OBJ) $(ERRORMAP_OBJ)
+ $(PRINTBASE_OBJ) $(ERRORMAP_OBJ)
SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
$(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) \
@@ -465,11 +463,11 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) \
SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSCHANGE_OBJ) $(PARAM_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\
$(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
- $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ) $(DUMMYROOT_OBJ)
+ $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ)
PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \
$(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \
- $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(DUMMYROOT_OBJ)
+ $(POPT_LIB_OBJ) $(SMBLDAP_OBJ)
SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ)
@@ -485,7 +483,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
$(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \
$(READLINE_OBJ) $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) \
$(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
- $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(DUMMYROOT_OBJ)
+ $(SMBLDAP_OBJ) $(DCUTIL_OBJ)
PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.@PICSUFFIX@ \
nsswitch/wb_common.@PICSUFFIX@ lib/replace1.@PICSUFFIX@ \
@@ -518,7 +516,7 @@ LIBBIGBALLOFMUD_MAJOR = 0
LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \
$(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \
- $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(DUMMYROOT_OBJ)
+ $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ)
LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.@PICSUFFIX@)
@@ -539,7 +537,7 @@ NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
$(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \
$(LIBMSRPC_OBJ) $(IDMAP_OBJ) \
$(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \
- $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(DUMMYROOT_OBJ) $(SERVER_MUTEX_OBJ) \
+ $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \
$(AFS_OBJ) $(AFS_SETTOKEN_OBJ)
CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
@@ -568,7 +566,7 @@ MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \
- $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(DUMMYROOT_OBJ) $(SECRETS_OBJ)
+ $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
$(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
@@ -580,7 +578,7 @@ SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ
LOG2PCAP_OBJ = utils/log2pcaphex.o
LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \
- $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(DUMMYROOT_OBJ) $(SECRETS_OBJ)
+ $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ)
SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
$(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \
@@ -633,7 +631,7 @@ LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@)
PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \
pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \
- $(DUMMYROOT_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
$(SECRETS_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ)
PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.@PICSUFFIX@)
@@ -663,7 +661,7 @@ 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) $(DUMMYROOT_OBJ) \
+ $(DCUTIL_OBJ) $(IDMAP_OBJ) \
$(AFS_OBJ) $(AFS_SETTOKEN_OBJ)
WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
@@ -1337,7 +1335,7 @@ installclientlib: installdirs libsmbclient
PYTHON_OBJS = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \
$(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
- $(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(DUMMYROOT_OBJ)
+ $(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ)
PYTHON_PICOBJS = $(PYTHON_OBJS:.o=.@PICSUFFIX@)
diff --git a/source/VERSION b/source/VERSION
index bd34be8040c..99d75e80bdd 100644
--- a/source/VERSION
+++ b/source/VERSION
@@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=12
# e.g. SAMBA_VERSION_PRE_RELEASE=1 #
# -> "2.2.9pre1" #
########################################################
-SAMBA_VERSION_PRE_RELEASE=1
+SAMBA_VERSION_PRE_RELEASE=
########################################################
# For 'rc' releases the version will be #
@@ -39,7 +39,7 @@ SAMBA_VERSION_PRE_RELEASE=1
# e.g. SAMBA_VERSION_RC_RELEASE=1 #
# -> "3.0.0rc1" #
########################################################
-SAMBA_VERSION_RC_RELEASE=
+SAMBA_VERSION_RC_RELEASE=1
########################################################
# To mark SVN snapshots this should be set to 'yes' #
diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c
index 35f85f5e608..9da59f220aa 100644
--- a/source/auth/auth_sam.c
+++ b/source/auth/auth_sam.c
@@ -232,6 +232,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
SAM_ACCOUNT *sampass=NULL;
BOOL ret;
NTSTATUS nt_status;
+ NTSTATUS update_login_attempts_status;
DATA_BLOB user_sess_key = data_blob(NULL, 0);
DATA_BLOB lm_sess_key = data_blob(NULL, 0);
BOOL updated_autolock = False, updated_badpw = False;
@@ -269,7 +270,12 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
nt_status = sam_password_ok(auth_context, mem_ctx, sampass,
user_info, &user_sess_key, &lm_sess_key);
-
+
+ /* Notify passdb backend of login success/failure. If not NT_STATUS_OK the backend doesn't like the login */
+ update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status));
+ if (!NT_STATUS_IS_OK(update_login_attempts_status))
+ nt_status = update_login_attempts_status;
+
if (!NT_STATUS_IS_OK(nt_status)) {
if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) &&
pdb_get_acct_ctrl(sampass) &ACB_NORMAL) {
diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c
index f3c01a58ca6..7cab3df99e4 100644
--- a/source/auth/auth_util.c
+++ b/source/auth/auth_util.c
@@ -50,6 +50,7 @@ static int smb_create_user(const char *domain, const char *unix_username, const
if (homedir)
all_string_sub(add_script, "%H", homedir, sizeof(pstring));
ret = smbrun(add_script,NULL);
+ flush_pwnam_cache();
DEBUG(ret ? 0 : 3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
return ret;
}
diff --git a/source/client/client.c b/source/client/client.c
index 55e9f1a71d9..b00e7f2273f 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -217,7 +217,7 @@ static int do_dskattr(void)
struct cli_state *targetcli;
pstring targetpath;
- if ( !cli_resolve_path( cli, cur_dir, &targetcli, targetpath ) ) {
+ if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
d_printf("Error in dskattr: %s\n", cli_errstr(cli));
}
@@ -277,7 +277,7 @@ static int do_cd(char *newdir)
pstrcat(cur_dir,"\\");
dos_clean_name(cur_dir);
- if ( !cli_resolve_path( cli, dname, &targetcli, targetpath ) ) {
+ if ( !cli_resolve_path( "", cli, dname, &targetcli, targetpath ) ) {
d_printf("cd %s: %s\n", dname, cli_errstr(cli));
pstrcpy(cur_dir,saved_dir);
goto out;
@@ -509,7 +509,7 @@ static int do_list_queue_empty(void)
A helper for do_list.
****************************************************************************/
-static void do_list_helper(file_info *f, const char *mask, void *state)
+static void do_list_helper(const char *mntpoint, file_info *f, const char *mask, void *state)
{
if (f->mode & aDIR) {
if (do_list_dirs && do_this_one(f)) {
@@ -526,7 +526,8 @@ static void do_list_helper(file_info *f, const char *mask, void *state)
return;
}
- pstrcpy(mask2, mask);
+ pstrcpy(mask2, mntpoint);
+ pstrcat(mask2, mask);
p = strrchr_m(mask2,'\\');
if (!p)
return;
@@ -581,8 +582,9 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
/* check for dfs */
- if ( !cli_resolve_path( cli, head, &targetcli, targetpath ) ) {
+ if ( !cli_resolve_path( "", cli, head, &targetcli, targetpath ) ) {
d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
+ remove_do_list_queue_head();
continue;
}
@@ -607,7 +609,7 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec,
} else {
/* check for dfs */
- if ( cli_resolve_path( cli, mask, &targetcli, targetpath ) ) {
+ if ( cli_resolve_path( "", cli, mask, &targetcli, targetpath ) ) {
if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1)
d_printf("%s listing %s\n", cli_errstr(targetcli), targetpath);
}
@@ -720,7 +722,7 @@ static int do_get(char *rname, char *lname, BOOL reget)
strlower_m(lname);
}
- if ( !cli_resolve_path( cli, rname, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, rname, &targetcli, targetname ) ) {
d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
return 1;
}
@@ -1016,7 +1018,7 @@ static BOOL do_mkdir(char *name)
struct cli_state *targetcli;
pstring targetname;
- if ( !cli_resolve_path( cli, name, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, name, &targetcli, targetname ) ) {
d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
return False;
}
@@ -1141,7 +1143,7 @@ static int do_put(char *rname, char *lname, BOOL reput)
struct cli_state *targetcli;
pstring targetname;
- if ( !cli_resolve_path( cli, rname, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, rname, &targetcli, targetname ) ) {
d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
return 1;
}
@@ -1653,7 +1655,7 @@ static int cmd_open(void)
}
pstrcat(mask,buf);
- if ( !cli_resolve_path( cli, mask, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
d_printf("open %s: %s\n", mask, cli_errstr(cli));
return 1;
}
@@ -1683,7 +1685,7 @@ static int cmd_rmdir(void)
}
pstrcat(mask,buf);
- if ( !cli_resolve_path( cli, mask, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, mask, &targetcli, targetname ) ) {
d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
return 1;
}
@@ -1719,7 +1721,7 @@ static int cmd_link(void)
pstrcat(oldname,buf);
pstrcat(newname,buf2);
- if ( !cli_resolve_path( cli, oldname, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, oldname, &targetcli, targetname ) ) {
d_printf("link %s: %s\n", oldname, cli_errstr(cli));
return 1;
}
@@ -1794,7 +1796,7 @@ static int cmd_chmod(void)
mode = (mode_t)strtol(buf, NULL, 8);
pstrcat(src,buf2);
- if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
d_printf("chmod %s: %s\n", src, cli_errstr(cli));
return 1;
}
@@ -1942,7 +1944,7 @@ static int cmd_getfacl(void)
pstrcat(src,name);
- if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
d_printf("stat %s: %s\n", src, cli_errstr(cli));
return 1;
}
@@ -2107,7 +2109,7 @@ static int cmd_stat(void)
pstrcat(src,name);
- if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
d_printf("stat %s: %s\n", src, cli_errstr(cli));
return 1;
}
@@ -2183,7 +2185,7 @@ static int cmd_chown(void)
gid = (gid_t)atoi(buf2);
pstrcat(src,buf3);
- if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
d_printf("chown %s: %s\n", src, cli_errstr(cli));
return 1;
}
@@ -2255,7 +2257,7 @@ static int cmd_hardlink(void)
pstrcat(src,buf);
pstrcat(dest,buf2);
- if ( !cli_resolve_path( cli, src, &targetcli, targetname ) ) {
+ if ( !cli_resolve_path( "", cli, src, &targetcli, targetname ) ) {
d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
return 1;
}
@@ -2667,7 +2669,7 @@ static int cmd_show_connect( void )
struct cli_state *targetcli;
pstring targetpath;
- if ( !cli_resolve_path( cli, cur_dir, &targetcli, targetpath ) ) {
+ if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) {
d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
return 1;
}
@@ -2871,7 +2873,7 @@ typedef struct {
int len;
} completion_remote_t;
-static void completion_remote_filter(file_info *f, const char *mask, void *state)
+static void completion_remote_filter(const char *mnt, file_info *f, const char *mask, void *state)
{
completion_remote_t *info = (completion_remote_t *)state;
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 14ebffb60ff..524feca1d2a 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -1761,11 +1761,7 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
}
} else {
- if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0)) {
- if (!dry_run) {
- DEBUG(0,("Output is /dev/null, assuming dry_run\n"));
- dry_run = True;
- }
+ if (tar_type=='c' && dry_run) {
tarhandle=-1;
} else if ((tar_type=='x' && (tarhandle = sys_open(argv[Optind], O_RDONLY, 0)) == -1)
|| (tar_type=='c' && (tarhandle=sys_creat(argv[Optind], 0644)) < 0)) {
diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c
index d648629f9c3..7b30b98fa7b 100755
--- a/source/client/mount.cifs.c
+++ b/source/client/mount.cifs.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/stat.h>
@@ -38,7 +39,7 @@
#include <fcntl.h>
#define MOUNT_CIFS_VERSION_MAJOR "1"
-#define MOUNT_CIFS_VERSION_MINOR "5"
+#define MOUNT_CIFS_VERSION_MINOR "6"
#ifndef MOUNT_CIFS_VENDOR_SUFFIX
#define MOUNT_CIFS_VENDOR_SUFFIX ""
@@ -78,7 +79,7 @@ static void mount_cifs_usage(void)
printf(" to a local directory.\n\nOptions:\n");
printf("\tuser=<arg>\n\tpass=<arg>\n\tdom=<arg>\n");
printf("\nLess commonly used options:");
- printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,\n\trw,ro,sep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec");
+ printf("\n\tcredentials=<filename>,guest,perm,noperm,setuids,nosetuids,\n\trw,ro,sep=<char>,iocharset=<codepage>,suid,nosuid,exec,noexec,directio");
printf("\n\nOptions not needed for servers supporting CIFS Unix extensions (e.g. most Samba versions):");
printf("\n\tuid=<uid>,gid=<gid>,dir_mode=<mode>,file_mode=<mode>");
printf("\n\nRarely used options:");
@@ -294,6 +295,8 @@ static int parse_options(char * options, int * filesys_flags)
if(!value || !*value) {
strncpy(data,",,,,,",5);
}
+ } else if (strncmp(data, "user_xattr",10) == 0) {
+ /* do nothing - need to skip so not parsed as user name */
} else if (strncmp(data, "user", 4) == 0) {
if (!value || !*value) {
if(data[4] == '\0') {
@@ -657,6 +660,7 @@ int main(int argc, char ** argv)
int gid = 0;
int optlen = 0;
int orgoptlen = 0;
+ int retry = 0; /* set when we have to retry mount with uppercase */
struct stat statbuf;
struct utsname sysinfo;
struct mntent mountent;
@@ -846,6 +850,7 @@ int main(int argc, char ** argv)
}
/* FIXME launch daemon (handles dfs name resolution and credential change)
remember to clear parms and overwrite password field before launching */
+mount_retry:
if(orgoptions) {
optlen = strlen(orgoptions);
orgoptlen = optlen;
@@ -897,6 +902,8 @@ int main(int argc, char ** argv)
printf("\nmount.cifs kernel mount options %s \n",options);
if(mount(share_name, mountpoint, "cifs", flags, options)) {
/* remember to kill daemon on error */
+ char * tmp;
+
switch (errno) {
case 0:
printf("mount failed but no error number set\n");
@@ -904,7 +911,21 @@ int main(int argc, char ** argv)
case ENODEV:
printf("mount error: cifs filesystem not supported by the system\n");
break;
+ case ENXIO:
+ if(retry == 0) {
+ retry = 1;
+ tmp = share_name;
+ while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) {
+ *tmp = toupper((unsigned char)*tmp);
+ tmp++;
+ }
+ if(!*tmp) {
+ printf("retrying with upper case share name\n");
+ goto mount_retry;
+ }
+ }
default:
+
printf("mount error %d = %s\n",errno,strerror(errno));
}
printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
diff --git a/source/configure.in b/source/configure.in
index 40aa263c7a1..7338b879eea 100644
--- a/source/configure.in
+++ b/source/configure.in
@@ -239,6 +239,22 @@ AC_ARG_ENABLE(developer, [ --enable-developer Turn on developer warnings a
[if eval "test x$enable_developer = xyes"; then
developer=yes
CFLAGS="${CFLAGS} -gstabs -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER"
+ # Add -Wdeclaration-after-statement if compiler supports it
+ AC_CACHE_CHECK(
+ [that the C compiler understands -Wdeclaration-after-statement],
+ samba_cv_HAVE_Wdeclaration_after_statement, [
+ AC_TRY_RUN_STRICT([
+ int main(void)
+ {
+ return 0;
+ }],[-Wdeclaration-after-statement],[$CPPFLAGS],[$LDFLAGS],
+ samba_cv_HAVE_Wdeclaration_after_statement=yes,
+ samba_cv_HAVE_Wdeclaration_after_statement=no,
+ samba_cv_HAVE_Wdeclaration_after_statement=cross)
+ ])
+ if test x"$samba_cv_HAVE_Wdeclaration_after_statement" = x"yes"; then
+ CFLAGS="${CFLAGS} -Wdeclaration-after-statement"
+ fi
fi])
AC_ARG_ENABLE(krb5developer, [ --enable-krb5developer Turn on developer warnings and debugging, except -Wstrict-prototypes (default=no)],
@@ -4525,7 +4541,7 @@ SMB_MODULE(pdb_pgsql, passdb/pdb_pgsql.o, "bin/pgsql.$SHLIBEXT", PDB,
## end of contributed pdb_modules
###########################################################################
-SMB_MODULE(pdb_ldap, passdb/pdb_ldap.o, "bin/ldapsam.$SHLIBEXT", PDB,
+SMB_MODULE(pdb_ldap, passdb/pdb_ldap.o passdb/pdb_nds.o, "bin/ldapsam.$SHLIBEXT", PDB,
[ PASSDB_LIBS="$PASSDB_LIBS $LDAP_LIBS" ] )
SMB_MODULE(pdb_smbpasswd, passdb/pdb_smbpasswd.o, "bin/smbpasswd.$SHLIBEXT", PDB)
SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB)
diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c
index 1c29cc77c42..5613240a121 100644
--- a/source/groupdb/mapping.c
+++ b/source/groupdb/mapping.c
@@ -1050,6 +1050,7 @@ int smb_set_primary_group(const char *unix_group, const char* unix_user)
all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
ret = smbrun(add_script,NULL);
+ flush_pwnam_cache();
DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
"Running the command `%s' gave %d\n",add_script,ret));
return ret;
@@ -1060,6 +1061,7 @@ int smb_set_primary_group(const char *unix_group, const char* unix_user)
if ( winbind_set_user_primary_group( unix_user, unix_group ) ) {
DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n",
unix_group, unix_user));
+ flush_pwnam_cache();
return 0;
}
diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h
index 9111f36eaf7..803f9e1f108 100644
--- a/source/include/libsmb_internal.h
+++ b/source/include/libsmb_internal.h
@@ -13,6 +13,7 @@ struct _SMBCSRV {
struct cli_state cli;
dev_t dev;
BOOL no_pathinfo2;
+ BOOL no_nt_session;
int server_fd;
SMBCSRV *next, *prev;
@@ -50,9 +51,18 @@ struct smbc_internal_data {
*/
int _initialized;
- /** INTERNAL: dirent pointer location
- */
- char _dirent[512];
+ /** INTERNAL: dirent pointer location
+ *
+ * Leave room for any urlencoded filename and the comment field.
+ *
+ * We really should use sizeof(struct smbc_dirent) plus (NAME_MAX * 3)
+ * plus whatever the max length of a comment is, plus a couple of null
+ * terminators (one after the filename, one after the comment).
+ *
+ * According to <linux/limits.h>, NAME_MAX is 255. Is it longer
+ * anyplace else?
+ */
+ char _dirent[1024];
/** INTERNAL: server connection list
*/
@@ -61,6 +71,66 @@ struct smbc_internal_data {
/** INTERNAL: open file/dir list
*/
SMBCFILE * _files;
+ /** user options selections that apply to this session
+ */
+ struct _smbc_options {
+
+ /*
+ * From how many local master browsers should the list of
+ * workgroups be retrieved? It can take up to 12 minutes or
+ * longer after a server becomes a local master browser, for
+ * it to have the entire browse list (the list of
+ * workgroups/domains) from an entire network. Since a client
+ * never knows which local master browser will be found first,
+ * the one which is found first and used to retrieve a browse
+ * list may have an incomplete or empty browse list. By
+ * requesting the browse list from multiple local master
+ * browsers, a more complete list can be generated. For small
+ * networks (few workgroups), it is recommended that this
+ * value be set to 0, causing the browse lists from all found
+ * local master browsers to be retrieved and merged. For
+ * networks with many workgroups, a suitable value for this
+ * variable is probably somewhere around 3. (Default: 3).
+ */
+ int browse_max_lmb_count;
+
+ /*
+ * There is a difference in the desired return strings from
+ * smbc_readdir() depending upon whether the filenames are to
+ * be displayed to the user, or whether they are to be
+ * appended to the path name passed to smbc_opendir() to call
+ * a further smbc_ function (e.g. open the file with
+ * smbc_open()). In the former case, the filename should be
+ * in "human readable" form. In the latter case, the smbc_
+ * functions expect a URL which must be url-encoded. Those
+ * functions decode the URL. If, for example, smbc_readdir()
+ * returned a file name of "abc%20def.txt", passing a path
+ * with this file name attached to smbc_open() would cause
+ * smbc_open to attempt to open the file "abc def.txt" since
+ * the %20 is decoded into a space.
+ *
+ * Set this option to True if the names returned by
+ * smbc_readdir() should be url-encoded such that they can be
+ * passed back to another smbc_ call. Set it to False if the
+ * names returned by smbc_readdir() are to be presented to the
+ * user.
+ *
+ * For backwards compatibility, this option defaults to False.
+ */
+ int urlencode_readdir_entries;
+
+ /*
+ * Some Windows versions appear to have a limit to the number
+ * of concurrent SESSIONs and/or TREE CONNECTions. In
+ * one-shot programs (i.e. the program runs and then quickly
+ * ends, thereby shutting down all connections), it is
+ * probably reasonable to establish a new connection for each
+ * share. In long-running applications, the limitation can be
+ * avoided by using only a single connection to each server,
+ * and issuing a new TREE CONNECT when the share is accessed.
+ */
+ int one_share_per_server;
+ } options;
};
diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h
index efb04285a7f..abcf660c9de 100644
--- a/source/include/libsmbclient.h
+++ b/source/include/libsmbclient.h
@@ -68,6 +68,8 @@
#include <fcntl.h>
#include <utime.h>
+#define SMBC_CTX_VERSION 1
+
#define SMBC_BASE_FD 10000 /* smallest file descriptor returned */
#define SMBC_WORKGROUP 1
@@ -125,6 +127,19 @@ struct smbc_dirent
#define SMBC_XATTR_FLAG_REPLACE 0x2 /* fail if attr does not exist */
+/*
+ * Mappings of the DOS mode bits, as returned by smbc_getxattr() when the
+ * attribute name "system.dos_attr.mode" (or "system.dos_attr.*" or
+ * "system.*") is specified.
+ */
+#define SMBC_DOS_MODE_READONLY 0x01
+#define SMBC_DOS_MODE_HIDDEN 0x02
+#define SMBC_DOS_MODE_SYSTEM 0x04
+#define SMBC_DOS_MODE_VOLUME_ID 0x08
+#define SMBC_DOS_MODE_DIRECTORY 0x10
+#define SMBC_DOS_MODE_ARCHIVE 0x20
+
+
#ifndef ENOATTR
# define ENOATTR ENOENT /* No such attribute */
#endif
@@ -457,13 +472,13 @@ struct _SMBCCTX {
struct smbc_internal_data * internal;
int flags;
-
};
/* Flags for SMBCCTX->flags */
#define SMB_CTX_FLAG_USE_KERBEROS (1 << 0)
#define SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS (1 << 1)
#define SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON (1 << 2) /* don't try to do automatic anon login */
+#define SMBCCTX_FLAG_CTXVER (1 << 3 ) /* internal flag used to define _SMBCCTX version */
/**@ingroup misc
* Create a new SBMCCTX (a context).
@@ -2185,4 +2200,75 @@ int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv);
}
#endif
+/**@ingroup directory
+ * Convert strings of %xx to their single character equivalent.
+ *
+ * @param dest A pointer to a buffer in which the resulting decoded
+ * string should be placed. This may be a pointer to the
+ * same buffer as src_segment.
+ *
+ * @param src A pointer to the buffer containing the URL to be decoded.
+ * Any %xx sequences herein are converted to their single
+ * character equivalent. Each 'x' must be a valid hexadecimal
+ * digit, or that % sequence is left undecoded.
+ *
+ * @param max_dest_len
+ * The size of the buffer pointed to by dest_segment.
+ *
+ * @return The number of % sequences which could not be converted
+ * due to lack of two following hexadecimal digits.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+int
+smbc_urldecode(char *dest, char * src, size_t max_dest_len);
+#ifdef __cplusplus
+}
+#endif
+
+
+/*
+ * Convert any characters not specifically allowed in a URL into their %xx
+ * equivalent.
+ *
+ * @param dest A pointer to a buffer in which the resulting encoded
+ * string should be placed. Unlike smbc_urldecode(), this
+ * must be a buffer unique from src.
+ *
+ * @param src A pointer to the buffer containing the string to be encoded.
+ * Any character not specifically allowed in a URL is converted
+ * into its hexadecimal value and encoded as %xx.
+ *
+ * @param max_dest_len
+ * The size of the buffer pointed to by dest_segment.
+ *
+ * @returns The remaining buffer length.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+int
+smbc_urlencode(char * dest, char * src, int max_dest_len);
+#ifdef __cplusplus
+}
+#endif
+
+
+/**@ingroup directory
+ * Return the version of the linked Samba code, and thus the version of the
+ * libsmbclient code.
+ *
+ * @return The version string.
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+const char *
+smbc_version(void);
+#ifdef __cplusplus
+}
+#endif
+
+
#endif /* SMBCLIENT_H_INCLUDED */
diff --git a/source/include/local.h b/source/include/local.h
index 7d5baa21fa8..8960a4af553 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -198,6 +198,9 @@
/* the maximum age in seconds of a password. Should be a lp_ parameter */
#define MAX_PASSWORD_AGE (21*24*60*60)
+/* Default allocation roundup. */
+#define SMB_ROUNDUP_ALLOCATION_SIZE 0x100000
+
/* shall we deny oplocks to clients that get timeouts? */
#define FASCIST_OPLOCK_BACKOFF 1
diff --git a/source/include/msdfs.h b/source/include/msdfs.h
index eaefa81c5b8..8b365d02ea6 100644
--- a/source/include/msdfs.h
+++ b/source/include/msdfs.h
@@ -72,14 +72,6 @@ struct dfs_path
return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \
ERRSRV, ERRbadpath);; }
-#define RESOLVE_FINDFIRST_DFSPATH(name, conn, inbuf, outbuf) \
-{ if ( (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) || \
- ((get_remote_arch() == RA_WIN95) && lp_msdfs_root(SNUM(conn))) ) \
- if (lp_host_msdfs() && dfs_redirect(name,conn,True)) \
- return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \
- ERRSRV, ERRbadpath);; }
-
-
#define init_dfsroot(conn, inbuf, outbuf) \
{ if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) { \
DEBUG(2,("Serving %s as a Dfs root\n", \
diff --git a/source/include/passdb.h b/source/include/passdb.h
index 3c244e7625b..5a70bb45a8c 100644
--- a/source/include/passdb.h
+++ b/source/include/passdb.h
@@ -241,7 +241,7 @@ struct acct_info
* this SAMBA will load. Increment this if *ANY* changes are made to the interface.
*/
-#define PASSDB_INTERFACE_VERSION 7
+#define PASSDB_INTERFACE_VERSION 8
typedef struct pdb_context
{
@@ -267,6 +267,8 @@ typedef struct pdb_context
NTSTATUS (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username);
+ NTSTATUS (*pdb_update_login_attempts)(struct pdb_context *context, SAM_ACCOUNT *sam_acct, BOOL success);
+
NTSTATUS (*pdb_getgrsid)(struct pdb_context *context, GROUP_MAP *map, DOM_SID sid);
NTSTATUS (*pdb_getgrgid)(struct pdb_context *context, GROUP_MAP *map, gid_t gid);
@@ -371,6 +373,8 @@ typedef struct pdb_methods
NTSTATUS (*delete_sam_account)(struct pdb_methods *, SAM_ACCOUNT *username);
+ NTSTATUS (*update_login_attempts)(struct pdb_methods *methods, SAM_ACCOUNT *sam_acct, BOOL success);
+
NTSTATUS (*getgrsid)(struct pdb_methods *methods, GROUP_MAP *map, DOM_SID sid);
NTSTATUS (*getgrgid)(struct pdb_methods *methods, GROUP_MAP *map, gid_t gid);
diff --git a/source/include/printing.h b/source/include/printing.h
index fd1e7e43e4e..43ff8dd39e8 100644
--- a/source/include/printing.h
+++ b/source/include/printing.h
@@ -75,7 +75,9 @@ extern struct printif cups_printif;
#define MAX_CACHE_VALID_TIME 3600
+#ifndef PRINT_SPOOL_PREFIX
#define PRINT_SPOOL_PREFIX "smbprn."
+#endif
#define PRINT_DATABASE_VERSION 5
/* There can be this many printing tdb's open, plus any locked ones. */
diff --git a/source/include/privileges.h b/source/include/privileges.h
index 5266e46e3a3..c7a9b0560da 100644
--- a/source/include/privileges.h
+++ b/source/include/privileges.h
@@ -6,7 +6,7 @@
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
Copyright (C) Simo Sorce 2003
- Copyright (C) Gerald (Jerry) Carter 2004
+ Copyright (C) Gerald (Jerry) Carter 2005
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
diff --git a/source/include/rpc_lsa.h b/source/include/rpc_lsa.h
index 01add64727c..a0d78280c20 100644
--- a/source/include/rpc_lsa.h
+++ b/source/include/rpc_lsa.h
@@ -698,20 +698,20 @@ typedef struct lsa_r_setsystemaccount
NTSTATUS status;
} LSA_R_SETSYSTEMACCOUNT;
+typedef struct {
+ UNIHDR hdr;
+ UNISTR2 unistring;
+} LSA_STRING;
-typedef struct lsa_q_lookupprivvalue
-{
+typedef struct {
POLICY_HND pol; /* policy handle */
- UNIHDR hdr_right;
- UNISTR2 uni2_right;
-} LSA_Q_LOOKUPPRIVVALUE;
+ LSA_STRING privname;
+} LSA_Q_LOOKUP_PRIV_VALUE;
-typedef struct lsa_r_lookupprivvalue
-{
+typedef struct {
LUID luid;
NTSTATUS status;
-} LSA_R_LOOKUPPRIVVALUE;
-
+} LSA_R_LOOKUP_PRIV_VALUE;
typedef struct lsa_q_addprivs
{
@@ -740,5 +740,4 @@ typedef struct lsa_r_removeprivs
NTSTATUS status;
} LSA_R_REMOVEPRIVS;
-
#endif /* _RPC_LSA_H */
diff --git a/source/include/rpc_samr.h b/source/include/rpc_samr.h
index e041ee26f0b..6559127df11 100644
--- a/source/include/rpc_samr.h
+++ b/source/include/rpc_samr.h
@@ -148,6 +148,8 @@ SamrTestPrivateFunctionsUser
typedef struct logon_hours_info
{
+ uint32 max_len; /* normally 1260 bytes */
+ uint32 offset;
uint32 len; /* normally 21 bytes */
uint8 hours[32];
@@ -212,9 +214,6 @@ typedef struct sam_user_info_23
UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel no */
- uint32 unknown_6; /* 0x0000 04ec */
- uint32 padding4;
-
LOGON_HRS logon_hrs;
} SAM_USER_INFO_23;
@@ -336,9 +335,6 @@ typedef struct sam_user_info_21
UNISTR2 uni_unknown_str ; /* don't know what this is, yet. */
UNISTR2 uni_munged_dial ; /* munged path name and dial-back tel number */
- uint32 unknown_6; /* 0x0000 04ec */
- uint32 padding4;
-
LOGON_HRS logon_hrs;
} SAM_USER_INFO_21;
diff --git a/source/include/smb.h b/source/include/smb.h
index ff645134109..91ec52df237 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -404,7 +404,9 @@ typedef struct files_struct {
struct timeval open_time;
int share_mode;
uint32 desired_access;
+ BOOL pending_modtime_owner;
time_t pending_modtime;
+ time_t last_write_time;
int oplock_type;
int sent_oplock_break;
unsigned long file_id;
@@ -1121,8 +1123,11 @@ struct bitmap {
#define FILE_ATTRIBUTE_NORMAL 0x080L
#define FILE_ATTRIBUTE_TEMPORARY 0x100L
#define FILE_ATTRIBUTE_SPARSE 0x200L
+#define FILE_ATTRIBUTE_REPARSE_POINT 0x400L
#define FILE_ATTRIBUTE_COMPRESSED 0x800L
+#define FILE_ATTRIBUTE_OFFLINE 0x1000L
#define FILE_ATTRIBUTE_NONINDEXED 0x2000L
+#define FILE_ATTRIBUTE_ENCRYPTED 0x4000L
#define SAMBA_ATTRIBUTES_MASK 0x7F
/* Flags - combined with attributes. */
diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h
index b1ac617f5cf..4fa9ffa5ace 100644
--- a/source/include/smb_macros.h
+++ b/source/include/smb_macros.h
@@ -178,6 +178,8 @@
/* this is how errors are generated */
#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__)
+#define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x))
+
/* Extra macros added by Ying Chen at IBM - speed increase by inlining. */
#define smb_buf(buf) (((char *)(buf)) + smb_size + CVAL(buf,smb_wct)*2)
#define smb_buflen(buf) (SVAL(buf,smb_vwv0 + (int)CVAL(buf, smb_wct)*2))
diff --git a/source/include/smbldap.h b/source/include/smbldap.h
index d005104dea4..e6a6a1b7c68 100644
--- a/source/include/smbldap.h
+++ b/source/include/smbldap.h
@@ -155,6 +155,31 @@ struct smbldap_state {
struct timeval last_rebind;
};
+/* struct used by both pdb_ldap.c and pdb_nds.c */
+
+struct ldapsam_privates {
+ struct smbldap_state *smbldap_state;
+
+ /* Former statics */
+ LDAPMessage *result;
+ LDAPMessage *entry;
+ int index;
+
+ const char *domain_name;
+ DOM_SID domain_sid;
+
+ /* configuration items */
+ int schema_ver;
+
+ char *domain_dn;
+
+ /* Is this NDS ldap? */
+ int is_nds_ldap;
+
+ /* ldap server location parameter */
+ char *location;
+};
+
#endif /* HAVE_LDAP */
struct smbldap_state;
diff --git a/source/include/trans2.h b/source/include/trans2.h
index b1fe2d9d832..68358344f4e 100644
--- a/source/include/trans2.h
+++ b/source/include/trans2.h
@@ -433,7 +433,12 @@ Offset Size Name
#define SMB_QUERY_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_UNIX_LINK 0x201
#define SMB_SET_FILE_UNIX_HLINK 0x203
+/* SMB_QUERY_POSIX_ACL 0x204 see below */
+#define SMB_QUERY_XATTR 0x205 /* need for non-user XATTRs */
+#define SMB_QUERY_ATTR_FLAGS 0x206 /* chflags, chattr */
+#define SMB_SET_ATTR_FLAGS 0x206
+/* Transact 2 Find First levels */
#define SMB_FIND_FILE_UNIX 0x202
/*
@@ -457,6 +462,26 @@ Offset Size Name
#define CIFS_UNIX_FCNTL_LOCKS_CAP 0x1
#define CIFS_UNIX_POSIX_ACLS_CAP 0x2
+#define SMB_QUERY_POSIX_FS_INFO 0x201
+
+/* Returns FILE_SYSTEM_POSIX_INFO struct as follows
+ (NB For undefined values return -1 in that field)
+ le32 OptimalTransferSize; bsize on some os, iosize on other os, This
+ is a hint to the client about best size. Server
+ can return -1 if no preference, ie if SMB
+ negotiated size is adequate for optimal
+ read/write performance
+ le32 BlockSize; (often 512 bytes) NB: BlockSize * TotalBlocks = disk space
+ le64 TotalBlocks; redundant with other infolevels but easy to ret here
+ le64 BlocksAvail; although redundant, easy to return
+ le64 UserBlocksAvail; bavail
+ le64 TotalFileNodes;
+ le64 FreeFileNodes;
+ le64 FileSysIdentifier; fsid
+ (NB statfs field Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call)
+ (NB statfs field flags can come from FILE_SYSTEM_DEVICE_INFO call)
+*/
+
/* ... more as we think of them :-). */
/* SMB POSIX ACL definitions. */
diff --git a/source/lib/privileges.c b/source/lib/privileges.c
index 5a5afa4d72c..8b5348e1f25 100644
--- a/source/lib/privileges.c
+++ b/source/lib/privileges.c
@@ -3,7 +3,7 @@
Privileges handling functions
Copyright (C) Jean François Micouleau 1998-2001
Copyright (C) Simo Sorce 2002-2003
- Copyright (C) Gerald (Jerry) Carter 2004
+ Copyright (C) Gerald (Jerry) Carter 2005
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
@@ -40,6 +40,43 @@ const SE_PRIV se_add_users = SE_ADD_USERS;
const SE_PRIV se_disk_operators = SE_DISK_OPERATOR;
const SE_PRIV se_remote_shutdown = SE_REMOTE_SHUTDOWN;
+/********************************************************************
+ This is a list of privileges reported by a WIndows 2000 SP4 AD DC
+ just for reference purposes:
+
+ SeCreateTokenPrivilege Create a token object
+ SeAssignPrimaryTokenPrivilege Replace a process level token
+ SeLockMemoryPrivilege Lock pages in memory
+ SeIncreaseQuotaPrivilege Increase quotas
+ SeMachineAccountPrivilege Add workstations to domain
+ SeTcbPrivilege Act as part of the operating system
+ SeSecurityPrivilege Manage auditing and security log
+ SeTakeOwnershipPrivilege Take ownership of files or other objects
+ SeLoadDriverPrivilege Load and unload device drivers
+ SeSystemProfilePrivilege Profile system performance
+ SeSystemtimePrivilege Change the system time
+ SeProfileSingleProcessPrivilege Profile single process
+ SeIncreaseBasePriorityPrivilege Increase scheduling priority
+ SeCreatePagefilePrivilege Create a pagefile
+ SeCreatePermanentPrivilege Create permanent shared objects
+ SeBackupPrivilege Back up files and directories
+ SeRestorePrivilege Restore files and directories
+ SeShutdownPrivilege Shut down the system
+ SeDebugPrivilege Debug programs
+ SeAuditPrivilege Generate security audits
+ SeSystemEnvironmentPrivilege Modify firmware environment values
+ SeChangeNotifyPrivilege Bypass traverse checking
+ SeRemoteShutdownPrivilege Force shutdown from a remote system
+ SeUndockPrivilege Remove computer from docking station
+ SeSyncAgentPrivilege Synchronize directory service data
+ SeEnableDelegationPrivilege Enable computer and user accounts to be trusted for delegation
+ SeManageVolumePrivilege Perform volume maintenance tasks
+ SeImpersonatePrivilege Impersonate a client after authentication
+ SeCreateGlobalPrivilege Create global objects
+
+********************************************************************/
+
+
PRIVS privs[] = {
#if 0 /* usrmgr will display these twice if you include them. We don't
use them but we'll keep the bitmasks reserved in privileges.h anyways */
@@ -58,38 +95,6 @@ PRIVS privs[] = {
{SE_END, "", ""}
};
-#if 0 /* not needed currently */
-PRIVS privs[] = {
- {SE_ASSIGN_PRIMARY_TOKEN, "SeAssignPrimaryTokenPrivilege", "Assign Primary Token"},
- {SE_CREATE_TOKEN, "SeCreateTokenPrivilege", "Create Token"},
- {SE_LOCK_MEMORY, "SeLockMemoryPrivilege", "Lock Memory"},
- {SE_INCREASE_QUOTA, "SeIncreaseQuotaPrivilege", "Increase Quota"},
- {SE_UNSOLICITED_INPUT, "SeUnsolicitedInputPrivilege", "Unsolicited Input"},
- {SE_TCB, "SeTcbPrivilege", "Act as part of the operating system"},
- {SE_SECURITY, "SeSecurityPrivilege", "Security Privilege"},
- {SE_TAKE_OWNERSHIP, "SeTakeOwnershipPrivilege", "Take Ownership Privilege"},
- {SE_LOAD_DRIVER, "SeLocalDriverPrivilege", "Local Driver Privilege"},
- {SE_SYSTEM_PROFILE, "SeSystemProfilePrivilege", "System Profile Privilege"},
- {SE_SYSTEM_TIME, "SeSystemtimePrivilege", "System Time"},
- {SE_PROF_SINGLE_PROCESS, "SeProfileSingleProcessPrivilege", "Profile Single Process Privilege"},
- {SE_INC_BASE_PRIORITY, "SeIncreaseBasePriorityPrivilege", "Increase Base Priority Privilege"},
- {SE_CREATE_PAGEFILE, "SeCreatePagefilePrivilege", "Create Pagefile Privilege"},
- {SE_CREATE_PERMANENT, "SeCreatePermanentPrivilege", "Create Permanent"},
- {SE_BACKUP, "SeBackupPrivilege", "Backup Privilege"},
- {SE_RESTORE, "SeRestorePrivilege", "Restore Privilege"},
- {SE_SHUTDOWN, "SeShutdownPrivilege", "Shutdown Privilege"},
- {SE_DEBUG, "SeDebugPrivilege", "Debug Privilege"},
- {SE_AUDIT, "SeAuditPrivilege", "Audit"},
- {SE_SYSTEM_ENVIRONMENT, "SeSystemEnvironmentPrivilege", "System Environment Privilege"},
- {SE_CHANGE_NOTIFY, "SeChangeNotifyPrivilege", "Change Notify"},
- {SE_UNDOCK, "SeUndockPrivilege", "Undock"},
- {SE_SYNC_AGENT, "SeSynchronizationAgentPrivilege", "Synchronization Agent"},
- {SE_ENABLE_DELEGATION, "SeEnableDelegationPrivilege", "Enable Delegation"},
- {SE_ALL_PRIVS, "SeAllPrivileges", "All Privileges"}
- {SE_END, "", ""}
-};
-#endif
-
typedef struct priv_sid_list {
SE_PRIV privilege;
SID_LIST sids;
@@ -177,6 +182,24 @@ static BOOL se_priv_empty( const SE_PRIV *mask )
return se_priv_equal( &p1, &se_priv_none );
}
+/*********************************************************************
+ Lookup the SE_PRIV value for a privilege name
+*********************************************************************/
+
+BOOL se_priv_from_name( const char *name, SE_PRIV *mask )
+{
+ int i;
+
+ for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
+ if ( strequal( privs[i].name, name ) ) {
+ se_priv_copy( mask, &privs[i].se_priv );
+ return True;
+ }
+ }
+
+ return False;
+}
+
/***************************************************************************
dump an SE_PRIV structure to the log files
****************************************************************************/
@@ -369,11 +392,9 @@ LUID_ATTR get_privilege_luid( SE_PRIV *mask )
for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
- /* just use the index+1 (so its non-zero) into the
- array as the lower portion of the LUID */
-
if ( se_priv_equal( &privs[i].se_priv, mask ) ) {
priv_luid.luid.low = GENERATE_LUID_LOW(i);
+ break;
}
}
@@ -664,9 +685,6 @@ NTSTATUS dup_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_l
{
int i;
- /* don't crash if the source pointer is NULL (since we don't
- do priviledges now anyways) */
-
if ( !old_la )
return NT_STATUS_OK;
@@ -731,26 +749,6 @@ char* luid_to_privilege_name(const LUID *set)
return name;
}
-/****************************************************************************
- Convert an LUID to a 32-bit mask
-****************************************************************************/
-
-SE_PRIV* luid_to_privilege_mask(const LUID *set)
-{
- static SE_PRIV mask;
- int max = count_all_privileges();
-
- if (set->high != 0)
- return NULL;
-
- if ( set->low > max )
- return NULL;
-
- se_priv_copy( &mask, &privs[set->low - 1].se_priv );
-
- return &mask;
-}
-
/*******************************************************************
return the number of elements in the privlege array
*******************************************************************/
diff --git a/source/lib/util_pw.c b/source/lib/util_pw.c
index 0d7ffe09e9b..13349bad34e 100644
--- a/source/lib/util_pw.c
+++ b/source/lib/util_pw.c
@@ -70,6 +70,20 @@ static void init_pwnam_cache(void)
return;
}
+void flush_pwnam_cache(void)
+{
+ int i;
+
+ init_pwnam_cache();
+
+ for (i=0; i<PWNAMCACHE_SIZE; i++) {
+ if (pwnam_cache[i] == NULL)
+ continue;
+
+ passwd_free(&pwnam_cache[i]);
+ }
+}
+
struct passwd *getpwnam_alloc(const char *name)
{
int i;
diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c
index 01a92a89ba4..aa37a29391c 100644
--- a/source/libsmb/cliconnect.c
+++ b/source/libsmb/cliconnect.c
@@ -888,7 +888,12 @@ BOOL cli_ulogoff(struct cli_state *cli)
if (!cli_receive_smb(cli))
return False;
- return !cli_is_error(cli);
+ if (cli_is_error(cli)) {
+ return False;
+ }
+
+ cli->cnum = -1;
+ return True;
}
/****************************************************************************
diff --git a/source/libsmb/clidfs.c b/source/libsmb/clidfs.c
index 6db6330ca6b..e4308fdb5a4 100644
--- a/source/libsmb/clidfs.c
+++ b/source/libsmb/clidfs.c
@@ -27,6 +27,7 @@
struct client_connection {
struct client_connection *prev, *next;
struct cli_state *cli;
+ pstring mount;
};
/* global state....globals reek! */
@@ -166,6 +167,44 @@ static struct cli_state *do_connect( const char *server, const char *share,
return c;
}
+/****************************************************************************
+****************************************************************************/
+
+static void cli_cm_set_mntpoint( struct cli_state *c, const char *mnt )
+{
+ struct client_connection *p;
+ int i;
+
+ for ( p=connections,i=0; p; p=p->next,i++ ) {
+ if ( strequal(p->cli->desthost, c->desthost) && strequal(p->cli->share, c->share) )
+ break;
+ }
+
+ if ( p ) {
+ pstrcpy( p->mount, mnt );
+ dos_clean_name( p->mount );
+ }
+}
+
+/****************************************************************************
+****************************************************************************/
+
+const char * cli_cm_get_mntpoint( struct cli_state *c )
+{
+ struct client_connection *p;
+ int i;
+
+ for ( p=connections,i=0; p; p=p->next,i++ ) {
+ if ( strequal(p->cli->desthost, c->desthost) && strequal(p->cli->share, c->share) )
+ break;
+ }
+
+ if ( p )
+ return p->mount;
+
+ return NULL;
+}
+
/********************************************************************
Add a new connection to the list
********************************************************************/
@@ -186,6 +225,8 @@ static struct cli_state* cli_cm_connect( const char *server, const char *share,
DLIST_ADD( connections, node );
+ cli_cm_set_mntpoint( node->cli, "" );
+
return node->cli;
}
@@ -443,7 +484,7 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
char *p;
size_t pathlen = 2*(strlen(path)+1);
uint16 num_referrals;
- CLIENT_DFS_REFERRAL *referrals;
+ CLIENT_DFS_REFERRAL *referrals = NULL;
memset(param, 0, sizeof(param));
SSVAL(param, 0, 0x03); /* max referral level */
@@ -516,7 +557,7 @@ BOOL cli_dfs_get_referral( struct cli_state *cli, const char *path,
/********************************************************************
********************************************************************/
-BOOL cli_resolve_path( struct cli_state *rootcli, const char *path,
+BOOL cli_resolve_path( const char *mountpt, struct cli_state *rootcli, const char *path,
struct cli_state **targetcli, pstring targetpath )
{
CLIENT_DFS_REFERRAL *refs = NULL;
@@ -528,6 +569,8 @@ BOOL cli_resolve_path( struct cli_state *rootcli, const char *path,
fstring server, share;
struct cli_state *newcli;
pstring newpath;
+ pstring newmount;
+ char *ppath;
SMB_STRUCT_STAT sbuf;
uint32 attributes;
@@ -585,16 +628,29 @@ BOOL cli_resolve_path( struct cli_state *rootcli, const char *path,
return False;
}
+
+ /* parse out the consumed mount path */
+ /* trim off the \server\share\ */
- /* check for another dfs refeerrali, note that we are not
+ fullpath[consumed/2] = '\0';
+ dos_clean_name( fullpath );
+ ppath = strchr_m( fullpath, '\\' );
+ ppath = strchr_m( ppath+1, '\\' );
+ ppath = strchr_m( ppath+1, '\\' );
+ ppath++;
+
+ pstr_sprintf( newmount, "%s\\%s", mountpt, ppath );
+ cli_cm_set_mntpoint( *targetcli, newmount );
+
+ /* check for another dfs referral, note that we are not
checking for loops here */
if ( !strequal( targetpath, "\\" ) ) {
- if ( cli_resolve_path( *targetcli, targetpath, &newcli, newpath ) ) {
+ if ( cli_resolve_path( newmount, *targetcli, targetpath, &newcli, newpath ) ) {
*targetcli = newcli;
pstrcpy( targetpath, newpath );
}
}
-
+
return True;
}
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index 369fba35218..b7bc780a1a1 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -282,6 +282,7 @@ struct cli_state *cli_initialise(struct cli_state *cli)
cli->inbuf = (char *)SMB_MALLOC(cli->bufsize+SAFETY_MARGIN);
cli->oplock_handler = cli_oplock_ack;
cli->case_sensitive = False;
+ cli->smb_rw_error = 0;
cli->use_spnego = lp_client_use_spnego();
diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c
index 532fb3a772e..dcac17d24a2 100644
--- a/source/libsmb/clilist.c
+++ b/source/libsmb/clilist.c
@@ -143,7 +143,7 @@ static int interpret_long_filename(struct cli_state *cli,
****************************************************************************/
int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
- void (*fn)(file_info *, const char *, void *), void *state)
+ void (*fn)(const char *, file_info *, const char *, void *), void *state)
{
#if 0
int max_matches = 1366; /* Match W2k - was 512. */
@@ -191,7 +191,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
setup = TRANSACT2_FINDFIRST;
SSVAL(param,0,attribute); /* attribute */
SSVAL(param,2,max_matches); /* max count */
- SSVAL(param,4,4+2); /* resume required + close on end */
+ SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
SSVAL(param,6,info_level);
SIVAL(param,8,0);
p = param+12;
@@ -203,7 +203,9 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
SSVAL(param,2,max_matches); /* max count */
SSVAL(param,4,info_level);
SIVAL(param,6,0); /* ff_resume_key */
- SSVAL(param,10,8+4+2); /* continue + resume required + close on end */
+ /* NB. *DON'T* use continue here. If you do it seems that W2K and bretheren
+ can miss filenames. Use last filename continue instead. JRA */
+ SSVAL(param,4,(FLAG_TRANS2_FIND_REQUIRE_RESUME|FLAG_TRANS2_FIND_CLOSE_IF_END)); /* resume required + close on end */
p = param+12;
p += clistr_push(cli, param+12, mask, sizeof(param)-12,
STR_TERMINATE);
@@ -268,24 +270,6 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
p = rdata;
/* we might need the lastname for continuations */
- if (ff_lastname > 0) {
- switch(info_level) {
- case 260:
- clistr_pull(cli, mask, p+ff_lastname,
- sizeof(mask),
- data_len-ff_lastname,
- STR_TERMINATE);
- break;
- case 1:
- clistr_pull(cli, mask, p+ff_lastname+1,
- sizeof(mask),
- -1,
- STR_TERMINATE);
- break;
- }
- } else {
- pstrcpy(mask,"");
- }
/* and add them to the dirlist pool */
tdl = SMB_REALLOC(dirlist,dirlist_len + data_len);
@@ -299,10 +283,18 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
/* put in a length for the last entry, to ensure we can chain entries
into the next packet */
- for (p2=p,i=0;i<(ff_searchcount-1);i++)
- p2 += interpret_long_filename(cli,info_level,p2,NULL);
+ for (p2=p,i=0;i<(ff_searchcount-1);i++) {
+ p2 += interpret_long_filename(cli,info_level,p2,&finfo);
+ }
SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
+ /* we might need the lastname for continuations */
+ if (ff_lastname > 0) {
+ pstrcpy(mask, finfo.name);
+ } else {
+ pstrcpy(mask,"");
+ }
+
/* grab the data for later use */
memcpy(dirlist+dirlist_len,p,data_len);
dirlist_len += data_len;
@@ -322,8 +314,11 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
}
for (p=dirlist,i=0;i<total_received;i++) {
+ const char *mnt = cli_cm_get_mntpoint( cli );
+
p += interpret_long_filename(cli,info_level,p,&finfo);
- fn(&finfo, Mask, state);
+
+ fn( mnt,&finfo, Mask, state );
}
/* free up the dirlist buffer */
@@ -365,7 +360,7 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
****************************************************************************/
int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
- void (*fn)(file_info *, const char *, void *), void *state)
+ void (*fn)(const char *, file_info *, const char *, void *), void *state)
{
char *p;
int received = 0;
@@ -472,7 +467,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
for (p=dirlist,i=0;i<num_received;i++) {
file_info finfo;
p += interpret_short_filename(cli, p,&finfo);
- fn(&finfo, Mask, state);
+ fn("\\", &finfo, Mask, state);
}
SAFE_FREE(dirlist);
@@ -485,7 +480,7 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
****************************************************************************/
int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
- void (*fn)(file_info *, const char *, void *), void *state)
+ void (*fn)(const char *, file_info *, const char *, void *), void *state)
{
if (cli->protocol <= PROTOCOL_LANMAN1)
return cli_list_old(cli, Mask, attribute, fn, state);
diff --git a/source/libsmb/libsmb_cache.c b/source/libsmb/libsmb_cache.c
index ddb27535233..71399f14db8 100644
--- a/source/libsmb/libsmb_cache.c
+++ b/source/libsmb/libsmb_cache.c
@@ -1,3 +1,4 @@
+
/*
Unix SMB/CIFS implementation.
SMB client library implementation (server cache)
@@ -23,12 +24,8 @@
#include "includes.h"
-/*
- * Define this to get the real SMBCFILE and SMBCSRV structures
- */
-#define _SMBC_INTERNAL
#include "include/libsmbclient.h"
-
+#include "../include/libsmb_internal.h"
/*
* Structure we use if internal caching mechanism is used
* nothing fancy here.
@@ -115,11 +112,53 @@ static SMBCSRV * smbc_get_cached_server(SMBCCTX * context, const char * server,
/* Search the cache lines */
for (srv=((struct smbc_server_cache *)context->server_cache);srv;srv=srv->next) {
+
if (strcmp(server,srv->server_name) == 0 &&
- strcmp(share,srv->share_name) == 0 &&
strcmp(workgroup,srv->workgroup) == 0 &&
- strcmp(user, srv->username) == 0)
- return srv->server;
+ strcmp(user, srv->username) == 0) {
+
+ /* If the share name matches, we're cool */
+ if (strcmp(share, srv->share_name) == 0) {
+ return srv->server;
+ }
+
+ /*
+ * We only return an empty share name or the attribute
+ * server on an exact match (which would have been
+ * caught above).
+ */
+ if (*share == '\0' || strcmp(share, "*IPC$") == 0)
+ continue;
+
+ /*
+ * Never return an empty share name or the attribute
+ * server if it wasn't what was requested.
+ */
+ if (*srv->share_name == '\0' ||
+ strcmp(srv->share_name, "*IPC$") == 0)
+ continue;
+
+ /*
+ * If we're only allowing one share per server, then
+ * a connection to the server (other than the
+ * attribute server connection) is cool.
+ */
+ if (context->internal->options.one_share_per_server) {
+ /*
+ * The currently connected share name
+ * doesn't match the requested share, so
+ * disconnect from the current share.
+ */
+ if (! cli_tdis(&srv->server->cli)) {
+ /* Sigh. Couldn't disconnect. */
+ cli_shutdown(&srv->server->cli);
+ context->callbacks.remove_cached_srv_fn(context, srv->server);
+ continue;
+ }
+
+ return srv->server;
+ }
+ }
}
return NULL;
diff --git a/source/libsmb/libsmbclient.c b/source/libsmb/libsmbclient.c
index 8eeadc8a783..c876720cfab 100644
--- a/source/libsmb/libsmbclient.c
+++ b/source/libsmb/libsmbclient.c
@@ -5,7 +5,7 @@
Copyright (C) Richard Sharpe 2000, 2002
Copyright (C) John Terpstra 2000
Copyright (C) Tom Jansen (Ninja ISD) 2002
- Copyright (C) Derrell Lipman 2003
+ Copyright (C) Derrell Lipman 2003, 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
@@ -26,6 +26,21 @@
#include "include/libsmb_internal.h"
+
+/*
+ * DOS Attribute values (used internally)
+ */
+typedef struct DOS_ATTR_DESC
+{
+ int mode;
+ unsigned long long size;
+ time_t a_time;
+ time_t c_time;
+ time_t m_time;
+ unsigned long long inode;
+} DOS_ATTR_DESC;
+
+
/*
* Internal flags for extended attributes
*/
@@ -84,73 +99,103 @@ hex2int( unsigned int _char )
return -1;
}
-static void
-decode_urlpart(char *segment, size_t sizeof_segment)
+/*
+ * smbc_urldecode()
+ *
+ * Convert strings of %xx to their single character equivalent. Each 'x' must
+ * be a valid hexadecimal digit, or that % sequence is left undecoded.
+ *
+ * dest may, but need not be, the same pointer as src.
+ *
+ * Returns the number of % sequences which could not be converted due to lack
+ * of two following hexadecimal digits.
+ */
+int
+smbc_urldecode(char *dest, char * src, size_t max_dest_len)
{
- int old_length = strlen(segment);
- int new_length = 0;
- int new_length2 = 0;
- int i = 0;
- pstring new_segment;
- char *new_usegment = 0;
-
- if ( !old_length ) {
- return;
- }
+ int old_length = strlen(src);
+ int i = 0;
+ int err_count = 0;
+ pstring temp;
+ char * p;
- /* make a copy of the old one */
- new_usegment = (char*)SMB_MALLOC( old_length * 3 + 1 );
-
- while( i < old_length ) {
- int bReencode = False;
- unsigned char character = segment[ i++ ];
- if ((character <= ' ') || (character > 127))
- bReencode = True;
-
- new_usegment [ new_length2++ ] = character;
- if (character == '%' ) {
- int a = i+1 < old_length ? hex2int( segment[i] ) : -1;
- int b = i+1 < old_length ? hex2int( segment[i+1] ) : -1;
- if ((a == -1) || (b == -1)) { /* Only replace if sequence is valid */
- /* Contains stray %, make sure to re-encode! */
- bReencode = True;
- } else {
- /* Valid %xx sequence */
- character = a * 16 + b; /* Replace with value of %dd */
- if (!character)
- break; /* Stop at %00 */
-
- new_usegment [ new_length2++ ] = (unsigned char) segment[i++];
- new_usegment [ new_length2++ ] = (unsigned char) segment[i++];
- }
- }
- if (bReencode) {
- unsigned int c = character / 16;
- new_length2--;
- new_usegment [ new_length2++ ] = '%';
-
- c += (c > 9) ? ('A' - 10) : '0';
- new_usegment[ new_length2++ ] = c;
-
- c = character % 16;
- c += (c > 9) ? ('A' - 10) : '0';
- new_usegment[ new_length2++ ] = c;
- }
-
- new_segment [ new_length++ ] = character;
- }
- new_segment [ new_length ] = 0;
+ if ( old_length == 0 ) {
+ return 0;
+ }
- free(new_usegment);
+ p = temp;
+ while ( i < old_length ) {
+ unsigned char character = src[ i++ ];
- /* realloc it with unix charset */
- pull_utf8_allocate(&new_usegment, new_segment);
+ if (character == '%') {
+ int a = i+1 < old_length ? hex2int( src[i] ) : -1;
+ int b = i+1 < old_length ? hex2int( src[i+1] ) : -1;
+
+ /* Replace valid sequence */
+ if (a != -1 && b != -1) {
+
+ /* Replace valid %xx sequence with %dd */
+ character = (a * 16) + b;
+
+ if (character == '\0') {
+ break; /* Stop at %00 */
+ }
- /* this assumes (very safely) that removing %aa sequences
- only shortens the string */
- strncpy(segment, new_usegment, sizeof_segment);
+ i += 2;
+ } else {
+
+ err_count++;
+ }
+ }
+
+ *p++ = character;
+ }
+
+ *p = '\0';
+
+ strncpy(dest, temp, max_dest_len);
+
+ return err_count;
+}
+
+/*
+ * smbc_urlencode()
+ *
+ * Convert any characters not specifically allowed in a URL into their %xx
+ * equivalent.
+ *
+ * Returns the remaining buffer length.
+ */
+int
+smbc_urlencode(char * dest, char * src, int max_dest_len)
+{
+ char hex[] = "0123456789ABCDEF";
+
+ for (; *src != '\0' && max_dest_len >= 3; src++) {
+
+ if ((*src < '0' &&
+ *src != '-' &&
+ *src != '.') ||
+ (*src > '9' &&
+ *src < 'A') ||
+ (*src > 'Z' &&
+ *src < 'a' &&
+ *src != '_') ||
+ (*src > 'z')) {
+ *dest++ = '%';
+ *dest++ = hex[(*src >> 4) & 0x0f];
+ *dest++ = hex[*src & 0x0f];
+ max_dest_len -= 3;
+ } else {
+ *dest++ = *src;
+ max_dest_len--;
+ }
+ }
- free(new_usegment);
+ *dest++ = '\0';
+ max_dest_len--;
+
+ return max_dest_len;
}
/*
@@ -158,10 +203,7 @@ decode_urlpart(char *segment, size_t sizeof_segment)
*
* The general format of an SMB URI is explain in Christopher Hertel's CIFS
* book, at http://ubiqx.org/cifs/Appendix-D.html. We accept a subset of the
- * general format ("smb:" only; we do not look for "cifs:"), and expand on
- * what he calls "context", herein called "options" to avoid conflict with the
- * SMBCCTX context used throughout this library. We add the "mb" keyword
- * which applies as follows:
+ * general format ("smb:" only; we do not look for "cifs:").
*
*
* We accept:
@@ -169,37 +211,28 @@ decode_urlpart(char *segment, size_t sizeof_segment)
*
* Meaning of URLs:
*
- * smb:// show all workgroups known by the first master browser found
- * smb://?mb=.any same as smb:// (i.e. without any options)
- *
- * smb://?mb=.all show all workgroups known by every master browser found.
- * Why might you want this? In an "appliance" application
- * where the workgroup/domain being used on the local network
- * is not known ahead of time, but where one wanted to
- * provide network services via samba, a unique workgroup
- * could be used. However, when the appliance is first
- * started, the local samba instance's master browser has not
- * synchronized with the other master browser(s) on the
- * network (and might not synchronize for 12 minutes) and
- * therefore is not aware of the workgroup/ domain names
- * available on the network. This option may be used to
- * overcome the problem of a libsmbclient application
- * arbitrarily selecting the local (still ignorant) master
- * browser to obtain its list of workgroups/domains and
- * getting back a practically emmpty list. By requesting
- * the list of workgroups/domains from each found master
- * browser on the local network, a complete list of
- * workgroups/domains can be built.
+ * smb:// Show all workgroups.
*
- * smb://?mb=name NOT YET IMPLEMENTED -- show all workgroups known by the
- * master browser whose name is "name"
+ * The method of locating the list of workgroups varies
+ * depending upon the setting of the context variable
+ * context->options.browse_max_lmb_count. This value
+ * determine the maximum number of local master browsers to
+ * query for the list of workgroups. In order to ensure that
+ * a complete list of workgroups is obtained, all master
+ * browsers must be queried, but if there are many
+ * workgroups, the time spent querying can begin to add up.
+ * For small networks (not many workgroups), it is suggested
+ * that this variable be set to 0, indicating query all local
+ * master browsers. When the network has many workgroups, a
+ * reasonable setting for this variable might be around 3.
*
* smb://name/ if name<1D> or name<1B> exists, list servers in
* workgroup, else, if name<20> exists, list all shares
* for server ...
*
- * If "options" are provided, this function returns the entire option list as
- * a string, for later parsing by the caller.
+ * If "options" are provided, this function returns the entire option list as a
+ * string, for later parsing by the caller. Note that currently, no options
+ * are supported.
*/
static const char *smbc_prefix = "smb:";
@@ -246,7 +279,7 @@ smbc_parse_path(SMBCCTX *context,
p += 2; /* Skip the double slash */
/* See if any options were specified */
- if ( (q = strrchr(p, '?')) != NULL ) {
+ if ((q = strrchr(p, '?')) != NULL ) {
/* There are options. Null terminate here and point to them */
*q++ = '\0';
@@ -333,11 +366,11 @@ smbc_parse_path(SMBCCTX *context,
all_string_sub(path, "/", "\\", 0);
decoding:
- decode_urlpart(path, path_len);
- decode_urlpart(server, server_len);
- decode_urlpart(share, share_len);
- decode_urlpart(user, user_len);
- decode_urlpart(password, password_len);
+ (void) smbc_urldecode(path, path, path_len);
+ (void) smbc_urldecode(server, server, server_len);
+ (void) smbc_urldecode(share, share, share_len);
+ (void) smbc_urldecode(user, user, user_len);
+ (void) smbc_urldecode(password, password, password_len);
return 0;
}
@@ -352,28 +385,8 @@ static int smbc_check_options(char *server, char *share, char *path, char *optio
/* No options at all is always ok */
if (! *options) return 0;
- /*
- * For right now, we only support a very few options possibilities.
- * No options are supported if server, share, or path are not empty.
- * If all are empty, then we support the following two choices right
- * now:
- *
- * mb=.any
- * mb=.all
- */
- if ((*server || *share || *path) && *options) {
- /* Invalid: options provided with server, share, or path */
- DEBUG(1, ("Found unsupported options (%s) with non-empty server, share, or path\n", options));
- return -1;
- }
-
- if (strcmp(options, "mb=.any") != 0 &&
- strcmp(options, "mb=.all") != 0) {
- DEBUG(1, ("Found unsupported options (%s)\n", options));
- return -1;
- }
-
- return 0;
+ /* Currently, we don't support any options. */
+ return -1;
}
/*
@@ -452,8 +465,6 @@ int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv)
context->callbacks.remove_cached_srv_fn(context, srv);
- SAFE_FREE(srv);
-
return 0;
}
@@ -471,7 +482,7 @@ SMBCSRV *find_server(SMBCCTX *context,
srv = context->callbacks.get_cached_srv_fn(context, server, share,
workgroup, username);
-
+
if (!auth_called && !srv && (!username[0] || !password[0])) {
context->callbacks.auth_fn(server, share,
workgroup, sizeof(fstring),
@@ -512,6 +523,7 @@ SMBCSRV *find_server(SMBCCTX *context,
*/
goto check_server_cache;
}
+
return srv;
}
@@ -541,6 +553,8 @@ SMBCSRV *smbc_server(SMBCCTX *context,
pstring ipenv;
struct in_addr ip;
int tried_reverse = 0;
+ int port_try_first;
+ int port_try_next;
zero_ip(&ip);
ZERO_STRUCT(c);
@@ -552,25 +566,56 @@ SMBCSRV *smbc_server(SMBCCTX *context,
srv = find_server(context, server, share,
workgroup, username, password);
- if (srv)
+
+ /*
+ * If we found a connection and we're only allowed one share per
+ * server...
+ */
+ if (srv && *share != '\0' && context->internal->options.one_share_per_server) {
+
+ /*
+ * ... then if there's no current connection to the share,
+ * connect to it. find_server(), or rather the function
+ * pointed to by context->callbacks.get_cached_srv_fn which
+ * was called by find_server(), will have issued a tree
+ * disconnect if the requested share is not the same as the
+ * one that was already connected.
+ */
+ if (srv->cli.cnum == (uint16) -1) {
+ /* Ensure we have accurate auth info */
+ context->callbacks.auth_fn(server, share,
+ workgroup, sizeof(fstring),
+ username, sizeof(fstring),
+ password, sizeof(fstring));
+
+ if (! cli_send_tconX(&srv->cli, share, "?????",
+ password, strlen(password)+1)) {
+
+ errno = smbc_errno(context, &srv->cli);
+ cli_shutdown(&srv->cli);
+ context->callbacks.remove_cached_srv_fn(context, srv);
+ srv = NULL;
+ }
+
+ /* Regenerate the dev value since it's based on both server and share */
+ if (srv) {
+ srv->dev = (dev_t)(str_checksum(server) ^ str_checksum(share));
+ }
+ }
+ }
+
+ /* If we have a connection... */
+ if (srv) {
+
+ /* ... then we're done here. Give 'em what they came for. */
return srv;
+ }
make_nmb_name(&calling, context->netbios_name, 0x0);
make_nmb_name(&called , server, 0x20);
DEBUG(4,("smbc_server: server_n=[%s] server=[%s]\n", server_n, server));
-#if 0 /* djl: obsolete code? neither group nor p is used beyond here */
- if ((p=strchr_m(server_n,'#')) &&
- (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
-
- fstrcpy(group, server_n);
- p = strchr_m(group,'#');
- *p = 0;
-
- }
-#endif
-
DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
again:
@@ -593,18 +638,31 @@ SMBCSRV *smbc_server(SMBCCTX *context,
c.timeout = context->timeout;
- /* Force use of port 139 for first try, so browse lists can work */
- c.port = 139;
+ /*
+ * Force use of port 139 for first try if share is $IPC, empty, or
+ * null, so browse lists can work
+ */
+ if (share == NULL || *share == '\0' || strcmp(share, "IPC$") == 0)
+ {
+ port_try_first = 139;
+ port_try_next = 445;
+ }
+ else
+ {
+ port_try_first = 445;
+ port_try_next = 139;
+ }
+
+ c.port = port_try_first;
if (!cli_connect(&c, server_n, &ip)) {
- /*
- * Port 139 connection failed. Try port 445 to handle
- * connections to newer (e.g. XP) hosts with NetBIOS disabled.
- */
- c.port = 445;
+
+ /* First connection attempt failed. Try alternate port. */
+ c.port = port_try_next;
+
if (!cli_connect(&c, server_n, &ip)) {
- cli_shutdown(&c);
- errno = ENETUNREACH;
+ cli_shutdown(&c);
+ errno = ETIMEDOUT;
return NULL;
}
}
@@ -625,7 +683,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server));
- errno = ENOENT;
+ errno = ETIMEDOUT;
return NULL;
}
@@ -639,7 +697,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
}
}
- errno = ENOENT;
+ errno = ETIMEDOUT;
return NULL;
}
@@ -647,7 +705,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
if (!cli_negprot(&c)) {
cli_shutdown(&c);
- errno = ENOENT;
+ errno = ETIMEDOUT;
return NULL;
}
@@ -732,10 +790,11 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
SMBCSRV *ipc_srv=NULL;
/*
- * See if we've already created this special connection. Reference
- * our "special" share name 'IPC$$'.
+ * See if we've already created this special connection. Reference our
+ * "special" share name '*IPC$', which is an impossible real share name
+ * due to the leading asterisk.
*/
- ipc_srv = find_server(context, server, "IPC$$",
+ ipc_srv = find_server(context, server, "*IPC$",
workgroup, username, password);
if (!ipc_srv) {
@@ -801,7 +860,7 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
errno = 0; /* let cache function set errno if it likes */
if (context->callbacks.add_cached_srv_fn(context, ipc_srv,
server,
- "IPC$$",
+ "*IPC$",
workgroup,
username)) {
DEBUG(3, (" Failed to add server to cache\n"));
@@ -1621,21 +1680,15 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint
{
struct smbc_dirent *dirent;
int size;
- char *u_name = NULL, *u_comment = NULL;
- size_t u_name_len = 0, u_comment_len = 0;
-
- if (name)
- u_name_len = push_utf8_allocate(&u_name, name);
- if (comment)
- u_comment_len = push_utf8_allocate(&u_comment, comment);
+ int name_length = (name == NULL ? 0 : strlen(name));
+ int comment_len = (comment == NULL ? 0 : strlen(comment));
/*
* Allocate space for the dirent, which must be increased by the
- * size of the name and the comment and 1 for the null on the comment.
- * The null on the name is already accounted for.
+ * size of the name and the comment and 1 each for the null terminator.
*/
- size = sizeof(struct smbc_dirent) + u_name_len + u_comment_len + 1;
+ size = sizeof(struct smbc_dirent) + name_length + comment_len + 2;
dirent = SMB_MALLOC(size);
@@ -1682,18 +1735,15 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint
dir->dir_end->dirent = dirent;
dirent->smbc_type = type;
- dirent->namelen = u_name_len;
- dirent->commentlen = u_comment_len;
+ dirent->namelen = name_length;
+ dirent->commentlen = comment_len;
dirent->dirlen = size;
- strncpy(dirent->name, (u_name?u_name:""), dirent->namelen + 1);
+ strncpy(dirent->name, (name?name:""), dirent->namelen + 1);
dirent->comment = (char *)(&dirent->name + dirent->namelen + 1);
- strncpy(dirent->comment, (u_comment?u_comment:""), dirent->commentlen + 1);
+ strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1);
- SAFE_FREE(u_comment);
- SAFE_FREE(u_name);
-
return 0;
}
@@ -1781,7 +1831,7 @@ list_fn(const char *name, uint32 type, const char *comment, void *state)
}
static void
-dir_list_fn(file_info *finfo, const char *mask, void *state)
+dir_list_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
{
if (add_dirent((SMBCFILE *)state, finfo->name, "",
@@ -1807,14 +1857,14 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
if (!context || !context->internal ||
!context->internal->_initialized) {
DEBUG(4, ("no valid context\n"));
- errno = EINVAL;
+ errno = EINVAL + 8192;
return NULL;
}
if (!fname) {
DEBUG(4, ("no valid fname\n"));
- errno = EINVAL;
+ errno = EINVAL + 8193;
return NULL;
}
@@ -1826,7 +1876,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
password, sizeof(password),
options, sizeof(options))) {
DEBUG(4, ("no valid path\n"));
- errno = EINVAL;
+ errno = EINVAL + 8194;
return NULL;
}
@@ -1835,7 +1885,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
/* Ensure the options are valid */
if (smbc_check_options(server, share, path, options)) {
DEBUG(4, ("unacceptable options (%s)\n", options));
- errno = EINVAL;
+ errno = EINVAL + 8195;
return NULL;
}
@@ -1861,108 +1911,11 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
dir->file = False;
dir->dir_list = dir->dir_next = dir->dir_end = NULL;
- if (server[0] == (char)0 &&
- (! *options || strcmp(options, "mb=.any") == 0)) {
- struct in_addr server_ip;
- if (share[0] != (char)0 || path[0] != (char)0) {
-
- errno = EINVAL;
- if (dir) {
- SAFE_FREE(dir->fname);
- SAFE_FREE(dir);
- }
- return NULL;
- }
-
- /*
- * We have server and share and path empty ... so list the
- * workgroups first try to get the LMB for our workgroup, and
- * if that fails, try the DMB
- */
-
- pstrcpy(workgroup, lp_workgroup());
-
- if (!find_master_ip(workgroup, &server_ip)) {
- struct user_auth_info u_info;
- struct cli_state *cli;
-
- DEBUG(4, ("Unable to find master browser for workgroup %s\n",
- workgroup));
-
- /* find the name of the server ... */
- pstrcpy(u_info.username, user);
- pstrcpy(u_info.password, password);
-
- if (!(cli = get_ipc_connect_master_ip_bcast(workgroup, &u_info))) {
- DEBUG(4, ("Unable to find master browser by "
- "broadcast\n"));
- errno = ENOENT;
- return NULL;
- }
-
- fstrcpy(server, cli->desthost);
-
- cli_shutdown(cli);
- } else {
- /*
- * Do a name status query to find out the name of the
- * master browser. We use <01><02>__MSBROWSE__<02>#01 if
- * *#00 fails because a domain master browser will not
- * respond to a wildcard query (or, at least, an NT4
- * server acting as the domain master browser will not).
- *
- * We might be able to use ONLY the query on MSBROWSE, but
- * that's not yet been tested with all Windows versions,
- * so until it is, leave the original wildcard query as
- * the first choice and fall back to MSBROWSE if the
- * wildcard query fails.
- */
- if (!name_status_find("*", 0, 0x20, server_ip, server) &&
- !name_status_find(MSBROWSE, 1, 0x1b, server_ip, server)) {
- errno = ENOENT;
- return NULL;
- }
- }
-
- DEBUG(4, ("using workgroup %s %s\n", workgroup, server));
-
- /*
- * Get a connection to IPC$ on the server if we do not already
- * have one
- */
-
- srv = smbc_server(context, server, "IPC$", workgroup, user, password);
- if (!srv) {
-
- if (dir) {
- SAFE_FREE(dir->fname);
- SAFE_FREE(dir);
- }
- return NULL;
- }
-
- dir->srv = srv;
- dir->dir_type = SMBC_WORKGROUP;
-
- /* Now, list the stuff ... */
-
- if (!cli_NetServerEnum(&srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, list_fn,
- (void *)dir)) {
-
- DEBUG(1, ("Could not enumerate domains using '%s'\n", workgroup));
- if (dir) {
- SAFE_FREE(dir->fname);
- SAFE_FREE(dir);
- }
-
- return NULL;
-
- }
- } else if (server[0] == (char)0 &&
- (! *options || strcmp(options, "mb=.all") == 0)) {
+ if (server[0] == (char)0) {
int i;
int count;
+ int max_lmb_count;
struct ip_service *ip_list;
struct ip_service server_addr;
struct user_auth_info u_info;
@@ -1970,7 +1923,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
if (share[0] != (char)0 || path[0] != (char)0) {
- errno = EINVAL;
+ errno = EINVAL + 8196;
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
@@ -1978,6 +1931,11 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
return NULL;
}
+ /* Determine how many local master browsers to query */
+ max_lmb_count = (context->internal->options.browse_max_lmb_count == 0
+ ? INT_MAX
+ : context->internal->options.browse_max_lmb_count);
+
pstrcpy(u_info.username, user);
pstrcpy(u_info.password, password);
@@ -2001,11 +1959,10 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
count = 1;
}
- for (i = 0; i < count; i++) {
+ for (i = 0; i < count && i < max_lmb_count; i++) {
DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, &u_info);
-
/* cli == NULL is the master browser refused to talk or
could not be found */
if ( !cli )
@@ -2060,7 +2017,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
if (path[0] != (char)0) { /* Should not have empty share with path */
- errno = EINVAL;
+ errno = EINVAL + 8197;
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
@@ -2254,12 +2211,54 @@ static int smbc_closedir_ctx(SMBCCTX *context, SMBCFILE *dir)
}
+static void smbc_readdir_internal(SMBCCTX * context,
+ struct smbc_dirent *dest,
+ struct smbc_dirent *src,
+ int max_namebuf_len)
+{
+ if (context->internal->options.urlencode_readdir_entries) {
+
+ /* url-encode the name. get back remaining buffer space */
+ max_namebuf_len =
+ smbc_urlencode(dest->name, src->name, max_namebuf_len);
+
+ /* We now know the name length */
+ dest->namelen = strlen(dest->name);
+
+ /* Save the pointer to the beginning of the comment */
+ dest->comment = dest->name + dest->namelen + 1;
+
+ /* Copy the comment */
+ strncpy(dest->comment, src->comment, max_namebuf_len);
+
+ /* Ensure the comment is null terminated */
+ if (max_namebuf_len > src->commentlen) {
+ dest->comment[src->commentlen] = '\0';
+ } else {
+ dest->comment[max_namebuf_len - 1] = '\0';
+ }
+
+ /* Save other fields */
+ dest->smbc_type = src->smbc_type;
+ dest->commentlen = strlen(dest->comment);
+ dest->dirlen = ((dest->comment + dest->commentlen + 1) -
+ (char *) dest);
+ } else {
+
+ /* No encoding. Just copy the entry as is. */
+ memcpy(dest, src, src->dirlen);
+ dest->comment = (char *)(&dest->name + src->namelen + 1);
+ }
+
+}
+
/*
* Routine to get a directory entry
*/
struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
{
+ int maxlen;
struct smbc_dirent *dirp, *dirent;
/* Check that all is ok first ... */
@@ -2292,37 +2291,40 @@ struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
if (!dir->dir_next) {
return NULL;
}
- else {
- dirent = dir->dir_next->dirent;
- if (!dirent) {
+ dirent = dir->dir_next->dirent;
+ if (!dirent) {
- errno = ENOENT;
- return NULL;
+ errno = ENOENT;
+ return NULL;
- }
+ }
- /* Hmmm, do I even need to copy it? */
+ dirp = (struct smbc_dirent *)context->internal->_dirent;
+ maxlen = (sizeof(context->internal->_dirent) -
+ sizeof(struct smbc_dirent));
- memcpy(context->internal->_dirent, dirent, dirent->dirlen); /* Copy the dirent */
- dirp = (struct smbc_dirent *)context->internal->_dirent;
- dirp->comment = (char *)(&dirp->name + dirent->namelen + 1);
- dir->dir_next = dir->dir_next->next;
+ smbc_readdir_internal(context, dirp, dirent, maxlen);
- return (struct smbc_dirent *)context->internal->_dirent;
- }
+ dir->dir_next = dir->dir_next->next;
+ return dirp;
}
/*
* Routine to get directory entries
*/
-static int smbc_getdents_ctx(SMBCCTX *context, SMBCFILE *dir, struct smbc_dirent *dirp, int count)
+static int smbc_getdents_ctx(SMBCCTX *context,
+ SMBCFILE *dir,
+ struct smbc_dirent *dirp,
+ int count)
{
- struct smbc_dir_list *dirlist;
- int rem = count, reqd;
+ int rem = count;
+ int reqd;
+ int maxlen;
char *ndir = (char *)dirp;
+ struct smbc_dir_list *dirlist;
/* Check that all is ok first ... */
@@ -2364,8 +2366,15 @@ static int smbc_getdents_ctx(SMBCCTX *context, SMBCFILE *dir, struct smbc_dirent
}
- if (rem < (reqd = (sizeof(struct smbc_dirent) + dirlist->dirent->namelen +
- dirlist->dirent->commentlen + 1))) {
+ /* Do urlencoding of next entry, if so selected */
+ dirent = (struct smbc_dirent *)context->internal->_dirent;
+ maxlen = (sizeof(context->internal->_dirent) -
+ sizeof(struct smbc_dirent));
+ smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen);
+
+ reqd = dirent->dirlen;
+
+ if (rem < reqd) {
if (rem < count) { /* We managed to copy something */
@@ -2382,12 +2391,12 @@ static int smbc_getdents_ctx(SMBCCTX *context, SMBCFILE *dir, struct smbc_dirent
}
- dirent = dirlist->dirent;
-
memcpy(ndir, dirent, reqd); /* Copy the data in ... */
((struct smbc_dirent *)ndir)->comment =
- (char *)(&((struct smbc_dirent *)ndir)->name + dirent->namelen + 1);
+ (char *)(&((struct smbc_dirent *)ndir)->name +
+ dirent->namelen +
+ 1);
ndir += reqd;
@@ -2453,27 +2462,6 @@ static int smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode)
}
- /* if (strncmp(srv->cli.dev, "IPC", 3) == 0) {
-
- mode = aDIR | aRONLY;
-
- }
- else if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
-
- if (strcmp(path, "\\") == 0) {
-
- mode = aDIR | aRONLY;
-
- }
- else {
-
- mode = aRONLY;
- smbc_stat_printjob(srv, path, &size, &m_time);
- c_time = a_time = m_time;
-
- }
- else { */
-
if (!cli_mkdir(&srv->cli, path)) {
errno = smbc_errno(context, &srv->cli);
@@ -2491,7 +2479,7 @@ static int smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode)
static int smbc_rmdir_dirempty = True;
-static void rmdir_list_fn(file_info *finfo, const char *mask, void *state)
+static void rmdir_list_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
{
if (strncmp(finfo->name, ".", 1) != 0 && strncmp(finfo->name, "..", 2) != 0)
@@ -3238,10 +3226,93 @@ static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx,
}
+/* Obtain the current dos attributes */
+static DOS_ATTR_DESC *dos_attr_query(SMBCCTX *context,
+ TALLOC_CTX *ctx,
+ const char *filename,
+ SMBCSRV *srv)
+{
+ time_t m_time = 0, a_time = 0, c_time = 0;
+ size_t size = 0;
+ uint16 mode = 0;
+ SMB_INO_T inode = 0;
+ DOS_ATTR_DESC *ret;
+
+ ret = talloc(ctx, sizeof(DOS_ATTR_DESC));
+ if (!ret) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ /* Obtain the DOS attributes */
+ if (!smbc_getatr(context, srv, filename, &mode, &size,
+ &c_time, &a_time, &m_time, &inode)) {
+
+ errno = smbc_errno(context, &srv->cli);
+ DEBUG(5, ("dos_attr_query Failed to query old attributes\n"));
+ return NULL;
+
+ }
+
+ ret->mode = mode;
+ ret->size = size;
+ ret->a_time = a_time;
+ ret->c_time = c_time;
+ ret->m_time = m_time;
+ ret->inode = inode;
+
+ return ret;
+}
+
+
+/* parse a ascii version of a security descriptor */
+static void dos_attr_parse(SMBCCTX *context,
+ DOS_ATTR_DESC *dad,
+ SMBCSRV *srv,
+ char *str)
+{
+ const char *p = str;
+ fstring tok;
+
+ while (next_token(&p, tok, "\t,\r\n", sizeof(tok))) {
+
+ if (StrnCaseCmp(tok, "MODE:", 5) == 0) {
+ dad->mode = strtol(tok+5, NULL, 16);
+ continue;
+ }
+
+ if (StrnCaseCmp(tok, "SIZE:", 5) == 0) {
+ dad->size = strtoll(tok+5, NULL, 10);
+ continue;
+ }
+
+ if (StrnCaseCmp(tok, "A_TIME:", 7) == 0) {
+ dad->a_time = strtoll(tok+7, NULL, 10);
+ continue;
+ }
+
+ if (StrnCaseCmp(tok, "C_TIME:", 7) == 0) {
+ dad->c_time = strtoll(tok+7, NULL, 10);
+ continue;
+ }
+
+ if (StrnCaseCmp(tok, "M_TIME:", 7) == 0) {
+ dad->m_time = strtoll(tok+7, NULL, 10);
+ continue;
+ }
+
+ if (StrnCaseCmp(tok, "INODE:", 6) == 0) {
+ dad->inode = strtoll(tok+6, NULL, 10);
+ continue;
+ }
+ }
+}
+
+
/*****************************************************
retrieve the acls for a file
*******************************************************/
-static int cacl_get(TALLOC_CTX *ctx, struct cli_state *cli,
+static int cacl_get(SMBCCTX *context, TALLOC_CTX *ctx, SMBCSRV *srv,
struct cli_state *ipc_cli, POLICY_HND *pol,
char *filename, char *name, char *buf, int bufsize)
{
@@ -3249,166 +3320,446 @@ static int cacl_get(TALLOC_CTX *ctx, struct cli_state *cli,
int n = 0;
int n_used;
BOOL all;
+ BOOL all_nt;
+ BOOL all_dos;
+ BOOL some_nt;
+ BOOL some_dos;
BOOL numeric = True;
BOOL determine_size = (bufsize == 0);
int fnum = -1;
SEC_DESC *sd;
fstring sidstr;
char *p;
+ time_t m_time = 0, a_time = 0, c_time = 0;
+ size_t size = 0;
+ uint16 mode = 0;
+ SMB_INO_T ino = 0;
+ struct cli_state *cli = &srv->cli;
- fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
+ all = (StrnCaseCmp(name, "system.*", 8) == 0);
+ all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0);
+ all_dos = (StrnCaseCmp(name, "system.dos_attr.*", 17) == 0);
+ some_nt = (StrnCaseCmp(name, "system.nt_sec_desc.", 19) == 0);
+ some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0);
+ numeric = (* (name + strlen(name) - 1) != '+');
- if (fnum == -1) {
- DEBUG(5, ("cacl_get failed to open %s: %s\n",
- filename, cli_errstr(cli)));
- errno = 0;
- return -1;
- }
+ n_used = 0;
- sd = cli_query_secdesc(cli, fnum, ctx);
+ /*
+ * If we are (possibly) talking to an NT or new system and some NT
+ * attributes have been requested...
+ */
+ if (ipc_cli && (all || some_nt)) {
+ /* Point to the portion after "system.nt_sec_desc." */
+ name += 19; /* if (all) this will be invalid but unused */
- if (!sd) {
- DEBUG(5, ("cacl_get Failed to query old descriptor\n"));
- errno = 0;
- return -1;
- }
+ /* ... then obtain any NT attributes which were requested */
+ fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
- cli_close(cli, fnum);
+ if (fnum == -1) {
+ DEBUG(5, ("cacl_get failed to open %s: %s\n",
+ filename, cli_errstr(cli)));
+ errno = 0;
+ return -1;
+ }
- all = (*name == '*');
- numeric = (* (name + strlen(name) - 1) != '+');
+ sd = cli_query_secdesc(cli, fnum, ctx);
- n_used = 0;
+ if (!sd) {
+ DEBUG(5,
+ ("cacl_get Failed to query old descriptor\n"));
+ errno = 0;
+ return -1;
+ }
- if (all) {
- if (determine_size) {
- p = talloc_asprintf(ctx,
- "REVISION:%d", sd->revision);
- if (!p) {
- errno = ENOMEM;
- return -1;
+ cli_close(cli, fnum);
+
+ if (all || all_nt) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ "REVISION:%d",
+ sd->revision);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ "REVISION:%d", sd->revision);
}
- n = strlen(p);
- } else {
- n = snprintf(buf, bufsize,
- "REVISION:%d", sd->revision);
- }
- } else if (StrCaseCmp(name, "revision") == 0) {
- if (determine_size) {
- p = talloc_asprintf(ctx, "%d", sd->revision);
- if (!p) {
- errno = ENOMEM;
- return -1;
+ } else if (StrCaseCmp(name, "revision") == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%d", sd->revision);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "%d", sd->revision);
}
- n = strlen(p);
- } else {
- n = snprintf(buf, bufsize, "%d", sd->revision);
}
- }
- if (!determine_size && n > bufsize) {
- errno = ERANGE;
- return -1;
- }
- buf += n;
- n_used += n;
- bufsize -= n;
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
- /* Get owner and group sid */
+ /* Get owner and group sid */
- if (sd->owner_sid) {
- convert_sid_to_string(ipc_cli, pol,
- sidstr, numeric, sd->owner_sid);
- } else {
- fstrcpy(sidstr, "");
- }
+ if (sd->owner_sid) {
+ convert_sid_to_string(ipc_cli, pol,
+ sidstr, numeric, sd->owner_sid);
+ } else {
+ fstrcpy(sidstr, "");
+ }
- if (all) {
- if (determine_size) {
- p = talloc_asprintf(ctx, ",OWNER:%s", sidstr);
- if (!p) {
- errno = ENOMEM;
- return -1;
+ if (all || all_nt) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, ",OWNER:%s", sidstr);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",OWNER:%s", sidstr);
}
- n = strlen(p);
+ } else if (StrnCaseCmp(name, "owner", 5) == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%s", sidstr);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "%s", sidstr);
+ }
+ }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
+
+ if (sd->grp_sid) {
+ convert_sid_to_string(ipc_cli, pol,
+ sidstr, numeric, sd->grp_sid);
} else {
- n = snprintf(buf, bufsize, ",OWNER:%s", sidstr);
+ fstrcpy(sidstr, "");
}
- } else if (StrnCaseCmp(name, "owner", 5) == 0) {
- if (determine_size) {
- p = talloc_asprintf(ctx, "%s", sidstr);
- if (!p) {
- errno = ENOMEM;
+
+ if (all || all_nt) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, ",GROUP:%s", sidstr);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",GROUP:%s", sidstr);
+ }
+ } else if (StrnCaseCmp(name, "group", 5) == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%s", sidstr);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "%s", sidstr);
+ }
+ }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
+
+ /* Add aces to value buffer */
+ for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+
+ SEC_ACE *ace = &sd->dacl->ace[i];
+ convert_sid_to_string(ipc_cli, pol,
+ sidstr, numeric, &ace->trustee);
+
+ if (all || all_nt) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ ",ACL:"
+ "%s:%d/%d/0x%08x",
+ sidstr,
+ ace->type,
+ ace->flags,
+ ace->info.mask);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",ACL:%s:%d/%d/0x%08x",
+ sidstr,
+ ace->type,
+ ace->flags,
+ ace->info.mask);
+ }
+ } else if ((StrnCaseCmp(name, "acl", 3) == 0 &&
+ StrCaseCmp(name + 3, sidstr) == 0) ||
+ (StrnCaseCmp(name, "acl+", 4) == 0 &&
+ StrCaseCmp(name + 4, sidstr) == 0)) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ "%d/%d/0x%08x",
+ ace->type,
+ ace->flags,
+ ace->info.mask);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ "%d/%d/0x%08x",
+ ace->type,
+ ace->flags,
+ ace->info.mask);
+ }
+ }
+ if (n > bufsize) {
+ errno = ERANGE;
return -1;
}
- n = strlen(p);
- } else {
- n = snprintf(buf, bufsize, "%s", sidstr);
+ buf += n;
+ n_used += n;
+ bufsize -= n;
}
- }
- if (!determine_size && n > bufsize) {
- errno = ERANGE;
- return -1;
+ /* Restore name pointer to its original value */
+ name -= 19;
}
- buf += n;
- n_used += n;
- bufsize -= n;
- if (sd->grp_sid) {
- convert_sid_to_string(ipc_cli, pol,
- sidstr, numeric, sd->grp_sid);
- } else {
- fstrcpy(sidstr, "");
- }
+ if (all || some_dos) {
+ /* Point to the portion after "system.dos_attr." */
+ name += 16; /* if (all) this will be invalid but unused */
- if (all) {
- if (determine_size) {
- p = talloc_asprintf(ctx, ",GROUP:%s", sidstr);
- if (!p) {
- errno = ENOMEM;
- return -1;
+ /* Obtain the DOS attributes */
+ if (!smbc_getatr(context, srv, filename, &mode, &size,
+ &c_time, &a_time, &m_time, &ino)) {
+
+ errno = smbc_errno(context, &srv->cli);
+ return -1;
+
+ }
+
+ if (all || all_dos) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ "%sMODE:0x%x",
+ (ipc_cli &&
+ (all || some_nt)
+ ? ","
+ : ""),
+ mode);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ "%sMODE:0x%x",
+ (ipc_cli &&
+ (all || some_nt)
+ ? ","
+ : ""),
+ mode);
+ }
+ } else if (StrCaseCmp(name, "mode") == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "0x%x", mode);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "0x%x", mode);
}
- n = strlen(p);
- } else {
- n = snprintf(buf, bufsize, ",GROUP:%s", sidstr);
}
- } else if (StrnCaseCmp(name, "group", 5) == 0) {
- if (determine_size) {
- p = talloc_asprintf(ctx, "%s", sidstr);
- if (!p) {
- errno = ENOMEM;
- return -1;
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
+
+ if (all || all_dos) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ ",SIZE:%llu",
+ (unsigned long long) size);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",SIZE:%llu",
+ (unsigned long long) size);
+ }
+ } else if (StrCaseCmp(name, "size") == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ "%llu",
+ (unsigned long long) size);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ "%llu",
+ (unsigned long long) size);
}
- n = strlen(p);
- } else {
- n = snprintf(buf, bufsize, "%s", sidstr);
}
- }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
- if (!determine_size && n > bufsize) {
- errno = ERANGE;
- return -1;
- }
- buf += n;
- n_used += n;
- bufsize -= n;
+ if (all || all_dos) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ ",C_TIME:%lu", c_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",C_TIME:%lu", c_time);
+ }
+ } else if (StrCaseCmp(name, "c_time") == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%lu", c_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "%lu", c_time);
+ }
+ }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
- /* Add aces to value buffer */
- for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
+ if (all || all_dos) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ ",A_TIME:%lu", a_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",A_TIME:%lu", a_time);
+ }
+ } else if (StrCaseCmp(name, "a_time") == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%lu", a_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "%lu", a_time);
+ }
+ }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
- SEC_ACE *ace = &sd->dacl->ace[i];
- convert_sid_to_string(ipc_cli, pol,
- sidstr, numeric, &ace->trustee);
+ if (all || all_dos) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx,
+ ",M_TIME:%lu", m_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize,
+ ",M_TIME:%lu", m_time);
+ }
+ } else if (StrCaseCmp(name, "m_time") == 0) {
+ if (determine_size) {
+ p = talloc_asprintf(ctx, "%lu", m_time);
+ if (!p) {
+ errno = ENOMEM;
+ return -1;
+ }
+ n = strlen(p);
+ } else {
+ n = snprintf(buf, bufsize, "%lu", m_time);
+ }
+ }
+
+ if (!determine_size && n > bufsize) {
+ errno = ERANGE;
+ return -1;
+ }
+ buf += n;
+ n_used += n;
+ bufsize -= n;
- if (all) {
+ if (all || all_dos) {
if (determine_size) {
- p = talloc_asprintf(ctx,
- ",ACL:%s:%d/%d/0x%08x",
- sidstr,
- ace->type,
- ace->flags,
- ace->info.mask);
+ p = talloc_asprintf(ctx,
+ ",INODE:%llu",
+ (unsigned long long) ino);
if (!p) {
errno = ENOMEM;
return -1;
@@ -3416,22 +3767,14 @@ static int cacl_get(TALLOC_CTX *ctx, struct cli_state *cli,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- ",ACL:%s:%d/%d/0x%08x",
- sidstr,
- ace->type,
- ace->flags,
- ace->info.mask);
+ ",INODE:%llu",
+ (unsigned long long) ino);
}
- } else if ((StrnCaseCmp(name, "acl", 3) == 0 &&
- StrCaseCmp(name + 3, sidstr) == 0) ||
- (StrnCaseCmp(name, "acl+", 4) == 0 &&
- StrCaseCmp(name + 4, sidstr) == 0)) {
+ } else if (StrCaseCmp(name, "inode") == 0) {
if (determine_size) {
- p = talloc_asprintf(ctx,
- "%d/%d/0x%08x",
- ace->type,
- ace->flags,
- ace->info.mask);
+ p = talloc_asprintf(ctx,
+ "%llu",
+ (unsigned long long) ino);
if (!p) {
errno = ENOMEM;
return -1;
@@ -3439,23 +3782,28 @@ static int cacl_get(TALLOC_CTX *ctx, struct cli_state *cli,
n = strlen(p);
} else {
n = snprintf(buf, bufsize,
- "%d/%d/0x%08x",
- ace->type, ace->flags, ace->info.mask);
+ "%llu",
+ (unsigned long long) ino);
}
}
- if (n > bufsize) {
+
+ if (!determine_size && n > bufsize) {
errno = ERANGE;
return -1;
}
buf += n;
n_used += n;
bufsize -= n;
- }
+
+ /* Restore name pointer to its original value */
+ name -= 16;
+ }
if (n_used == 0) {
errno = ENOATTR;
return -1;
}
+
return n_used;
}
@@ -3492,8 +3840,7 @@ static int cacl_set(TALLOC_CTX *ctx, struct cli_state *cli,
the_acl = p + 1;
}
- sd = sec_desc_parse(ctx, ipc_cli, pol,
- numeric, (char *) the_acl);
+ sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, the_acl);
if (!sd) {
errno = EINVAL;
@@ -3653,12 +4000,14 @@ int smbc_setxattr_ctx(SMBCCTX *context,
int flags)
{
int ret;
+ int ret2;
SMBCSRV *srv;
SMBCSRV *ipc_srv;
fstring server, share, user, password, workgroup;
pstring path;
TALLOC_CTX *ctx;
POLICY_HND pol;
+ DOS_ATTR_DESC *dad;
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -3675,8 +4024,7 @@ int smbc_setxattr_ctx(SMBCCTX *context,
}
- DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n",
- fname, name, (int) size, (char *) value));
+ DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n", fname, name, (int) size, (const char*)value));
if (smbc_parse_path(context, fname,
server, sizeof(server),
@@ -3698,11 +4046,13 @@ int smbc_setxattr_ctx(SMBCCTX *context,
return -1; /* errno set by smbc_server */
}
- ipc_srv = smbc_attr_server(context, server, share,
- workgroup, user, password,
- &pol);
- if (!ipc_srv) {
- return -1;
+ if (! srv->no_nt_session) {
+ ipc_srv = smbc_attr_server(context, server, share,
+ workgroup, user, password,
+ &pol);
+ srv->no_nt_session = True;
+ } else {
+ ipc_srv = NULL;
}
ctx = talloc_init("smbc_setxattr");
@@ -3712,6 +4062,71 @@ int smbc_setxattr_ctx(SMBCCTX *context,
}
/*
+ * Are they asking to set the entire set of known attributes?
+ */
+ if (StrCaseCmp(name, "system.*") == 0 ||
+ StrCaseCmp(name, "system.*+") == 0) {
+ /* Yup. */
+ char *namevalue =
+ talloc_asprintf(ctx, "%s:%s", name+7, (const char *) value);
+ if (! namevalue) {
+ errno = ENOMEM;
+ ret = -1;
+ return -1;
+ }
+
+ if (ipc_srv) {
+ ret = cacl_set(ctx, &srv->cli,
+ &ipc_srv->cli, &pol, path,
+ namevalue,
+ (*namevalue == '*'
+ ? SMBC_XATTR_MODE_SET
+ : SMBC_XATTR_MODE_ADD),
+ flags);
+ } else {
+ ret = 0;
+ }
+
+ /* get a DOS Attribute Descriptor with current attributes */
+ dad = dos_attr_query(context, ctx, path, srv);
+ if (dad) {
+ /* Overwrite old with new, using what was provided */
+ dos_attr_parse(context, dad, srv, namevalue);
+
+ /* Set the new DOS attributes */
+#warning "Should try Set Path Info first, but it's not yet implemented"
+#if 0 /* not yet implemented */
+ if (! cli_setpathinfo(&srv->cli, path,
+ dad->c_time,
+ dad->a_time,
+ dad->m_time,
+ dad->mode)) {
+ if (!cli_setatr(&srv->cli, path,
+ dad->mode, dad->m_time)) {
+ errno = smbc_errno(context, &srv->cli);
+ }
+ }
+#else
+ if (!cli_setatr(&srv->cli, path,
+ dad->mode, dad->m_time)) {
+ errno = smbc_errno(context, &srv->cli);
+ }
+#endif
+ }
+
+ /* we only fail if both NT and DOS sets failed */
+ if (ret < 0 && ! dad) {
+ ret = -1; /* in case dad was null */
+ }
+ else {
+ ret = 0;
+ }
+
+ talloc_destroy(ctx);
+ return ret;
+ }
+
+ /*
* Are they asking to set an access control element or to set
* the entire access control list?
*/
@@ -3723,8 +4138,12 @@ int smbc_setxattr_ctx(SMBCCTX *context,
/* Yup. */
char *namevalue =
- talloc_asprintf(ctx, "%s:%s", name+19, (char *) value);
- if (! namevalue) {
+ talloc_asprintf(ctx, "%s:%s", name+19, (const char *) value);
+
+ if (! ipc_srv) {
+ ret = -1; /* errno set by smbc_server() */
+ }
+ else if (! namevalue) {
errno = ENOMEM;
ret = -1;
} else {
@@ -3748,8 +4167,13 @@ int smbc_setxattr_ctx(SMBCCTX *context,
/* Yup. */
char *namevalue =
- talloc_asprintf(ctx, "%s:%s", name+19, (char *) value);
- if (! namevalue) {
+ talloc_asprintf(ctx, "%s:%s", name+19, (const char *) value);
+
+ if (! ipc_srv) {
+
+ ret = -1; /* errno set by smbc_server() */
+ }
+ else if (! namevalue) {
errno = ENOMEM;
ret = -1;
} else {
@@ -3769,8 +4193,13 @@ int smbc_setxattr_ctx(SMBCCTX *context,
/* Yup. */
char *namevalue =
- talloc_asprintf(ctx, "%s:%s", name+19, (char *) value);
- if (! namevalue) {
+ talloc_asprintf(ctx, "%s:%s", name+19, (const char *) value);
+
+ if (! ipc_srv) {
+ /* errno set by smbc_server() */
+ ret = -1;
+ }
+ else if (! namevalue) {
errno = ENOMEM;
ret = -1;
} else {
@@ -3782,6 +4211,67 @@ int smbc_setxattr_ctx(SMBCCTX *context,
return ret;
}
+ /*
+ * Are they asking to set a DOS attribute?
+ */
+ if (StrCaseCmp(name, "system.dos_attr.*") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.mode") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.c_time") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.a_time") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.m_time") == 0) {
+
+ /* get a DOS Attribute Descriptor with current attributes */
+ dad = dos_attr_query(context, ctx, path, srv);
+ if (dad) {
+ char *namevalue =
+ talloc_asprintf(ctx, "%s:%s", name+16, (const char *) value);
+ if (! namevalue) {
+ errno = ENOMEM;
+ ret = -1;
+ } else {
+ /* Overwrite old with provided new params */
+ dos_attr_parse(context, dad, srv, namevalue);
+
+ /* Set the new DOS attributes */
+#warning "Should try Set Path Info first, but it's not yet implemented"
+#if 0 /* not yet implemented */
+ ret2 = cli_setpathinfo(&srv->cli, path,
+ dad->c_time,
+ dad->a_time,
+ dad->m_time,
+ dad->mode);
+ if (! ret2) {
+ ret2 = cli_setatr(&srv->cli, path,
+ dad->mode,
+ dad->m_time);
+ if (! ret2) {
+ errno = smbc_errno(context,
+ &srv->cli);
+ }
+ }
+#else
+ ret2 = cli_setatr(&srv->cli, path,
+ dad->mode, dad->m_time);
+ if (! ret2) {
+ errno = smbc_errno(context, &srv->cli);
+ }
+#endif
+
+ /* ret2 has True (success) / False (failure) */
+ if (ret2) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+ }
+ } else {
+ ret = -1;
+ }
+
+ talloc_destroy(ctx);
+ return ret;
+ }
+
/* Unsupported attribute name */
talloc_destroy(ctx);
errno = EINVAL;
@@ -3802,6 +4292,7 @@ int smbc_getxattr_ctx(SMBCCTX *context,
TALLOC_CTX *ctx;
POLICY_HND pol;
+
if (!context || !context->internal ||
!context->internal->_initialized) {
@@ -3839,11 +4330,15 @@ int smbc_getxattr_ctx(SMBCCTX *context,
return -1; /* errno set by smbc_server */
}
- ipc_srv = smbc_attr_server(context, server, share,
- workgroup, user, password,
- &pol);
- if (!ipc_srv) {
- return -1;
+ if (! srv->no_nt_session) {
+ ipc_srv = smbc_attr_server(context, server, share,
+ workgroup, user, password,
+ &pol);
+ if (! ipc_srv) {
+ srv->no_nt_session = True;
+ }
+ } else {
+ ipc_srv = NULL;
}
ctx = talloc_init("smbc:getxattr");
@@ -3853,7 +4348,9 @@ int smbc_getxattr_ctx(SMBCCTX *context,
}
/* Are they requesting a supported attribute? */
- if (StrCaseCmp(name, "system.nt_sec_desc.*") == 0 ||
+ if (StrCaseCmp(name, "system.*") == 0 ||
+ StrCaseCmp(name, "system.*+") == 0 ||
+ StrCaseCmp(name, "system.nt_sec_desc.*") == 0 ||
StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 ||
StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 ||
StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 ||
@@ -3861,13 +4358,19 @@ int smbc_getxattr_ctx(SMBCCTX *context,
StrCaseCmp(name, "system.nt_sec_desc.group") == 0 ||
StrCaseCmp(name, "system.nt_sec_desc.group+") == 0 ||
StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 ||
- StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0) {
+ StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0 ||
+ StrCaseCmp(name, "system.dos_attr.*") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.mode") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.size") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.c_time") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.a_time") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.m_time") == 0 ||
+ StrCaseCmp(name, "system.dos_attr.inode") == 0) {
/* Yup. */
- ret = cacl_get(ctx, &srv->cli,
- &ipc_srv->cli, &pol,
- (char *) path, (char *) name + 19,
- (char *) value, size);
+ ret = cacl_get(context, ctx, srv,
+ ipc_srv == NULL ? NULL : &ipc_srv->cli,
+ &pol, path, name, (const char *) value, size);
if (ret < 0 && errno == 0) {
errno = smbc_errno(context, &srv->cli);
}
@@ -3931,20 +4434,19 @@ int smbc_removexattr_ctx(SMBCCTX *context,
return -1; /* errno set by smbc_server */
}
- ipc_srv = smbc_attr_server(context, server, share,
- workgroup, user, password,
- &pol);
- if (!ipc_srv) {
- return -1;
+ if (! srv->no_nt_session) {
+ ipc_srv = smbc_attr_server(context, server, share,
+ workgroup, user, password,
+ &pol);
+ srv->no_nt_session = True;
+ } else {
+ ipc_srv = NULL;
}
- ipc_srv = smbc_attr_server(context, server, share,
- workgroup, user, password,
- &pol);
- if (!ipc_srv) {
- return -1;
+ if (! ipc_srv) {
+ return -1; /* errno set by smbc_attr_server */
}
-
+
ctx = talloc_init("smbc_removexattr");
if (!ctx) {
errno = ENOMEM;
@@ -3996,10 +4498,12 @@ int smbc_listxattr_ctx(SMBCCTX *context,
{
/*
* This isn't quite what listxattr() is supposed to do. This returns
- * the complete set of attributes, always, rather than only those
+ * the complete set of attribute names, always, rather than only those
* attribute names which actually exist for a file. Hmmm...
*/
const char supported[] =
+ "system.*\0"
+ "system.*+\0"
"system.nt_sec_desc.revision\0"
"system.nt_sec_desc.owner\0"
"system.nt_sec_desc.owner+\0"
@@ -4009,6 +4513,11 @@ int smbc_listxattr_ctx(SMBCCTX *context,
"system.nt_sec_desc.acl+\0"
"system.nt_sec_desc.*\0"
"system.nt_sec_desc.*+\0"
+ "system.dos_attr.*\0"
+ "system.dos_attr.mode\0"
+ "system.dos_attr.c_time\0"
+ "system.dos_attr.a_time\0"
+ "system.dos_attr.m_time\0"
;
if (size == 0) {
@@ -4295,6 +4804,8 @@ SMBCCTX * smbc_new_context(void)
return NULL;
}
+ context->flags = SMBCCTX_FLAG_CTXVER;
+
ZERO_STRUCTP(context->internal);
@@ -4302,37 +4813,41 @@ SMBCCTX * smbc_new_context(void)
context->debug = 0;
context->timeout = 20000; /* 20 seconds */
- context->open = smbc_open_ctx;
- context->creat = smbc_creat_ctx;
- context->read = smbc_read_ctx;
- context->write = smbc_write_ctx;
- context->close = smbc_close_ctx;
- context->unlink = smbc_unlink_ctx;
- context->rename = smbc_rename_ctx;
- context->lseek = smbc_lseek_ctx;
- context->stat = smbc_stat_ctx;
- context->fstat = smbc_fstat_ctx;
- context->opendir = smbc_opendir_ctx;
- context->closedir = smbc_closedir_ctx;
- context->readdir = smbc_readdir_ctx;
- context->getdents = smbc_getdents_ctx;
- context->mkdir = smbc_mkdir_ctx;
- context->rmdir = smbc_rmdir_ctx;
- context->telldir = smbc_telldir_ctx;
- context->lseekdir = smbc_lseekdir_ctx;
- context->fstatdir = smbc_fstatdir_ctx;
- context->chmod = smbc_chmod_ctx;
- context->utimes = smbc_utimes_ctx;
- context->setxattr = smbc_setxattr_ctx;
- context->getxattr = smbc_getxattr_ctx;
- context->removexattr = smbc_removexattr_ctx;
- context->listxattr = smbc_listxattr_ctx;
- context->open_print_job = smbc_open_print_job_ctx;
- context->print_file = smbc_print_file_ctx;
- context->list_print_jobs = smbc_list_print_jobs_ctx;
- context->unlink_print_job = smbc_unlink_print_job_ctx;
-
- context->callbacks.check_server_fn = smbc_check_server;
+ context->internal->options.browse_max_lmb_count = 3; /* # LMBs to query */
+ context->internal->options.urlencode_readdir_entries = False;/* backward compat */
+ context->internal->options.one_share_per_server = False;/* backward compat */
+
+ context->open = smbc_open_ctx;
+ context->creat = smbc_creat_ctx;
+ context->read = smbc_read_ctx;
+ context->write = smbc_write_ctx;
+ context->close = smbc_close_ctx;
+ context->unlink = smbc_unlink_ctx;
+ context->rename = smbc_rename_ctx;
+ context->lseek = smbc_lseek_ctx;
+ context->stat = smbc_stat_ctx;
+ context->fstat = smbc_fstat_ctx;
+ context->opendir = smbc_opendir_ctx;
+ context->closedir = smbc_closedir_ctx;
+ context->readdir = smbc_readdir_ctx;
+ context->getdents = smbc_getdents_ctx;
+ context->mkdir = smbc_mkdir_ctx;
+ context->rmdir = smbc_rmdir_ctx;
+ context->telldir = smbc_telldir_ctx;
+ context->lseekdir = smbc_lseekdir_ctx;
+ context->fstatdir = smbc_fstatdir_ctx;
+ context->chmod = smbc_chmod_ctx;
+ context->utimes = smbc_utimes_ctx;
+ context->setxattr = smbc_setxattr_ctx;
+ context->getxattr = smbc_getxattr_ctx;
+ context->removexattr = smbc_removexattr_ctx;
+ context->listxattr = smbc_listxattr_ctx;
+ context->open_print_job = smbc_open_print_job_ctx;
+ context->print_file = smbc_print_file_ctx;
+ context->list_print_jobs = smbc_list_print_jobs_ctx;
+ context->unlink_print_job = smbc_unlink_print_job_ctx;
+
+ context->callbacks.check_server_fn = smbc_check_server;
context->callbacks.remove_unused_server_fn = smbc_remove_unused_server;
smbc_default_cache_functions(context);
@@ -4548,3 +5063,11 @@ SMBCCTX * smbc_init_context(SMBCCTX * context)
return context;
}
+
+
+/* Return the verion of samba, and thus libsmbclient */
+const char *
+smbc_version(void)
+{
+ return samba_version_string();
+}
diff --git a/source/locking/brlock.c b/source/locking/brlock.c
index 3451b0cc1ab..09c96b1286a 100644
--- a/source/locking/brlock.c
+++ b/source/locking/brlock.c
@@ -132,11 +132,6 @@ static BOOL brl_conflict(struct lock_struct *lck1,
return False;
}
- if (lck1->start >= (lck2->start + lck2->size) ||
- lck2->start >= (lck1->start + lck1->size)) {
- return False;
- }
-
return brl_overlap(lck1, lck2);
}
@@ -193,10 +188,6 @@ static BOOL brl_conflict_other(struct lock_struct *lck1, struct lock_struct *lck
return False;
}
- if (lck1->start >= (lck2->start + lck2->size) ||
- lck2->start >= (lck1->start + lck1->size))
- return False;
-
return brl_overlap(lck1, lck2);
}
diff --git a/source/locking/posix.c b/source/locking/posix.c
index 6ab2ed377e2..95d4518c172 100644
--- a/source/locking/posix.c
+++ b/source/locking/posix.c
@@ -563,9 +563,9 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
* and the underlying system can handle 64 bit signed locks.
*/
- SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
- SMB_OFF_T mask = (mask2<<1);
- SMB_OFF_T max_positive_lock_offset = ~mask;
+ SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
+ SMB_OFF_T mask = (mask2<<1);
+ SMB_OFF_T max_positive_lock_offset = ~mask;
#else /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
@@ -575,7 +575,7 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
* All offsets & counts must be 2^31 or less.
*/
- SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
+ SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
#endif /* !LARGE_SMB_OFF_T || HAVE_BROKEN_FCNTL64_LOCKS */
diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c
index b01ffcffc16..75319724616 100644
--- a/source/nmbd/nmbd_winsproxy.c
+++ b/source/nmbd/nmbd_winsproxy.c
@@ -190,12 +190,15 @@ void make_wins_proxy_name_query_request( struct subnet_record *subrec,
struct packet_struct *incoming_packet,
struct nmb_name *question_name)
{
- long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) +
- sizeof(struct packet_struct *))/sizeof(long *) + 1];
- struct userdata_struct *userdata = (struct userdata_struct *)ud;
+ union {
+ struct userdata_struct ud;
+ char c[sizeof(struct userdata_struct) + sizeof(struct subrec *) +
+ sizeof(struct packet_struct *)+sizeof(long*)];
+ } ud;
+ struct userdata_struct *userdata = &ud.ud;
unstring qname;
- memset(ud, '\0', sizeof(ud));
+ memset(&ud, '\0', sizeof(ud));
userdata->copy_fn = wins_proxy_userdata_copy_fn;
userdata->free_fn = wins_proxy_userdata_free_fn;
diff --git a/source/nsswitch/winbindd_passdb.c b/source/nsswitch/winbindd_passdb.c
index 4dcc018c64b..554687d7b83 100644
--- a/source/nsswitch/winbindd_passdb.c
+++ b/source/nsswitch/winbindd_passdb.c
@@ -294,7 +294,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- uint32 num_sids, const DOM_SID **sids,
+ uint32 num_sids, DOM_SID **sids,
uint32 *num_aliases, DOM_SID ***aliases)
{
return NT_STATUS_NO_SUCH_USER;
diff --git a/source/nsswitch/winbindd_rpc.c b/source/nsswitch/winbindd_rpc.c
index 42f451c5051..99d12563c6c 100644
--- a/source/nsswitch/winbindd_rpc.c
+++ b/source/nsswitch/winbindd_rpc.c
@@ -970,16 +970,47 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
DEBUG(3,("rpc: trusted_domains\n"));
*num_domains = 0;
+ *names = NULL;
*alt_names = NULL;
+ *dom_sids = NULL;
retry = 0;
do {
if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
goto done;
- result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
- &hnd->pol, &enum_ctx,
- num_domains, names, dom_sids);
+ result = STATUS_MORE_ENTRIES;
+
+ while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
+ uint32 start_idx, num;
+ char **tmp_names;
+ DOM_SID *tmp_sids;
+ int i;
+
+ result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
+ &hnd->pol, &enum_ctx,
+ &num, &tmp_names,
+ &tmp_sids);
+
+ if (!NT_STATUS_IS_OK(result) &&
+ !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
+ break;
+
+ start_idx = *num_domains;
+ *num_domains += num;
+ *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names,
+ char *, *num_domains);
+ *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids,
+ DOM_SID,
+ *num_domains);
+ if ((*names == NULL) || (*dom_sids == NULL))
+ return NT_STATUS_NO_MEMORY;
+
+ for (i=0; i<num; i++) {
+ (*names)[start_idx+i] = tmp_names[i];
+ (*dom_sids)[start_idx+i] = tmp_sids[i];
+ }
+ }
} while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1);
done:
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 80843eda829..d86f4b391a2 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -424,6 +424,7 @@ typedef struct
BOOL bMap_acl_inherit;
BOOL bAfs_Share;
BOOL bEASupport;
+ int iallocation_roundup_size;
param_opt_struct *param_opt;
char dummy[3]; /* for alignment */
@@ -549,6 +550,7 @@ static service sDefault = {
False, /* bMap_acl_inherit */
False, /* bAfs_Share */
False, /* bEASupport */
+ SMB_ROUNDUP_ALLOCATION_SIZE, /* iallocation_roundup_size */
NULL, /* Parametric options */
@@ -893,6 +895,7 @@ static struct parm_struct parm_table[] = {
{N_("Protocol Options"), P_SEP, P_SEPARATOR},
+ {"allocation roundup size", P_INTEGER, P_LOCAL, &sDefault.iallocation_roundup_size, NULL, NULL, FLAG_ADVANCED},
{"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED},
{"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},
@@ -953,7 +956,7 @@ static struct parm_struct parm_table[] = {
{"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_ADVANCED},
{"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
{"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED},
- {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
+ {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED},
{"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED},
@@ -1236,9 +1239,9 @@ static void init_printer_values(service *pService)
string_set(&pService->szQueuepausecommand, "");
string_set(&pService->szQueueresumecommand, "");
#else
- string_set(&pService->szLpqcommand, "/usr/bin/lpstat -o '%p'");
- string_set(&pService->szLprmcommand, "/usr/bin/cancel '%p-%j'");
- string_set(&pService->szPrintcommand, "/usr/bin/lp -d '%p' %s; rm %s");
+ string_set(&pService->szLpqcommand, "/usr/bin/lpq -P'%p'");
+ string_set(&pService->szLprmcommand, "/usr/bin/lprm -P'%p' %j");
+ string_set(&pService->szPrintcommand, "/usr/bin/lpr -P'%p' %s; rm %s");
string_set(&pService->szLppausecommand, "lp -i '%p-%j' -H hold");
string_set(&pService->szLpresumecommand, "lp -i '%p-%j' -H resume");
string_set(&pService->szQueuepausecommand, "/usr/bin/disable '%p'");
@@ -1931,6 +1934,7 @@ FN_LOCAL_INTEGER(lp_oplock_contention_limit, iOplockContentionLimit)
FN_LOCAL_INTEGER(lp_csc_policy, iCSCPolicy)
FN_LOCAL_INTEGER(lp_write_cache_size, iWriteCacheSize)
FN_LOCAL_INTEGER(lp_block_size, iBlock_size)
+FN_LOCAL_INTEGER(lp_allocation_roundup_size, iallocation_roundup_size);
FN_LOCAL_CHAR(lp_magicchar, magic_char)
FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time)
FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase)
diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c
index 36a575214b9..84d398ccd64 100644
--- a/source/passdb/pdb_interface.c
+++ b/source/passdb/pdb_interface.c
@@ -325,6 +325,24 @@ static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCO
return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);
}
+static NTSTATUS context_update_login_attempts(struct pdb_context *context,
+ SAM_ACCOUNT *sam_acct, BOOL success)
+{
+ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
+ if (!context) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return ret;
+ }
+
+ if (!sam_acct || !sam_acct->methods){
+ DEBUG(0, ("invalid sam_acct specified\n"));
+ return ret;
+ }
+
+ return sam_acct->methods->update_login_attempts(sam_acct->methods, sam_acct, success);
+}
+
static NTSTATUS context_getgrsid(struct pdb_context *context,
GROUP_MAP *map, DOM_SID sid)
{
@@ -749,6 +767,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
(*context)->pdb_add_sam_account = context_add_sam_account;
(*context)->pdb_update_sam_account = context_update_sam_account;
(*context)->pdb_delete_sam_account = context_delete_sam_account;
+ (*context)->pdb_update_login_attempts = context_update_login_attempts;
(*context)->pdb_getgrsid = context_getgrsid;
(*context)->pdb_getgrgid = context_getgrgid;
(*context)->pdb_getgrnam = context_getgrnam;
@@ -992,6 +1011,17 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct));
}
+NTSTATUS pdb_update_login_attempts(SAM_ACCOUNT *sam_acct, BOOL success)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
+ return pdb_context->pdb_update_login_attempts(pdb_context, sam_acct, success);
+}
+
BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid)
{
struct pdb_context *pdb_context = pdb_get_static_context(False);
@@ -1279,6 +1309,11 @@ static NTSTATUS pdb_default_delete_sam_account (struct pdb_methods *methods, SAM
return NT_STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS pdb_default_update_login_attempts (struct pdb_methods *methods, SAM_ACCOUNT *newpwd, BOOL success)
+{
+ return NT_STATUS_OK;
+}
+
static NTSTATUS pdb_default_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask)
{
return NT_STATUS_NOT_IMPLEMENTED;
@@ -1422,6 +1457,7 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
(*methods)->add_sam_account = pdb_default_add_sam_account;
(*methods)->update_sam_account = pdb_default_update_sam_account;
(*methods)->delete_sam_account = pdb_default_delete_sam_account;
+ (*methods)->update_login_attempts = pdb_default_update_login_attempts;
(*methods)->getgrsid = pdb_default_getgrsid;
(*methods)->getgrgid = pdb_default_getgrgid;
diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c
index 0a0426ef2ab..f086b3f09b2 100644
--- a/source/passdb/pdb_ldap.c
+++ b/source/passdb/pdb_ldap.c
@@ -83,28 +83,11 @@
#include "smbldap.h"
-struct ldapsam_privates {
- struct smbldap_state *smbldap_state;
-
- /* Former statics */
- LDAPMessage *result;
- LDAPMessage *entry;
- int index;
-
- const char *domain_name;
- DOM_SID domain_sid;
-
- /* configuration items */
- int schema_ver;
-
- char *domain_dn;
-};
-
/**********************************************************************
Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
**********************************************************************/
-static void private_data_free_fn(void **result)
+void private_data_free_fn(void **result)
{
ldap_msgfree(*result);
*result = NULL;
@@ -134,7 +117,7 @@ static const char* get_userattr_key2string( int schema_ver, int key )
Return the list of attribute names given a user schema version.
**********************************************************************/
-static const char** get_userattr_list( int schema_ver )
+const char** get_userattr_list( int schema_ver )
{
switch ( schema_ver ) {
case SCHEMAVER_SAMBAACCOUNT:
@@ -199,7 +182,7 @@ static const char* get_objclass_filter( int schema_ver )
Run the search by name.
******************************************************************/
-static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state,
+int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
const char *user,
LDAPMessage ** result,
const char **attr)
@@ -444,7 +427,7 @@ static time_t ldapsam_get_entry_timestamp(
(Based on init_sam_from_buffer in pdb_tdb.c)
*********************************************************************/
-static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
+static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
SAM_ACCOUNT * sampass,
LDAPMessage * entry)
{
@@ -470,6 +453,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
uint32 user_rid;
uint8 smblmpwd[LM_HASH_LEN],
smbntpwd[NT_HASH_LEN];
+ BOOL use_samba_attrs = True;
uint16 acct_ctrl = 0,
logon_divs;
uint16 bad_password_count = 0,
@@ -708,27 +692,56 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
hours_len = 21;
memset(hours, 0xff, hours_len);
- if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
- /* leave as default */
- } else {
- pdb_gethexpwd(temp, smblmpwd);
- memset((char *)temp, '\0', strlen(temp)+1);
- if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
- return False;
- ZERO_STRUCT(smblmpwd);
- }
+ if (ldap_state->is_nds_ldap) {
+ char *user_dn;
+ size_t pwd_len;
+ uchar clear_text_pw[512];
+
+ /* Make call to Novell eDirectory ldap extension to get clear text password.
+ NOTE: This will only work if we have an SSL connection to eDirectory. */
+ user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
+ if (user_dn != NULL) {
+ DEBUG(3, ("init_sam_from_ldap: smbldap_get_dn(%s) returned '%s'\n", username, user_dn));
+
+ pwd_len = sizeof(clear_text_pw);
+ if (pdb_nds_get_password(ldap_state->smbldap_state, user_dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
+ nt_lm_owf_gen(clear_text_pw, smbntpwd, smblmpwd);
+ if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smblmpwd);
+ if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smbntpwd);
+ use_samba_attrs = False;
+ }
+ } else {
+ DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
+ }
+ }
- if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
- get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
- /* leave as default */
- } else {
- pdb_gethexpwd(temp, smbntpwd);
- memset((char *)temp, '\0', strlen(temp)+1);
- if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
- return False;
- ZERO_STRUCT(smbntpwd);
- }
+ if (use_samba_attrs) {
+ if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) {
+ /* leave as default */
+ } else {
+ pdb_gethexpwd(temp, smblmpwd);
+ memset((char *)temp, '\0', strlen(temp)+1);
+ if (!pdb_set_lanman_passwd(sampass, smblmpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smblmpwd);
+ }
+
+ if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) {
+ /* leave as default */
+ } else {
+ pdb_gethexpwd(temp, smbntpwd);
+ memset((char *)temp, '\0', strlen(temp)+1);
+ if (!pdb_set_nt_passwd(sampass, smbntpwd, PDB_SET))
+ return False;
+ ZERO_STRUCT(smbntpwd);
+ }
+ }
account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
if (pwHistLen > 0){
@@ -1491,15 +1504,17 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
(pdb_get_plaintext_passwd(newpwd)!=NULL)) {
BerElement *ber;
struct berval *bv;
- char *retoid;
- struct berval *retdata;
+ char *retoid = NULL;
+ struct berval *retdata = NULL;
char *utf8_password;
char *utf8_dn;
- if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
- DEBUG(2, ("ldap password change requested, but LDAP "
- "server does not support it -- ignoring\n"));
- return NT_STATUS_OK;
+ if (!ldap_state->is_nds_ldap) {
+ if (!ldapsam_can_pwchange_exop(ldap_state->smbldap_state)) {
+ DEBUG(2, ("ldap password change requested, but LDAP "
+ "server does not support it -- ignoring\n"));
+ return NT_STATUS_OK;
+ }
}
if (push_utf8_allocate(&utf8_password, pdb_get_plaintext_passwd(newpwd)) == (size_t)-1) {
@@ -1533,10 +1548,16 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
SAFE_FREE(utf8_password);
ber_free(ber, 1);
- if ((rc = smbldap_extended_operation(ldap_state->smbldap_state,
- LDAP_EXOP_MODIFY_PASSWD,
- bv, NULL, NULL, &retoid,
- &retdata)) != LDAP_SUCCESS) {
+ if (!ldap_state->is_nds_ldap) {
+ rc = smbldap_extended_operation(ldap_state->smbldap_state,
+ LDAP_EXOP_MODIFY_PASSWD,
+ bv, NULL, NULL, &retoid,
+ &retdata);
+ } else {
+ rc = pdb_nds_set_password(ldap_state->smbldap_state, dn,
+ pdb_get_plaintext_passwd(newpwd));
+ }
+ if (rc != LDAP_SUCCESS) {
char *ld_error = NULL;
if (rc == LDAP_OBJECT_CLASS_VIOLATION) {
@@ -1559,8 +1580,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
#ifdef DEBUG_PASSWORD
DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd)));
#endif
- ber_bvfree(retdata);
- ber_memfree(retoid);
+ if (retdata)
+ ber_bvfree(retdata);
+ if (retoid)
+ ber_memfree(retoid);
}
ber_bvfree(bv);
}
@@ -2134,10 +2157,10 @@ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
{
pstring filter;
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
+ pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
LDAP_OBJ_GROUPMAP,
get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
- (unsigned long)gid);
+ gid);
return ldapsam_getgroup(methods, filter, map);
}
@@ -2490,10 +2513,10 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
{
pstring filter;
- pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))",
+ pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%d))",
LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
- (unsigned long)gid);
+ gid);
return ldapsam_search_one_group(ldap_state, filter, result);
}
@@ -2543,7 +2566,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
ldap_msgfree(result);
pstrcpy( suffix, lp_ldap_idmap_suffix() );
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
+ pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
map->gid);
@@ -3174,7 +3197,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
Initialise the 'compat' mode for pdb_ldap
*********************************************************************/
-static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
@@ -3213,7 +3236,7 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **
Initialise the normal mode for pdb_ldap
*********************************************************************/
-static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
{
NTSTATUS nt_status;
struct ldapsam_privates *ldap_state;
@@ -3318,5 +3341,8 @@ NTSTATUS pdb_ldap_init(void)
if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "ldapsam_compat", pdb_init_ldapsam_compat)))
return nt_status;
+ /* Let pdb_nds register backends */
+ pdb_nds_init();
+
return NT_STATUS_OK;
}
diff --git a/source/passdb/pdb_pgsql.c b/source/passdb/pdb_pgsql.c
index 0955ea1881f..4474bf04e36 100644
--- a/source/passdb/pdb_pgsql.c
+++ b/source/passdb/pdb_pgsql.c
@@ -104,10 +104,15 @@ static NTSTATUS row_to_sam_account ( PGresult *r, long row, SAM_ACCOUNT *u )
pdb_set_logon_count ( u, PQgetlong ( r, row, 27 ), PDB_SET ) ;
pdb_set_unknown_6 ( u, PQgetlong ( r, row, 28 ), PDB_SET ) ;
- if ( !PQgetisnull( r, row, 18 ) ) string_to_sid( &sid, PQgetvalue( r, row, 18 ) ) ;
- pdb_set_user_sid ( u, &sid, PDB_SET ) ;
- if ( !PQgetisnull( r, row, 19 ) ) string_to_sid( &sid, PQgetvalue( r, row, 19 ) ) ;
- pdb_set_group_sid( u, &sid, PDB_SET ) ;
+ if ( !PQgetisnull( r, row, 18 ) ) {
+ string_to_sid( &sid, PQgetvalue( r, row, 18 ) ) ;
+ pdb_set_user_sid ( u, &sid, PDB_SET ) ;
+ }
+
+ if ( !PQgetisnull( r, row, 19 ) ) {
+ string_to_sid( &sid, PQgetvalue( r, row, 19 ) ) ;
+ pdb_set_group_sid( u, &sid, PDB_SET ) ;
+ }
if ( pdb_gethexpwd( PQgetvalue( r, row, 20 ), temp ), PDB_SET ) pdb_set_lanman_passwd( u, temp, PDB_SET ) ;
if ( pdb_gethexpwd( PQgetvalue( r, row, 21 ), temp ), PDB_SET ) pdb_set_nt_passwd ( u, temp, PDB_SET ) ;
@@ -146,7 +151,7 @@ static NTSTATUS pgsqlsam_setsampwent(struct pdb_methods *methods, BOOL update, u
}
else
{
- DEBUG( 5, ("pgsqlsam_setsampwent succeeded(%llu results)!\n", PQntuples(data->pwent)) ) ;
+ DEBUG( 5, ("pgsqlsam_setsampwent succeeded(%d results)!\n", PQntuples(data->pwent)) ) ;
retval = NT_STATUS_OK ;
}
diff --git a/source/passdb/pdb_sql.c b/source/passdb/pdb_sql.c
index ee9ece2baf0..ce92a067d17 100644
--- a/source/passdb/pdb_sql.c
+++ b/source/passdb/pdb_sql.c
@@ -315,12 +315,14 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
CONFIG_TABLE_DEFAULT));
}
- pdb_sql_int_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_ACCTCTRL)) {
+ pdb_sql_int_field(&query,
config_value_write(location, "acct ctrl column",
CONFIG_ACCT_CTRL_DEFAULT),
pdb_get_acct_ctrl(newpwd));
+ }
- if (pdb_get_init_flags(newpwd, PDB_LOGONTIME) != PDB_DEFAULT) {
+ if (IS_SAM_CHANGED(newpwd, PDB_LOGONTIME)) {
pdb_sql_int_field(&query,
config_value_write(location,
"logon time column",
@@ -328,7 +330,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_logon_time(newpwd));
}
- if (pdb_get_init_flags(newpwd, PDB_LOGOFFTIME) != PDB_DEFAULT) {
+ if (IS_SAM_CHANGED(newpwd, PDB_LOGOFFTIME)) {
pdb_sql_int_field(&query,
config_value_write(location,
"logoff time column",
@@ -336,7 +338,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_logoff_time(newpwd));
}
- if (pdb_get_init_flags(newpwd, PDB_KICKOFFTIME) != PDB_DEFAULT) {
+ if (IS_SAM_CHANGED(newpwd, PDB_KICKOFFTIME)) {
pdb_sql_int_field(&query,
config_value_write(location,
"kickoff time column",
@@ -344,7 +346,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_kickoff_time(newpwd));
}
- if (pdb_get_init_flags(newpwd, PDB_CANCHANGETIME) != PDB_DEFAULT) {
+ if (IS_SAM_CHANGED(newpwd, PDB_CANCHANGETIME)) {
pdb_sql_int_field(&query,
config_value_write(location,
"pass can change time column",
@@ -352,7 +354,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_pass_can_change_time(newpwd));
}
- if (pdb_get_init_flags(newpwd, PDB_MUSTCHANGETIME) != PDB_DEFAULT) {
+ if (IS_SAM_CHANGED(newpwd, PDB_MUSTCHANGETIME)) {
pdb_sql_int_field(&query,
config_value_write(location,
"pass must change time column",
@@ -360,7 +362,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_pass_must_change_time(newpwd));
}
- if (pdb_get_pass_last_set_time(newpwd)) {
+ if (IS_SAM_CHANGED(newpwd, PDB_PASSLASTSET)) {
pdb_sql_int_field(&query,
config_value_write(location,
"pass last set time column",
@@ -368,7 +370,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_pass_last_set_time(newpwd));
}
- if (pdb_get_hours_len(newpwd)) {
+ if (IS_SAM_CHANGED(newpwd, PDB_HOURSLEN)) {
pdb_sql_int_field(&query,
config_value_write(location,
"hours len column",
@@ -376,7 +378,7 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_hours_len(newpwd));
}
- if (pdb_get_logon_divs(newpwd)) {
+ if (IS_SAM_CHANGED(newpwd, PDB_LOGONDIVS)) {
pdb_sql_int_field(&query,
config_value_write(location,
"logon divs column",
@@ -384,85 +386,113 @@ char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd,
pdb_get_logon_divs(newpwd));
}
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_USERSID)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "user sid column",
CONFIG_USER_SID_DEFAULT),
sid_to_string(sid_str,
pdb_get_user_sid(newpwd)));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_GROUPSID)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "group sid column",
CONFIG_GROUP_SID_DEFAULT),
sid_to_string(sid_str,
pdb_get_group_sid(newpwd)));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_USERNAME)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "username column",
CONFIG_USERNAME_DEFAULT),
pdb_get_username(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_DOMAIN)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "domain column",
CONFIG_DOMAIN_DEFAULT),
pdb_get_domain(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_USERNAME)) {
+ pdb_sql_string_field(&query,
config_value_write(location,
"nt username column",
CONFIG_NT_USERNAME_DEFAULT),
pdb_get_nt_username(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_FULLNAME)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "fullname column",
CONFIG_FULLNAME_DEFAULT),
pdb_get_fullname(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_LOGONSCRIPT)) {
+ pdb_sql_string_field(&query,
config_value_write(location,
"logon script column",
CONFIG_LOGON_SCRIPT_DEFAULT),
pdb_get_logon_script(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_PROFILE)) {
+ pdb_sql_string_field(&query,
config_value_write(location,
"profile path column",
CONFIG_PROFILE_PATH_DEFAULT),
pdb_get_profile_path(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_DRIVE)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "dir drive column",
CONFIG_DIR_DRIVE_DEFAULT),
pdb_get_dir_drive(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_SMBHOME)) {
+ pdb_sql_string_field(&query,
config_value_write(location, "home dir column",
CONFIG_HOME_DIR_DEFAULT),
pdb_get_homedir(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_WORKSTATIONS)) {
+ pdb_sql_string_field(&query,
config_value_write(location,
"workstations column",
CONFIG_WORKSTATIONS_DEFAULT),
pdb_get_workstations(newpwd));
+ }
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_UNKNOWNSTR)) {
+ pdb_sql_string_field(&query,
config_value_write(location,
"unknown string column",
CONFIG_UNKNOWN_STR_DEFAULT),
pdb_get_workstations(newpwd));
+ }
- pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd),
- pdb_get_acct_ctrl(newpwd));
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_LMPASSWD)) {
+ pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd),
+ pdb_get_acct_ctrl(newpwd));
+ pdb_sql_string_field(&query,
config_value_write(location,
"lanman pass column",
CONFIG_LM_PW_DEFAULT), temp);
+ }
- pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd),
- pdb_get_acct_ctrl(newpwd));
- pdb_sql_string_field(&query,
+ if (IS_SAM_CHANGED(newpwd, PDB_NTPASSWD)) {
+ pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd),
+ pdb_get_acct_ctrl(newpwd));
+ pdb_sql_string_field(&query,
config_value_write(location, "nt pass column",
CONFIG_NT_PW_DEFAULT), temp);
+ }
if (query.update) {
query.part1[strlen(query.part1) - 1] = '\0';
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index 2a525ef560b..ad911c3b05b 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -1820,6 +1820,9 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
ZERO_STRUCT(driver);
architecture = get_short_archi(arch);
+
+ if ( !architecture )
+ return WERR_UNKNOWN_PRINTER_DRIVER;
/* Windows 4.0 (i.e. win9x) should always use a version of 0 */
@@ -4333,34 +4336,70 @@ BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
int snum;
int n_services = lp_numservices();
NT_PRINTER_INFO_LEVEL *printer = NULL;
+ BOOL in_use = False;
if ( !info_3 )
return False;
- DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
+ DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
/* loop through the printers.tdb and check for the drivername */
- for (snum=0; snum<n_services; snum++) {
+ for (snum=0; snum<n_services && !in_use; snum++) {
if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
continue;
if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
continue;
- if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
- free_a_printer( &printer, 2 );
- return True;
- }
+ if ( strequal(info_3->name, printer->info_2->drivername) )
+ in_use = True;
free_a_printer( &printer, 2 );
}
- DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
+ DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
+
+ if ( in_use ) {
+ NT_PRINTER_DRIVER_INFO_LEVEL d;
+ WERROR werr;
+
+ DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
+
+ /* we can still remove the driver if there is one of
+ "Windows NT x86" version 2 or 3 left */
+
+ if ( !strequal( "Windows NT x86", info_3->environment ) ) {
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
+ }
+ else {
+ switch ( info_3->cversion ) {
+ case 2:
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
+ break;
+ case 3:
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
+ break;
+ default:
+ DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
+ info_3->cversion));
+ werr = WERR_UNKNOWN_PRINTER_DRIVER;
+ break;
+ }
+ }
+
+ /* now check the error code */
+
+ if ( W_ERROR_IS_OK(werr) ) {
+ /* it's ok to remove the driver, we have other architctures left */
+ in_use = False;
+ free_a_printer_driver( d, 3 );
+ }
+ }
/* report that the driver is not in use by default */
- return False;
+ return in_use;
}
diff --git a/source/printing/pcap.c b/source/printing/pcap.c
index 0495b6fc1fc..e9d81953667 100644
--- a/source/printing/pcap.c
+++ b/source/printing/pcap.c
@@ -129,7 +129,7 @@ void pcap_cache_reload(void)
}
#endif
-#ifdef SYSV
+#if defined(SYSV) || defined(HPUX)
if (strequal(pcap_name, "lpstat")) {
pcap_reloaded = sysv_cache_reload();
goto done;
diff --git a/source/printing/print_svid.c b/source/printing/print_svid.c
index 3a7c9356344..1213b917342 100644
--- a/source/printing/print_svid.c
+++ b/source/printing/print_svid.c
@@ -34,7 +34,7 @@
#include "includes.h"
-#ifdef SYSV
+#if defined(SYSV) || defined(HPUX)
BOOL sysv_cache_reload(void)
{
char **lines;
diff --git a/source/printing/printing.c b/source/printing/printing.c
index b4d0f3a44b3..5483005e1bd 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -810,7 +810,7 @@ static void print_cache_flush(int snum)
Check if someone already thinks they are doing the update.
****************************************************************************/
-static pid_t get_updating_pid(fstring sharename)
+static pid_t get_updating_pid(const char *sharename)
{
fstring keystr;
TDB_DATA data, key;
@@ -1075,12 +1075,6 @@ static void print_queue_update_internal( const char *sharename,
DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
sharename, current_printif->type, lpq_command));
- if ( !print_cache_expired(sharename, False) ) {
- DEBUG(5,("print_queue_update_internal: print cache for %s is still ok\n", sharename));
- release_print_db(pdb);
- return;
- }
-
/*
* Update the cache time FIRST ! Stops others even
* attempting to get the lock and doing this
@@ -1212,20 +1206,24 @@ static void print_queue_update_internal( const char *sharename,
smbd processes maytry to update the lpq cache concurrently).
****************************************************************************/
-static void print_queue_update_with_lock(int snum)
+static void print_queue_update_with_lock( const char *sharename,
+ struct printif *current_printif,
+ char *lpq_command )
{
- fstring sharename, keystr;
- pstring lpq_command;
+ fstring keystr;
struct tdb_print_db *pdb;
- struct printif *current_printif = get_printer_fns( snum );
-
- fstrcpy(sharename, lp_const_servicename(snum));
DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
pdb = get_print_db_byname(sharename);
if (!pdb)
return;
+ if ( !print_cache_expired(sharename, False) ) {
+ DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
+ release_print_db(pdb);
+ return;
+ }
+
/*
* Check to see if someone else is doing this update.
* This is essentially a mutex on the update.
@@ -1276,12 +1274,6 @@ static void print_queue_update_with_lock(int snum)
tdb_unlock_bystring(pdb->tdb, keystr);
/* do the main work now */
- /* have to substitute any variables here since
- print_queue_get_internal() will not */
-
- pstrcpy( lpq_command, lp_lpqcommand(snum) );
- pstring_sub( lpq_command, "%p", PRINTERNAME(snum) );
- standard_sub_snum( snum, lpq_command, sizeof(lpq_command) );
print_queue_update_internal( sharename, current_printif, lpq_command );
@@ -1313,7 +1305,7 @@ static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msgle
ctx.sharename = sharename;
ctx.lpqcommand = lpqcommand;
- print_queue_update_internal(ctx.sharename,
+ print_queue_update_with_lock(ctx.sharename,
get_printer_fns_from_type(ctx.printing_type),
ctx.lpqcommand );
@@ -1380,9 +1372,9 @@ void start_background_queue(void)
/****************************************************************************
update the internal database from the system print queue for a queue
****************************************************************************/
-static void print_queue_update(int snum)
+
+static void print_queue_update(int snum, BOOL force)
{
- struct print_queue_update_context ctx;
fstring key;
fstring sharename;
pstring lpqcommand;
@@ -1390,48 +1382,49 @@ static void print_queue_update(int snum)
size_t len = 0;
size_t newlen;
struct tdb_print_db *pdb;
+ enum printing_types type;
+ struct printif *current_printif;
+ fstrcpy( sharename, lp_const_servicename(snum));
+
+ pstrcpy( lpqcommand, lp_lpqcommand(snum));
+ pstring_sub( lpqcommand, "%p", PRINTERNAME(snum) );
+ standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
+
/*
* Make sure that the background queue process exists.
* Otherwise just do the update ourselves
*/
- if ( background_lpq_updater_pid == -1 ) {
- print_queue_update_with_lock( snum );
+ if ( force || background_lpq_updater_pid == -1 ) {
+ DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
+ current_printif = get_printer_fns( snum );
+ print_queue_update_with_lock( sharename, current_printif, lpqcommand );
+
return;
}
- fstrcpy( sharename, lp_const_servicename(snum));
-
- ctx.printing_type = lp_printing(snum);
-
- pstrcpy( lpqcommand, lp_lpqcommand(snum));
- pstring_sub( lpqcommand, "%p", PRINTERNAME(snum) );
- standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
-
- ctx.sharename = SMB_STRDUP( sharename );
- ctx.lpqcommand = SMB_STRDUP( lpqcommand );
-
+ type = lp_printing(snum);
+
/* get the length */
len = tdb_pack( buffer, len, "fdP",
- ctx.sharename,
- ctx.printing_type,
- ctx.lpqcommand );
+ sharename,
+ type,
+ lpqcommand );
buffer = SMB_XMALLOC_ARRAY( char, len );
/* now pack the buffer */
newlen = tdb_pack( buffer, len, "fdP",
- ctx.sharename,
- ctx.printing_type,
- ctx.lpqcommand );
+ sharename,
+ type,
+ lpqcommand );
SMB_ASSERT( newlen == len );
DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
- "type = %d, lpq command = [%s]\n",
- ctx.sharename, ctx.printing_type, ctx.lpqcommand ));
+ "type = %d, lpq command = [%s]\n", sharename, type, lpqcommand ));
/* here we set a msg pending record for other smbd processes
to throttle the number of duplicate print_queue_update msgs
@@ -1456,8 +1449,6 @@ static void print_queue_update(int snum)
MSG_PRINTER_UPDATE, buffer, len, False);
unbecome_root();
- SAFE_FREE( ctx.sharename );
- SAFE_FREE( ctx.lpqcommand );
SAFE_FREE( buffer );
return;
@@ -1920,7 +1911,7 @@ pause, or resume print job. User name: %s. Printer name: %s.",
/* force update the database and say the delete failed if the
job still exists */
- print_queue_update(snum);
+ print_queue_update(snum, True);
deleted = !print_job_exists(sharename, jobid);
if ( !deleted )
@@ -2104,7 +2095,7 @@ int print_queue_length(int snum, print_status_struct *pstatus)
/* make sure the database is up to date */
if (print_cache_expired(lp_const_servicename(snum), True))
- print_queue_update(snum);
+ print_queue_update(snum, False);
/* also fetch the queue status */
memset(&status, 0, sizeof(status));
@@ -2419,7 +2410,7 @@ BOOL print_job_end(int snum, uint32 jobid, BOOL normal_close)
/* make sure the database is up to date */
if (print_cache_expired(lp_const_servicename(snum), True))
- print_queue_update(snum);
+ print_queue_update(snum, False);
return True;
@@ -2451,7 +2442,7 @@ static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun
/* make sure the database is up to date */
if (print_cache_expired(lp_const_servicename(snum), True))
- print_queue_update(snum);
+ print_queue_update(snum, False);
*pcount = 0;
*ppqueue = NULL;
@@ -2572,7 +2563,7 @@ int print_queue_status(int snum,
/* make sure the database is up to date */
if (print_cache_expired(lp_const_servicename(snum), True))
- print_queue_update(snum);
+ print_queue_update(snum, False);
/* return if we are done */
if ( !ppqueue || !status )
@@ -2631,9 +2622,14 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
*errcode = WERR_ACCESS_DENIED;
return False;
}
+
+ become_root();
+
ret = (*(current_printif->queue_pause))(snum);
+ unbecome_root();
+
if (ret != 0) {
*errcode = WERR_INVALID_PARAM;
return False;
@@ -2662,9 +2658,13 @@ BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
*errcode = WERR_ACCESS_DENIED;
return False;
}
-
+
+ become_root();
+
ret = (*(current_printif->queue_resume))(snum);
+ unbecome_root();
+
if (ret != 0) {
*errcode = WERR_INVALID_PARAM;
return False;
@@ -2672,7 +2672,7 @@ BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
/* make sure the database is up to date */
if (print_cache_expired(lp_const_servicename(snum), True))
- print_queue_update(snum);
+ print_queue_update(snum, True);
/* Send a printer notify message */
@@ -2693,10 +2693,13 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
BOOL can_job_admin;
/* Force and update so the count is accurate (i.e. not a cached count) */
- print_queue_update(snum);
+ print_queue_update(snum, True);
can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
njobs = print_queue_status(snum, &queue, &status);
+
+ if ( can_job_admin )
+ become_root();
for (i=0;i<njobs;i++) {
BOOL owner = is_owner(user, snum, queue[i].job);
@@ -2705,6 +2708,12 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
print_job_delete1(snum, queue[i].job);
}
}
+
+ if ( can_job_admin )
+ unbecome_root();
+
+ /* update the cache */
+ print_queue_update( snum, True );
SAFE_FREE(queue);
diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c
index 98c2475a658..45b7509d451 100644
--- a/source/rpc_client/cli_lsarpc.c
+++ b/source/rpc_client/cli_lsarpc.c
@@ -1110,12 +1110,12 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/** Get a privilege value given its name */
-NTSTATUS cli_lsa_lookupprivvalue(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, const char *name, LUID *luid)
{
prs_struct qbuf, rbuf;
- LSA_Q_LOOKUPPRIVVALUE q;
- LSA_R_LOOKUPPRIVVALUE r;
+ LSA_Q_LOOKUP_PRIV_VALUE q;
+ LSA_R_LOOKUP_PRIV_VALUE r;
NTSTATUS result;
ZERO_STRUCT(q);
@@ -1128,9 +1128,9 @@ NTSTATUS cli_lsa_lookupprivvalue(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Marshall data and send request */
- init_lsa_q_lookupprivvalue(&q, pol, name);
+ init_lsa_q_lookup_priv_value(&q, pol, name);
- if (!lsa_io_q_lookupprivvalue("", &q, &qbuf, 0) ||
+ if (!lsa_io_q_lookup_priv_value("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, PI_LSARPC, LSA_LOOKUPPRIVVALUE, &qbuf, &rbuf)) {
result = NT_STATUS_UNSUCCESSFUL;
goto done;
@@ -1138,7 +1138,7 @@ NTSTATUS cli_lsa_lookupprivvalue(struct cli_state *cli, TALLOC_CTX *mem_ctx,
/* Unmarshall response */
- if (!lsa_io_r_lookupprivvalue("", &r, &rbuf, 0)) {
+ if (!lsa_io_r_lookup_priv_value("", &r, &rbuf, 0)) {
result = NT_STATUS_UNSUCCESSFUL;
goto done;
}
diff --git a/source/rpc_client/cli_samr.c b/source/rpc_client/cli_samr.c
index 5473168c0f8..75751dbcbd6 100644
--- a/source/rpc_client/cli_samr.c
+++ b/source/rpc_client/cli_samr.c
@@ -2051,6 +2051,54 @@ NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
return result;
}
+/* Remove foreign SID */
+
+NTSTATUS cli_samr_remove_sid_foreign_domain(struct cli_state *cli,
+ TALLOC_CTX *mem_ctx,
+ POLICY_HND *user_pol,
+ DOM_SID *sid)
+{
+ prs_struct qbuf, rbuf;
+ SAMR_Q_REMOVE_SID_FOREIGN_DOMAIN q;
+ SAMR_R_REMOVE_SID_FOREIGN_DOMAIN r;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+ DEBUG(10,("cli_samr_remove_sid_foreign_domain\n"));
+
+ 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);
+
+ /* Marshall data and send request */
+
+ init_samr_q_remove_sid_foreign_domain(&q, user_pol, sid);
+
+ if (!samr_io_q_remove_sid_foreign_domain("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req(cli, PI_SAMR, SAMR_REMOVE_SID_FOREIGN_DOMAIN, &qbuf, &rbuf)) {
+ goto done;
+ }
+
+ /* Unmarshall response */
+
+ if (!samr_io_r_remove_sid_foreign_domain("", &r, &rbuf, 0)) {
+ goto done;
+ }
+
+ /* Return output parameters */
+
+ result = r.status;
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ return result;
+}
+
/* Query user security object */
NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c
index e38197ddba1..bbff258722a 100644
--- a/source/rpc_parse/parse_lsa.c
+++ b/source/rpc_parse/parse_lsa.c
@@ -1981,20 +1981,38 @@ BOOL lsa_io_r_setsystemaccount(const char *desc, LSA_R_SETSYSTEMACCOUNT *r_c, p
}
-void init_lsa_q_lookupprivvalue(LSA_Q_LOOKUPPRIVVALUE *trn, POLICY_HND *hnd, const char *name)
+static void init_lsa_string( LSA_STRING *uni, const char *string )
{
- memcpy(&trn->pol, hnd, sizeof(trn->pol));
- init_unistr2(&trn->uni2_right, name, UNI_FLAGS_NONE);
- init_uni_hdr(&trn->hdr_right, &trn->uni2_right);
+ init_unistr2(&uni->unistring, string, UNI_FLAGS_NONE);
+ init_uni_hdr(&uni->hdr, &uni->unistring);
+}
+
+void init_lsa_q_lookup_priv_value(LSA_Q_LOOKUP_PRIV_VALUE *q_u, POLICY_HND *hnd, const char *name)
+{
+ memcpy(&q_u->pol, hnd, sizeof(q_u->pol));
+ init_lsa_string( &q_u->privname, name );
+}
+
+BOOL smb_io_lsa_string( const char *desc, LSA_STRING *string, prs_struct *ps, int depth )
+{
+ prs_debug(ps, depth, desc, "smb_io_lsa_string");
+ depth++;
+
+ if(!smb_io_unihdr ("hdr", &string->hdr, ps, depth))
+ return False;
+ if(!smb_io_unistr2("unistring", &string->unistring, string->hdr.buffer, ps, depth))
+ return False;
+
+ return True;
}
/*******************************************************************
- Reads or writes an LSA_Q_LOOKUPPRIVVALUE structure.
+ Reads or writes an LSA_Q_LOOKUP_PRIV_VALUE structure.
********************************************************************/
-BOOL lsa_io_q_lookupprivvalue(const char *desc, LSA_Q_LOOKUPPRIVVALUE *r_c, prs_struct *ps, int depth)
+BOOL lsa_io_q_lookup_priv_value(const char *desc, LSA_Q_LOOKUP_PRIV_VALUE *r_c, prs_struct *ps, int depth)
{
- prs_debug(ps, depth, desc, "lsa_io_q_lookupprivvalue");
+ prs_debug(ps, depth, desc, "lsa_io_q_lookup_priv_value");
depth++;
if(!prs_align(ps))
@@ -2002,21 +2020,19 @@ BOOL lsa_io_q_lookupprivvalue(const char *desc, LSA_Q_LOOKUPPRIVVALUE *r_c, prs
if(!smb_io_pol_hnd("pol", &r_c->pol, ps, depth))
return False;
- if(!smb_io_unihdr ("hdr_name", &r_c->hdr_right, ps, depth))
- return False;
- if(!smb_io_unistr2("uni2_right", &r_c->uni2_right, r_c->hdr_right.buffer, ps, depth))
+ if(!smb_io_lsa_string("privname", &r_c->privname, ps, depth))
return False;
return True;
}
/*******************************************************************
- Reads or writes an LSA_R_LOOKUPPRIVVALUE structure.
+ Reads or writes an LSA_R_LOOKUP_PRIV_VALUE structure.
********************************************************************/
-BOOL lsa_io_r_lookupprivvalue(const char *desc, LSA_R_LOOKUPPRIVVALUE *r_c, prs_struct *ps, int depth)
+BOOL lsa_io_r_lookup_priv_value(const char *desc, LSA_R_LOOKUP_PRIV_VALUE *r_c, prs_struct *ps, int depth)
{
- prs_debug(ps, depth, desc, "lsa_io_r_lookupprivvalue");
+ prs_debug(ps, depth, desc, "lsa_io_r_lookup_priv_value");
depth++;
if(!prs_align(ps))
@@ -2271,7 +2287,6 @@ BOOL lsa_io_r_query_info2(const char *desc, LSA_R_QUERY_INFO2 *r_c,
return True;
}
-
/*******************************************************************
Inits an LSA_Q_ENUM_ACCT_RIGHTS structure.
********************************************************************/
diff --git a/source/rpc_parse/parse_samr.c b/source/rpc_parse/parse_samr.c
index 27570ae8213..14d4bb9fdf7 100644
--- a/source/rpc_parse/parse_samr.c
+++ b/source/rpc_parse/parse_samr.c
@@ -5148,6 +5148,12 @@ static BOOL sam_io_logon_hrs(const char *desc, LOGON_HRS * hrs,
if(!prs_align(ps))
return False;
+ if(!prs_uint32("maxlen", ps, depth, &hrs->max_len))
+ return False;
+
+ if(!prs_uint32("offset", ps, depth, &hrs->offset))
+ return False;
+
if(!prs_uint32("len ", ps, depth, &hrs->len))
return False;
@@ -5471,7 +5477,7 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
LOGON_HRS * hrs,
uint16 bad_password_count,
uint16 logon_count,
- char newpass[516], uint32 unknown_6)
+ char newpass[516])
{
usr->logon_time = *logon_time; /* all zeros */
usr->logoff_time = *logoff_time; /* all zeros */
@@ -5535,9 +5541,6 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
copy_unistr2(&usr->uni_munged_dial, mung_dial);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
- usr->unknown_6 = unknown_6; /* 0x0000 04ec */
- usr->padding4 = 0;
-
memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
}
@@ -5562,7 +5565,7 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
uint32 group_rid, uint32 acb_info,
uint32 fields_present, uint16 logon_divs,
LOGON_HRS * hrs, uint16 bad_password_count, uint16 logon_count,
- char newpass[516], uint32 unknown_6)
+ char newpass[516])
{
DATA_BLOB blob = base64_decode_data_blob(mung_dial);
@@ -5630,9 +5633,6 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z
data_blob_free(&blob);
- usr->unknown_6 = unknown_6; /* 0x0000 04ec */
- usr->padding4 = 0;
-
memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
}
@@ -5757,16 +5757,9 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr,
/* ok, this is only guess-work (as usual) */
if (usr->ptr_logon_hrs) {
- if(!prs_uint32("unknown_6 ", ps, depth, &usr->unknown_6))
- return False;
- if(!prs_uint32("padding4 ", ps, depth, &usr->padding4))
- return False;
if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
return False;
- } else if (UNMARSHALLING(ps)) {
- usr->unknown_6 = 0;
- usr->padding4 = 0;
- }
+ }
return True;
}
@@ -5876,16 +5869,9 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str
#if 0 /* JRA - unknown... */
/* ok, this is only guess-work (as usual) */
if (usr->ptr_logon_hrs) {
- if(!prs_uint32("unknown_6 ", ps, depth, &usr->unknown_6))
- return False;
- if(!prs_uint32("padding4 ", ps, depth, &usr->padding4))
- return False;
if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
return False;
- } else if (UNMARSHALLING(ps)) {
- usr->unknown_6 = 0;
- usr->padding4 = 0;
- }
+ }
#endif
return True;
@@ -5925,8 +5911,7 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
uint16 logon_divs,
LOGON_HRS * hrs,
uint16 bad_password_count,
- uint16 logon_count,
- uint32 unknown_6)
+ uint16 logon_count)
{
usr->logon_time = *logon_time;
usr->logoff_time = *logoff_time;
@@ -5987,9 +5972,6 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr,
copy_unistr2(&usr->uni_munged_dial, mung_dial);
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
- usr->unknown_6 = unknown_6; /* 0x0000 04ec */
- usr->padding4 = 0;
-
memcpy(&usr->logon_hrs, hrs, sizeof(usr->logon_hrs));
}
@@ -6136,14 +6118,17 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID *
init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial);
data_blob_free(&munged_dial_blob);
- usr->unknown_6 = pdb_get_unknown_6(pw);
- usr->padding4 = 0;
-
if (pdb_get_hours(pw)) {
+ usr->logon_hrs.max_len = 1260;
+ usr->logon_hrs.offset = 0;
usr->logon_hrs.len = pdb_get_hours_len(pw);
memcpy(&usr->logon_hrs.hours, pdb_get_hours(pw), MAX_HOURS_LEN);
- } else
+ } else {
+ usr->logon_hrs.max_len = 1260;
+ usr->logon_hrs.offset = 0;
+ usr->logon_hrs.len = 0;
memset(&usr->logon_hrs, 0xff, sizeof(usr->logon_hrs));
+ }
return NT_STATUS_OK;
}
@@ -6256,17 +6241,8 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr,
/* ok, this is only guess-work (as usual) */
if (usr->ptr_logon_hrs) {
- if(!prs_align(ps))
- return False;
- if(!prs_uint32("unknown_6 ", ps, depth, &usr->unknown_6))
- return False;
- if(!prs_uint32("padding4 ", ps, depth, &usr->padding4))
- return False;
if(!sam_io_logon_hrs("logon_hrs", &usr->logon_hrs, ps, depth))
return False;
- } else if (UNMARSHALLING(ps)) {
- usr->unknown_6 = 0;
- usr->padding4 = 0;
}
return True;
diff --git a/source/rpc_server/srv_lsa.c b/source/rpc_server/srv_lsa.c
index e3c7832aacb..dbd5d8c0bf6 100644
--- a/source/rpc_server/srv_lsa.c
+++ b/source/rpc_server/srv_lsa.c
@@ -735,6 +735,39 @@ static BOOL api_lsa_enum_acct_rights(pipes_struct *p)
}
/***************************************************************************
+ api_lsa_lookup_priv_value
+ ***************************************************************************/
+
+static BOOL api_lsa_lookup_priv_value(pipes_struct *p)
+{
+ LSA_Q_LOOKUP_PRIV_VALUE q_u;
+ LSA_R_LOOKUP_PRIV_VALUE r_u;
+
+ prs_struct *data = &p->in_data.data;
+ prs_struct *rdata = &p->out_data.rdata;
+
+ ZERO_STRUCT(q_u);
+ ZERO_STRUCT(r_u);
+
+ if(!lsa_io_q_lookup_priv_value("", &q_u, data, 0)) {
+ DEBUG(0,("api_lsa_lookup_priv_value: failed to unmarshall LSA_Q_LOOKUP_PRIV_VALUE .\n"));
+ return False;
+ }
+
+ r_u.status = _lsa_lookup_priv_value(p, &q_u, &r_u);
+
+ /* store the response in the SMB stream */
+ if(!lsa_io_r_lookup_priv_value("", &r_u, rdata, 0)) {
+ DEBUG(0,("api_lsa_lookup_priv_value: Failed to marshall LSA_R_LOOKUP_PRIV_VALUE.\n"));
+ return False;
+ }
+
+ return True;
+}
+
+#if 0 /* AD DC work in ongoing in Samba 4 */
+
+/***************************************************************************
api_lsa_query_info2
***************************************************************************/
@@ -763,7 +796,7 @@ static BOOL api_lsa_query_info2(pipes_struct *p)
return True;
}
-
+#endif /* AD DC work in ongoing in Samba 4 */
/***************************************************************************
\PIPE\ntlsa commands
@@ -794,15 +827,19 @@ static struct api_struct api_lsa_cmds[] =
{ "LSA_REMOVEACCTRIGHTS", LSA_REMOVEACCTRIGHTS, api_lsa_remove_acct_rights },
{ "LSA_ENUMACCTRIGHTS" , LSA_ENUMACCTRIGHTS , api_lsa_enum_acct_rights },
{ "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj },
+ { "LSA_LOOKUPPRIVVALUE" , LSA_LOOKUPPRIVVALUE , api_lsa_lookup_priv_value }
+#if 0 /* AD DC work in ongoing in Samba 4 */
/* be careful of the adding of new RPC's. See commentrs below about
ADS DC capabilities */
{ "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 }
+#endif /* AD DC work in ongoing in Samba 4 */
};
static int count_fns(void)
{
int funcs = sizeof(api_lsa_cmds) / sizeof(struct api_struct);
+#if 0 /* AD DC work is on going in Samba 4 */
/*
* NOTE: Certain calls can not be enabled if we aren't an ADS DC. Make sure
* these calls are always last and that you decrement by the amount of calls
@@ -811,6 +848,7 @@ static int count_fns(void)
if (!(SEC_ADS == lp_security() && ROLE_DOMAIN_PDC == lp_server_role())) {
funcs -= 1;
}
+#endif /* AD DC work in ongoing in Samba 4 */
return funcs;
}
diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c
index 225e5efd54c..7ea35a91faf 100644
--- a/source/rpc_server/srv_lsa_nt.c
+++ b/source/rpc_server/srv_lsa_nt.c
@@ -8,6 +8,7 @@
* Copyright (C) Rafal Szczesniak 2002,
* Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002,
* Copyright (C) Simo Sorce 2003.
+ * Copyright (C) Gerald (Jerry) Carter 2005.
*
* 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
@@ -345,6 +346,8 @@ static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s
return NT_STATUS_OK;
}
+#if 0 /* AD DC work in ongoing in Samba 4 */
+
/***************************************************************************
Init_dns_dom_info.
***************************************************************************/
@@ -384,6 +387,8 @@ static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name,
init_dom_sid2(&r_l->dom_sid, dom_sid);
}
}
+#endif /* AD DC work in ongoing in Samba 4 */
+
/***************************************************************************
_lsa_open_policy2.
@@ -776,9 +781,6 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV
DEBUG(10,("_lsa_enum_privs: enum_context:%d total entries:%d\n",
enum_context, num_privs));
- if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs + 1)))
- return NT_STATUS_NO_MEMORY;
-
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
return NT_STATUS_INVALID_HANDLE;
@@ -791,7 +793,6 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV
if ( !(entries = TALLOC_ZERO_ARRAY(p->mem_ctx, LSA_PRIV_ENTRY, num_privs )) )
return NT_STATUS_NO_MEMORY;
-
for (i = 0; i < num_privs; i++) {
if( i < enum_context) {
init_unistr2(&entries[i].name, NULL, UNI_FLAGS_NONE);
@@ -1143,7 +1144,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u
/* check to see if the pipe_user is root or a Domain Admin since
account_pol.tdb was already opened as root, this is all we have */
-
+
get_current_user( &user, p );
if ( user.uid != sec_initial_uid()
&& !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
@@ -1184,7 +1185,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP
/* check to see if the pipe_user is root or a Domain Admin since
account_pol.tdb was already opened as root, this is all we have */
-
+
get_current_user( &user, p );
if ( user.uid != sec_initial_uid()
&& !nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ) )
@@ -1261,6 +1262,8 @@ NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUER
return r_u->status;
}
+#if 0 /* AD DC work in ongoing in Samba 4 */
+
/***************************************************************************
***************************************************************************/
@@ -1323,6 +1326,7 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I
return r_u->status;
}
+#endif /* AD DC work in ongoing in Samba 4 */
/***************************************************************************
***************************************************************************/
@@ -1474,3 +1478,31 @@ NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA
}
+NTSTATUS _lsa_lookup_priv_value(pipes_struct *p, LSA_Q_LOOKUP_PRIV_VALUE *q_u, LSA_R_LOOKUP_PRIV_VALUE *r_u)
+{
+ struct lsa_info *info = NULL;
+ fstring name;
+ LUID_ATTR priv_luid;
+ SE_PRIV mask;
+
+ /* find the connection policy handle. */
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
+ return NT_STATUS_INVALID_HANDLE;
+
+ unistr2_to_ascii(name, &q_u->privname.unistring, sizeof(name));
+
+ DEBUG(10,("_lsa_priv_get_dispname: name = %s\n", name));
+
+ if ( !se_priv_from_name( name, &mask ) )
+ return NT_STATUS_NO_SUCH_PRIVILEGE;
+
+ priv_luid = get_privilege_luid( &mask );
+
+ r_u->luid.low = priv_luid.luid.low;
+ r_u->luid.high = priv_luid.luid.high;
+
+
+ return NT_STATUS_OK;
+}
+
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c
index 8a10fa6d2da..139960f6613 100644
--- a/source/rpc_server/srv_samr_nt.c
+++ b/source/rpc_server/srv_samr_nt.c
@@ -2335,6 +2335,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
/* implicit call to getpwnam() next. we have a valid SID coming out of this call */
+ flush_pwnam_cache();
nt_status = pdb_init_sam_new(&sam_pass, account, new_rid);
/* this code is order such that we have no unnecessary retuns
@@ -3805,6 +3806,7 @@ static int smb_delete_user(const char *unix_user)
return -1;
all_string_sub(del_script, "%u", unix_user, sizeof(del_script));
ret = smbrun(del_script,NULL);
+ flush_pwnam_cache();
DEBUG(ret ? 0 : 3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret));
return ret;
diff --git a/source/rpc_server/srv_samr_util.c b/source/rpc_server/srv_samr_util.c
index dd12a438cae..6797730be97 100644
--- a/source/rpc_server/srv_samr_util.c
+++ b/source/rpc_server/srv_samr_util.c
@@ -268,12 +268,6 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
if (!strequal(old, new)) {
pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
}
-
- /* This is max logon hours */
- DEBUG(10,("INFO_21 UNKNOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6));
- if (from->unknown_6 != pdb_get_unknown_6(to)) {
- pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED);
- }
}
if (from->fields_present & ACCT_BAD_PWD_COUNT) {
@@ -296,8 +290,6 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
}
DEBUG(10,("INFO_21 PADDING_2: %02X\n",from->padding2));
-
- DEBUG(10,("INFO_21 PADDING_4: %08X\n",from->padding4));
}
@@ -499,11 +491,6 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
/* Fix me: only update if it changes --metze */
pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);
- /* This is max logon hours */
- DEBUG(10,("INFO_23 UNKOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6));
- if (from->unknown_6 != pdb_get_unknown_6(to)) {
- pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED);
- }
}
if (from->fields_present & ACCT_BAD_PWD_COUNT) {
@@ -526,6 +513,4 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
}
DEBUG(10,("INFO_23 PADDING_2: %02X\n",from->padding2));
-
- DEBUG(10,("INFO_23 PADDING_4: %08X\n",from->padding4));
}
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index ed7a544d72d..ffeeb0af9a9 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -2310,7 +2310,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
DEBUG(8,("getprinterdata_printer_server:%s\n", value));
if (!StrCaseCmp(value, "W3SvcInstalled")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
return WERR_NOMEM;
*needed = 0x4;
@@ -2318,7 +2318,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
}
if (!StrCaseCmp(value, "BeepEnabled")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
return WERR_NOMEM;
SIVAL(*data, 0, 0x00);
@@ -2327,7 +2327,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
}
if (!StrCaseCmp(value, "EventLog")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
return WERR_NOMEM;
/* formally was 0x1b */
@@ -2337,7 +2337,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
}
if (!StrCaseCmp(value, "NetPopup")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
return WERR_NOMEM;
SIVAL(*data, 0, 0x00);
@@ -2346,7 +2346,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
}
if (!StrCaseCmp(value, "MajorVersion")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
return WERR_NOMEM;
@@ -2365,7 +2365,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
}
if (!StrCaseCmp(value, "MinorVersion")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
return WERR_NOMEM;
SIVAL(*data, 0, 0);
@@ -2381,7 +2381,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
* extra unicode string = e.g. "Service Pack 3"
*/
if (!StrCaseCmp(value, "OSVersion")) {
- *type = 0x3;
+ *type = REG_BINARY;
*needed = 0x114;
if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
@@ -2401,7 +2401,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
const char *string="C:\\PRINTERS";
- *type = 0x1;
+ *type = REG_SZ;
*needed = 2*(strlen(string)+1);
if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
return WERR_NOMEM;
@@ -2417,7 +2417,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
if (!StrCaseCmp(value, "Architecture")) {
const char *string="Windows NT x86";
- *type = 0x1;
+ *type = REG_SZ;
*needed = 2*(strlen(string)+1);
if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
return WERR_NOMEM;
@@ -2430,10 +2430,18 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
}
if (!StrCaseCmp(value, "DsPresent")) {
- *type = 0x4;
+ *type = REG_DWORD;
if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
return WERR_NOMEM;
- SIVAL(*data, 0, 0x01);
+
+ /* only show the publish check box if we are a
+ memeber of a AD domain */
+
+ if ( lp_security() == SEC_ADS )
+ SIVAL(*data, 0, 0x01);
+ else
+ SIVAL(*data, 0, 0x00);
+
*needed = 0x4;
return WERR_OK;
}
@@ -2443,7 +2451,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint
if (!get_mydnsfullname(hostname))
return WERR_BADFILE;
- *type = 0x1;
+ *type = REG_SZ;
*needed = 2*(strlen(hostname)+1);
if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
return WERR_NOMEM;
diff --git a/source/rpcclient/cmd_lsarpc.c b/source/rpcclient/cmd_lsarpc.c
index 597c950a241..f6ecd8c706d 100644
--- a/source/rpcclient/cmd_lsarpc.c
+++ b/source/rpcclient/cmd_lsarpc.c
@@ -176,6 +176,8 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli,
sid_type_lookup(types[i]), types[i]);
}
+ cli_lsa_close(cli, mem_ctx, &pol);
+
done:
return result;
}
@@ -242,6 +244,8 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
names[i] ? names[i] : "*unknown*", types[i]);
}
+ cli_lsa_close(cli, mem_ctx, &pol);
+
done:
return result;
}
@@ -673,7 +677,7 @@ static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli,
/* Get a privilege value given its name */
-static NTSTATUS cmd_lsa_lookupprivvalue(struct cli_state *cli,
+static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli,
TALLOC_CTX *mem_ctx, int argc,
const char **argv)
{
@@ -693,7 +697,7 @@ static NTSTATUS cmd_lsa_lookupprivvalue(struct cli_state *cli,
if (!NT_STATUS_IS_OK(result))
goto done;
- result = cli_lsa_lookupprivvalue(cli, mem_ctx, &pol, argv[1], &luid);
+ result = cli_lsa_lookup_priv_value(cli, mem_ctx, &pol, argv[1], &luid);
if (!NT_STATUS_IS_OK(result))
goto done;
@@ -765,7 +769,7 @@ struct cmd_set lsarpc_commands[] = {
#endif
{ "lsaaddacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights, NULL, PI_LSARPC, "Add rights to an account", "" },
{ "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account", "" },
- { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookupprivvalue, NULL, PI_LSARPC, "Get a privilege value given its name", "" },
+ { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value, NULL, PI_LSARPC, "Get a privilege value given its name", "" },
{ "lsaquerysecobj", RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj, NULL, PI_LSARPC, "Query LSA security object", "" },
{ NULL }
diff --git a/source/sam/idmap_ldap.c b/source/sam/idmap_ldap.c
index b4a8c8a7528..5773cd34790 100644
--- a/source/sam/idmap_ldap.c
+++ b/source/sam/idmap_ldap.c
@@ -71,8 +71,7 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
else
fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) );
- pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid :
- (unsigned long)id.gid));
+ pstr_sprintf(id_str, "%d", ((id_type & ID_USERID) ? id.uid : id.gid));
smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDMAP_ENTRY );
@@ -501,9 +500,9 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER );
pstrcpy( suffix, lp_ldap_idmap_suffix() );
- pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
+ pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
LDAP_OBJ_IDMAP_ENTRY, type,
- ((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid));
+ ((id_type & ID_USERID) ? id.uid : id.gid));
attr_list = get_attr_list( sidmap_attr_list );
rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE,
@@ -701,8 +700,8 @@ static NTSTATUS verify_idpool( void )
return NT_STATUS_UNSUCCESSFUL;
}
- fstr_sprintf( uid_str, "%lu", (unsigned long)luid );
- fstr_sprintf( gid_str, "%lu", (unsigned long)lgid );
+ fstr_sprintf( uid_str, "%d", luid );
+ fstr_sprintf( gid_str, "%d", lgid );
smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL );
smbldap_set_mod( &mods, LDAP_MOD_ADD,
diff --git a/source/sam/idmap_rid.c b/source/sam/idmap_rid.c
index 6315c6ab2e6..48e496b4b7a 100644
--- a/source/sam/idmap_rid.c
+++ b/source/sam/idmap_rid.c
@@ -146,9 +146,9 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name
uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
fstring dc_name;
struct in_addr dc_ip;
- char *password = NULL;
- char *username = NULL;
- char *domain = NULL;
+ const char *password = NULL;
+ const char *username = NULL;
+ const char *domain = NULL;
uint32 info_class = 5;
char *domain_name = NULL;
DOM_SID *domain_sid, sid;
diff --git a/source/smbd/close.c b/source/smbd/close.c
index 4445f2516bc..b3244432ff5 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -260,8 +260,10 @@ with error %s\n", fsp->fsp_name, strerror(errno) ));
* Ensure pending modtime is set after close.
*/
- if(fsp->pending_modtime) {
+ if(fsp->pending_modtime && fsp->pending_modtime_owner) {
set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
+ } else if (fsp->last_write_time) {
+ set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
}
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index 7dde18f4306..d9fd382d520 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -525,10 +525,17 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
pstring pathreal;
ZERO_STRUCTP(pst);
+
if (dptr->has_wild) {
return dptr_normal_ReadDirName(dptr, poffset, pst);
}
+ /* If poffset is -1 then we know we returned this name before and we have
+ no wildcards. We're at the end of the directory. */
+ if (*poffset == -1) {
+ return NULL;
+ }
+
/* We know the stored wcard contains no wildcard characters. See if we can match
with a stat call. If we can't, then set has_wild to true to
prevent us from doing this on every call. */
@@ -540,6 +547,9 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
}
if (VALID_STAT(*pst)) {
+ /* We need to set the underlying dir_hdn offset to -1 also as
+ this function is usually called with the output from TellDir. */
+ dptr->dir_hnd->offset = *poffset = -1;
return dptr->wcard;
}
@@ -548,11 +558,17 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
pstrcat(pathreal,dptr->wcard);
if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
+ /* We need to set the underlying dir_hdn offset to -1 also as
+ this function is usually called with the output from TellDir. */
+ dptr->dir_hnd->offset = *poffset = -1;
return dptr->wcard;
} else {
/* If we get any other error than ENOENT or ENOTDIR
then the file exists we just can't stat it. */
if (errno != ENOENT && errno != ENOTDIR) {
+ /* We need to set the underlying dir_hdn offset to -1 also as
+ this function is usually called with the output from TellDir. */
+ dptr->dir_hnd->offset = *poffset = -1;
return dptr->wcard;
}
}
@@ -563,6 +579,9 @@ const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT
with a stat we will fail. */
if (dptr->conn->case_sensitive) {
+ /* We need to set the underlying dir_hdn offset to -1 also as
+ this function is usually called with the output from TellDir. */
+ dptr->dir_hnd->offset = *poffset = -1;
return NULL;
} else {
return dptr_normal_ReadDirName(dptr, poffset, pst);
@@ -1033,6 +1052,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
*poffset = e->offset= dirp->offset;
return e->name;
}
+ dirp->offset = -1;
return NULL;
}
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index a21bd69a36c..3048c27fa25 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -142,6 +142,12 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_
if (fsp->pending_modtime) {
set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime);
+
+ /* If we didn't get the "set modtime" call ourselves, we must
+ store the last write time to restore on close. JRA. */
+ if (!fsp->pending_modtime_owner) {
+ fsp->last_write_time = time(NULL);
+ }
}
/* Yes - this is correct - writes don't update this. JRA. */
diff --git a/source/smbd/files.c b/source/smbd/files.c
index ecf39c2b54f..143c1196937 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -37,6 +37,13 @@ static files_struct *oplock_save_chain_fsp = NULL;
static int files_used;
+/* A singleton cache to speed up searching by dev/inode. */
+static struct fsp_singleton_cache {
+ files_struct *fsp;
+ SMB_DEV_T dev;
+ SMB_INO_T inode;
+} fsp_fi_cache;
+
/****************************************************************************
Return a unique number identifying this fsp over the life of this pid.
****************************************************************************/
@@ -122,6 +129,11 @@ files_struct *file_new(connection_struct *conn)
i, fsp->fnum, files_used));
chain_fsp = fsp;
+
+ /* A new fsp invalidates a negative fsp_fi_cache. */
+ if (fsp_fi_cache.fsp == NULL) {
+ ZERO_STRUCT(fsp_fi_cache);
+ }
return fsp;
}
@@ -299,19 +311,34 @@ files_struct *file_find_fsp(files_struct *orig_fsp)
/****************************************************************************
Find the first fsp given a device and inode.
+ We use a singleton cache here to speed up searching from getfilepathinfo
+ calls.
****************************************************************************/
files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
{
files_struct *fsp;
+ if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) {
+ /* Positive or negative cache hit. */
+ return fsp_fi_cache.fsp;
+ }
+
+ fsp_fi_cache.dev = dev;
+ fsp_fi_cache.inode = inode;
+
for (fsp=Files;fsp;fsp=fsp->next) {
if ( fsp->fd != -1 &&
fsp->dev == dev &&
- fsp->inode == inode )
+ fsp->inode == inode ) {
+ /* Setup positive cache. */
+ fsp_fi_cache.fsp = fsp;
return fsp;
+ }
}
+ /* Setup negative cache. */
+ fsp_fi_cache.fsp = NULL;
return NULL;
}
@@ -342,13 +369,40 @@ files_struct *file_find_print(void)
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next) {
- if (fsp->print_file) return fsp;
+ if (fsp->print_file) {
+ return fsp;
+ }
}
return NULL;
}
/****************************************************************************
+ Set a pending modtime across all files with a given dev/ino pair.
+ Record the owner of that modtime.
+****************************************************************************/
+
+void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
+{
+ files_struct *fsp;
+
+ if (null_mtime(pmod)) {
+ return;
+ }
+
+ for (fsp = Files;fsp;fsp=fsp->next) {
+ if ( fsp->fd != -1 &&
+ fsp->dev == tfsp->dev &&
+ fsp->inode == tfsp->inode ) {
+ fsp->pending_modtime = pmod;
+ fsp->pending_modtime_owner = False;
+ }
+ }
+
+ tfsp->pending_modtime_owner = True;
+}
+
+/****************************************************************************
Sync open files on a connection.
****************************************************************************/
@@ -392,6 +446,11 @@ void file_free(files_struct *fsp)
chain_fsp = NULL;
}
+ /* Closing a file can invalidate the positive cache. */
+ if (fsp == fsp_fi_cache.fsp) {
+ ZERO_STRUCT(fsp_fi_cache);
+ }
+
SAFE_FREE(fsp);
}
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 675da4c7478..fbb73640901 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -929,7 +929,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
#endif
if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
- fsp->initial_allocation_size = allocation_size;
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (fsp->is_directory) {
close_file(fsp,False);
END_PROFILE(SMBntcreateX);
@@ -942,7 +942,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
- fsp->initial_allocation_size = (SMB_BIG_UINT)file_len;
+ fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len);
}
/*
@@ -1012,7 +1012,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+ SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
p += 8;
SOFF_T(p,0,file_len);
p += 8;
@@ -1472,7 +1472,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
#endif
if (allocation_size && (allocation_size > file_len)) {
- fsp->initial_allocation_size = allocation_size;
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (fsp->is_directory) {
close_file(fsp,False);
END_PROFILE(SMBntcreateX);
@@ -1484,7 +1484,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
return ERROR_NT(NT_STATUS_DISK_FULL);
}
} else {
- fsp->initial_allocation_size = (SMB_BIG_UINT)file_len;
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len);
}
/* Realloc the size of parameters and data we will return */
@@ -1529,7 +1529,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+ SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
p += 8;
SOFF_T(p,0,file_len);
p += 8;
@@ -1698,7 +1698,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
close_file(fsp1,False);
/* Ensure the modtime is set correctly on the destination file. */
- fsp2->pending_modtime = sbuf1.st_mtime;
+ fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
close_ret = close_file(fsp2,False);
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 70632a20eb7..a552dc5b610 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -491,9 +491,18 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadshare;
unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
+ return False;
+ }
+#if 0
+ /* Bluarc test may need this ... needs further investigation. */
+ if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+ unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;
return False;
}
+#endif
/*
* If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE
@@ -502,7 +511,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign
if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
!(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) {
- DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\
+ DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with \
existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
return True;
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index d02edc5ea06..c5f96db85c1 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -3903,10 +3903,26 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
if (current_user.uid == sbuf.st_uid) {
return (sbuf.st_mode & S_IWUSR) ? True : False;
}
+
+#ifdef S_ISVTX
+ /* sticky bit means delete only by owner or root. */
+ if (sbuf.st_mode & S_ISVTX) {
+ SMB_STRUCT_STAT sbuf_file;
+ if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
+ return False;
+ }
+ if (current_user.uid == sbuf_file.st_uid) {
+ return True;
+ }
+ return False;
+ }
+#endif
+
/* Check group ownership. */
ret = check_posix_acl_group_write(conn, dname, &sbuf);
if (ret == 0 || ret == 1) {
return ret ? True : False;
}
+
return (sbuf.st_mode & S_IWOTH) ? True : False;
}
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index 89183aed347..f149b79f793 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -2876,6 +2876,13 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
conn->num_files_open));
/*
+ * Take care of any time sent in the close.
+ */
+
+ mtime = make_unix_date3(inbuf+smb_vwv1);
+ fsp_set_pending_modtime(fsp, mtime);
+
+ /*
* close_file() returns the unix errno if an error
* was detected on close - normally this is due to
* a disk full error. If not then it was probably an I/O error.
@@ -2886,16 +2893,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
END_PROFILE(SMBclose);
return (UNIXERROR(ERRHRD,ERRgeneral));
}
-
- /*
- * Now take care of any time sent in the close.
- */
-
- mtime = make_unix_date3(inbuf+smb_vwv1);
-
- /* try and set the date */
- set_filetime(conn, file_name, mtime);
-
}
/* We have a cached error */
@@ -4233,7 +4230,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
close_file(fsp1,False);
/* Ensure the modtime is set correctly on the destination file. */
- fsp2->pending_modtime = src_sbuf.st_mtime;
+ fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
/*
* As we are opening fsp1 read-only we only expect
@@ -4917,7 +4914,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
* Sometimes times are sent as zero - ignore them.
*/
- if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
+ if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
/* Ignore request */
if( DEBUGLVL( 3 ) ) {
dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
@@ -4925,12 +4922,13 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
}
END_PROFILE(SMBsetattrE);
return(outsize);
- } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
- /* set modify time = to access time if modify time was 0 */
+ } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+ /* set modify time = to access time if modify time was unset */
unix_times.modtime = unix_times.actime;
}
/* Set the date on this file */
+ /* Should we set pending modtime here ? JRA */
if(file_utime(conn, fsp->fsp_name, &unix_times)) {
END_PROFILE(SMBsetattrE);
return ERROR_DOS(ERRDOS,ERRnoaccess);
@@ -5170,13 +5168,14 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
+ /* Should we check pending modtime here ? JRA */
put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
if (mode & aDIR) {
SIVAL(outbuf,smb_vwv6,0);
SIVAL(outbuf,smb_vwv8,0);
} else {
- uint32 allocation_size = get_allocation_size(fsp, &sbuf);
+ uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
SIVAL(outbuf,smb_vwv8,allocation_size);
}
diff --git a/source/smbd/service.c b/source/smbd/service.c
index f199fe3ade6..684d49c56ae 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -278,6 +278,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
*user = 0;
fstrcpy(dev, pdev);
+ ZERO_STRUCT(st);
if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
return NULL;
@@ -605,24 +606,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
}
#endif
-#if CHECK_PATH_ON_TCONX
/* win2000 does not check the permissions on the directory
during the tree connect, instead relying on permission
check during individual operations. To match this behaviour
I have disabled this chdir check (tridge) */
- if (vfs_ChDir(conn,conn->connectpath) != 0) {
- DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
- get_remote_machine_name(), conn->client_address,
- conn->connectpath,strerror(errno)));
- change_to_root_user();
- yield_connection(conn, lp_servicename(SNUM(conn)));
- conn_free(conn);
- *status = NT_STATUS_BAD_NETWORK_NAME;
- return NULL;
- }
-#else
/* the alternative is just to check the directory exists */
- if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
+ if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
change_to_root_user();
yield_connection(conn, lp_servicename(SNUM(conn)));
@@ -630,7 +619,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
*status = NT_STATUS_BAD_NETWORK_NAME;
return NULL;
}
-#endif
string_set(&conn->origpath,conn->connectpath);
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index d22705214e4..3f3d9c2f461 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -33,11 +33,28 @@ extern struct current_user current_user;
#define DIR_ENTRY_SAFETY_MARGIN 4096
/********************************************************************
+ Roundup a value to the nearest allocation roundup size boundary.
+ Only do this for Windows clients.
+********************************************************************/
+
+SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
+{
+ SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
+
+ /* Only roundup for Windows clients. */
+ enum remote_arch_types ra_type = get_remote_arch();
+ if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
+ val = SMB_ROUNDUP(val,rval);
+ }
+ return val;
+}
+
+/********************************************************************
Given a stat buffer return the allocated size on disk, taking into
account sparse files.
********************************************************************/
-SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
{
SMB_BIG_UINT ret;
@@ -50,7 +67,7 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
if (!ret && fsp && fsp->initial_allocation_size)
ret = fsp->initial_allocation_size;
- return ret;
+ return smb_roundup(conn, ret);
}
/****************************************************************************
@@ -794,7 +811,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
BOOL dont_descend,char **ppdata,
char *base_data, int space_remaining,
BOOL *out_of_space, BOOL *got_exact_match,
- int *last_name_off)
+ int *last_entry_off)
{
const char *dname;
BOOL found = False;
@@ -811,6 +828,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
uint32 len;
time_t mdate=0, adate=0, cdate=0;
char *nameptr;
+ char *last_entry_ptr;
BOOL was_8_3;
int nt_extmode; /* Used for NT connections instead of mode */
BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
@@ -919,7 +937,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
}
file_size = get_file_size(sbuf);
- allocation_size = get_allocation_size(NULL,&sbuf);
+ allocation_size = get_allocation_size(conn,NULL,&sbuf);
mdate = sbuf.st_mtime;
adate = sbuf.st_atime;
cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
@@ -947,7 +965,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
mangle_map(fname,False,True,SNUM(conn));
p = pdata;
- nameptr = p;
+ last_entry_ptr = p;
nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
@@ -1215,7 +1233,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
p+= 8;
- SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
+ SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
p+= 8;
put_long_date(p,sbuf.st_ctime); /* Inode change Time 64 Bit */
@@ -1277,8 +1295,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
return False; /* Not finished - just out of space */
}
- /* Setup the last_filename pointer, as an offset from base_data */
- *last_name_off = PTR_DIFF(nameptr,base_data);
+ /* Setup the last entry pointer, as an offset from base_data */
+ *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
/* Advance the data pointer to the next slot */
*ppdata = p;
@@ -1310,7 +1328,7 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb
pstring directory;
pstring mask;
char *p;
- int last_name_off=0;
+ int last_entry_off=0;
int dptr_num = -1;
int numentries = 0;
int i;
@@ -1360,7 +1378,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return ERROR_NT(ntstatus);
}
- RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
unix_convert(directory,conn,0,&bad_path,&sbuf);
if (bad_path) {
@@ -1437,7 +1455,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
mask,dirtype,info_level,
requires_resume_key,dont_descend,
&p,pdata,space_remaining, &out_of_space, &got_exact_match,
- &last_name_off);
+ &last_entry_off);
}
if (finished && out_of_space)
@@ -1482,7 +1500,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
SSVAL(params,2,numentries);
SSVAL(params,4,finished);
SSVAL(params,6,0); /* Never an EA error */
- SSVAL(params,8,last_name_off);
+ SSVAL(params,8,last_entry_off);
send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
@@ -1537,7 +1555,7 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
char *p;
uint16 dirtype;
int numentries = 0;
- int i, last_name_off=0;
+ int i, last_entry_off=0;
BOOL finished = False;
BOOL dont_descend = False;
BOOL out_of_space = False;
@@ -1674,7 +1692,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
mask,dirtype,info_level,
requires_resume_key,dont_descend,
&p,pdata,space_remaining, &out_of_space, &got_exact_match,
- &last_name_off);
+ &last_entry_off);
}
if (finished && out_of_space)
@@ -1706,7 +1724,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
SSVAL(params,0,numentries);
SSVAL(params,2,finished);
SSVAL(params,4,0); /* Never an EA error */
- SSVAL(params,6,last_name_off);
+ SSVAL(params,6,last_entry_off);
send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
@@ -2422,7 +2440,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
fullpathname = fname;
file_size = get_file_size(sbuf);
- allocation_size = get_allocation_size(fsp,&sbuf);
+ allocation_size = get_allocation_size(conn,fsp,&sbuf);
if (mode & aDIR) {
/* This is necessary, as otherwise the desktop.ini file in
* this folder is ignored */
@@ -2451,9 +2469,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
- if (fsp && fsp->pending_modtime) {
- /* the pending modtime overrides the current modtime */
- sbuf.st_mtime = fsp->pending_modtime;
+ if (fsp) {
+ if (fsp->pending_modtime) {
+ /* the pending modtime overrides the current modtime */
+ sbuf.st_mtime = fsp->pending_modtime;
+ }
+ } else {
+ /* Do we have this path open ? */
+ files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
+ if (fsp1 && fsp1->pending_modtime) {
+ /* the pending modtime overrides the current modtime */
+ sbuf.st_mtime = fsp1->pending_modtime;
+ }
}
if (lp_dos_filetime_resolution(SNUM(conn))) {
@@ -2768,7 +2795,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
SOFF_T(pdata,0,get_file_size(sbuf)); /* File size 64 Bit */
pdata += 8;
- SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
+ SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
pdata += 8;
put_long_date(pdata,sbuf.st_ctime); /* Creation Time 64 Bit */
@@ -3305,9 +3332,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
tvs.modtime = write_time;
}
/* Prefer a defined time to an undefined one. */
- if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
- tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
- ? changed_time : write_time);
+ if (null_mtime(tvs.modtime)) {
+ tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
+ }
/* attributes */
dosmode = IVAL(pdata,32);
@@ -3333,6 +3360,10 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
fname, (double)allocation_size ));
+ if (allocation_size) {
+ allocation_size = smb_roundup(conn, allocation_size);
+ }
+
if(allocation_size != get_file_size(sbuf)) {
SMB_STRUCT_STAT new_sbuf;
@@ -3783,11 +3814,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
+ if (null_mtime(tvs.actime)) {
tvs.actime = sbuf.st_atime;
+ }
- if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
+ if (null_mtime(tvs.modtime)) {
tvs.modtime = sbuf.st_mtime;
+ }
DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
@@ -3819,30 +3852,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
* Try and set the times, size and mode of this file -
* if they are different from the current values
*/
- if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
- if(fsp != NULL) {
- /*
- * This was a setfileinfo on an open file.
- * NT does this a lot. We also need to
- * set the time here, as it can be read by
- * FindFirst/FindNext and with the patch for bug #2045
- * in smbd/fileio.c it ensures that this timestamp is
- * kept sticky even after a write. We save the request
- * away and will set it on file close and after a write. JRA.
- */
-
- if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
- DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
- fsp->pending_modtime = tvs.modtime;
- }
-
- DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
-
- if(file_utime(conn, fname, &tvs)!=0) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
- }
- }
/* check the mode isn't different, before changing it */
if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
@@ -3855,6 +3864,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
}
}
+ /* Now the size. */
if (size != get_file_size(sbuf)) {
int ret;
@@ -3895,6 +3905,34 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
return (UNIXERROR(ERRHRD,ERRdiskfull));
}
+ /*
+ * Finally the times.
+ */
+ if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
+ if(fsp != NULL) {
+ /*
+ * This was a setfileinfo on an open file.
+ * NT does this a lot. We also need to
+ * set the time here, as it can be read by
+ * FindFirst/FindNext and with the patch for bug #2045
+ * in smbd/fileio.c it ensures that this timestamp is
+ * kept sticky even after a write. We save the request
+ * away and will set it on file close and after a write. JRA.
+ */
+
+ if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
+ DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
+ fsp_set_pending_modtime(fsp, tvs.modtime);
+ }
+
+ }
+ DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
+
+ if(file_utime(conn, fname, &tvs)!=0) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+ }
+
SSVAL(params,0,0);
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
diff --git a/source/torture/torture.c b/source/torture/torture.c
index ec13abc1c1f..37aefc55acf 100644
--- a/source/torture/torture.c
+++ b/source/torture/torture.c
@@ -2666,9 +2666,10 @@ static BOOL run_oplock2(int dummy)
sleep(2);
- /* Ensure cli1 processes the break. */
+ /* Ensure cli1 processes the break. Empty file should always return 0
+ * bytes. */
- if (cli_read(cli1, fnum1, buf, 0, 4) != 4) {
+ if (cli_read(cli1, fnum1, buf, 0, 4) != 0) {
printf("read on fnum1 failed (%s)\n", cli_errstr(cli1));
correct = False;
}
@@ -4138,7 +4139,7 @@ static BOOL run_openattrtest(int dummy)
return correct;
}
-static void list_fn(file_info *finfo, const char *name, void *state)
+static void list_fn(const char *mnt, file_info *finfo, const char *name, void *state)
{
}
@@ -4198,7 +4199,7 @@ static BOOL run_dirtest(int dummy)
return correct;
}
-static void del_fn(file_info *finfo, const char *mask, void *state)
+static void del_fn(const char *mnt, file_info *finfo, const char *mask, void *state)
{
struct cli_state *pcli = (struct cli_state *)state;
fstring fname;
diff --git a/source/utils/net_help.c b/source/utils/net_help.c
index 26d59beda2b..e25316818a5 100644
--- a/source/utils/net_help.c
+++ b/source/utils/net_help.c
@@ -99,6 +99,8 @@ int net_help_group(int argc, const char **argv)
d_printf("\nnet [<method>] group ADD <name> [-C comment] [-c container]"\
" [misc. options] [targets]\n\tCreate specified group\n");
d_printf("\nnet rpc group MEMBERS <name>\n\tList Group Members\n\n");
+ d_printf("\nnet rpc group ADDMEM <group> <member>\n\tAdd Group Members\n\n");
+ d_printf("\nnet rpc group DELMEM <group> <member>\n\tDelete Group Members\n\n");
net_common_methods_usage(argc, argv);
net_common_flags_usage(argc, argv);
d_printf("\t-C or --comment=<comment>\tdescriptive comment (for add only)\n");
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index b18d4b0ba5e..1a5e98b34e9 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -2792,7 +2792,7 @@ typedef struct copy_clistate {
* @param state arg-pointer
*
**/
-static void copy_fn(file_info *f, const char *mask, void *state)
+static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
struct copy_clistate *local_state = (struct copy_clistate *)state;
@@ -4377,7 +4377,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
}
/* Create trusting domain's account */
- acb_info = ACB_DOMTRUST;
+ acb_info = ACB_NORMAL;
unknown = 0xe00500b0; /* No idea what this is - a permission mask?
mimir: yes, most probably it is */
@@ -4390,20 +4390,34 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
{
SAM_USERINFO_CTR ctr;
- SAM_USER_INFO_24 p24;
+ SAM_USER_INFO_23 p23;
+ NTTIME notime;
+ char nostr[] = "";
+ LOGON_HRS hrs;
uchar pwbuf[516];
encode_pw_buffer((char *)pwbuf, argv[1], STR_UNICODE);
ZERO_STRUCT(ctr);
- ZERO_STRUCT(p24);
-
- init_sam_user_info24(&p24, (char *)pwbuf, 24);
-
- ctr.switch_value = 24;
- ctr.info.id24 = &p24;
-
- result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
+ ZERO_STRUCT(p23);
+ ZERO_STRUCT(notime);
+ hrs.max_len = 1260;
+ hrs.offset = 0;
+ hrs.len = 21;
+ memset(hrs.hours, 0xFF, sizeof(hrs.hours));
+ acb_info = ACB_DOMTRUST;
+
+ init_sam_user_info23A(&p23, &notime, &notime, &notime,
+ &notime, &notime, &notime,
+ nostr, nostr, nostr, nostr, nostr,
+ nostr, nostr, nostr, nostr, nostr,
+ 0, 0, acb_info, ACCT_FLAGS, 168, &hrs,
+ 0, 0, (char *)pwbuf);
+ ctr.switch_value = 23;
+ ctr.info.id23 = &p23;
+ p23.passmustchange = 0;
+
+ result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 23,
&cli->user_session_key, &ctr);
if (!NT_STATUS_IS_OK(result)) {
@@ -4438,6 +4452,112 @@ static int rpc_trustdom_add(int argc, const char **argv)
}
}
+/**
+ * Remove interdomain trust account from the RPC server.
+ * All parameters (except for argc and argv) are passed by run_rpc_command
+ * function.
+ *
+ * @param domain_sid The domain sid acquired from the server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc Standard main() style argc
+ * @param argc Standard main() style argv. Initial components are already
+ * stripped
+ *
+ * @return normal NTSTATUS return code
+ */
+
+static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
+ const char *domain_name,
+ struct cli_state *cli, TALLOC_CTX *mem_ctx,
+ int argc, const char **argv) {
+
+ POLICY_HND connect_pol, domain_pol, user_pol;
+ NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+ char *acct_name;
+ DOM_SID trust_acct_sid;
+ uint32 *user_rids, num_rids, *name_types;
+ uint32 flags = 0x000003e8; /* Unknown */
+
+ if (argc != 1) {
+ d_printf("Usage: net rpc trustdom del <domain_name>\n");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /*
+ * Make valid trusting domain account (ie. uppercased and with '$' appended)
+ */
+
+ if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ strupper_m(acct_name);
+
+ /* Get samr policy handle */
+ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+ &connect_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Get domain policy handle */
+ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ domain_sid, &domain_pol);
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1,
+ &acct_name, &num_rids, &user_rids,
+ &name_types);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+ MAXIMUM_ALLOWED_ACCESS,
+ user_rids[0], &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* append the rid to the domain sid */
+ sid_copy(&trust_acct_sid, domain_sid);
+ if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
+ goto done;
+ }
+
+ /* remove the sid */
+
+ result = cli_samr_remove_sid_foreign_domain(cli, mem_ctx, &user_pol,
+ &trust_acct_sid);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ /* Delete user */
+
+ result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
+
+ if (!NT_STATUS_IS_OK(result)) {
+ goto done;
+ }
+
+ if (!NT_STATUS_IS_OK(result)) {
+ DEBUG(0,("Could not set trust account password: %s\n",
+ nt_errstr(result)));
+ goto done;
+ }
+
+ done:
+ SAFE_FREE(acct_name);
+ return result;
+}
/**
* Delete interdomain trust account for a remote domain.
@@ -4447,15 +4567,18 @@ static int rpc_trustdom_add(int argc, const char **argv)
*
* @return Integer status (0 means success)
**/
-
+
static int rpc_trustdom_del(int argc, const char **argv)
{
- d_printf("Sorry, not yet implemented.\n");
- d_printf("Use 'smbpasswd -x -i' instead.\n");
- return -1;
+ if (argc > 0) {
+ return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
+ argc, argv);
+ } else {
+ d_printf("Usage: net rpc trustdom del <domain>\n");
+ return -1;
+ }
}
-
/**
* Establish trust relationship to a trusting domain.
* Interdomain account must already be created on remote PDC.
diff --git a/source/utils/net_rpc_rights.c b/source/utils/net_rpc_rights.c
index feb50b457a8..32cb6a4650b 100644
--- a/source/utils/net_rpc_rights.c
+++ b/source/utils/net_rpc_rights.c
@@ -385,7 +385,7 @@ static int net_help_rights( int argc, const char **argv )
d_printf("\nBoth 'grant' and 'revoke' require a SID and a list of privilege names.\n");
d_printf("For example\n");
- d_printf("\n net rpc grant 'VALE\\biddle' SePrintOperatorPrivilege SeDiskOperatorPrivlege\n");
+ d_printf("\n net rpc rights grant 'VALE\\biddle' SePrintOperatorPrivilege SeDiskOperatorPrivilege\n");
d_printf("\nwould grant the printer admin and disk manager rights to the user 'VALE\\biddle'\n\n");