diff options
author | Gerald Carter <jerry@samba.org> | 2005-03-11 10:52:54 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2005-03-11 10:52:54 +0000 |
commit | 061a07f6b476428c622618d83a5a1e54c5f05fe5 (patch) | |
tree | 5e926c06e720253210687391b68aa82f553c9ad3 | |
parent | 6c30768e14f5639328e06a73940f133f9078b90e (diff) | |
download | samba-061a07f6b476428c622618d83a5a1e54c5f05fe5.tar.gz |
r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
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, ¬ime, ¬ime, ¬ime, + ¬ime, ¬ime, ¬ime, + 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"); |