diff options
Diffstat (limited to 'source3')
160 files changed, 6578 insertions, 4835 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 4c927e7346..e6d0cf00dd 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -381,7 +381,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ lib/interface.o lib/pidfile.o \ lib/system.o lib/sendfile.o lib/recvfile.o lib/time.o \ lib/username.o \ - lib/ads_flags.o \ + ../libds/common/flag_mapping.o \ lib/util_pw.o lib/access.o lib/smbrun.o \ lib/bitmap.o lib/dprintf.o $(UTIL_REG_OBJ) \ lib/wins_srv.o \ @@ -667,6 +667,8 @@ OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o \ NOTIFY_OBJ = smbd/notify.o smbd/notify_inotify.o smbd/notify_internal.o +FNAME_UTIL_OBJ = smbd/filename_util.o + VFS_DEFAULT_OBJ = modules/vfs_default.o VFS_AUDIT_OBJ = modules/vfs_audit.o VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o @@ -786,7 +788,7 @@ SMBD_OBJ_BASE = $(PARAM_WITHOUT_REG_OBJ) $(SMBD_OBJ_SRV) $(LIBSMB_OBJ) \ $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \ $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \ - $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \ + $(NOTIFY_OBJ) $(FNAME_UTIL_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \ $(LIBMSRPC_OBJ) $(LIBMSRPC_GEN_OBJ) $(AVAHI_OBJ) \ $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \ $(REG_FULL_OBJ) $(POPT_LIB_OBJ) $(BUILDOPT_OBJ) \ @@ -828,16 +830,16 @@ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(PRINTBASE_OBJ) $(LIBSMB_O $(LOCKING_OBJ) $(PASSDB_OBJ) $(KRBCLIENT_OBJ) \ $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_GEN_OBJ) $(LIBMSRPC_OBJ) \ - $(PASSCHANGE_OBJ) $(LDB_OBJ) + $(PASSCHANGE_OBJ) $(LDB_OBJ) $(FNAME_UTIL_OBJ) STATUS_OBJ = utils/status.o utils/status_profile.o \ $(LOCKING_OBJ) $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ - $(LIBSAMBA_OBJ) + $(LIBSAMBA_OBJ) $(FNAME_UTIL_OBJ) SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ - $(LIBSAMBA_OBJ) \ + $(LIBSAMBA_OBJ) $(FNAME_UTIL_OBJ) \ $(PRINTBASE_OBJ) SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \ @@ -1033,7 +1035,7 @@ MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIEN LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \ $(LIBSMB_OBJ) $(LDB_OBJ) $(LIB_NONSMBD_OBJ) \ - $(LIBNDR_GEN_OBJ0) + $(LIBNDR_GEN_OBJ0) $(FNAME_UTIL_OBJ) NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) $(KRBCLIENT_OBJ) \ $(LIB_NONSMBD_OBJ) \ @@ -1052,7 +1054,7 @@ LOG2PCAP_OBJ = utils/log2pcaphex.o LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) $(LDB_OBJ) \ $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ - $(LIBNDR_GEN_OBJ0) + $(LIBNDR_GEN_OBJ0) $(FNAME_UTIL_OBJ) SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \ @@ -1476,10 +1478,10 @@ bin/swat@EXEEXT@: $(BINARY_PREREQS) $(SWAT_OBJ) @BUILD_POPT@ @LIBTALLOC_TARGET@ bin/rpcclient@EXEEXT@: $(BINARY_PREREQS) $(RPCCLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_TARGET@ @LIBTDB_TARGET@ @LIBWBCLIENT_TARGET@ @echo Linking $@ - @$(CC) -o $@ $(LDFLAGS) $(PASSDB_LIBS) $(RPCCLIENT_OBJ) \ + @$(CC) -o $@ $(LDFLAGS) $(RPCCLIENT_OBJ) \ $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) $(POPT_LIBS) \ $(KRB5LIBS) $(LDAP_LIBS) $(LIBTALLOC_LIBS) $(LIBTDB_LIBS) \ - $(LIBWBCLIENT_LIBS) $(ZLIB_LIBS) + $(LIBWBCLIENT_LIBS) $(ZLIB_LIBS) $(PASSDB_LIBS) bin/smbclient@EXEEXT@: $(BINARY_PREREQS) $(CLIENT_OBJ) @BUILD_POPT@ @LIBTALLOC_TARGET@ @LIBTDB_TARGET@ @LIBWBCLIENT_TARGET@ @echo Linking $@ @@ -1517,7 +1519,7 @@ bin/umount.cifs@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UMOUNT_OBJ) bin/cifs.upcall@EXEEXT@: $(BINARY_PREREQS) $(CIFS_UPCALL_OBJ) $(LIBSMBCLIENT_OBJ1) @LIBTALLOC_TARGET@ @LIBTDB_TARGET@ @LIBWBCLIENT_TARGET@ @echo Linking $@ @$(CC) -o $@ $(CIFS_UPCALL_OBJ) $(DYNEXP) $(LDFLAGS) \ - -lkeyutils $(LIBS) $(LIBSMBCLIENT_OBJ1) $(KRB5LIBS) \ + $(LIBSMBCLIENT_OBJ1) $(LIBS) -lkeyutils $(KRB5LIBS) \ $(LDAP_LIBS) $(LIBTALLOC_LIBS) $(LIBWBCLIENT_LIBS) \ $(LIBTDB_LIBS) $(NSCD_LIBS) $(ZLIB_LIBS) diff --git a/source3/auth/auth.c b/source3/auth/auth.c index fd4c503752..ce8722a1b4 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -82,7 +82,6 @@ static void get_ntlm_challenge(struct auth_context *auth_context, DATA_BLOB challenge = data_blob_null; const char *challenge_set_by = NULL; auth_methods *auth_method; - TALLOC_CTX *mem_ctx; if (auth_context->challenge.length) { DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", @@ -106,12 +105,8 @@ static void get_ntlm_challenge(struct auth_context *auth_context, continue; } - mem_ctx = talloc_init("auth_get_challenge for module %s", auth_method->name); - if (!mem_ctx) { - smb_panic("talloc_init() failed!"); - } - - challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx); + challenge = auth_method->get_chal(auth_context, &auth_method->private_data, + auth_context->mem_ctx); if (!challenge.length) { DEBUG(3, ("auth_get_challenge: getting challenge from authentication method %s FAILED.\n", auth_method->name)); @@ -121,7 +116,6 @@ static void get_ntlm_challenge(struct auth_context *auth_context, challenge_set_by = auth_method->name; auth_context->challenge_set_method = auth_method; } - talloc_destroy(mem_ctx); } if (!challenge_set_by) { diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index a2634feb6c..26b45e47e5 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -226,10 +226,10 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, if (*workstation_list) { bool invalid_ws = True; - char *tok; + char *tok = NULL; const char *s = workstation_list; + char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name); - const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name); if (machine_name == NULL) return NT_STATUS_NO_MEMORY; @@ -251,6 +251,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, TALLOC_FREE(tok); } TALLOC_FREE(tok); + TALLOC_FREE(machine_name); if (invalid_ws) return NT_STATUS_INVALID_WORKSTATION; diff --git a/source3/client/client.c b/source3/client/client.c index ed45f4e2ca..6b273b47b0 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -2605,7 +2605,7 @@ static int cmd_lock(void) len = (uint64_t)strtol(buf, (char **)NULL, 16); - if (!cli_posix_lock(cli, fnum, start, len, true, lock_type)) { + if (!NT_STATUS_IS_OK(cli_posix_lock(cli, fnum, start, len, true, lock_type))) { d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli)); } @@ -2639,7 +2639,7 @@ static int cmd_unlock(void) len = (uint64_t)strtol(buf, (char **)NULL, 16); - if (!cli_posix_unlock(cli, fnum, start, len)) { + if (!NT_STATUS_IS_OK(cli_posix_unlock(cli, fnum, start, len))) { d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli)); } diff --git a/source3/include/ads.h b/source3/include/ads.h index afa4e12175..9761d54086 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -6,6 +6,8 @@ basically this is a wrapper around ldap */ +#include "../libds/common/flags.h" + enum wb_posix_mapping { WB_POSIX_MAP_UNKNOWN = -1, WB_POSIX_MAP_TEMPLATE = 0, @@ -202,124 +204,6 @@ typedef void **ADS_MODLIST; #define ADS_LDAP_MATCHING_RULE_BIT_AND "1.2.840.113556.1.4.803" #define ADS_LDAP_MATCHING_RULE_BIT_OR "1.2.840.113556.1.4.804" -/* UserFlags for userAccountControl */ -#define UF_SCRIPT 0x00000001 -#define UF_ACCOUNTDISABLE 0x00000002 -#define UF_UNUSED_1 0x00000004 -#define UF_HOMEDIR_REQUIRED 0x00000008 - -#define UF_LOCKOUT 0x00000010 -#define UF_PASSWD_NOTREQD 0x00000020 -#define UF_PASSWD_CANT_CHANGE 0x00000040 -#define UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED 0x00000080 - -#define UF_TEMP_DUPLICATE_ACCOUNT 0x00000100 -#define UF_NORMAL_ACCOUNT 0x00000200 -#define UF_UNUSED_2 0x00000400 -#define UF_INTERDOMAIN_TRUST_ACCOUNT 0x00000800 - -#define UF_WORKSTATION_TRUST_ACCOUNT 0x00001000 -#define UF_SERVER_TRUST_ACCOUNT 0x00002000 -#define UF_UNUSED_3 0x00004000 -#define UF_UNUSED_4 0x00008000 - -#define UF_DONT_EXPIRE_PASSWD 0x00010000 -#define UF_MNS_LOGON_ACCOUNT 0x00020000 -#define UF_SMARTCARD_REQUIRED 0x00040000 -#define UF_TRUSTED_FOR_DELEGATION 0x00080000 - -#define UF_NOT_DELEGATED 0x00100000 -#define UF_USE_DES_KEY_ONLY 0x00200000 -#define UF_DONT_REQUIRE_PREAUTH 0x00400000 -#define UF_PASSWORD_EXPIRED 0x00800000 - -#define UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION 0x01000000 -#define UF_NO_AUTH_DATA_REQUIRED 0x02000000 -#define UF_UNUSED_8 0x04000000 -#define UF_UNUSED_9 0x08000000 - -#define UF_UNUSED_10 0x10000000 -#define UF_UNUSED_11 0x20000000 -#define UF_UNUSED_12 0x40000000 -#define UF_UNUSED_13 0x80000000 - -#define UF_MACHINE_ACCOUNT_MASK (\ - UF_INTERDOMAIN_TRUST_ACCOUNT |\ - UF_WORKSTATION_TRUST_ACCOUNT |\ - UF_SERVER_TRUST_ACCOUNT \ - ) - -#define UF_ACCOUNT_TYPE_MASK (\ - UF_TEMP_DUPLICATE_ACCOUNT |\ - UF_NORMAL_ACCOUNT |\ - UF_INTERDOMAIN_TRUST_ACCOUNT |\ - UF_WORKSTATION_TRUST_ACCOUNT |\ - UF_SERVER_TRUST_ACCOUNT \ - ) - -#define UF_SETTABLE_BITS (\ - UF_SCRIPT |\ - UF_ACCOUNTDISABLE |\ - UF_HOMEDIR_REQUIRED |\ - UF_LOCKOUT |\ - UF_PASSWD_NOTREQD |\ - UF_PASSWD_CANT_CHANGE |\ - UF_ACCOUNT_TYPE_MASK | \ - UF_DONT_EXPIRE_PASSWD | \ - UF_MNS_LOGON_ACCOUNT |\ - UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED |\ - UF_SMARTCARD_REQUIRED |\ - UF_TRUSTED_FOR_DELEGATION |\ - UF_NOT_DELEGATED |\ - UF_USE_DES_KEY_ONLY |\ - UF_DONT_REQUIRE_PREAUTH \ - ) - -/* sAMAccountType */ -#define ATYPE_NORMAL_ACCOUNT 0x30000000 /* 805306368 */ -#define ATYPE_WORKSTATION_TRUST 0x30000001 /* 805306369 */ -#define ATYPE_INTERDOMAIN_TRUST 0x30000002 /* 805306370 */ -#define ATYPE_SECURITY_GLOBAL_GROUP 0x10000000 /* 268435456 */ -#define ATYPE_DISTRIBUTION_GLOBAL_GROUP 0x10000001 /* 268435457 */ -#define ATYPE_DISTRIBUTION_UNIVERSAL_GROUP ATYPE_DISTRIBUTION_GLOBAL_GROUP -#define ATYPE_SECURITY_LOCAL_GROUP 0x20000000 /* 536870912 */ -#define ATYPE_DISTRIBUTION_LOCAL_GROUP 0x20000001 /* 536870913 */ - -#define ATYPE_ACCOUNT ATYPE_NORMAL_ACCOUNT /* 0x30000000 805306368 */ -#define ATYPE_GLOBAL_GROUP ATYPE_SECURITY_GLOBAL_GROUP /* 0x10000000 268435456 */ -#define ATYPE_LOCAL_GROUP ATYPE_SECURITY_LOCAL_GROUP /* 0x20000000 536870912 */ - -/* groupType */ -#define GROUP_TYPE_BUILTIN_LOCAL_GROUP 0x00000001 -#define GROUP_TYPE_ACCOUNT_GROUP 0x00000002 -#define GROUP_TYPE_RESOURCE_GROUP 0x00000004 -#define GROUP_TYPE_UNIVERSAL_GROUP 0x00000008 -#define GROUP_TYPE_APP_BASIC_GROUP 0x00000010 -#define GROUP_TYPE_APP_QUERY_GROUP 0x00000020 -#define GROUP_TYPE_SECURITY_ENABLED 0x80000000 - -#define GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ( /* 0x80000005 -2147483643 */ \ - GROUP_TYPE_BUILTIN_LOCAL_GROUP| \ - GROUP_TYPE_RESOURCE_GROUP| \ - GROUP_TYPE_SECURITY_ENABLED \ - ) -#define GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ( /* 0x80000004 -2147483644 */ \ - GROUP_TYPE_RESOURCE_GROUP| \ - GROUP_TYPE_SECURITY_ENABLED \ - ) -#define GTYPE_SECURITY_GLOBAL_GROUP ( /* 0x80000002 -2147483646 */ \ - GROUP_TYPE_ACCOUNT_GROUP| \ - GROUP_TYPE_SECURITY_ENABLED \ - ) -#define GTYPE_SECURITY_UNIVERSAL_GROUP ( /* 0x80000008 -2147483656 */ \ - GROUP_TYPE_UNIVERSAL_GROUP| \ - GROUP_TYPE_SECURITY_ENABLED \ - ) - -#define GTYPE_DISTRIBUTION_GLOBAL_GROUP 0x00000002 /* 2 */ -#define GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP 0x00000004 /* 4 */ -#define GTYPE_DISTRIBUTION_UNIVERSAL_GROUP 0x00000008 /* 8 */ - #define ADS_PINGS 0x0000FFFF /* Ping response */ #define ADS_DNS_CONTROLLER 0x20000000 /* DomainControllerName is a DNS name*/ #define ADS_DNS_DOMAIN 0x40000000 /* DomainName is a DNS name */ @@ -411,11 +295,4 @@ typedef struct { #define ADS_IGNORE_PRINCIPAL "not_defined_in_RFC4178@please_ignore" -/* Settings for the domainFunctionality attribute in the rootDSE */ - -#define DS_DOMAIN_FUNCTION_2000 0 -#define DS_DOMAIN_FUCNTION_2003_MIXED 1 -#define DS_DOMAIN_FUNCTION_2003 2 -#define DS_DOMAIN_FUNCTION_2008 3 - #endif /* _INCLUDE_ADS_H_ */ diff --git a/source3/include/passdb.h b/source3/include/passdb.h index 4e53311eba..2b4f9c2e43 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -205,6 +205,22 @@ struct pdb_domain_info { struct GUID guid; }; +/* + * Types of account policy. + */ +enum pdb_policy_type { + PDB_POLICY_MIN_PASSWORD_LEN = 1, + PDB_POLICY_PASSWORD_HISTORY = 2, + PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS = 3, + PDB_POLICY_MAX_PASSWORD_AGE = 4, + PDB_POLICY_MIN_PASSWORD_AGE = 5, + PDB_POLICY_LOCK_ACCOUNT_DURATION = 6, + PDB_POLICY_RESET_COUNT_TIME = 7, + PDB_POLICY_BAD_ATTEMPT_LOCKOUT = 8, + PDB_POLICY_TIME_TO_LOGOUT = 9, + PDB_POLICY_REFUSE_MACHINE_PW_CHANGE = 10 +}; + #define PDB_CAP_STORE_RIDS 0x0001 #define PDB_CAP_ADS 0x0002 @@ -351,10 +367,12 @@ struct pdb_methods enum lsa_SidType *attrs); NTSTATUS (*get_account_policy)(struct pdb_methods *methods, - int policy_index, uint32 *value); + enum pdb_policy_type type, + uint32_t *value); NTSTATUS (*set_account_policy)(struct pdb_methods *methods, - int policy_index, uint32 value); + enum pdb_policy_type type, + uint32_t value); NTSTATUS (*get_seq_num)(struct pdb_methods *methods, time_t *seq_num); diff --git a/source3/include/proto.h b/source3/include/proto.h index f887b4e796..77283d9cf0 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -290,16 +290,16 @@ bool check_access(int sock, const char **allow_list, const char **deny_list); /* The following definitions come from lib/account_pol.c */ void account_policy_names_list(const char ***names, int *num_names); -const char *decode_account_policy_name(int field); -const char *get_account_policy_attr(int field); -const char *account_policy_get_desc(int field); -int account_policy_name_to_fieldnum(const char *name); -bool account_policy_get_default(int account_policy, uint32 *val); +const char *decode_account_policy_name(enum pdb_policy_type type); +const char *get_account_policy_attr(enum pdb_policy_type type); +const char *account_policy_get_desc(enum pdb_policy_type type); +enum pdb_policy_type account_policy_name_to_typenum(const char *name); +bool account_policy_get_default(enum pdb_policy_type type, uint32_t *val); bool init_account_policy(void); -bool account_policy_get(int field, uint32 *value); -bool account_policy_set(int field, uint32 value); -bool cache_account_policy_set(int field, uint32 value); -bool cache_account_policy_get(int field, uint32 *value); +bool account_policy_get(enum pdb_policy_type type, uint32_t *value); +bool account_policy_set(enum pdb_policy_type type, uint32_t value); +bool cache_account_policy_set(enum pdb_policy_type type, uint32_t value); +bool cache_account_policy_get(enum pdb_policy_type type, uint32_t *value); struct db_context *get_account_pol_db( void ); /* The following definitions come from lib/adt_tree.c */ @@ -454,6 +454,14 @@ NTSTATUS dbwrap_trans_store_uint32(struct db_context *db, const char *keystr, NTSTATUS dbwrap_trans_store_bystring(struct db_context *db, const char *key, TDB_DATA data, int flags); NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key); +NTSTATUS dbwrap_trans_do(struct db_context *db, + NTSTATUS (*action)(struct db_context *, void *), + void *private_data); +NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key); +NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key, + TDB_DATA data, int flags); +TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx, + const char *key); /* The following definitions come from lib/debug.c */ @@ -515,17 +523,15 @@ void pull_file_id_24(char *buf, struct file_id *id); /* The following definitions come from lib/gencache.c */ -bool gencache_init(void); -bool gencache_shutdown(void); bool gencache_set(const char *keystr, const char *value, time_t timeout); bool gencache_del(const char *keystr); bool gencache_get(const char *keystr, char **valstr, time_t *timeout); -bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, bool *expired); +bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, + time_t *timeout); +bool gencache_stabilize(void); bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, time_t timeout); void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void* dptr), void* data, const char* keystr_pattern); -int gencache_lock_entry( const char *key ); -void gencache_unlock_entry( const char *key ); /* The following definitions come from lib/interface.c */ @@ -554,7 +560,7 @@ void init_ldap_debugging(void); /* The following definitions come from lib/ldap_escape.c */ -char *escape_ldap_string_alloc(const char *s); +char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s); char *escape_rdn_val_string_alloc(const char *s); /* The following definitions come from lib/module.c */ @@ -1678,13 +1684,6 @@ ADS_STRUCT *ads_init(const char *realm, const char *ldap_server); void ads_destroy(ADS_STRUCT **ads); -/* The following definitions come from libads/ads_utils.c */ - -uint32 ads_acb2uf(uint32 acb); -uint32 ads_uf2acb(uint32 uf); -uint32 ads_uf2atype(uint32 uf); -uint32 ads_gtype2atype(uint32 gtype); -enum lsa_SidType ads_atype_map(uint32 atype); const char *ads_get_ldap_server_name(ADS_STRUCT *ads); /* The following definitions come from libads/authdata.c */ @@ -2271,13 +2270,6 @@ bool cli_resolve_path(TALLOC_CTX *ctx, /* The following definitions come from libsmb/clidgram.c */ -bool cli_send_mailslot(struct messaging_context *msg_ctx, - bool unique, const char *mailslot, - uint16 priority, - char *buf, int len, - const char *srcname, int src_type, - const char *dstname, int dest_type, - const struct sockaddr_storage *dest_ss); bool send_getdc_request(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx, struct sockaddr_storage *dc_ss, @@ -2519,15 +2511,44 @@ NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum, int timeout, unsigned char locktype); bool cli_lock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type); -bool cli_unlock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len); +struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len); +NTSTATUS cli_unlock_recv(struct tevent_req *req); +NTSTATUS cli_unlock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len); bool cli_lock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type); -bool cli_unlock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len); -bool cli_posix_lock(struct cli_state *cli, uint16_t fnum, +struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len); +NTSTATUS cli_unlock64_recv(struct tevent_req *req); +NTSTATUS cli_unlock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len); +struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len, + bool wait_lock, + enum brl_type lock_type); +NTSTATUS cli_posix_lock_recv(struct tevent_req *req); +NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len, bool wait_lock, enum brl_type lock_type); -bool cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len); -bool cli_posix_getlock(struct cli_state *cli, uint16_t fnum, uint64_t *poffset, uint64_t *plen); +struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len); +NTSTATUS cli_posix_unlock_recv(struct tevent_req *req); +NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len); struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, @@ -4587,8 +4608,8 @@ NTSTATUS pdb_lookup_names(const DOM_SID *domain_sid, const char **names, uint32 *rids, enum lsa_SidType *attrs); -bool pdb_get_account_policy(int policy_index, uint32 *value); -bool pdb_set_account_policy(int policy_index, uint32 value); +bool pdb_get_account_policy(enum pdb_policy_type type, uint32_t *value); +bool pdb_set_account_policy(enum pdb_policy_type type, uint32_t value); bool pdb_get_seq_num(time_t *seq_num); bool pdb_uid_to_rid(uid_t uid, uint32 *rid); bool pdb_uid_to_sid(uid_t uid, DOM_SID *sid); @@ -5083,6 +5104,7 @@ WERROR registry_init_smbconf(const char *keyname); /* The following definitions come from registry/reg_objects.c */ WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr); +WERROR regsubkey_ctr_reinit(struct regsubkey_ctr *ctr); WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum); int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr); WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname ); @@ -5647,32 +5669,16 @@ void prs_switch_type(prs_struct *ps, bool io); void prs_force_dynamic(prs_struct *ps); void prs_set_session_key(prs_struct *ps, const char sess_key[16]); bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8); -bool prs_pointer( const char *name, prs_struct *ps, int depth, - void *dta, size_t data_size, - bool (*prs_fn)(const char*, prs_struct*, int, void*) ); bool prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16); bool prs_uint32(const char *name, prs_struct *ps, int depth, uint32 *data32); bool prs_int32(const char *name, prs_struct *ps, int depth, int32 *data32); bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64); -bool prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status); bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *status); -bool prs_werror(const char *name, prs_struct *ps, int depth, WERROR *status); bool prs_uint8s(bool charmode, const char *name, prs_struct *ps, int depth, uint8 *data8s, int len); bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); -bool prs_uint16uni(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len); bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, uint32 *data32s, int len); bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str); bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_buf_size); -bool prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str); -bool prs_uint16_pre(const char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset); -bool prs_uint16_post(const char *name, prs_struct *ps, int depth, uint16 *data16, - uint32 ptr_uint16, uint32 start_offset); -bool prs_uint32_pre(const char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset); -bool prs_uint32_post(const char *name, prs_struct *ps, int depth, uint32 *data32, - uint32 ptr_uint32, uint32 data_size); -int tdb_prs_store(TDB_CONTEXT *tdb, TDB_DATA kbuf, prs_struct *ps); -int tdb_prs_fetch(TDB_CONTEXT *tdb, TDB_DATA kbuf, prs_struct *ps, TALLOC_CTX *mem_ctx); -bool prs_hash1(prs_struct *ps, uint32 offset, int len); void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level, enum schannel_direction direction, RPC_AUTH_SCHANNEL_CHK * verf, @@ -5877,7 +5883,6 @@ void copy_id26_to_sam_passwd(struct samu *to, /* The following definitions come from rpc_server/srv_spoolss_nt.c */ -WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename ); void do_drv_upgrade_printer(struct messaging_context *msg, void *private_data, uint32_t msg_type, @@ -5966,9 +5971,7 @@ void construct_info_data(struct spoolss_Notify *info_data, int id); struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx, const char *servicename); -WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri ); bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer); -WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines ); /* The following definitions come from rpc_server/srv_srvsvc_nt.c */ @@ -6260,16 +6263,14 @@ void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode, void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode, NTSTATUS status, int line, const char *file); void reply_openerror(struct smb_request *req, NTSTATUS status); -void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, - NTSTATUS defstatus, int line, const char *file); /* The following definitions come from smbd/fake_file.c */ -enum FAKE_FILE_TYPE is_fake_file(const char *fname); +enum FAKE_FILE_TYPE is_fake_file(const struct smb_filename *smb_fname); NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn, uint16_t current_vuid, enum FAKE_FILE_TYPE fake_file_type, - const char *fname, + const struct smb_filename *smb_fname, uint32 access_mask, files_struct **result); NTSTATUS close_fake_file(struct smb_request *req, files_struct *fsp); @@ -6306,6 +6307,23 @@ int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst); /* The following definitions come from smbd/filename.c */ +NTSTATUS unix_convert(TALLOC_CTX *ctx, + connection_struct *conn, + const char *orig_path, + struct smb_filename **smb_fname, + uint32_t ucf_flags); +NTSTATUS check_name(connection_struct *conn, const char *name); +int get_real_filename(connection_struct *conn, const char *path, + const char *name, TALLOC_CTX *mem_ctx, + char **found_name); +NTSTATUS filename_convert(TALLOC_CTX *mem_ctx, + connection_struct *conn, + bool dfs_path, + const char *name_in, + struct smb_filename **pp_smb_fname); + +/* The following definitions come from smbd/filename_utils.c */ + NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_fname, char **full_name); NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, @@ -6316,29 +6334,13 @@ NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx, const char *fname, const SMB_STRUCT_STAT *psbuf, struct smb_filename **smb_fname_out); -int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf); -int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf); const char *smb_fname_str_dbg(const struct smb_filename *smb_fname); +const char *fsp_str_dbg(const struct files_struct *fsp); NTSTATUS copy_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_fname_in, struct smb_filename **smb_fname_out); -NTSTATUS unix_convert(TALLOC_CTX *ctx, - connection_struct *conn, - const char *orig_path, - struct smb_filename **smb_fname, - uint32_t ucf_flags); -NTSTATUS check_name(connection_struct *conn, const char *name); -int get_real_filename(connection_struct *conn, const char *path, - const char *name, TALLOC_CTX *mem_ctx, - char **found_name); -NTSTATUS filename_convert(TALLOC_CTX *mem_ctx, - connection_struct *conn, - bool dfs_path, - const char *name_in, - struct smb_filename **pp_smb_fname, - char **pp_name); +bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname); +bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname); /* The following definitions come from smbd/files.c */ @@ -6364,9 +6366,11 @@ void file_sync_all(connection_struct *conn); void file_free(struct smb_request *req, files_struct *fsp); files_struct *file_fnum(uint16 fnum); files_struct *file_fsp(struct smb_request *req, uint16 fid); -void dup_file_fsp(struct smb_request *req, files_struct *from, +NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from, uint32 access_mask, uint32 share_access, uint32 create_options, files_struct *to); +NTSTATUS fsp_set_smb_fname(struct files_struct *fsp, + const struct smb_filename *smb_fname_in); /* The following definitions come from smbd/ipc.c */ @@ -6544,8 +6548,6 @@ void send_nt_replies(connection_struct *conn, struct smb_request *req, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize); -bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname); -bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname); void reply_ntcreate_and_X(struct smb_request *req); void reply_ntcancel(struct smb_request *req); void reply_ntrename(struct smb_request *req); @@ -6586,7 +6588,8 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, uint32 access_mask, uint32 share_access, uint32 create_options); -bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, +bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname, + int deny_mode, int open_func, uint32 *paccess_mask, uint32 *pshare_mode, uint32 *pcreate_disposition, @@ -7113,6 +7116,10 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf); int vfs_ChDir(connection_struct *conn, const char *path); char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn); NTSTATUS check_reduced_name(connection_struct *conn, const char *fname); +int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf); +int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf); /* The following definitions come from torture/denytest.c */ @@ -7262,6 +7269,16 @@ NTSTATUS access_check_object( SEC_DESC *psd, NT_USER_TOKEN *token, SE_PRIV *rights, uint32 rights_mask, uint32 des_access, uint32 *acc_granted, const char *debug); -void map_max_allowed_access(const NT_USER_TOKEN *token, - uint32_t *pacc_requested); +void map_max_allowed_access(const NT_USER_TOKEN *nt_token, + const struct unix_user_token *unix_token, + uint32_t *pacc_requested); + +/* The following definitions come from ../libds/common/flag_mapping.c */ + +uint32_t ds_acb2uf(uint32_t acb); +uint32_t ds_uf2acb(uint32_t uf); +uint32_t ds_uf2atype(uint32_t uf); +uint32_t ds_gtype2atype(uint32_t gtype); +enum lsa_SidType ds_atype_map(uint32_t atype); + #endif /* _PROTO_H_ */ diff --git a/source3/include/smb.h b/source3/include/smb.h index 9afeb67b00..94ed2186fb 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -452,7 +452,7 @@ typedef struct files_struct { bool lockdb_clean; bool initial_delete_on_close; /* Only set at NTCreateX if file was created. */ bool posix_open; - char *fsp_name; + struct smb_filename *fsp_name; struct vfs_fsp_data *vfs_extension; struct fake_file_handle *fake_file_handle; @@ -834,20 +834,6 @@ struct pipe_open_rec { #define MAX_PW_HISTORY_LEN 24 /* - * Flags for account policy. - */ -#define AP_MIN_PASSWORD_LEN 1 -#define AP_PASSWORD_HISTORY 2 -#define AP_USER_MUST_LOGON_TO_CHG_PASS 3 -#define AP_MAX_PASSWORD_AGE 4 -#define AP_MIN_PASSWORD_AGE 5 -#define AP_LOCK_ACCOUNT_DURATION 6 -#define AP_RESET_COUNT_TIME 7 -#define AP_BAD_ATTEMPT_LOCKOUT 8 -#define AP_TIME_TO_LOGOUT 9 -#define AP_REFUSE_MACHINE_PW_CHANGE 10 - -/* * Flags for local user manipulation. */ diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 7528883c2d..10ee78b394 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -115,7 +115,6 @@ #define reply_force_nterror(req,status) reply_force_nt_error(req,status,__LINE__,__FILE__) #define reply_doserror(req,eclass,ecode) reply_dos_error(req,eclass,ecode,__LINE__,__FILE__) #define reply_botherror(req,status,eclass,ecode) reply_both_error(req,eclass,ecode,status,__LINE__,__FILE__) -#define reply_unixerror(req,defclass,deferror) reply_unix_error(req,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__) #if 0 /* defined in IDL */ diff --git a/source3/include/util_tdb.h b/source3/include/util_tdb.h index c79436434f..80b95921d7 100644 --- a/source3/include/util_tdb.h +++ b/source3/include/util_tdb.h @@ -59,4 +59,6 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err); +int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2); + #endif /* __TDBUTIL_H__ */ diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c index 1e435ca53e..f4101e96bc 100644 --- a/source3/lib/account_pol.c +++ b/source3/lib/account_pol.c @@ -1,20 +1,20 @@ -/* +/* * Unix SMB/CIFS implementation. * account policy storage * Copyright (C) Jean François Micouleau 1998-2001. * Copyright (C) Andrew Bartlett 2002 * Copyright (C) Guenther Deschner 2004-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 * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. */ @@ -31,7 +31,7 @@ static struct db_context *db; struct ap_table { - int field; + enum pdb_policy_type type; const char *string; uint32 default_val; const char *description; @@ -39,51 +39,51 @@ struct ap_table { }; static const struct ap_table account_policy_names[] = { - {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, - "Minimal password length (default: 5)", + {PDB_POLICY_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, + "Minimal password length (default: 5)", "sambaMinPwdLength" }, - {AP_PASSWORD_HISTORY, "password history", 0, - "Length of Password History Entries (default: 0 => off)", + {PDB_POLICY_PASSWORD_HISTORY, "password history", 0, + "Length of Password History Entries (default: 0 => off)", "sambaPwdHistoryLength" }, - - {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0, + + {PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0, "Force Users to logon for password change (default: 0 => off, 2 => on)", "sambaLogonToChgPwd" }, - - {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1, - "Maximum password age, in seconds (default: -1 => never expire passwords)", + + {PDB_POLICY_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1, + "Maximum password age, in seconds (default: -1 => never expire passwords)", "sambaMaxPwdAge" }, - - {AP_MIN_PASSWORD_AGE,"minimum password age", 0, - "Minimal password age, in seconds (default: 0 => allow immediate password change)", + + {PDB_POLICY_MIN_PASSWORD_AGE,"minimum password age", 0, + "Minimal password age, in seconds (default: 0 => allow immediate password change)", "sambaMinPwdAge" }, - - {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30, + + {PDB_POLICY_LOCK_ACCOUNT_DURATION, "lockout duration", 30, "Lockout duration in minutes (default: 30, -1 => forever)", "sambaLockoutDuration" }, - - {AP_RESET_COUNT_TIME, "reset count minutes", 30, - "Reset time after lockout in minutes (default: 30)", + + {PDB_POLICY_RESET_COUNT_TIME, "reset count minutes", 30, + "Reset time after lockout in minutes (default: 30)", "sambaLockoutObservationWindow" }, - - {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0, - "Lockout users after bad logon attempts (default: 0 => off)", + + {PDB_POLICY_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0, + "Lockout users after bad logon attempts (default: 0 => off)", "sambaLockoutThreshold" }, - - {AP_TIME_TO_LOGOUT, "disconnect time", (uint32) -1, - "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", - "sambaForceLogoff" }, - - {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0, + + {PDB_POLICY_TIME_TO_LOGOUT, "disconnect time", (uint32) -1, + "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", + "sambaForceLogoff" }, + + {PDB_POLICY_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0, "Allow Machine Password changes (default: 0 => off)", "sambaRefuseMachinePwdChange" }, - + {0, NULL, 0, "", NULL} }; void account_policy_names_list(const char ***names, int *num_names) -{ +{ const char **nl; int i, count; @@ -106,11 +106,11 @@ void account_policy_names_list(const char ***names, int *num_names) Get the account policy name as a string from its #define'ed number ****************************************************************************/ -const char *decode_account_policy_name(int field) +const char *decode_account_policy_name(enum pdb_policy_type type) { int i; for (i=0; account_policy_names[i].string; i++) { - if (field == account_policy_names[i].field) { + if (type == account_policy_names[i].type) { return account_policy_names[i].string; } } @@ -121,11 +121,11 @@ const char *decode_account_policy_name(int field) Get the account policy LDAP attribute as a string from its #define'ed number ****************************************************************************/ -const char *get_account_policy_attr(int field) +const char *get_account_policy_attr(enum pdb_policy_type type) { int i; - for (i=0; account_policy_names[i].field; i++) { - if (field == account_policy_names[i].field) { + for (i=0; account_policy_names[i].type; i++) { + if (type == account_policy_names[i].type) { return account_policy_names[i].ldap_attr; } } @@ -136,11 +136,11 @@ const char *get_account_policy_attr(int field) Get the account policy description as a string from its #define'ed number ****************************************************************************/ -const char *account_policy_get_desc(int field) +const char *account_policy_get_desc(enum pdb_policy_type type) { int i; for (i=0; account_policy_names[i].string; i++) { - if (field == account_policy_names[i].field) { + if (type == account_policy_names[i].type) { return account_policy_names[i].description; } } @@ -151,12 +151,12 @@ const char *account_policy_get_desc(int field) Get the account policy name as a string from its #define'ed number ****************************************************************************/ -int account_policy_name_to_fieldnum(const char *name) +enum pdb_policy_type account_policy_name_to_typenum(const char *name) { int i; for (i=0; account_policy_names[i].string; i++) { if (strcmp(name, account_policy_names[i].string) == 0) { - return account_policy_names[i].field; + return account_policy_names[i].type; } } return 0; @@ -166,35 +166,35 @@ int account_policy_name_to_fieldnum(const char *name) Get default value for account policy *****************************************************************************/ -bool account_policy_get_default(int account_policy, uint32 *val) +bool account_policy_get_default(enum pdb_policy_type type, uint32_t *val) { int i; - for (i=0; account_policy_names[i].field; i++) { - if (account_policy_names[i].field == account_policy) { + for (i=0; account_policy_names[i].type; i++) { + if (account_policy_names[i].type == type) { *val = account_policy_names[i].default_val; return True; } } - DEBUG(0,("no default for account_policy index %d found. This should never happen\n", - account_policy)); + DEBUG(0,("no default for account_policy index %d found. This should never happen\n", + type)); return False; } /***************************************************************************** - Set default for a field if it is empty + Set default for a type if it is empty *****************************************************************************/ -static bool account_policy_set_default_on_empty(int account_policy) +static bool account_policy_set_default_on_empty(enum pdb_policy_type type) { uint32 value; - if (!account_policy_get(account_policy, &value) && - !account_policy_get_default(account_policy, &value)) { + if (!account_policy_get(type, &value) && + !account_policy_get_default(type, &value)) { return False; } - return account_policy_set(account_policy, value); + return account_policy_set(type, value); } /***************************************************************************** @@ -255,9 +255,9 @@ bool init_account_policy(void) goto cancel; } - for (i=0; account_policy_names[i].field; i++) { + for (i=0; account_policy_names[i].type; i++) { - if (!account_policy_set_default_on_empty(account_policy_names[i].field)) { + if (!account_policy_set_default_on_empty(account_policy_names[i].type)) { DEBUG(0,("failed to set default value in account policy tdb\n")); goto cancel; } @@ -299,10 +299,10 @@ bool init_account_policy(void) } /***************************************************************************** -Get an account policy (from tdb) +Get an account policy (from tdb) *****************************************************************************/ -bool account_policy_get(int field, uint32 *value) +bool account_policy_get(enum pdb_policy_type type, uint32_t *value) { const char *name; uint32 regval; @@ -315,17 +315,17 @@ bool account_policy_get(int field, uint32 *value) *value = 0; } - name = decode_account_policy_name(field); + name = decode_account_policy_name(type); if (name == NULL) { - DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", field)); + DEBUG(1, ("account_policy_get: Field %d is not a valid account policy type! Cannot get, returning 0.\n", type)); return False; } - + if (!dbwrap_fetch_uint32(db, name, ®val)) { - DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for field %d (%s), returning 0\n", field, name)); + DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for type %d (%s), returning 0\n", type, name)); return False; } - + if (value) { *value = regval; } @@ -336,10 +336,10 @@ bool account_policy_get(int field, uint32 *value) /**************************************************************************** -Set an account policy (in tdb) +Set an account policy (in tdb) ****************************************************************************/ -bool account_policy_set(int field, uint32 value) +bool account_policy_set(enum pdb_policy_type type, uint32_t value) { const char *name; NTSTATUS status; @@ -348,36 +348,36 @@ bool account_policy_set(int field, uint32 value) return False; } - name = decode_account_policy_name(field); + name = decode_account_policy_name(type); if (name == NULL) { - DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", field)); + DEBUG(1, ("Field %d is not a valid account policy type! Cannot set.\n", type)); return False; } status = dbwrap_trans_store_uint32(db, name, value); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("store_uint32 failed for field %d (%s) on value " - "%u: %s\n", field, name, value, nt_errstr(status))); + DEBUG(1, ("store_uint32 failed for type %d (%s) on value " + "%u: %s\n", type, name, value, nt_errstr(status))); return False; } DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value)); - + return True; } /**************************************************************************** -Set an account policy in the cache +Set an account policy in the cache ****************************************************************************/ -bool cache_account_policy_set(int field, uint32 value) +bool cache_account_policy_set(enum pdb_policy_type type, uint32_t value) { const char *policy_name = NULL; char *cache_key = NULL; char *cache_value = NULL; bool ret = False; - policy_name = decode_account_policy_name(field); + policy_name = decode_account_policy_name(type); if (policy_name == NULL) { DEBUG(0,("cache_account_policy_set: no policy found\n")); return False; @@ -404,17 +404,17 @@ bool cache_account_policy_set(int field, uint32 value) } /***************************************************************************** -Get an account policy from the cache +Get an account policy from the cache *****************************************************************************/ -bool cache_account_policy_get(int field, uint32 *value) +bool cache_account_policy_get(enum pdb_policy_type type, uint32_t *value) { const char *policy_name = NULL; char *cache_key = NULL; char *cache_value = NULL; bool ret = False; - policy_name = decode_account_policy_name(field); + policy_name = decode_account_policy_name(type); if (policy_name == NULL) { DEBUG(0,("cache_account_policy_set: no policy found\n")); return False; diff --git a/source3/lib/ads_flags.c b/source3/lib/ads_flags.c deleted file mode 100644 index a8fa062f2a..0000000000 --- a/source3/lib/ads_flags.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - Unix SMB/CIFS implementation. - ads (active directory) utility library - - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Andrew Tridgell 2001 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -/* -translated the ACB_CTRL Flags to UserFlags (userAccountControl) -*/ -uint32 ads_acb2uf(uint32 acb) -{ - uint32 uf = 0x00000000; - - if (acb & ACB_DISABLED) uf |= UF_ACCOUNTDISABLE; - if (acb & ACB_HOMDIRREQ) uf |= UF_HOMEDIR_REQUIRED; - if (acb & ACB_PWNOTREQ) uf |= UF_PASSWD_NOTREQD; - if (acb & ACB_TEMPDUP) uf |= UF_TEMP_DUPLICATE_ACCOUNT; - if (acb & ACB_NORMAL) uf |= UF_NORMAL_ACCOUNT; - if (acb & ACB_MNS) uf |= UF_MNS_LOGON_ACCOUNT; - if (acb & ACB_DOMTRUST) uf |= UF_INTERDOMAIN_TRUST_ACCOUNT; - if (acb & ACB_WSTRUST) uf |= UF_WORKSTATION_TRUST_ACCOUNT; - if (acb & ACB_SVRTRUST) uf |= UF_SERVER_TRUST_ACCOUNT; - if (acb & ACB_PWNOEXP) uf |= UF_DONT_EXPIRE_PASSWD; - if (acb & ACB_AUTOLOCK) uf |= UF_LOCKOUT; - if (acb & ACB_USE_DES_KEY_ONLY) uf |= UF_USE_DES_KEY_ONLY; - if (acb & ACB_SMARTCARD_REQUIRED) uf |= UF_SMARTCARD_REQUIRED; - if (acb & ACB_TRUSTED_FOR_DELEGATION) uf |= UF_TRUSTED_FOR_DELEGATION; - if (acb & ACB_DONT_REQUIRE_PREAUTH) uf |= UF_DONT_REQUIRE_PREAUTH; - if (acb & ACB_NO_AUTH_DATA_REQD) uf |= UF_NO_AUTH_DATA_REQUIRED; - if (acb & ACB_NOT_DELEGATED) uf |= UF_NOT_DELEGATED; - if (acb & ACB_ENC_TXT_PWD_ALLOWED) uf |= UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED; - - return uf; -} - -/* -translated the UserFlags (userAccountControl) to ACB_CTRL Flags -*/ -uint32 ads_uf2acb(uint32 uf) -{ - uint32 acb = 0x00000000; - - if (uf & UF_ACCOUNTDISABLE) acb |= ACB_DISABLED; - if (uf & UF_HOMEDIR_REQUIRED) acb |= ACB_HOMDIRREQ; - if (uf & UF_PASSWD_NOTREQD) acb |= ACB_PWNOTREQ; - if (uf & UF_MNS_LOGON_ACCOUNT) acb |= ACB_MNS; - if (uf & UF_DONT_EXPIRE_PASSWD) acb |= ACB_PWNOEXP; - if (uf & UF_LOCKOUT) acb |= ACB_AUTOLOCK; - if (uf & UF_USE_DES_KEY_ONLY) acb |= ACB_USE_DES_KEY_ONLY; - if (uf & UF_SMARTCARD_REQUIRED) acb |= ACB_SMARTCARD_REQUIRED; - if (uf & UF_TRUSTED_FOR_DELEGATION) acb |= ACB_TRUSTED_FOR_DELEGATION; - if (uf & UF_DONT_REQUIRE_PREAUTH) acb |= ACB_DONT_REQUIRE_PREAUTH; - if (uf & UF_NO_AUTH_DATA_REQUIRED) acb |= ACB_NO_AUTH_DATA_REQD; - if (uf & UF_NOT_DELEGATED) acb |= ACB_NOT_DELEGATED; - if (uf & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED) acb |= ACB_ENC_TXT_PWD_ALLOWED; - - switch (uf & UF_ACCOUNT_TYPE_MASK) - { - case UF_TEMP_DUPLICATE_ACCOUNT: acb |= ACB_TEMPDUP;break; - case UF_NORMAL_ACCOUNT: acb |= ACB_NORMAL;break; - case UF_INTERDOMAIN_TRUST_ACCOUNT: acb |= ACB_DOMTRUST;break; - case UF_WORKSTATION_TRUST_ACCOUNT: acb |= ACB_WSTRUST;break; - case UF_SERVER_TRUST_ACCOUNT: acb |= ACB_SVRTRUST;break; - /*Fix Me: what should we do here? */ - default: acb |= ACB_NORMAL;break; - } - - return acb; -} - -/* -get the accountType from the UserFlags -*/ -uint32 ads_uf2atype(uint32 uf) -{ - uint32 atype = 0x00000000; - - if (uf & UF_NORMAL_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; - else if (uf & UF_TEMP_DUPLICATE_ACCOUNT) atype = ATYPE_NORMAL_ACCOUNT; - else if (uf & UF_SERVER_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; - else if (uf & UF_WORKSTATION_TRUST_ACCOUNT) atype = ATYPE_WORKSTATION_TRUST; - else if (uf & UF_INTERDOMAIN_TRUST_ACCOUNT) atype = ATYPE_INTERDOMAIN_TRUST; - - return atype; -} - -/* -get the accountType from the groupType -*/ -uint32 ads_gtype2atype(uint32 gtype) -{ - uint32 atype = 0x00000000; - - switch(gtype) { - case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP: - atype = ATYPE_SECURITY_LOCAL_GROUP; - break; - case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP: - atype = ATYPE_SECURITY_LOCAL_GROUP; - break; - case GTYPE_SECURITY_GLOBAL_GROUP: - atype = ATYPE_SECURITY_GLOBAL_GROUP; - break; - - case GTYPE_DISTRIBUTION_GLOBAL_GROUP: - atype = ATYPE_DISTRIBUTION_GLOBAL_GROUP; - break; - case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP: - atype = ATYPE_DISTRIBUTION_UNIVERSAL_GROUP; - break; - case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP: - atype = ATYPE_DISTRIBUTION_LOCAL_GROUP; - break; - } - - return atype; -} - -/* turn a sAMAccountType into a SID_NAME_USE */ -enum lsa_SidType ads_atype_map(uint32 atype) -{ - switch (atype & 0xF0000000) { - case ATYPE_GLOBAL_GROUP: - return SID_NAME_DOM_GRP; - case ATYPE_SECURITY_LOCAL_GROUP: - return SID_NAME_ALIAS; - case ATYPE_ACCOUNT: - return SID_NAME_USER; - default: - DEBUG(1,("hmm, need to map account type 0x%x\n", atype)); - } - return SID_NAME_UNKNOWN; -} diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index a1663c1f38..272f107138 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -753,7 +753,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer; - if (!push_ucs2_talloc(NULL, &buffer, src, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) { return (size_t)-1; } @@ -837,7 +837,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer = NULL; - if (!convert_string_talloc(NULL, CH_UNIX, CH_UTF16LE, src, srclen, + if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen, (void **)(void *)&buffer, &size, True)) { @@ -951,7 +951,7 @@ size_t push_ascii_nstring(void *dest, const char *src) smb_ucs2_t *buffer; conv_silent = True; - if (!push_ucs2_talloc(NULL, &buffer, src, &buffer_len)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &buffer_len)) { smb_panic("failed to create UCS2 buffer"); } @@ -1268,7 +1268,7 @@ static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) } if (flags & STR_UPPER) { - tmpbuf = strupper_talloc(NULL, src); + tmpbuf = strupper_talloc(talloc_tos(), src); if (!tmpbuf) { return (size_t)-1; } diff --git a/source3/lib/ctdbd_conn.c b/source3/lib/ctdbd_conn.c index dde377581b..449e049ffa 100644 --- a/source3/lib/ctdbd_conn.c +++ b/source3/lib/ctdbd_conn.c @@ -358,7 +358,7 @@ static NTSTATUS ctdb_read_req(struct ctdbd_connection *conn, uint32 reqid, goto next_pkt; } - if (!(msg_state = TALLOC_P(NULL, struct deferred_msg_state))) { + if (!(msg_state = TALLOC_P(talloc_autofree_context(), struct deferred_msg_state))) { DEBUG(0, ("talloc failed\n")); TALLOC_FREE(hdr); goto next_pkt; diff --git a/source3/lib/dbwrap_tdb.c b/source3/lib/dbwrap_tdb.c index c71e073b41..297a351764 100644 --- a/source3/lib/dbwrap_tdb.c +++ b/source3/lib/dbwrap_tdb.c @@ -94,7 +94,7 @@ static struct db_record *db_tdb_fetch_locked(struct db_context *db, /* Do not accidently allocate/deallocate w/o need when debug level is lower than needed */ if(DEBUGLEVEL >= 10) { - char *keystr = hex_encode_talloc(NULL, (unsigned char*)key.dptr, key.dsize); + char *keystr = hex_encode_talloc(talloc_tos(), (unsigned char*)key.dptr, key.dsize); DEBUG(10, (DEBUGLEVEL > 10 ? "Locking key %s\n" : "Locking key %.20s\n", keystr)); diff --git a/source3/lib/dbwrap_util.c b/source3/lib/dbwrap_util.c index 3be3a49e7d..c3ab93c4df 100644 --- a/source3/lib/dbwrap_util.c +++ b/source3/lib/dbwrap_util.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Utility functions for the dbwrap API Copyright (C) Volker Lendecke 2007 + Copyright (C) Michael Adam 2009 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 @@ -178,96 +179,77 @@ int32 dbwrap_change_int32_atomic(struct db_context *db, const char *keystr, return 0; } -NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf, - int flag) +struct dbwrap_store_context { + TDB_DATA *key; + TDB_DATA *dbuf; + int flag; +}; + +static NTSTATUS dbwrap_store_action(struct db_context *db, void *private_data) { - int res; struct db_record *rec = NULL; NTSTATUS status; + struct dbwrap_store_context *store_ctx; - res = db->transaction_start(db); - if (res != 0) { - DEBUG(5, ("transaction_start failed\n")); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } + store_ctx = (struct dbwrap_store_context *)private_data; - rec = db->fetch_locked(db, talloc_tos(), key); + rec = db->fetch_locked(db, talloc_tos(), *(store_ctx->key)); if (rec == NULL) { DEBUG(5, ("fetch_locked failed\n")); - status = NT_STATUS_NO_MEMORY; - goto cancel; + return NT_STATUS_NO_MEMORY; } - status = rec->store(rec, dbuf, flag); + status = rec->store(rec, *(store_ctx->dbuf), store_ctx->flag); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("store returned %s\n", nt_errstr(status))); - goto cancel; } TALLOC_FREE(rec); + return status; +} - res = db->transaction_commit(db); - if (res != 0) { - DEBUG(5, ("tdb_transaction_commit failed\n")); - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - TALLOC_FREE(rec); - return status; - } +NTSTATUS dbwrap_trans_store(struct db_context *db, TDB_DATA key, TDB_DATA dbuf, + int flag) +{ + NTSTATUS status; + struct dbwrap_store_context store_ctx; - return NT_STATUS_OK; + store_ctx.key = &key; + store_ctx.dbuf = &dbuf; + store_ctx.flag = flag; - cancel: - TALLOC_FREE(rec); + status = dbwrap_trans_do(db, dbwrap_store_action, &store_ctx); - if (db->transaction_cancel(db) != 0) { - smb_panic("Cancelling transaction failed"); - } return status; } -NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key) +static NTSTATUS dbwrap_delete_action(struct db_context * db, void *private_data) { - int res; - struct db_record *rec = NULL; NTSTATUS status; + struct db_record *rec; + TDB_DATA *key = (TDB_DATA *)private_data; - res = db->transaction_start(db); - if (res != 0) { - DEBUG(5, ("transaction_start failed\n")); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - rec = db->fetch_locked(db, talloc_tos(), key); + rec = db->fetch_locked(db, talloc_tos(), *key); if (rec == NULL) { DEBUG(5, ("fetch_locked failed\n")); - status = NT_STATUS_NO_MEMORY; - goto cancel; + return NT_STATUS_NO_MEMORY; } status = rec->delete_rec(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("delete_rec returned %s\n", nt_errstr(status))); - goto cancel; } - TALLOC_FREE(rec); - - res = db->transaction_commit(db); - if (res != 0) { - DEBUG(5, ("tdb_transaction_commit failed\n")); - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - TALLOC_FREE(rec); - return status; - } + talloc_free(rec); + return status; +} - return NT_STATUS_OK; +NTSTATUS dbwrap_trans_delete(struct db_context *db, TDB_DATA key) +{ + NTSTATUS status; - cancel: - TALLOC_FREE(rec); + status = dbwrap_trans_do(db, dbwrap_delete_action, &key); - if (db->transaction_cancel(db) != 0) { - smb_panic("Cancelling transaction failed"); - } return status; } @@ -307,3 +289,86 @@ NTSTATUS dbwrap_trans_delete_bystring(struct db_context *db, const char *key) { return dbwrap_trans_delete(db, string_term_tdb_data(key)); } + +/** + * Wrap db action(s) into a transaction. + */ +NTSTATUS dbwrap_trans_do(struct db_context *db, + NTSTATUS (*action)(struct db_context *, void *), + void *private_data) +{ + int res; + NTSTATUS status; + + res = db->transaction_start(db); + if (res != 0) { + DEBUG(5, ("transaction_start failed\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = action(db, private_data); + if (!NT_STATUS_IS_OK(status)) { + if (db->transaction_cancel(db) != 0) { + smb_panic("Cancelling transaction failed"); + } + return status; + } + + res = db->transaction_commit(db); + if (res == 0) { + return NT_STATUS_OK; + } + + DEBUG(2, ("transaction_commit failed\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; +} + +NTSTATUS dbwrap_delete_bystring_upper(struct db_context *db, const char *key) +{ + char *key_upper; + NTSTATUS status; + + key_upper = talloc_strdup_upper(talloc_tos(), key); + if (key_upper == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = dbwrap_delete_bystring(db, key_upper); + + talloc_free(key_upper); + return status; +} + +NTSTATUS dbwrap_store_bystring_upper(struct db_context *db, const char *key, + TDB_DATA data, int flags) +{ + char *key_upper; + NTSTATUS status; + + key_upper = talloc_strdup_upper(talloc_tos(), key); + if (key_upper == NULL) { + return NT_STATUS_NO_MEMORY; + } + + status = dbwrap_store_bystring(db, key_upper, data, flags); + + talloc_free(key_upper); + return status; +} + +TDB_DATA dbwrap_fetch_bystring_upper(struct db_context *db, TALLOC_CTX *mem_ctx, + const char *key) +{ + char *key_upper; + TDB_DATA result; + + key_upper = talloc_strdup_upper(talloc_tos(), key); + if (key_upper == NULL) { + return make_tdb_data(NULL, 0); + } + + result = dbwrap_fetch_bystring(db, mem_ctx, key_upper); + + talloc_free(key_upper); + return result; +} diff --git a/source3/lib/errmap_unix.c b/source3/lib/errmap_unix.c index 0c39a572ad..00c5475394 100644 --- a/source3/lib/errmap_unix.c +++ b/source3/lib/errmap_unix.c @@ -40,6 +40,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = { { EISDIR, ERRDOS, ERRnoaccess, NT_STATUS_FILE_IS_A_DIRECTORY}, { EMLINK, ERRDOS, ERRgeneral, NT_STATUS_TOO_MANY_LINKS }, { EINTR, ERRHRD, ERRgeneral, NT_STATUS_RETRY }, + { ENOSYS, ERRDOS, ERRunsup, NT_STATUS_NOT_SUPPORTED }, #ifdef ELOOP { ELOOP, ERRDOS, ERRbadpath, NT_STATUS_OBJECT_PATH_NOT_FOUND }, #endif diff --git a/source3/lib/events.c b/source3/lib/events.c index 08debb4252..7a06ad0829 100644 --- a/source3/lib/events.c +++ b/source3/lib/events.c @@ -286,7 +286,7 @@ static void s3_event_debug(void *context, enum tevent_debug_level level, samba_level = 2; break; case TEVENT_DEBUG_TRACE: - samba_level = 10; + samba_level = 11; break; }; diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 7f133f20b0..ee1f4b70b3 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -26,12 +26,13 @@ #define DBGC_CLASS DBGC_TDB #define TIMEOUT_LEN 12 -#define CACHE_DATA_FMT "%12u/%s" +#define CACHE_DATA_FMT "%12u/" #define READ_CACHE_DATA_FMT_TEMPLATE "%%12u/%%%us" #define BLOB_TYPE "DATA_BLOB" #define BLOB_TYPE_LEN 9 -static TDB_CONTEXT *cache; +static struct tdb_context *cache; +static struct tdb_context *cache_notrans; /** * @file gencache.c @@ -49,9 +50,10 @@ static TDB_CONTEXT *cache; * false on failure **/ -bool gencache_init(void) +static bool gencache_init(void) { char* cache_fname = NULL; + int open_flags = O_RDWR|O_CREAT; /* skip file open if it's already opened */ if (cache) return True; @@ -60,11 +62,12 @@ bool gencache_init(void) DEBUG(5, ("Opening cache file at %s\n", cache_fname)); - cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0644); + cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, open_flags, 0644); if (!cache && (errno == EACCES)) { - cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, O_RDONLY, 0644); + open_flags = O_RDONLY; + cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, open_flags, + 0644); if (cache) { DEBUG(5, ("gencache_init: Opening cache file %s read-only.\n", cache_fname)); } @@ -74,65 +77,123 @@ bool gencache_init(void) DEBUG(5, ("Attempt to open gencache.tdb has failed.\n")); return False; } - return True; -} + cache_fname = lock_path("gencache_notrans.tdb"); -/** - * Cache shutdown function. Closes opened cache tdb file. - * - * @return true on successful closing the cache or - * false on failure during cache shutdown - **/ + DEBUG(5, ("Opening cache file at %s\n", cache_fname)); -bool gencache_shutdown(void) -{ - int ret; - /* tdb_close routine returns -1 on error */ - if (!cache) return False; - DEBUG(5, ("Closing cache file\n")); - ret = tdb_close(cache); - cache = NULL; - return ret != -1; + cache_notrans = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST, + open_flags, 0644); + if (cache_notrans == NULL) { + DEBUG(5, ("Opening %s failed: %s\n", cache_fname, + strerror(errno))); + tdb_close(cache); + return false; + } + + return True; } +static TDB_DATA last_stabilize_key(void) +{ + TDB_DATA result; + result.dptr = (uint8_t *)"@LAST_STABILIZED"; + result.dsize = 17; + return result; +} /** * Set an entry in the cache file. If there's no such * one, then add it. * * @param keystr string that represents a key of this entry - * @param value text representation value being cached + * @param blob DATA_BLOB value being cached * @param timeout time when the value is expired * * @retval true when entry is successfuly stored * @retval false on failure **/ -bool gencache_set(const char *keystr, const char *value, time_t timeout) +bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, + time_t timeout) { int ret; TDB_DATA databuf; - char* valstr = NULL; + char* val; + time_t last_stabilize; + static int writecount; + + if (tdb_data_cmp(string_term_tdb_data(keystr), + last_stabilize_key()) == 0) { + DEBUG(10, ("Can't store %s as a key\n", keystr)); + return false; + } - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr && value); + if ((keystr == NULL) || (blob == NULL)) { + return false; + } if (!gencache_init()) return False; - if (asprintf(&valstr, CACHE_DATA_FMT, (int)timeout, value) == -1) { + val = talloc_asprintf(talloc_tos(), CACHE_DATA_FMT, (int)timeout); + if (val == NULL) { return False; } + val = talloc_realloc(NULL, val, char, talloc_array_length(val)-1); + if (val == NULL) { + return false; + } + val = (char *)talloc_append_blob(NULL, val, *blob); + if (val == NULL) { + return false; + } - databuf = string_term_tdb_data(valstr); - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" - " %s (%d seconds %s)\n", keystr, value,ctime(&timeout), + DEBUG(10, ("Adding cache entry with key = %s and timeout =" + " %s (%d seconds %s)\n", keystr, ctime(&timeout), (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); - ret = tdb_store_bystring(cache, keystr, databuf, 0); - SAFE_FREE(valstr); + ret = tdb_store_bystring( + cache_notrans, keystr, + make_tdb_data((uint8_t *)val, talloc_array_length(val)), + 0); + TALLOC_FREE(val); + if (ret != 0) { + return false; + } + + /* + * Every 100 writes within a single process, stabilize the cache with + * a transaction. This is done to prevent a single transaction to + * become huge and chew lots of memory. + */ + writecount += 1; + if (writecount > lp_parm_int(-1, "gencache", "stabilize_count", 100)) { + gencache_stabilize(); + writecount = 0; + goto done; + } + + /* + * Every 5 minutes, call gencache_stabilize() to not let grow + * gencache_notrans.tdb too large. + */ + + last_stabilize = 0; + databuf = tdb_fetch(cache_notrans, last_stabilize_key()); + if ((databuf.dptr != NULL) + && (databuf.dptr[databuf.dsize-1] == '\0')) { + last_stabilize = atoi((char *)databuf.dptr); + SAFE_FREE(databuf.dptr); + } + if ((last_stabilize + + lp_parm_int(-1, "gencache", "stabilize_interval", 300)) + < time(NULL)) { + gencache_stabilize(); + } + +done: return ret == 0; } @@ -147,26 +208,63 @@ bool gencache_set(const char *keystr, const char *value, time_t timeout) bool gencache_del(const char *keystr) { - int ret; + bool exists; + bool ret = false; + char *value; - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr); + if (keystr == NULL) { + return false; + } if (!gencache_init()) return False; DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); - ret = tdb_delete_bystring(cache, keystr); - return ret == 0; + if (tdb_lock_bystring(cache_notrans, keystr) == -1) { + DEBUG(5, ("Could not lock key for %s\n", keystr)); + return false; + } + + /* + * We delete an element by setting its timeout to 0. This way we don't + * have to do a transaction on gencache.tdb every time we delete an + * element. + */ + + exists = gencache_get(keystr, &value, NULL); + if (exists) { + SAFE_FREE(value); + ret = gencache_set(keystr, "", 0); + } + tdb_unlock_bystring(cache_notrans, keystr); + return ret; } +static bool gencache_pull_timeout(char *val, time_t *pres, char **pendptr) +{ + time_t res; + char *endptr; + + res = strtol(val, &endptr, 10); + + if ((endptr == NULL) || (*endptr != '/')) { + DEBUG(2, ("Invalid gencache data format: %s\n", val)); + return false; + } + if (pres != NULL) { + *pres = res; + } + if (pendptr != NULL) { + *pendptr = endptr; + } + return true; +} /** * Get existing entry from the cache file. * * @param keystr string that represents a key of this entry - * @param valstr buffer that is allocated and filled with the entry value - * buffer's disposing must be done outside + * @param blob DATA_BLOB that is filled with entry's blob * @param timeout pointer to a time_t that is filled with entry's * timeout * @@ -174,31 +272,40 @@ bool gencache_del(const char *keystr) * @retval False for failure **/ -bool gencache_get(const char *keystr, char **valstr, time_t *timeout) +bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, + time_t *timeout) { TDB_DATA databuf; time_t t; char *endptr; - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr); + if (keystr == NULL) { + return false; + } + + if (tdb_data_cmp(string_term_tdb_data(keystr), + last_stabilize_key()) == 0) { + DEBUG(10, ("Can't get %s as a key\n", keystr)); + return false; + } if (!gencache_init()) { return False; } - databuf = tdb_fetch_bystring(cache, keystr); + databuf = tdb_fetch_bystring(cache_notrans, keystr); if (databuf.dptr == NULL) { - DEBUG(10, ("Cache entry with key = %s couldn't be found\n", + databuf = tdb_fetch_bystring(cache, keystr); + } + + if (databuf.dptr == NULL) { + DEBUG(10, ("Cache entry with key = %s couldn't be found \n", keystr)); return False; } - t = strtol((const char *)databuf.dptr, &endptr, 10); - - if ((endptr == NULL) || (*endptr != '/')) { - DEBUG(2, ("Invalid gencache data format: %s\n", databuf.dptr)); + if (!gencache_pull_timeout((char *)databuf.dptr, &t, &endptr)) { SAFE_FREE(databuf.dptr); return False; } @@ -207,20 +314,33 @@ bool gencache_get(const char *keystr, char **valstr, time_t *timeout) "timeout = %s", t > time(NULL) ? "valid" : "expired", keystr, endptr+1, ctime(&t))); + if (t == 0) { + /* Deleted */ + SAFE_FREE(databuf.dptr); + return False; + } + if (t <= time(NULL)) { - /* We're expired, delete the entry */ - tdb_delete_bystring(cache, keystr); + /* + * We're expired, delete the entry. We can't use gencache_del + * here, because that uses gencache_get_data_blob for checking + * the existence of a record. We know the thing exists and + * directly store an empty value with 0 timeout. + */ + gencache_set(keystr, "", 0); SAFE_FREE(databuf.dptr); return False; } - if (valstr) { - *valstr = SMB_STRDUP(endptr+1); - if (*valstr == NULL) { + if (blob != NULL) { + *blob = data_blob( + endptr+1, + databuf.dsize - PTR_DIFF(endptr+1, databuf.dptr)); + if (blob->data == NULL) { SAFE_FREE(databuf.dptr); - DEBUG(0, ("strdup failed\n")); + DEBUG(0, ("memdup failed\n")); return False; } } @@ -234,155 +354,192 @@ bool gencache_get(const char *keystr, char **valstr, time_t *timeout) return True; } +struct stabilize_state { + bool written; + bool error; +}; +static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, + void *priv); + /** - * Get existing entry from the cache file. - * - * @param keystr string that represents a key of this entry - * @param blob DATA_BLOB that is filled with entry's blob - * @param expired pointer to a bool that indicates whether the entry is expired + * Stabilize gencache * - * @retval true when entry is successfuly fetched - * @retval False for failure - **/ + * Migrate the clear-if-first gencache data to the stable, + * transaction-based gencache.tdb + */ -bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, bool *expired) +bool gencache_stabilize(void) { - TDB_DATA databuf; - time_t t; - char *blob_type; - unsigned char *buf = NULL; - bool ret = False; - fstring valstr; - int buflen = 0, len = 0, blob_len = 0; - unsigned char *blob_buf = NULL; - - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr); + struct stabilize_state state; + int res; + char *now; if (!gencache_init()) { - return False; + return false; } - databuf = tdb_fetch_bystring(cache, keystr); - if (!databuf.dptr) { - DEBUG(10,("Cache entry with key = %s couldn't be found\n", - keystr)); - return False; + res = tdb_transaction_start(cache); + if (res == -1) { + DEBUG(10, ("Could not start transaction on gencache.tdb: " + "%s\n", tdb_errorstr(cache))); + return false; + } + res = tdb_transaction_start(cache_notrans); + if (res == -1) { + tdb_transaction_cancel(cache); + DEBUG(10, ("Could not start transaction on " + "gencache_notrans.tdb: %s\n", + tdb_errorstr(cache_notrans))); + return false; } - buf = (unsigned char *)databuf.dptr; - buflen = databuf.dsize; + state.error = false; + state.written = false; - len += tdb_unpack(buf+len, buflen-len, "fB", - &valstr, - &blob_len, &blob_buf); - if (len == -1) { - goto out; + res = tdb_traverse(cache_notrans, stabilize_fn, &state); + if ((res == -1) || state.error) { + if ((tdb_transaction_cancel(cache_notrans) == -1) + || (tdb_transaction_cancel(cache) == -1)) { + smb_panic("tdb_transaction_cancel failed\n"); + } + return false; } - t = strtol(valstr, &blob_type, 10); + if (!state.written) { + if ((tdb_transaction_cancel(cache_notrans) == -1) + || (tdb_transaction_cancel(cache) == -1)) { + smb_panic("tdb_transaction_cancel failed\n"); + } + return true; + } - if (strcmp(blob_type+1, BLOB_TYPE) != 0) { - goto out; + res = tdb_transaction_commit(cache); + if (res == -1) { + DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: " + "%s\n", tdb_errorstr(cache))); + if (tdb_transaction_cancel(cache_notrans) == -1) { + smb_panic("tdb_transaction_cancel failed\n"); + } + return false; } - DEBUG(10,("Returning %s cache entry: key = %s, " - "timeout = %s", t > time(NULL) ? "valid" : - "expired", keystr, ctime(&t))); + res = tdb_transaction_commit(cache_notrans); + if (res == -1) { + DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: " + "%s\n", tdb_errorstr(cache))); + return false; + } - if (t <= time(NULL)) { - /* We're expired */ - if (expired) { - *expired = True; - } + now = talloc_asprintf(talloc_tos(), "%d", (int)time(NULL)); + if (now != NULL) { + tdb_store(cache_notrans, last_stabilize_key(), + string_term_tdb_data(now), 0); + TALLOC_FREE(now); } - if (blob) { - *blob = data_blob(blob_buf, blob_len); - if (!blob->data) { - goto out; + return true; +} + +static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, + void *priv) +{ + struct stabilize_state *state = (struct stabilize_state *)priv; + int res; + time_t timeout; + + if (tdb_data_cmp(key, last_stabilize_key()) == 0) { + return 0; + } + + if (!gencache_pull_timeout((char *)val.dptr, &timeout, NULL)) { + DEBUG(10, ("Ignoring invalid entry\n")); + return 0; + } + if ((timeout < time(NULL)) || (val.dsize == 0)) { + res = tdb_delete(cache, key); + if ((res == -1) && (tdb_error(cache) == TDB_ERR_NOEXIST)) { + res = 0; + } else { + state->written = true; + } + } else { + res = tdb_store(cache, key, val, 0); + if (res == 0) { + state->written = true; } } - ret = True; - out: - SAFE_FREE(blob_buf); - SAFE_FREE(databuf.dptr); + if (res == -1) { + DEBUG(10, ("Transfer to gencache.tdb failed: %s\n", + tdb_errorstr(cache))); + state->error = true; + return -1; + } - return ret; + if (tdb_delete(cache_notrans, key) == -1) { + DEBUG(10, ("tdb_delete from gencache_notrans.tdb failed: " + "%s\n", tdb_errorstr(cache_notrans))); + state->error = true; + return -1; + } + return 0; } /** - * Set an entry in the cache file. If there's no such - * one, then add it. + * Get existing entry from the cache file. * * @param keystr string that represents a key of this entry - * @param blob DATA_BLOB value being cached - * @param timeout time when the value is expired + * @param valstr buffer that is allocated and filled with the entry value + * buffer's disposing must be done outside + * @param timeout pointer to a time_t that is filled with entry's + * timeout * - * @retval true when entry is successfuly stored - * @retval false on failure + * @retval true when entry is successfuly fetched + * @retval False for failure **/ -bool gencache_set_data_blob(const char *keystr, const DATA_BLOB *blob, time_t timeout) +bool gencache_get(const char *keystr, char **value, time_t *ptimeout) { + DATA_BLOB blob; bool ret = False; - int tdb_ret; - TDB_DATA databuf; - char *valstr = NULL; - unsigned char *buf = NULL; - int len = 0, buflen = 0; - /* fail completely if get null pointers passed */ - SMB_ASSERT(keystr && blob); - - if (!gencache_init()) { - return False; + ret = gencache_get_data_blob(keystr, &blob, ptimeout); + if (!ret) { + return false; } - - if (asprintf(&valstr, "%12u/%s", (int)timeout, BLOB_TYPE) == -1) { - return False; + if ((blob.data == NULL) || (blob.length == 0)) { + SAFE_FREE(blob.data); + return false; } - - again: - len = 0; - - len += tdb_pack(buf+len, buflen-len, "fB", - valstr, - blob->length, blob->data); - - if (len == -1) { - goto out; + if (blob.data[blob.length-1] != '\0') { + /* Not NULL terminated, can't be a string */ + SAFE_FREE(blob.data); + return false; } - - if (buflen < len) { - SAFE_FREE(buf); - buf = SMB_MALLOC_ARRAY(unsigned char, len); - if (!buf) { - goto out; - } - buflen = len; - goto again; - } - - databuf = make_tdb_data(buf, len); - - DEBUG(10,("Adding cache entry with key = %s; " - "blob size = %d and timeout = %s" - "(%d seconds %s)\n", keystr, (int)databuf.dsize, - ctime(&timeout), (int)(timeout - time(NULL)), - timeout > time(NULL) ? "ahead" : "in the past")); - - tdb_ret = tdb_store_bystring(cache, keystr, databuf, 0); - if (tdb_ret == 0) { - ret = True; + *value = SMB_STRDUP((char *)blob.data); + data_blob_free(&blob); + if (*value == NULL) { + return false; } + return true; +} - out: - SAFE_FREE(valstr); - SAFE_FREE(buf); +/** + * Set an entry in the cache file. If there's no such + * one, then add it. + * + * @param keystr string that represents a key of this entry + * @param value text representation value being cached + * @param timeout time when the value is expired + * + * @retval true when entry is successfuly stored + * @retval false on failure + **/ - return ret; +bool gencache_set(const char *keystr, const char *value, time_t timeout) +{ + DATA_BLOB blob = data_blob_const(value, strlen(value)+1); + return gencache_set_data_blob(keystr, &blob, timeout); } /** @@ -401,6 +558,7 @@ struct gencache_iterate_state { void *priv); const char *pattern; void *priv; + bool in_persistent; }; static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key, @@ -416,6 +574,14 @@ static int gencache_iterate_fn(struct tdb_context *tdb, TDB_DATA key, time_t timeout; char *timeout_endp; + if (tdb_data_cmp(key, last_stabilize_key()) == 0) { + return 0; + } + + if (state->in_persistent && tdb_exists(cache_notrans, key)) { + return 0; + } + if (key.dptr[key.dsize-1] == '\0') { keystr = (char *)key.dptr; } else { @@ -465,8 +631,9 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time { struct gencache_iterate_state state; - /* fail completely if get null pointers passed */ - SMB_ASSERT(fn && keystr_pattern); + if ((fn == NULL) || (keystr_pattern == NULL)) { + return; + } if (!gencache_init()) return; @@ -475,30 +642,10 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time state.fn = fn; state.pattern = keystr_pattern; state.priv = data; - tdb_traverse(cache, gencache_iterate_fn, &state); -} -/******************************************************************** - lock a key -********************************************************************/ + state.in_persistent = false; + tdb_traverse(cache_notrans, gencache_iterate_fn, &state); -int gencache_lock_entry( const char *key ) -{ - if (!gencache_init()) - return -1; - - return tdb_lock_bystring(cache, key); -} - -/******************************************************************** - unlock a key -********************************************************************/ - -void gencache_unlock_entry( const char *key ) -{ - if (!gencache_init()) - return; - - tdb_unlock_bystring(cache, key); - return; + state.in_persistent = true; + tdb_traverse(cache, gencache_iterate_fn, &state); } diff --git a/source3/lib/ldap_escape.c b/source3/lib/ldap_escape.c index d101bc5ecd..a731cb9864 100644 --- a/source3/lib/ldap_escape.c +++ b/source3/lib/ldap_escape.c @@ -32,10 +32,10 @@ * and to be free()ed by the caller. **/ -char *escape_ldap_string_alloc(const char *s) +char *escape_ldap_string(TALLOC_CTX *mem_ctx, const char *s) { size_t len = strlen(s)+1; - char *output = (char *)SMB_MALLOC(len); + char *output = talloc_array(mem_ctx, char, len); const char *sub; int i = 0; char *p = output; @@ -43,7 +43,7 @@ char *escape_ldap_string_alloc(const char *s) if (output == NULL) { return NULL; } - + while (*s) { switch (*s) @@ -64,14 +64,17 @@ char *escape_ldap_string_alloc(const char *s) sub = NULL; break; } - + if (sub) { + char *tmp; len = len + 3; - output = (char *)SMB_REALLOC(output, len); - if (!output) { + tmp = talloc_realloc(mem_ctx, output, char, len); + if (tmp == NULL) { + TALLOC_FREE(output); return NULL; } - + output = tmp; + p = &output[i]; strncpy (p, sub, 3); p += 3; @@ -84,7 +87,7 @@ char *escape_ldap_string_alloc(const char *s) } s++; } - + *p = '\0'; return output; } @@ -101,7 +104,7 @@ char *escape_rdn_val_string_alloc(const char *s) } p = output; - + while (*s) { switch (*s) @@ -122,10 +125,10 @@ char *escape_rdn_val_string_alloc(const char *s) *p = *s; p++; } - + s++; } - + *p = '\0'; /* resize the string to the actual final size */ diff --git a/source3/lib/netapi/netapi.c b/source3/lib/netapi/netapi.c index 2f8474b37f..e80879a1d2 100644 --- a/source3/lib/netapi/netapi.c +++ b/source3/lib/netapi/netapi.c @@ -170,7 +170,6 @@ NET_API_STATUS libnetapi_free(struct libnetapi_ctx *ctx) gfree_charcnv(); gfree_interfaces(); - gencache_shutdown(); secrets_shutdown(); TALLOC_FREE(ctx); diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c index 39472b20d7..9fa3ddd9a8 100644 --- a/source3/lib/netapi/user.c +++ b/source3/lib/netapi/user.c @@ -770,7 +770,7 @@ static uint32_t samr_acb_flags_to_netapi_flags(uint32_t acb) { uint32_t fl = UF_SCRIPT; /* god knows why */ - fl |= ads_acb2uf(acb); + fl |= ds_acb2uf(acb); return fl; } diff --git a/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c index 66aef6ba66..478a3d24ca 100644 --- a/source3/lib/smbldap_util.c +++ b/source3/lib/smbldap_util.c @@ -126,7 +126,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, char *escape_domain_name; /* escape for filter */ - escape_domain_name = escape_ldap_string_alloc(domain_name); + escape_domain_name = escape_ldap_string(talloc_tos(), domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; @@ -135,11 +135,11 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, if (asprintf(&filter, "(&(%s=%s)(objectclass=%s))", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name, LDAP_OBJ_DOMINFO) < 0) { - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); attr_list = get_attr_list(NULL, dominfo_attr_list ); rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result); @@ -258,7 +258,7 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, int count; char *escape_domain_name; - escape_domain_name = escape_ldap_string_alloc(domain_name); + escape_domain_name = escape_ldap_string(talloc_tos(), domain_name); if (!escape_domain_name) { DEBUG(0, ("Out of memory!\n")); return NT_STATUS_NO_MEMORY; @@ -268,11 +268,11 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, LDAP_OBJ_DOMINFO, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), escape_domain_name) < 0) { - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(escape_domain_name); + TALLOC_FREE(escape_domain_name); DEBUG(2, ("smbldap_search_domain_info: Searching for:[%s]\n", filter)); diff --git a/source3/lib/system.c b/source3/lib/system.c index ffc236e93b..6a4f5d5413 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -458,8 +458,6 @@ static struct timespec calc_create_time_stat_ex(const struct stat_ex *st) static void get_create_timespec(const struct stat *pst, struct stat_ex *dst) { - struct timespec ret; - if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) { dst->st_ex_btime.tv_sec = 315493200L; /* 1/1/1980 */ dst->st_ex_btime.tv_nsec = 0; @@ -483,7 +481,7 @@ static void get_create_timespec(const struct stat *pst, struct stat_ex *dst) /* Deal with systems that don't initialize birthtime correctly. * Pointed out by SATOH Fumiyasu <fumiyas@osstech.jp>. */ - if (null_timespec(ret)) { + if (null_timespec(dst->st_ex_btime)) { dst->st_ex_btime = calc_create_time_stat(pst); dst->st_ex_calculated_birthtime = true; } diff --git a/source3/lib/tldap.c b/source3/lib/tldap.c index 451bc18d2e..fa56763a33 100644 --- a/source3/lib/tldap.c +++ b/source3/lib/tldap.c @@ -1618,7 +1618,7 @@ struct tevent_req *tldap_add_send(TALLOC_CTX *mem_ctx, static void tldap_add_done(struct tevent_req *subreq) { - return tldap_simple_done(subreq, TLDAP_RES_ADD); + tldap_simple_done(subreq, TLDAP_RES_ADD); } int tldap_add_recv(struct tevent_req *req) @@ -1718,7 +1718,7 @@ struct tevent_req *tldap_modify_send(TALLOC_CTX *mem_ctx, static void tldap_modify_done(struct tevent_req *subreq) { - return tldap_simple_done(subreq, TLDAP_RES_MODIFY); + tldap_simple_done(subreq, TLDAP_RES_MODIFY); } int tldap_modify_recv(struct tevent_req *req) @@ -1795,7 +1795,7 @@ struct tevent_req *tldap_delete_send(TALLOC_CTX *mem_ctx, static void tldap_delete_done(struct tevent_req *subreq) { - return tldap_simple_done(subreq, TLDAP_RES_DELETE); + tldap_simple_done(subreq, TLDAP_RES_DELETE); } int tldap_delete_recv(struct tevent_req *req) diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 31261afd72..af64f370ba 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -349,6 +349,9 @@ static const smb_socket_option socket_options[] = { #ifdef TCP_FASTACK {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT}, #endif +#ifdef TCP_QUICKACK + {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL}, +#endif {NULL,0,0,0,0}}; /**************************************************************************** diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index cdd7d0a300..c197fd7515 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -96,14 +96,14 @@ int StrCaseCmp(const char *s, const char *t) return +1; } - if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) { return strcmp(ps, pt); /* Not quite the right answer, but finding the right one under this failure case is expensive, and it's pretty close */ } - if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) { TALLOC_FREE(buffer_s); return strcmp(ps, pt); /* Not quite the right answer, but finding the right one @@ -157,14 +157,14 @@ int StrnCaseCmp(const char *s, const char *t, size_t len) return 0; } - if (!push_ucs2_talloc(NULL, &buffer_s, ps, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_s, ps, &size)) { return strncmp(ps, pt, len-n); /* Not quite the right answer, but finding the right one under this failure case is expensive, and it's pretty close */ } - if (!push_ucs2_talloc(NULL, &buffer_t, pt, &size)) { + if (!push_ucs2_talloc(talloc_tos(), &buffer_t, pt, &size)) { TALLOC_FREE(buffer_s); return strncmp(ps, pt, len-n); /* Not quite the right answer, but finding the right one @@ -366,7 +366,7 @@ size_t str_charnum(const char *s) { size_t ret, converted_size; smb_ucs2_t *tmpbuf2 = NULL; - if (!push_ucs2_talloc(NULL, &tmpbuf2, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) { return 0; } ret = strlen_w(tmpbuf2); @@ -384,7 +384,7 @@ size_t str_ascii_charnum(const char *s) { size_t ret, converted_size; char *tmpbuf2 = NULL; - if (!push_ascii_talloc(NULL, &tmpbuf2, s, &converted_size)) { + if (!push_ascii_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) { return 0; } ret = strlen(tmpbuf2); @@ -455,7 +455,7 @@ bool strhasupper(const char *s) bool ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) { return false; } @@ -480,7 +480,7 @@ bool strhaslower(const char *s) bool ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &tmp, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &tmp, s, &converted_size)) { return false; } @@ -1177,7 +1177,7 @@ char *strchr_m(const char *src, char c) s = src; #endif - if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { /* Wrong answer, but what can we do... */ return strchr(src, c); } @@ -1187,7 +1187,7 @@ char *strchr_m(const char *src, char c) return NULL; } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { SAFE_FREE(ws); /* Wrong answer, but what can we do... */ return strchr(src, c); @@ -1248,7 +1248,7 @@ char *strrchr_m(const char *s, char c) char *ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { /* Wrong answer, but what can we do. */ return strrchr(s, c); } @@ -1258,7 +1258,7 @@ char *strrchr_m(const char *s, char c) return NULL; } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { TALLOC_FREE(ws); /* Wrong answer, but what can we do. */ return strrchr(s, c); @@ -1283,7 +1283,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n) char *ret; size_t converted_size; - if (!push_ucs2_talloc(NULL, &ws, s, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) { /* Too hard to try and get right. */ return NULL; } @@ -1293,7 +1293,7 @@ char *strnrchr_m(const char *s, char c, unsigned int n) return NULL; } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, ws, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) { TALLOC_FREE(ws); /* Too hard to try and get right. */ return NULL; @@ -1352,12 +1352,12 @@ char *strstr_m(const char *src, const char *findstr) s = src; #endif - if (!push_ucs2_talloc(NULL, &src_w, src, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &src_w, src, &converted_size)) { DEBUG(0,("strstr_m: src malloc fail\n")); return NULL; } - if (!push_ucs2_talloc(NULL, &find_w, findstr, &converted_size)) { + if (!push_ucs2_talloc(talloc_tos(), &find_w, findstr, &converted_size)) { TALLOC_FREE(src_w); DEBUG(0,("strstr_m: find malloc fail\n")); return NULL; @@ -1372,7 +1372,7 @@ char *strstr_m(const char *src, const char *findstr) } *p = 0; - if (!pull_ucs2_talloc(NULL, &s2, src_w, &converted_size)) { + if (!pull_ucs2_talloc(talloc_tos(), &s2, src_w, &converted_size)) { TALLOC_FREE(src_w); TALLOC_FREE(find_w); DEBUG(0,("strstr_m: dest malloc fail\n")); @@ -1932,7 +1932,7 @@ char *base64_encode_data_blob(TALLOC_CTX *mem_ctx, DATA_BLOB data) result = TALLOC_ARRAY(mem_ctx, char, output_len); /* get us plenty of space */ SMB_ASSERT(result != NULL); - while (len-- && out_cnt < (data.length * 2) - 5) { + while (len--) { int c = (unsigned char) *(data.data++); bits += c; char_count++; diff --git a/source3/lib/util_tdb.c b/source3/lib/util_tdb.c index 78fa7cd0a1..5b3d94dabe 100644 --- a/source3/lib/util_tdb.c +++ b/source3/lib/util_tdb.c @@ -630,3 +630,22 @@ NTSTATUS map_nt_error_from_tdb(enum TDB_ERROR err) return NT_STATUS_INTERNAL_ERROR; } + +int tdb_data_cmp(TDB_DATA t1, TDB_DATA t2) +{ + int ret; + if (t1.dptr == NULL && t2.dptr != NULL) { + return -1; + } + if (t1.dptr != NULL && t2.dptr == NULL) { + return 1; + } + if (t1.dptr == t2.dptr) { + return t1.dsize - t2.dsize; + } + ret = memcmp(t1.dptr, t2.dptr, MIN(t1.dsize, t2.dsize)); + if (ret == 0) { + return t1.dsize - t2.dsize; + } + return ret; +} diff --git a/source3/libads/dns.c b/source3/libads/dns.c index 3a9e849668..5cf768de67 100644 --- a/source3/libads/dns.c +++ b/source3/libads/dns.c @@ -754,10 +754,6 @@ bool sitename_store(const char *realm, const char *sitename) bool ret = False; char *key; - if (!gencache_init()) { - return False; - } - if (!realm || (strlen(realm) == 0)) { DEBUG(0,("sitename_store: no realm\n")); return False; @@ -795,10 +791,6 @@ char *sitename_fetch(const char *realm) const char *query_realm; char *key; - if (!gencache_init()) { - return NULL; - } - if (!realm || (strlen(realm) == 0)) { query_realm = lp_realm(); } else { diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c index eecd9045e5..69dc05335e 100644 --- a/source3/libads/ldap_user.c +++ b/source3/libads/ldap_user.c @@ -30,18 +30,18 @@ ADS_STATUS status; char *ldap_exp; const char *attrs[] = {"*", NULL}; - char *escaped_user = escape_ldap_string_alloc(user); + char *escaped_user = escape_ldap_string(talloc_tos(), user); if (!escaped_user) { return ADS_ERROR(LDAP_NO_MEMORY); } if (asprintf(&ldap_exp, "(samAccountName=%s)", escaped_user) == -1) { - SAFE_FREE(escaped_user); + TALLOC_FREE(escaped_user); return ADS_ERROR(LDAP_NO_MEMORY); } status = ads_search(ads, res, ldap_exp, attrs); SAFE_FREE(ldap_exp); - SAFE_FREE(escaped_user); + TALLOC_FREE(escaped_user); return status; } diff --git a/source3/libnet/libnet_samsync_passdb.c b/source3/libnet/libnet_samsync_passdb.c index 27c7aac7e7..41a9b3d9f3 100644 --- a/source3/libnet/libnet_samsync_passdb.c +++ b/source3/libnet/libnet_samsync_passdb.c @@ -676,21 +676,24 @@ static NTSTATUS fetch_domain_info(TALLOC_CTX *mem_ctx, } - if (!pdb_set_account_policy(AP_PASSWORD_HISTORY, + if (!pdb_set_account_policy(PDB_POLICY_PASSWORD_HISTORY, r->password_history_length)) return nt_status; - if (!pdb_set_account_policy(AP_MIN_PASSWORD_LEN, + if (!pdb_set_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, r->min_password_length)) return nt_status; - if (!pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (uint32)u_max_age)) + if (!pdb_set_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, + (uint32)u_max_age)) return nt_status; - if (!pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (uint32)u_min_age)) + if (!pdb_set_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, + (uint32)u_min_age)) return nt_status; - if (!pdb_set_account_policy(AP_TIME_TO_LOGOUT, (uint32)u_logout)) + if (!pdb_set_account_policy(PDB_POLICY_TIME_TO_LOGOUT, + (uint32)u_logout)) return nt_status; if (lockstr) { @@ -699,21 +702,23 @@ static NTSTATUS fetch_domain_info(TALLOC_CTX *mem_ctx, u_lockoutreset = uint64s_nt_time_to_unix_abs(&lockstr->reset_count); u_lockouttime = uint64s_nt_time_to_unix_abs((uint64_t *)&lockstr->lockout_duration); - if (!pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, + if (!pdb_set_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, lockstr->bad_attempt_lockout)) return nt_status; - if (!pdb_set_account_policy(AP_RESET_COUNT_TIME, (uint32_t)u_lockoutreset/60)) + if (!pdb_set_account_policy(PDB_POLICY_RESET_COUNT_TIME, + (uint32_t)u_lockoutreset/60)) return nt_status; if (u_lockouttime != -1) u_lockouttime /= 60; - if (!pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (uint32_t)u_lockouttime)) + if (!pdb_set_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, + (uint32_t)u_lockouttime)) return nt_status; } - if (!pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + if (!pdb_set_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, r->logon_to_chgpass)) return nt_status; diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c index 349a8331b4..f5dbd72f22 100644 --- a/source3/libsmb/clidgram.c +++ b/source3/libsmb/clidgram.c @@ -25,7 +25,7 @@ * cli_send_mailslot, send a mailslot for client code ... */ -bool cli_send_mailslot(struct messaging_context *msg_ctx, +static bool cli_send_mailslot(struct messaging_context *msg_ctx, bool unique, const char *mailslot, uint16 priority, char *buf, int len, @@ -309,4 +309,3 @@ bool receive_getdc_response(TALLOC_CTX *mem_ctx, return True; } - diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index af67fcb746..5ea0579839 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -1893,7 +1893,6 @@ struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx, SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); /* Setup param array. */ - memset(state->param, '\0', 6); SSVAL(state->param,0,fnum); SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO); @@ -2010,6 +2009,7 @@ struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + vwv = state->vwv; SCVAL(vwv+0, 0, 0xFF); @@ -2367,6 +2367,7 @@ struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx, if (req == NULL) { return NULL; } + SSVAL(state->vwv+0, 0, fnum); SIVALS(state->vwv+1, 0, -1); @@ -2708,42 +2709,114 @@ bool cli_lock(struct cli_state *cli, uint16_t fnum, Unlock a file. ****************************************************************************/ -bool cli_unlock(struct cli_state *cli, uint16_t fnum, uint32_t offset, uint32_t len) +struct cli_unlock_state { + uint16_t vwv[8]; + uint8_t data[10]; +}; + +static void cli_unlock_done(struct tevent_req *subreq); + +struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) + { - char *p; + struct tevent_req *req = NULL, *subreq = NULL; + struct cli_unlock_state *state = NULL; + uint8_t additional_flags = 0; - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); + req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state); + if (req == NULL) { + return NULL; + } - cli_set_message(cli->outbuf,8,0,True); + SCVAL(state->vwv+0, 0, 0xFF); + SSVAL(state->vwv+2, 0, fnum); + SCVAL(state->vwv+3, 0, 0); + SIVALS(state->vwv+4, 0, 0); + SSVAL(state->vwv+6, 0, 1); + SSVAL(state->vwv+7, 0, 0); - SCVAL(cli->outbuf,smb_com,SMBlockingX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); + SSVAL(state->data, 0, cli->pid); + SIVAL(state->data, 2, offset); + SIVAL(state->data, 6, len); - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,fnum); - SCVAL(cli->outbuf,smb_vwv3,0); - SIVALS(cli->outbuf, smb_vwv4, 0); - SSVAL(cli->outbuf,smb_vwv6,1); - SSVAL(cli->outbuf,smb_vwv7,0); + subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, + 8, state->vwv, 10, state->data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_unlock_done, req); + return req; +} - p = smb_buf(cli->outbuf); - SSVAL(p, 0, cli->pid); - SIVAL(p, 2, offset); - SIVAL(p, 6, len); - p += 10; - cli_setup_bcc(cli, p); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return False; +static void cli_unlock_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + NTSTATUS status; + + status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } + tevent_req_done(req); +} - if (cli_is_error(cli)) { - return False; +NTSTATUS cli_unlock_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +NTSTATUS cli_unlock(struct cli_state *cli, + uint16_t fnum, + uint32_t offset, + uint32_t len) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } - return True; + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_unlock_send(frame, ev, cli, + fnum, offset, len); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_unlock_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -2811,149 +2884,378 @@ bool cli_lock64(struct cli_state *cli, uint16_t fnum, Unlock a file with 64 bit offsets. ****************************************************************************/ -bool cli_unlock64(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len) +struct cli_unlock64_state { + uint16_t vwv[8]; + uint8_t data[20]; +}; + +static void cli_unlock64_done(struct tevent_req *subreq); + +struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) + { - char *p; + struct tevent_req *req = NULL, *subreq = NULL; + struct cli_unlock64_state *state = NULL; + uint8_t additional_flags = 0; - if (! (cli->capabilities & CAP_LARGE_FILES)) { - return cli_unlock(cli, fnum, offset, len); + req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state); + if (req == NULL) { + return NULL; } - memset(cli->outbuf,'\0',smb_size); - memset(cli->inbuf,'\0',smb_size); + SCVAL(state->vwv+0, 0, 0xff); + SSVAL(state->vwv+2, 0, fnum); + SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES); + SIVALS(state->vwv+4, 0, 0); + SSVAL(state->vwv+6, 0, 1); + SSVAL(state->vwv+7, 0, 0); - cli_set_message(cli->outbuf,8,0,True); + SIVAL(state->data, 0, cli->pid); + SOFF_T_R(state->data, 4, offset); + SOFF_T_R(state->data, 12, len); - SCVAL(cli->outbuf,smb_com,SMBlockingX); - SSVAL(cli->outbuf,smb_tid,cli->cnum); - cli_setup_packet(cli); + subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, + 8, state->vwv, 20, state->data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_unlock64_done, req); + return req; +} - SCVAL(cli->outbuf,smb_vwv0,0xFF); - SSVAL(cli->outbuf,smb_vwv2,fnum); - SCVAL(cli->outbuf,smb_vwv3,LOCKING_ANDX_LARGE_FILES); - SIVALS(cli->outbuf, smb_vwv4, 0); - SSVAL(cli->outbuf,smb_vwv6,1); - SSVAL(cli->outbuf,smb_vwv7,0); +static void cli_unlock64_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + NTSTATUS status; - p = smb_buf(cli->outbuf); - SIVAL(p, 0, cli->pid); - SOFF_T_R(p, 4, offset); - SOFF_T_R(p, 12, len); - p += 20; - cli_setup_bcc(cli, p); - cli_send_smb(cli); - if (!cli_receive_smb(cli)) { - return False; + status = cli_smb_recv(subreq, 0, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; } + tevent_req_done(req); +} - if (cli_is_error(cli)) { - return False; +NTSTATUS cli_unlock64_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +NTSTATUS cli_unlock64(struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; + + if (! (cli->capabilities & CAP_LARGE_FILES)) { + return cli_unlock(cli, fnum, offset, len); } - return True; + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_unlock64_send(frame, ev, cli, + fnum, offset, len); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_unlock64_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** Get/unlock a POSIX lock on a file - internal function. ****************************************************************************/ -static bool cli_posix_lock_internal(struct cli_state *cli, uint16_t fnum, - uint64_t offset, uint64_t len, bool wait_lock, enum brl_type lock_type) +struct posix_lock_state { + uint16_t setup; + uint8_t param[4]; + uint8_t data[POSIX_LOCK_DATA_SIZE]; +}; + +static void cli_posix_unlock_internal_done(struct tevent_req *subreq) { - unsigned int param_len = 4; - unsigned int data_len = POSIX_LOCK_DATA_SIZE; - uint16_t setup = TRANSACT2_SETFILEINFO; - char param[4]; - unsigned char data[POSIX_LOCK_DATA_SIZE]; - char *rparam=NULL, *rdata=NULL; - int saved_timeout = cli->timeout; + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct posix_lock_state *state = tevent_req_data(req, struct posix_lock_state); + NTSTATUS status; - SSVAL(param,0,fnum); - SSVAL(param,2,SMB_SET_POSIX_LOCK); + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, NULL, NULL); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + tevent_req_done(req); +} +static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len, + bool wait_lock, + enum brl_type lock_type) +{ + struct tevent_req *req = NULL, *subreq = NULL; + struct posix_lock_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct posix_lock_state); + if (req == NULL) { + return NULL; + } + + /* Setup setup word. */ + SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO); + + /* Setup param array. */ + SSVAL(&state->param, 0, fnum); + SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK); + + /* Setup data array. */ switch (lock_type) { case READ_LOCK: - SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_READ); + SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET, + POSIX_LOCK_TYPE_READ); break; case WRITE_LOCK: - SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_WRITE); + SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET, + POSIX_LOCK_TYPE_WRITE); break; case UNLOCK_LOCK: - SSVAL(data, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK); + SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET, + POSIX_LOCK_TYPE_UNLOCK); break; default: - return False; + return NULL; } if (wait_lock) { - SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_WAIT); - cli->timeout = 0x7FFFFFFF; + SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET, + POSIX_LOCK_FLAG_WAIT); } else { - SSVAL(data, POSIX_LOCK_FLAGS_OFFSET, POSIX_LOCK_FLAG_NOWAIT); - } - - SIVAL(data, POSIX_LOCK_PID_OFFSET, cli->pid); - SOFF_T(data, POSIX_LOCK_START_OFFSET, offset); - SOFF_T(data, POSIX_LOCK_LEN_OFFSET, len); + SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET, + POSIX_LOCK_FLAG_NOWAIT); + } + + SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli->pid); + SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset); + SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len); + + subreq = cli_trans_send(state, /* mem ctx. */ + ev, /* event ctx. */ + cli, /* cli_state. */ + SMBtrans2, /* cmd. */ + NULL, /* pipe name. */ + -1, /* fid. */ + 0, /* function. */ + 0, /* flags. */ + &state->setup, /* setup. */ + 1, /* num setup uint16_t words. */ + 0, /* max returned setup. */ + state->param, /* param. */ + 4, /* num param. */ + 2, /* max returned param. */ + state->data, /* data. */ + POSIX_LOCK_DATA_SIZE, /* num data. */ + 0); /* max returned data. */ - if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - (char *)&data, data_len, cli->max_xmit /* data, length, max */ - )) { - cli->timeout = saved_timeout; - return False; - } - - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, ¶m_len, - &rdata, &data_len)) { - cli->timeout = saved_timeout; - SAFE_FREE(rdata); - SAFE_FREE(rparam); - return False; + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } - - cli->timeout = saved_timeout; - - SAFE_FREE(rdata); - SAFE_FREE(rparam); - - return True; + tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req); + return req; } /**************************************************************************** POSIX Lock a file. ****************************************************************************/ -bool cli_posix_lock(struct cli_state *cli, uint16_t fnum, +struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len, + bool wait_lock, + enum brl_type lock_type) +{ + return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len, + wait_lock, lock_type); +} + +NTSTATUS cli_posix_lock_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + return NT_STATUS_OK; +} + +NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len, bool wait_lock, enum brl_type lock_type) { + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) { - return False; + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_lock_send(frame, + ev, + cli, + fnum, + offset, + len, + wait_lock, + lock_type); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_lock_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); } - return cli_posix_lock_internal(cli, fnum, offset, len, wait_lock, lock_type); + return status; } /**************************************************************************** POSIX Unlock a file. ****************************************************************************/ -bool cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len) +struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx, + struct event_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint64_t offset, + uint64_t len) { - return cli_posix_lock_internal(cli, fnum, offset, len, False, UNLOCK_LOCK); + return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len, + false, UNLOCK_LOCK); } -/**************************************************************************** - POSIX Get any lock covering a file. -****************************************************************************/ +NTSTATUS cli_posix_unlock_recv(struct tevent_req *req) +{ + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + return NT_STATUS_OK; +} -bool cli_posix_getlock(struct cli_state *cli, uint16_t fnum, uint64_t *poffset, uint64_t *plen) +NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len) { - return True; + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev = NULL; + struct tevent_req *req = NULL; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + req = cli_posix_unlock_send(frame, + ev, + cli, + fnum, + offset, + len); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } + + status = cli_posix_unlock_recv(req); + + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -3264,7 +3566,7 @@ NTSTATUS cli_getatr(struct cli_state *cli, static void cli_setattrE_done(struct tevent_req *subreq); struct cli_setattrE_state { - int dummy; + uint16_t vwv[7]; }; struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx, @@ -3278,21 +3580,19 @@ struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx, struct tevent_req *req = NULL, *subreq = NULL; struct cli_setattrE_state *state = NULL; uint8_t additional_flags = 0; - uint16_t vwv[7]; req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state); if (req == NULL) { return NULL; } - memset(vwv, '\0', sizeof(vwv)); - SSVAL(vwv+0, 0, fnum); - cli_put_dos_date2(cli, (char *)&vwv[1], 0, change_time); - cli_put_dos_date2(cli, (char *)&vwv[3], 0, access_time); - cli_put_dos_date2(cli, (char *)&vwv[5], 0, write_time); + SSVAL(state->vwv+0, 0, fnum); + cli_put_dos_date2(cli, (char *)&state->vwv[1], 0, change_time); + cli_put_dos_date2(cli, (char *)&state->vwv[3], 0, access_time); + cli_put_dos_date2(cli, (char *)&state->vwv[5], 0, write_time); subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, - 7, vwv, 0, NULL); + 7, state->vwv, 0, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -3399,7 +3699,6 @@ struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx, return NULL; } - memset(state->vwv, '\0', sizeof(state->vwv)); SSVAL(state->vwv+0, 0, attr); cli_put_dos_date3(cli, (char *)&state->vwv[1], 0, mtime); diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 8a567dc751..152c23bd15 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -346,7 +346,7 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, } asn1_start_tag(data, ASN1_CONTEXT(2)); - asn1_read_OctetString(data, NULL, &edata_contents); + asn1_read_OctetString(data, talloc_autofree_context(), &edata_contents); asn1_end_tag(data); asn1_end_tag(data); asn1_end_tag(data); @@ -389,7 +389,7 @@ bool unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_ asn1_end_tag(data); asn1_start_tag(data, ASN1_CONTEXT(1)); - asn1_read_OctetString(data, NULL, &pac_contents); + asn1_read_OctetString(data, talloc_autofree_context(), &pac_contents); asn1_end_tag(data); asn1_end_tag(data); asn1_end_tag(data); diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index fb95d71925..e586d976cf 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -151,7 +151,7 @@ bool spnego_parse_negTokenInit(DATA_BLOB blob, asn1_start_tag(data,ASN1_SEQUENCE(0)); for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) { const char *oid_str = NULL; - asn1_read_OID(data,NULL,&oid_str); + asn1_read_OID(data,talloc_autofree_context(),&oid_str); OIDs[i] = CONST_DISCARD(char *, oid_str); } OIDs[i] = NULL; @@ -163,7 +163,7 @@ bool spnego_parse_negTokenInit(DATA_BLOB blob, asn1_start_tag(data, ASN1_CONTEXT(3)); asn1_start_tag(data, ASN1_SEQUENCE(0)); asn1_start_tag(data, ASN1_CONTEXT(0)); - asn1_read_GeneralString(data,NULL,principal); + asn1_read_GeneralString(data,talloc_autofree_context(),principal); asn1_end_tag(data); asn1_end_tag(data); asn1_end_tag(data); @@ -256,7 +256,7 @@ bool parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *se asn1_start_tag(data, ASN1_SEQUENCE(0)); for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) { const char *oid_str = NULL; - asn1_read_OID(data,NULL,&oid_str); + asn1_read_OID(data,talloc_autofree_context(),&oid_str); OIDs[i] = CONST_DISCARD(char *, oid_str); } OIDs[i] = NULL; @@ -276,7 +276,7 @@ bool parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *se } asn1_start_tag(data, ASN1_CONTEXT(2)); - asn1_read_OctetString(data,NULL,secblob); + asn1_read_OctetString(data,talloc_autofree_context(),secblob); asn1_end_tag(data); asn1_end_tag(data); @@ -436,13 +436,13 @@ bool spnego_parse_challenge(const DATA_BLOB blob, asn1_end_tag(data); asn1_start_tag(data,ASN1_CONTEXT(2)); - asn1_read_OctetString(data, NULL, chal1); + asn1_read_OctetString(data, talloc_autofree_context(), chal1); asn1_end_tag(data); /* the second challenge is optional (XP doesn't send it) */ if (asn1_tag_remaining(data)) { asn1_start_tag(data,ASN1_CONTEXT(3)); - asn1_read_OctetString(data, NULL, chal2); + asn1_read_OctetString(data, talloc_autofree_context(), chal2); asn1_end_tag(data); } @@ -505,7 +505,7 @@ bool spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth) asn1_start_tag(data, ASN1_CONTEXT(1)); asn1_start_tag(data, ASN1_SEQUENCE(0)); asn1_start_tag(data, ASN1_CONTEXT(2)); - asn1_read_OctetString(data, NULL, auth); + asn1_read_OctetString(data, talloc_autofree_context(), auth); asn1_end_tag(data); asn1_end_tag(data); asn1_end_tag(data); @@ -609,7 +609,7 @@ bool spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status, if (asn1_tag_remaining(data)) { asn1_start_tag(data,ASN1_CONTEXT(2)); - asn1_read_OctetString(data, NULL, auth); + asn1_read_OctetString(data, talloc_autofree_context(), auth); asn1_end_tag(data); } } else if (negResult == SPNEGO_NEG_RESULT_INCOMPLETE) { @@ -623,7 +623,7 @@ bool spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status, if (asn1_tag_remaining(data)) { DATA_BLOB mechList = data_blob_null; asn1_start_tag(data, ASN1_CONTEXT(3)); - asn1_read_OctetString(data, NULL, &mechList); + asn1_read_OctetString(data, talloc_autofree_context(), &mechList); asn1_end_tag(data); data_blob_free(&mechList); DEBUG(5,("spnego_parse_auth_response received mechListMIC, " diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index fb87b4dc9a..3e0f4977aa 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -133,10 +133,6 @@ static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx, { char *key; - if (!gencache_init()) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - key = dsgetdcname_cache_key(mem_ctx, domain_name); if (!key) { return NT_STATUS_NO_MEMORY; @@ -160,10 +156,6 @@ static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx, char *key; bool ret = false; - if (!gencache_init()) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - key = dsgetdcname_cache_key(mem_ctx, domain_name); if (!key) { return NT_STATUS_NO_MEMORY; @@ -171,14 +163,8 @@ static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx, expire_time = time(NULL) + DSGETDCNAME_CACHE_TTL; - if (gencache_lock_entry(key) != 0) { - return NT_STATUS_LOCK_NOT_GRANTED; - } - ret = gencache_set_data_blob(key, blob, expire_time); - gencache_unlock_entry(key); - return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -353,8 +339,7 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx, struct GUID *domain_guid, uint32_t flags, const char *site_name, - struct netr_DsRGetDCNameInfo **info_p, - bool *expired) + struct netr_DsRGetDCNameInfo **info_p) { char *key; DATA_BLOB blob; @@ -363,17 +348,13 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx, struct NETLOGON_SAM_LOGON_RESPONSE_EX r; NTSTATUS status; - if (!gencache_init()) { - return NT_STATUS_INTERNAL_DB_ERROR; - } - key = dsgetdcname_cache_key(mem_ctx, domain_name); if (!key) { return NT_STATUS_NO_MEMORY; } - if (!gencache_get_data_blob(key, &blob, expired)) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + if (!gencache_get_data_blob(key, &blob, NULL)) { + return NT_STATUS_NOT_FOUND; } info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo); @@ -428,11 +409,11 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx, struct netr_DsRGetDCNameInfo **info) { NTSTATUS status; - bool expired = false; status = dsgetdcname_cache_fetch(mem_ctx, domain_name, domain_guid, - flags, site_name, info, &expired); - if (!NT_STATUS_IS_OK(status)) { + flags, site_name, info); + if (!NT_STATUS_IS_OK(status) + && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { DEBUG(10,("dsgetdcname_cached: cache fetch failed with: %s\n", nt_errstr(status))); return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; @@ -442,7 +423,7 @@ static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx, return status; } - if (expired) { + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { status = dsgetdcname_cache_refresh(mem_ctx, msg_ctx, domain_name, domain_guid, flags, diff --git a/source3/libsmb/libsmb_context.c b/source3/libsmb/libsmb_context.c index 98885876b3..8b22ee5023 100644 --- a/source3/libsmb/libsmb_context.c +++ b/source3/libsmb/libsmb_context.c @@ -123,7 +123,6 @@ SMBC_module_init(void * punused) static void SMBC_module_terminate(void) { - gencache_shutdown(); secrets_shutdown(); gfree_all(); SMBC_initialized = false; diff --git a/source3/libsmb/libsmb_thread_posix.c b/source3/libsmb/libsmb_thread_posix.c index 411ffbdfbb..6519659c25 100644 --- a/source3/libsmb/libsmb_thread_posix.c +++ b/source3/libsmb/libsmb_thread_posix.c @@ -17,8 +17,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <pthread.h> #include "includes.h" +#include <pthread.h> #include "libsmbclient.h" #include "libsmb_internal.h" diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c index d3230cffef..dcfc609dcd 100644 --- a/source3/libsmb/namecache.c +++ b/source3/libsmb/namecache.c @@ -45,14 +45,6 @@ bool namecache_enable(void) return False; } - /* Init namecache by calling gencache initialisation */ - - if (!gencache_init()) { - DEBUG(2, ("namecache_enable: " - "Couldn't initialise namecache on top of gencache.\n")); - return False; - } - /* I leave it for now, though I don't think we really * need this (mimir, 27.09.2002) */ DEBUG(5, ("namecache_enable: enabling netbios namecache, timeout %d " @@ -102,14 +94,6 @@ bool namecache_store(const char *name, int i; bool ret; - /* - * we use gecache call to avoid annoying debug messages about - * initialised namecache again and again... - */ - if (!gencache_init()) { - return False; - } - if (name_type > 255) { return False; /* Don't store non-real name types. */ } @@ -186,10 +170,6 @@ bool namecache_fetch(const char *name, return False; } - if (!gencache_init()) { - return False; - } - if (name_type > 255) { return False; /* Don't fetch non-real name types. */ } @@ -233,9 +213,6 @@ bool namecache_delete(const char *name, int name_type) bool ret; char *key; - if (!gencache_init()) - return False; - if (name_type > 255) { return False; /* Don't fetch non-real name types. */ } @@ -274,10 +251,6 @@ static void flush_netbios_name(const char *key, void namecache_flush(void) { - if (!gencache_init()) { - return; - } - /* * iterate through each NBT cache's entry and flush it * by flush_netbios_name function @@ -312,10 +285,6 @@ bool namecache_status_store(const char *keyname, int keyname_type, time_t expiry; bool ret; - if (!gencache_init()) { - return False; - } - key = namecache_status_record_key(keyname, keyname_type, name_type, keyip); if (!key) @@ -348,9 +317,6 @@ bool namecache_status_fetch(const char *keyname, char *value = NULL; time_t timeout; - if (!gencache_init()) - return False; - key = namecache_status_record_key(keyname, keyname_type, name_type, keyip); if (!key) diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 50fb9f1620..05143270b9 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -76,9 +76,6 @@ bool saf_store( const char *domain, const char *servername ) return False; } - if ( !gencache_init() ) - return False; - key = saf_key( domain ); expire = time( NULL ) + lp_parm_int(-1, "saf","ttl", SAF_TTL); @@ -108,9 +105,6 @@ bool saf_join_store( const char *domain, const char *servername ) return False; } - if ( !gencache_init() ) - return False; - key = saf_join_key( domain ); expire = time( NULL ) + lp_parm_int(-1, "saf","join ttl", SAFJOIN_TTL); @@ -134,9 +128,6 @@ bool saf_delete( const char *domain ) return False; } - if ( !gencache_init() ) - return False; - key = saf_join_key(domain); ret = gencache_del(key); SAFE_FREE(key); @@ -171,9 +162,6 @@ char *saf_fetch( const char *domain ) return NULL; } - if ( !gencache_init() ) - return False; - key = saf_join_key( domain ); ret = gencache_get( key, &server, &timeout ); diff --git a/source3/libsmb/spnego.c b/source3/libsmb/spnego.c index ee2c3c3d5a..528c7f4009 100644 --- a/source3/libsmb/spnego.c +++ b/source3/libsmb/spnego.c @@ -41,17 +41,18 @@ static bool read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) asn1_start_tag(asn1, ASN1_CONTEXT(0)); asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - token->mechTypes = TALLOC_P(NULL, const char *); + token->mechTypes = TALLOC_P(talloc_autofree_context(), const char *); for (i = 0; !asn1->has_error && 0 < asn1_tag_remaining(asn1); i++) { const char *p_oid = NULL; token->mechTypes = - TALLOC_REALLOC_ARRAY(NULL, token->mechTypes, const char *, i + 2); + TALLOC_REALLOC_ARRAY(talloc_autofree_context(), + token->mechTypes, const char *, i + 2); if (!token->mechTypes) { asn1->has_error = True; return False; } - asn1_read_OID(asn1, NULL, &p_oid); + asn1_read_OID(asn1, talloc_autofree_context(), &p_oid); token->mechTypes[i] = p_oid; } token->mechTypes[i] = NULL; @@ -69,14 +70,15 @@ static bool read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) /* Read mechToken */ case ASN1_CONTEXT(2): asn1_start_tag(asn1, ASN1_CONTEXT(2)); - asn1_read_OctetString(asn1, NULL, &token->mechToken); + asn1_read_OctetString(asn1, + talloc_autofree_context(), &token->mechToken); asn1_end_tag(asn1); break; /* Read mecListMIC */ case ASN1_CONTEXT(3): asn1_start_tag(asn1, ASN1_CONTEXT(3)); if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) { - asn1_read_OctetString(asn1, NULL, + asn1_read_OctetString(asn1, talloc_autofree_context(), &token->mechListMIC); } else { /* RFC 2478 says we have an Octet String here, @@ -84,7 +86,8 @@ static bool read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) char *mechListMIC; asn1_push_tag(asn1, ASN1_SEQUENCE(0)); asn1_push_tag(asn1, ASN1_CONTEXT(0)); - asn1_read_GeneralString(asn1, NULL, &mechListMIC); + asn1_read_GeneralString(asn1, + talloc_autofree_context(), &mechListMIC); asn1_pop_tag(asn1); asn1_pop_tag(asn1); @@ -188,19 +191,21 @@ static bool read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token) case ASN1_CONTEXT(1): { const char *mech = NULL; asn1_start_tag(asn1, ASN1_CONTEXT(1)); - asn1_read_OID(asn1, NULL, &mech); + asn1_read_OID(asn1, talloc_autofree_context(), &mech); asn1_end_tag(asn1); token->supportedMech = CONST_DISCARD(char *, mech); } break; case ASN1_CONTEXT(2): asn1_start_tag(asn1, ASN1_CONTEXT(2)); - asn1_read_OctetString(asn1, NULL, &token->responseToken); + asn1_read_OctetString(asn1, + talloc_autofree_context(), &token->responseToken); asn1_end_tag(asn1); break; case ASN1_CONTEXT(3): asn1_start_tag(asn1, ASN1_CONTEXT(3)); - asn1_read_OctetString(asn1, NULL, &token->mechListMIC); + asn1_read_OctetString(asn1, + talloc_autofree_context(), &token->mechListMIC); asn1_end_tag(asn1); break; default: diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c index 6755de3814..eb52b3588d 100644 --- a/source3/libsmb/trustdom_cache.c +++ b/source3/libsmb/trustdom_cache.c @@ -4,17 +4,17 @@ Trusted domain names cache on top of gencache. Copyright (C) Rafal Szczesniak 2002 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -38,7 +38,6 @@ * list of trusted domains **/ - /** * Initialise trustdom name caching system. Call gencache * initialisation routine to perform necessary activities. @@ -46,15 +45,9 @@ * @return true upon successful cache initialisation or * false if cache init failed **/ - + bool trustdom_cache_enable(void) { - /* Init trustdom cache by calling gencache initialisation */ - if (!gencache_init()) { - DEBUG(2, ("trustdomcache_enable: Couldn't initialise trustdom cache on top of gencache.\n")); - return False; - } - return True; } @@ -66,15 +59,9 @@ bool trustdom_cache_enable(void) * @return true upon successful cache close or * false if it failed **/ - + bool trustdom_cache_shutdown(void) { - /* Close trustdom cache by calling gencache shutdown */ - if (!gencache_shutdown()) { - DEBUG(2, ("trustdomcache_shutdown: Couldn't shutdown trustdom cache on top of gencache.\n")); - return False; - } - return True; } @@ -91,7 +78,7 @@ static char* trustdom_cache_key(const char* name) { char* keystr = NULL; asprintf_strupper_m(&keystr, TDOMKEY_FMT, name); - + return keystr; } @@ -115,13 +102,6 @@ bool trustdom_cache_store(char* name, char* alt_name, const DOM_SID *sid, fstring sid_string; bool ret; - /* - * we use gecache call to avoid annoying debug messages - * about initialised trustdom - */ - if (!gencache_init()) - return False; - DEBUG(5, ("trustdom_store: storing SID %s of domain %s\n", sid_string_dbg(sid), name)); @@ -160,16 +140,12 @@ bool trustdom_cache_store(char* name, char* alt_name, const DOM_SID *sid, * @return true if entry is found or * false if has expired/doesn't exist **/ - + bool trustdom_cache_fetch(const char* name, DOM_SID* sid) { char *key = NULL, *value = NULL; time_t timeout; - /* init the cache */ - if (!gencache_init()) - return False; - /* exit now if null pointers were passed as they're required further */ if (!sid) return False; @@ -178,7 +154,7 @@ bool trustdom_cache_fetch(const char* name, DOM_SID* sid) key = trustdom_cache_key(name); if (!key) return False; - + if (!gencache_get(key, &value, &timeout)) { DEBUG(5, ("no entry for trusted domain %s found.\n", name)); SAFE_FREE(key); @@ -194,7 +170,7 @@ bool trustdom_cache_fetch(const char* name, DOM_SID* sid) SAFE_FREE(value); return False; } - + SAFE_FREE(value); return True; } @@ -210,10 +186,6 @@ uint32 trustdom_cache_fetch_timestamp( void ) time_t timeout; uint32 timestamp; - /* init the cache */ - if (!gencache_init()) - return False; - if (!gencache_get(TDOMTSKEY, &value, &timeout)) { DEBUG(5, ("no timestamp for trusted domain cache located.\n")); SAFE_FREE(value); @@ -221,7 +193,7 @@ uint32 trustdom_cache_fetch_timestamp( void ) } timestamp = atoi(value); - + SAFE_FREE(value); return timestamp; } @@ -234,12 +206,8 @@ bool trustdom_cache_store_timestamp( uint32 t, time_t timeout ) { fstring value; - /* init the cache */ - if (!gencache_init()) - return False; - fstr_sprintf(value, "%d", t ); - + if (!gencache_set(TDOMTSKEY, value, timeout)) { DEBUG(5, ("failed to set timestamp for trustdom_cache\n")); return False; @@ -268,9 +236,6 @@ static void flush_trustdom_name(const char* key, const char *value, time_t timeo void trustdom_cache_flush(void) { - if (!gencache_init()) - return; - /* * iterate through each TDOM cache's entry and flush it * by flush_trustdom_name function @@ -294,13 +259,13 @@ void update_trustdom_cache( void ) TALLOC_CTX *mem_ctx = NULL; time_t now = time(NULL); int i; - + /* get the timestamp. We have to initialise it if the last timestamp == 0 */ if ( (last_check = trustdom_cache_fetch_timestamp()) == 0 ) trustdom_cache_store_timestamp(0, now+TRUSTDOM_UPDATE_INTERVAL); time_diff = (int) (now - last_check); - + if ( (time_diff > 0) && (time_diff < TRUSTDOM_UPDATE_INTERVAL) ) { DEBUG(10,("update_trustdom_cache: not time to update trustdom_cache yet\n")); return; @@ -310,14 +275,14 @@ void update_trustdom_cache( void ) smbd from blocking all other smbd daemons while we enumerate the trusted domains */ trustdom_cache_store_timestamp(now, now+TRUSTDOM_UPDATE_INTERVAL); - + if ( !(mem_ctx = talloc_init("update_trustdom_cache")) ) { DEBUG(0,("update_trustdom_cache: talloc_init() failed!\n")); goto done; } /* get the domains and store them */ - + if ( enumerate_domain_trusts(mem_ctx, lp_workgroup(), &domain_names, &num_domains, &dom_sids)) { for ( i=0; i<num_domains; i++ ) { @@ -333,6 +298,6 @@ void update_trustdom_cache( void ) done: talloc_destroy( mem_ctx ); - + return; } diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index be2948c531..e238ec959b 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -1196,7 +1196,7 @@ bool brl_locktest(struct byte_range_lock *br_lck, DEBUG(10,("brl_locktest: posix start=%.0f len=%.0f %s for fnum %d file %s\n", (double)start, (double)size, ret ? "locked" : "unlocked", - fsp->fnum, fsp->fsp_name )); + fsp->fnum, fsp_str_dbg(fsp))); /* We need to return the inverse of is_posix_locked. */ ret = !ret; @@ -1262,7 +1262,7 @@ NTSTATUS brl_lockquery(struct byte_range_lock *br_lck, DEBUG(10,("brl_lockquery: posix start=%.0f len=%.0f %s for fnum %d file %s\n", (double)*pstart, (double)*psize, ret ? "locked" : "unlocked", - fsp->fnum, fsp->fsp_name )); + fsp->fnum, fsp_str_dbg(fsp))); if (ret) { /* Hmmm. No clue what to set smbpid to - use -1. */ diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 91fe137fdc..fba871c704 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -109,11 +109,11 @@ bool strict_lock_default(files_struct *fsp, struct lock_struct *plock) if (strict_locking == Auto) { if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (plock->lock_type == READ_LOCK || plock->lock_type == WRITE_LOCK)) { - DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); + DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp_str_dbg(fsp))); ret = True; } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) && (plock->lock_type == READ_LOCK)) { - DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); + DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp_str_dbg(fsp))); ret = True; } else { struct byte_range_lock *br_lck = brl_get_locks_readonly(talloc_tos(), fsp); @@ -149,7 +149,7 @@ bool strict_lock_default(files_struct *fsp, struct lock_struct *plock) lock_flav_name(plock->lock_flav), (double)plock->start, (double)plock->size, ret ? "unlocked" : "locked", - plock->fnum, fsp->fsp_name )); + plock->fnum, fsp_str_dbg(fsp))); return ret; } @@ -259,7 +259,7 @@ struct byte_range_lock *do_lock(struct messaging_context *msg_ctx, "blocking_lock=%s requested for fnum %d file %s\n", lock_flav_name(lock_flav), lock_type_name(lock_type), (double)offset, (double)count, blocking_lock ? "true" : - "false", fsp->fnum, fsp->fsp_name)); + "false", fsp->fnum, fsp_str_dbg(fsp))); br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { @@ -308,7 +308,8 @@ NTSTATUS do_unlock(struct messaging_context *msg_ctx, } DEBUG(10,("do_unlock: unlock start=%.0f len=%.0f requested for fnum %d file %s\n", - (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); + (double)offset, (double)count, fsp->fnum, + fsp_str_dbg(fsp))); br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { @@ -358,7 +359,8 @@ NTSTATUS do_lock_cancel(files_struct *fsp, } DEBUG(10,("do_lock_cancel: cancel start=%.0f len=%.0f requested for fnum %d file %s\n", - (double)offset, (double)count, fsp->fnum, fsp->fsp_name )); + (double)offset, (double)count, fsp->fnum, + fsp_str_dbg(fsp))); br_lck = brl_get_locks(talloc_tos(), fsp); if (!br_lck) { @@ -1311,7 +1313,7 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, bool delete_on_close, !lp_delete_readonly(SNUM(fsp->conn))) { DEBUG(10,("can_set_delete_on_close: file %s delete on close " "flag set but file attribute is readonly.\n", - fsp->fsp_name )); + fsp_str_dbg(fsp))); return NT_STATUS_CANNOT_DELETE; } @@ -1322,7 +1324,7 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, bool delete_on_close, if (!CAN_WRITE(fsp->conn)) { DEBUG(10,("can_set_delete_on_close: file %s delete on " "close flag set but write access denied on share.\n", - fsp->fsp_name )); + fsp_str_dbg(fsp))); return NT_STATUS_ACCESS_DENIED; } @@ -1334,13 +1336,15 @@ NTSTATUS can_set_delete_on_close(files_struct *fsp, bool delete_on_close, if (!(fsp->access_mask & DELETE_ACCESS)) { DEBUG(10,("can_set_delete_on_close: file %s delete on " "close flag set but delete access denied.\n", - fsp->fsp_name )); + fsp_str_dbg(fsp))); return NT_STATUS_ACCESS_DENIED; } /* Don't allow delete on close for non-empty directories. */ if (fsp->is_directory) { - return can_delete_directory(fsp->conn, fsp->fsp_name); + SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name)); + return can_delete_directory(fsp->conn, + fsp->fsp_name->base_name); } return NT_STATUS_OK; @@ -1422,7 +1426,7 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USE DEBUG(10,("set_delete_on_close: %s delete on close flag for " "fnum = %d, file %s\n", delete_on_close ? "Adding" : "Removing", fsp->fnum, - fsp->fsp_name )); + fsp_str_dbg(fsp))); lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL); @@ -1443,7 +1447,8 @@ bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USE set_delete_on_close_lck(lck, delete_on_close, tok); if (fsp->is_directory) { - send_stat_cache_delete_message(fsp->fsp_name); + SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name)); + send_stat_cache_delete_message(fsp->fsp_name->base_name); } TALLOC_FREE(lck); diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 9b51c3aa6a..33ffaf95ca 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -280,8 +280,9 @@ bool is_posix_locked(files_struct *fsp, SMB_OFF_T count; int posix_lock_type = map_posix_lock_type(fsp,*plock_type); - DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) )); + DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, " + "type = %s\n", fsp_str_dbg(fsp), (double)*pu_offset, + (double)*pu_count, posix_lock_type_name(*plock_type))); /* * If the requested lock won't fit in the POSIX range, we will @@ -424,7 +425,7 @@ static void increment_windows_lock_ref_count(files_struct *fsp) TALLOC_FREE(rec); DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n", - fsp->fsp_name, lock_ref_count )); + fsp_str_dbg(fsp), lock_ref_count)); } /**************************************************************************** @@ -460,7 +461,7 @@ void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount) TALLOC_FREE(rec); DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n", - fsp->fsp_name, lock_ref_count )); + fsp_str_dbg(fsp), lock_ref_count)); } static void decrement_windows_lock_ref_count(files_struct *fsp) @@ -492,7 +493,7 @@ static int get_windows_lock_ref_count(files_struct *fsp) } DEBUG(10,("get_windows_lock_count for file %s = %d\n", - fsp->fsp_name, lock_ref_count )); + fsp_str_dbg(fsp), lock_ref_count)); return lock_ref_count; } @@ -518,7 +519,7 @@ static void delete_windows_lock_ref_count(files_struct *fsp) TALLOC_FREE(rec); DEBUG(10,("delete_windows_lock_ref_count for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); } /**************************************************************************** @@ -555,7 +556,7 @@ static void add_fd_to_close_entry(files_struct *fsp) TALLOC_FREE(rec); DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n", - fsp->fh->fd, fsp->fsp_name )); + fsp->fh->fd, fsp_str_dbg(fsp))); } /**************************************************************************** @@ -945,8 +946,10 @@ bool set_posix_lock_windows_flavour(files_struct *fsp, struct lock_list *llist = NULL; struct lock_list *ll = NULL; - DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); + DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, " + "count = %.0f, type = %s\n", fsp_str_dbg(fsp), + (double)u_offset, (double)u_count, + posix_lock_type_name(lock_type))); /* * If the requested lock won't fit in the POSIX range, we will @@ -1079,8 +1082,9 @@ bool release_posix_lock_windows_flavour(files_struct *fsp, struct lock_list *ulist = NULL; struct lock_list *ul = NULL; - DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n", - fsp->fsp_name, (double)u_offset, (double)u_count )); + DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, " + "count = %.0f\n", fsp_str_dbg(fsp), + (double)u_offset, (double)u_count)); /* Remember the number of Windows locks we have on this dev/ino pair. */ decrement_windows_lock_ref_count(fsp); @@ -1197,8 +1201,10 @@ bool set_posix_lock_posix_flavour(files_struct *fsp, SMB_OFF_T count; int posix_lock_type = map_posix_lock_type(fsp,lock_type); - DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n", - fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) )); + DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count " + "= %.0f, type = %s\n", fsp_str_dbg(fsp), + (double)u_offset, (double)u_count, + posix_lock_type_name(lock_type))); /* * If the requested lock won't fit in the POSIX range, we will @@ -1241,8 +1247,9 @@ bool release_posix_lock_posix_flavour(files_struct *fsp, struct lock_list *ulist = NULL; struct lock_list *ul = NULL; - DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n", - fsp->fsp_name, (double)u_offset, (double)u_count )); + DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, " + "count = %.0f\n", fsp_str_dbg(fsp), + (double)u_offset, (double)u_count)); /* * If the requested lock won't fit in the POSIX range, we will diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 9b3c8725d5..748f17d457 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -183,7 +183,8 @@ static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); if (fsp->is_directory || fsp->fh->fd == -1) { - return smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, psbuf); + return smbacl4_GetFileOwner(fsp->conn, + fsp->fsp_name->base_name, psbuf); } if (SMB_VFS_FSTAT(fsp, psbuf) != 0) { @@ -327,7 +328,7 @@ NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp, { SMB_STRUCT_STAT sbuf; - DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp))); if (smbacl4_fGetFileOwner(fsp, &sbuf)) { return map_nt_error_from_unix(errno); @@ -717,7 +718,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, gid_t newGID = (gid_t)-1; int saved_errno; - DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp))); if ((security_info_sent & (DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0) @@ -743,26 +744,23 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, } if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) || ((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - status = create_synthetic_smb_fname_split(talloc_tos(), - fsp->fsp_name, NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if(try_chown(fsp->conn, smb_fname, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + if(try_chown(fsp->conn, fsp->fsp_name, newUID, + newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = " + "%s.\n", fsp_str_dbg(fsp), + (unsigned int)newUID, + (unsigned int)newGID, strerror(errno))); - TALLOC_FREE(smb_fname); return map_nt_error_from_unix(errno); } - TALLOC_FREE(smb_fname); DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, &sbuf)) + fsp_str_dbg(fsp), (unsigned int)newUID, + (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp->conn, + fsp->fsp_name->base_name, + &sbuf)) return map_nt_error_from_unix(errno); /* If we successfully chowned, we know we must @@ -777,7 +775,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, return NT_STATUS_OK; } - theacl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, + theacl = smbacl4_win2nfs4(fsp->fsp_name->base_name, psd->dacl, ¶ms, sbuf.st_ex_uid, sbuf.st_ex_gid); if (!theacl) return map_nt_error_from_unix(errno); diff --git a/source3/modules/onefs_acl.c b/source3/modules/onefs_acl.c index 5c72d10a6b..2753a9e885 100644 --- a/source3/modules/onefs_acl.c +++ b/source3/modules/onefs_acl.c @@ -395,8 +395,8 @@ onefs_canon_acl(files_struct *fsp, struct ifs_security_descriptor *sd) if ((sbuf.st_ex_flags & SF_HASNTFSACL) != 0) { DEBUG(10, ("Did not canonicalize ACLs because a " - "Windows ACL set was found for file %s\n", - fsp->fsp_name)); + "Windows ACL set was found for file %s\n", + fsp_str_dbg(fsp))); return true; } break; @@ -436,7 +436,7 @@ onefs_canon_acl(files_struct *fsp, struct ifs_security_descriptor *sd) SMB_ASSERT(new_aces_count == sd->dacl->num_aces); DEBUG(10, ("Performed canonicalization of ACLs for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); /* * At this point you would think we could just do this: @@ -535,32 +535,21 @@ static bool add_sfs_aces(files_struct *fsp, struct ifs_security_descriptor *sd) if (error) { DEBUG(0, ("Failed to stat %s in simple files sharing " "compatibility mode. errno=%d\n", - fsp->fsp_name, errno)); + fsp_str_dbg(fsp), errno)); return false; } /* Only continue if this is a synthetic ACL and a directory. */ if (S_ISDIR(sbuf.st_ex_mode) && (sbuf.st_ex_flags & SF_HASNTFSACL) == 0) { - struct smb_filename *smb_fname = NULL; struct ifs_ace new_aces[6]; struct ifs_ace *old_aces; int i, num_aces_to_add = 0; mode_t file_mode = 0, dir_mode = 0; - NTSTATUS status; - - status = create_synthetic_smb_fname_split(talloc_tos(), - fsp->fsp_name, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return false; - } /* Use existing samba logic to derive the mode bits. */ - file_mode = unix_mode(fsp->conn, 0, smb_fname, NULL); - dir_mode = unix_mode(fsp->conn, aDIR, smb_fname, NULL); - - TALLOC_FREE(smb_fname); + file_mode = unix_mode(fsp->conn, 0, fsp->fsp_name, NULL); + dir_mode = unix_mode(fsp->conn, aDIR, fsp->fsp_name, NULL); /* Initialize ACEs. */ new_aces[0] = onefs_init_ace(fsp->conn, file_mode, false, USR); @@ -631,18 +620,18 @@ onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, *ppdesc = NULL; DEBUG(5, ("Getting sd for file %s. security_info=%u\n", - fsp->fsp_name, security_info)); + fsp_str_dbg(fsp), security_info)); if (lp_parm_bool(SNUM(fsp->conn), PARM_ONEFS_TYPE, PARM_IGNORE_SACLS, PARM_IGNORE_SACLS_DEFAULT)) { - DEBUG(5, ("Ignoring SACL on %s.\n", fsp->fsp_name)); + DEBUG(5, ("Ignoring SACL on %s.\n", fsp_str_dbg(fsp))); security_info &= ~SACL_SECURITY_INFORMATION; } if (fsp->fh->fd == -1) { if ((fsp->fh->fd = onefs_sys_create_file(handle->conn, -1, - fsp->fsp_name, + fsp->fsp_name->base_name, 0, 0, 0, @@ -655,7 +644,7 @@ onefs_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, 0, NULL)) == -1) { DEBUG(0, ("Error opening file %s. errno=%d (%s)\n", - fsp->fsp_name, errno, strerror(errno))); + fsp_str_dbg(fsp), errno, strerror(errno))); status = map_nt_error_from_unix(errno); goto out; } @@ -801,6 +790,7 @@ onefs_get_nt_acl(vfs_handle_struct *handle, const char* name, { files_struct finfo; struct fd_handle fh; + NTSTATUS status; ZERO_STRUCT(finfo); ZERO_STRUCT(fh); @@ -809,9 +799,16 @@ onefs_get_nt_acl(vfs_handle_struct *handle, const char* name, finfo.conn = handle->conn; finfo.fh = &fh; finfo.fh->fd = -1; - finfo.fsp_name = CONST_DISCARD(char *, name); + status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL, + &finfo.fsp_name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - return onefs_fget_nt_acl(handle, &finfo, security_info, ppdesc); + status = onefs_fget_nt_acl(handle, &finfo, security_info, ppdesc); + + TALLOC_FREE(finfo.fsp_name); + return status; } /** @@ -918,7 +915,7 @@ onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, START_PROFILE(syscall_set_sd); - DEBUG(5,("Setting SD on file %s.\n", fsp->fsp_name )); + DEBUG(5,("Setting SD on file %s.\n", fsp_str_dbg(fsp))); status = onefs_samba_sd_to_sd(sec_info_sent, psd, &sd, SNUM(handle->conn), &sec_info_effective); @@ -930,10 +927,10 @@ onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, fd = fsp->fh->fd; if (fd == -1) { - DEBUG(10,("Reopening file %s.\n", fsp->fsp_name)); + DEBUG(10,("Reopening file %s.\n", fsp_str_dbg(fsp))); if ((fd = onefs_sys_create_file(handle->conn, -1, - fsp->fsp_name, + fsp->fsp_name->base_name, 0, 0, 0, @@ -946,7 +943,7 @@ onefs_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, 0, NULL)) == -1) { DEBUG(0, ("Error opening file %s. errno=%d (%s)\n", - fsp->fsp_name, errno, strerror(errno))); + fsp_str_dbg(fsp), errno, strerror(errno))); status = map_nt_error_from_unix(errno); goto out; } diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index b51d516956..31f27e907a 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -81,7 +81,6 @@ static NTSTATUS onefs_open_file(files_struct *fsp, struct security_descriptor *sd, int *granted_oplock) { - char *path = NULL; struct smb_filename *smb_fname_onefs = NULL; NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); @@ -157,7 +156,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * wildcard characters are allowed in stream names * only test the basefilename */ - wild = fsp->base_fsp->fsp_name; + wild = fsp->base_fsp->fsp_name->base_name; } else { wild = smb_fname->base_name; } @@ -323,15 +322,13 @@ static NTSTATUS onefs_open_file(files_struct *fsp, fsp->aio_write_behind = True; } - status = get_full_smb_filename(talloc_tos(), smb_fname, - &path); + status = fsp_set_smb_fname(fsp, smb_fname); if (!NT_STATUS_IS_OK(status)) { + fd_close(fsp); + errno = map_errno_from_nt_status(status); return status; } - string_set(&fsp->fsp_name, path); - TALLOC_FREE(path); - fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -1592,7 +1589,12 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, fsp->is_directory = True; fsp->posix_open = posix_open; - string_set(&fsp->fsp_name, smb_dname->base_name); + status = fsp_set_smb_fname(fsp, smb_dname); + if (!NT_STATUS_IS_OK(status)) { + fd_close(fsp); + file_free(req, fsp); + return status; + } mtimespec = smb_dname->st.st_ex_mtime; diff --git a/source3/modules/onefs_streams.c b/source3/modules/onefs_streams.c index ded7dc672d..66eda57a34 100644 --- a/source3/modules/onefs_streams.c +++ b/source3/modules/onefs_streams.c @@ -376,7 +376,7 @@ int onefs_fstat(vfs_handle_struct *handle, struct files_struct *fsp, } } - onefs_adjust_stat_time(handle->conn, fsp->fsp_name, sbuf); + onefs_adjust_stat_time(handle->conn, fsp->fsp_name->base_name, sbuf); return ret; } @@ -600,7 +600,11 @@ static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp, fake_fs.conn = conn; fake_fs.fh = &fake_fh; - fake_fs.fsp_name = SMB_STRDUP(fname); + status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL, + &fake_fs.fsp_name); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } /* Iterate over the streams in the ADS directory. */ while ((dp = SMB_VFS_READDIR(conn, dirp, NULL)) != NULL) { @@ -667,7 +671,7 @@ out: close(base_fd); } - SAFE_FREE(fake_fs.fsp_name); + TALLOC_FREE(fake_fs.fsp_name); return status; } diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index 64ad3e1a78..ce84bd0e3a 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -272,27 +272,24 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, { uint8 id_buf[16]; struct file_id id; - SMB_STRUCT_STAT sbuf; TDB_DATA data; struct db_context *db; struct db_record *rec; int ret = -1; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", - (unsigned int)pblob->length, fsp->fsp_name)); + (unsigned int)pblob->length, fsp_str_dbg(fsp))); SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return NT_STATUS_INTERNAL_DB_CORRUPTION); if (fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); } else { if (fsp->posix_open) { - ret = vfs_lstat_smb_fname(handle->conn, fsp->fsp_name, - &sbuf); + ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name); } else { - ret = vfs_stat_smb_fname(handle->conn, fsp->fsp_name, - &sbuf); + ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name); } } @@ -300,7 +297,7 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, return map_nt_error_from_unix(errno); } - id = vfs_file_id_from_sbuf(handle->conn, &sbuf); + id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); @@ -381,7 +378,7 @@ static NTSTATUS get_nt_acl_tdb_internal(vfs_handle_struct *handle, NTSTATUS status; if (fsp && name == NULL) { - name = fsp->fsp_name; + name = fsp->fsp_name->base_name; } DEBUG(10, ("get_nt_acl_tdb_internal: name=%s\n", name)); @@ -450,7 +447,7 @@ static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx, *********************************************************************/ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, - const char *fname, + struct smb_filename *smb_fname, files_struct *fsp, bool container) { @@ -462,7 +459,7 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, size_t size; char *parent_name; - if (!parent_dirname(ctx, fname, &parent_name, NULL)) { + if (!parent_dirname(ctx, smb_fname->base_name, &parent_name, NULL)) { return NT_STATUS_NO_MEMORY; } @@ -508,25 +505,22 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, } if (!psd || psd->dacl == NULL) { - SMB_STRUCT_STAT sbuf; int ret; TALLOC_FREE(psd); if (fsp && !fsp->is_directory && fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); } else { if (fsp && fsp->posix_open) { - ret = vfs_lstat_smb_fname(handle->conn,fname, - &sbuf); + ret = SMB_VFS_LSTAT(handle->conn, smb_fname); } else { - ret = vfs_stat_smb_fname(handle->conn,fname, - &sbuf); + ret = SMB_VFS_STAT(handle->conn, smb_fname); } } if (ret == -1) { return map_nt_error_from_unix(errno); } - psd = default_file_sd(ctx, &sbuf); + psd = default_file_sd(ctx, &smb_fname->st); if (!psd) { return NT_STATUS_NO_MEMORY; } @@ -544,7 +538,8 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, if (fsp) { return store_acl_blob_fsp(handle, fsp, &blob); } else { - return store_acl_blob_pathname(handle, fname, &blob); + return store_acl_blob_pathname(handle, smb_fname->base_name, + &blob); } } @@ -561,19 +556,11 @@ static int open_acl_tdb(vfs_handle_struct *handle, uint32_t access_granted = 0; struct security_descriptor *pdesc = NULL; bool file_existed = true; - char *fname = NULL; NTSTATUS status; - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; - } - status = get_nt_acl_tdb_internal(handle, NULL, - fname, + smb_fname->base_name, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), @@ -605,10 +592,13 @@ static int open_acl_tdb(vfs_handle_struct *handle, if (!file_existed && fsp->fh->fd != -1) { /* File was created. Inherit from parent directory. */ - string_set(&fsp->fsp_name, fname); - inherit_new_acl(handle, fname, fsp, false); + status = fsp_set_smb_fname(fsp, smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + inherit_new_acl(handle, smb_fname, fsp, false); } - return fsp->fh->fd; } @@ -659,13 +649,24 @@ static int unlink_acl_tdb(vfs_handle_struct *handle, static int mkdir_acl_tdb(vfs_handle_struct *handle, const char *path, mode_t mode) { + struct smb_filename *smb_fname = NULL; int ret = SMB_VFS_NEXT_MKDIR(handle, path, mode); + NTSTATUS status; if (ret == -1) { return ret; } + + status = create_synthetic_smb_fname(talloc_tos(), path, NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + /* New directory - inherit from parent. */ - inherit_new_acl(handle, path, NULL, true); + inherit_new_acl(handle, smb_fname, NULL, true); + TALLOC_FREE(smb_fname); return ret; } @@ -713,15 +714,14 @@ static NTSTATUS fget_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp, if (NT_STATUS_IS_OK(status)) { if (DEBUGLEVEL >= 10) { DEBUG(10,("fget_nt_acl_tdb: returning tdb sd for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, *ppdesc); } return NT_STATUS_OK; } DEBUG(10,("fget_nt_acl_tdb: failed to get tdb sd for file %s, Error %s\n", - fsp->fsp_name, - nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc); @@ -765,7 +765,7 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp, if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_tdb: incoming sd for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } @@ -778,7 +778,6 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp, /* Ensure owner and group are set. */ if (!psd->owner_sid || !psd->group_sid) { int ret; - SMB_STRUCT_STAT sbuf; DOM_SID owner_sid, group_sid; struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd); @@ -787,23 +786,19 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp, } if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { - ret = vfs_lstat_smb_fname(fsp->conn, - fsp->fsp_name, - &sbuf); + ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); } else { - ret = vfs_stat_smb_fname(fsp->conn, - fsp->fsp_name, - &sbuf); + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); } } else { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); } if (ret == -1) { /* Lower level acl set succeeded, * so still return OK. */ return NT_STATUS_OK; } - create_file_sids(&sbuf, &owner_sid, &group_sid); + create_file_sids(&fsp->fsp_name->st, &owner_sid, &group_sid); /* This is safe as nc_psd is discarded at fn exit. */ nc_psd->owner_sid = &owner_sid; nc_psd->group_sid = &group_sid; @@ -831,7 +826,7 @@ static NTSTATUS fset_nt_acl_tdb(vfs_handle_struct *handle, files_struct *fsp, if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_tdb: storing tdb sd for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } @@ -913,7 +908,6 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl) { - SMB_STRUCT_STAT sbuf; struct db_context *db; int ret; @@ -921,14 +915,12 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle, if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { - ret = vfs_lstat_smb_fname(fsp->conn,fsp->fsp_name, - &sbuf); + ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); } else { - ret = vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, - &sbuf); + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); } } else { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); } if (ret == -1) { return -1; @@ -941,7 +933,7 @@ static int sys_acl_set_fd_tdb(vfs_handle_struct *handle, return -1; } - acl_tdb_delete(handle, db, &sbuf); + acl_tdb_delete(handle, db, &fsp->fsp_name->st); return 0; } diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index 66bf21c4f7..b18bc658ff 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -27,13 +27,45 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +static NTSTATUS create_acl_blob(const struct security_descriptor *psd, + DATA_BLOB *pblob, + uint8_t hash[16]); + +#define HASH_SECURITY_INFO (OWNER_SECURITY_INFORMATION | \ + GROUP_SECURITY_INFORMATION | \ + DACL_SECURITY_INFORMATION | \ + SACL_SECURITY_INFORMATION) + +/******************************************************************* + Hash a security descriptor. +*******************************************************************/ + +static NTSTATUS hash_sd(struct security_descriptor *psd, + uint8_t hash[16]) +{ + DATA_BLOB blob; + struct MD5Context tctx; + NTSTATUS status; + + memset(hash, '\0', 16); + status = create_acl_blob(psd, &blob, hash); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + MD5Init(&tctx); + MD5Update(&tctx, blob.data, blob.length); + MD5Final(hash, &tctx); + return NT_STATUS_OK; +} + /******************************************************************* Parse out a struct security_descriptor from a DATA_BLOB. *******************************************************************/ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, uint32 security_info, - struct security_descriptor **ppdesc) + struct security_descriptor **ppdesc, + uint8_t hash[16]) { TALLOC_CTX *ctx = talloc_tos(); struct xattr_NTACL xacl; @@ -64,6 +96,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, ? xacl.info.sd_hs->sd->dacl : NULL, &sd_size); + memcpy(hash, xacl.info.sd_hs->hash, 16); TALLOC_FREE(xacl.info.sd); return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY; @@ -131,7 +164,9 @@ static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, Create a DATA_BLOB from a security descriptor. *******************************************************************/ -static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob) +static NTSTATUS create_acl_blob(const struct security_descriptor *psd, + DATA_BLOB *pblob, + uint8_t hash[16]) { struct xattr_NTACL xacl; struct security_descriptor_hash sd_hs; @@ -144,7 +179,7 @@ static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB xacl.version = 2; xacl.info.sd_hs = &sd_hs; xacl.info.sd_hs->sd = CONST_DISCARD(struct security_descriptor *, psd); - memset(&xacl.info.sd_hs->hash[0], '\0', 16); + memcpy(&xacl.info.sd_hs->hash[0], hash, 16); ndr_err = ndr_push_struct_blob( pblob, ctx, NULL, &xacl, @@ -171,14 +206,14 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, int saved_errno = 0; DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n", - (unsigned int)pblob->length, fsp->fsp_name)); + (unsigned int)pblob->length, fsp_str_dbg(fsp))); become_root(); if (fsp->fh->fd != -1) { ret = SMB_VFS_FSETXATTR(fsp, XATTR_NTACL_NAME, pblob->data, pblob->length, 0); } else { - ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name, + ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name, XATTR_NTACL_NAME, pblob->data, pblob->length, 0); } @@ -190,7 +225,7 @@ static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle, errno = saved_errno; DEBUG(5, ("store_acl_blob_fsp: setting attr failed for file %s" "with error %s\n", - fsp->fsp_name, + fsp_str_dbg(fsp), strerror(errno) )); return map_nt_error_from_unix(errno); } @@ -242,29 +277,86 @@ static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle, uint32 security_info, struct security_descriptor **ppdesc) { - TALLOC_CTX *ctx = talloc_tos(); DATA_BLOB blob; NTSTATUS status; + uint8_t hash[16]; + uint8_t hash_tmp[16]; + struct security_descriptor *pdesc_next = NULL; if (fsp && name == NULL) { - name = fsp->fsp_name; + name = fsp->fsp_name->base_name; } DEBUG(10, ("get_nt_acl_xattr_internal: name=%s\n", name)); - status = get_acl_blob(ctx, handle, fsp, name, &blob); + status = get_acl_blob(talloc_tos(), handle, fsp, name, &blob); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("get_acl_blob returned %s\n", nt_errstr(status))); return status; } - status = parse_acl_blob(&blob, security_info, ppdesc); + status = parse_acl_blob(&blob, security_info, ppdesc, &hash[0]); if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("parse_acl_blob returned %s\n", nt_errstr(status))); return status; } + /* If there was no stored hash, don't check. */ + memset(&hash_tmp[0], '\0', 16); + if (memcmp(&hash[0], &hash_tmp[0], 16) == 0) { + /* No hash, goto return blob sd. */ + goto out; + } + + /* Get the full underlying sd, then hash. */ + if (fsp) { + status = SMB_VFS_NEXT_FGET_NT_ACL(handle, + fsp, + HASH_SECURITY_INFO, + &pdesc_next); + } else { + status = SMB_VFS_NEXT_GET_NT_ACL(handle, + name, + HASH_SECURITY_INFO, + &pdesc_next); + } + + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + status = hash_sd(pdesc_next, hash_tmp); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + if (memcmp(&hash[0], &hash_tmp[0], 16) == 0) { + TALLOC_FREE(pdesc_next); + /* Hash matches, return blob sd. */ + goto out; + } + + /* Hash doesn't match, return underlying sd. */ + + if (!(security_info & OWNER_SECURITY_INFORMATION)) { + pdesc_next->owner_sid = NULL; + } + if (!(security_info & GROUP_SECURITY_INFORMATION)) { + pdesc_next->group_sid = NULL; + } + if (!(security_info & DACL_SECURITY_INFORMATION)) { + pdesc_next->dacl = NULL; + } + if (!(security_info & SACL_SECURITY_INFORMATION)) { + pdesc_next->sacl = NULL; + } + + TALLOC_FREE(*ppdesc); + *ppdesc = pdesc_next; + + out: + TALLOC_FREE(blob.data); return status; } @@ -316,7 +408,7 @@ static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx, *********************************************************************/ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, - const char *fname, + struct smb_filename *smb_fname, files_struct *fsp, bool container) { @@ -324,11 +416,13 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, NTSTATUS status; struct security_descriptor *parent_desc = NULL; struct security_descriptor *psd = NULL; + struct security_descriptor *pdesc_next = NULL; DATA_BLOB blob; size_t size; char *parent_name; + uint8_t hash[16]; - if (!parent_dirname(ctx, fname, &parent_name, NULL)) { + if (!parent_dirname(ctx, smb_fname->base_name, &parent_name, NULL)) { return NT_STATUS_NO_MEMORY; } @@ -374,25 +468,22 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, } if (!psd || psd->dacl == NULL) { - SMB_STRUCT_STAT sbuf; int ret; TALLOC_FREE(psd); if (fsp && !fsp->is_directory && fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); } else { if (fsp && fsp->posix_open) { - ret = vfs_lstat_smb_fname(handle->conn, fname, - &sbuf); + ret = SMB_VFS_LSTAT(handle->conn, smb_fname); } else { - ret = vfs_stat_smb_fname(handle->conn, fname, - &sbuf); + ret = SMB_VFS_STAT(handle->conn, smb_fname); } } if (ret == -1) { return map_nt_error_from_unix(errno); } - psd = default_file_sd(ctx, &sbuf); + psd = default_file_sd(ctx, &smb_fname->st); if (!psd) { return NT_STATUS_NO_MEMORY; } @@ -403,14 +494,36 @@ static NTSTATUS inherit_new_acl(vfs_handle_struct *handle, } } - status = create_acl_blob(psd, &blob); + /* Object exists. Read the current SD to get the hash. */ + if (fsp) { + status = SMB_VFS_NEXT_FGET_NT_ACL(handle, + fsp, + HASH_SECURITY_INFO, + &pdesc_next); + } else { + status = SMB_VFS_NEXT_GET_NT_ACL(handle, + smb_fname->base_name, + HASH_SECURITY_INFO, + &pdesc_next); + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = hash_sd(pdesc_next, hash); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + status = create_acl_blob(psd, &blob, hash); if (!NT_STATUS_IS_OK(status)) { return status; } if (fsp) { return store_acl_blob_fsp(handle, fsp, &blob); } else { - return store_acl_blob_pathname(handle, fname, &blob); + return store_acl_blob_pathname(handle, smb_fname->base_name, + &blob); } } @@ -430,6 +543,13 @@ static int open_acl_xattr(vfs_handle_struct *handle, char *fname = NULL; NTSTATUS status; + if (fsp->base_fsp) { + /* Stream open. Base filename open already did the ACL check. */ + DEBUG(10,("open_acl_xattr: stream open on %s\n", + smb_fname_str_dbg(smb_fname) )); + return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); + } + status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); if (!NT_STATUS_IS_OK(status)) { @@ -471,8 +591,12 @@ static int open_acl_xattr(vfs_handle_struct *handle, if (!file_existed && fsp->fh->fd != -1) { /* File was created. Inherit from parent directory. */ - string_set(&fsp->fsp_name, fname); - inherit_new_acl(handle, fname, fsp, false); + status = fsp_set_smb_fname(fsp, smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + inherit_new_acl(handle, smb_fname, fsp, false); } return fsp->fh->fd; @@ -480,13 +604,24 @@ static int open_acl_xattr(vfs_handle_struct *handle, static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t mode) { + struct smb_filename *smb_fname = NULL; int ret = SMB_VFS_NEXT_MKDIR(handle, path, mode); + NTSTATUS status; if (ret == -1) { return ret; } + + status = create_synthetic_smb_fname(talloc_tos(), path, NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + /* New directory - inherit from parent. */ - inherit_new_acl(handle, path, NULL, true); + inherit_new_acl(handle, smb_fname, NULL, true); + TALLOC_FREE(smb_fname); return ret; } @@ -497,23 +632,8 @@ static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t m static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, struct security_descriptor **ppdesc) { - NTSTATUS status = get_nt_acl_xattr_internal(handle, fsp, + return get_nt_acl_xattr_internal(handle, fsp, NULL, security_info, ppdesc); - if (NT_STATUS_IS_OK(status)) { - if (DEBUGLEVEL >= 10) { - DEBUG(10,("fget_nt_acl_xattr: returning xattr sd for file %s\n", - fsp->fsp_name)); - NDR_PRINT_DEBUG(security_descriptor, *ppdesc); - } - return NT_STATUS_OK; - } - - DEBUG(10,("fget_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n", - fsp->fsp_name, - nt_errstr(status) )); - - return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, - security_info, ppdesc); } /********************************************************************* @@ -523,23 +643,8 @@ static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle, const char *name, uint32 security_info, struct security_descriptor **ppdesc) { - NTSTATUS status = get_nt_acl_xattr_internal(handle, NULL, + return get_nt_acl_xattr_internal(handle, NULL, name, security_info, ppdesc); - if (NT_STATUS_IS_OK(status)) { - if (DEBUGLEVEL >= 10) { - DEBUG(10,("get_nt_acl_xattr: returning xattr sd for file %s\n", - name)); - NDR_PRINT_DEBUG(security_descriptor, *ppdesc); - } - return NT_STATUS_OK; - } - - DEBUG(10,("get_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n", - name, - nt_errstr(status) )); - - return SMB_VFS_NEXT_GET_NT_ACL(handle, name, - security_info, ppdesc); } /********************************************************************* @@ -551,23 +656,19 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, { NTSTATUS status; DATA_BLOB blob; + struct security_descriptor *pdesc_next = NULL; + uint8_t hash[16]; if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } - status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Ensure owner and group are set. */ if (!psd->owner_sid || !psd->group_sid) { int ret; - SMB_STRUCT_STAT sbuf; DOM_SID owner_sid, group_sid; struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd); @@ -576,23 +677,19 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, } if (fsp->is_directory || fsp->fh->fd == -1) { if (fsp->posix_open) { - ret = vfs_lstat_smb_fname(fsp->conn, - fsp->fsp_name, - &sbuf); + ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); } else { - ret = vfs_stat_smb_fname(fsp->conn, - fsp->fsp_name, - &sbuf); + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); } } else { - ret = SMB_VFS_FSTAT(fsp, &sbuf); + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); } if (ret == -1) { /* Lower level acl set succeeded, * so still return OK. */ return NT_STATUS_OK; } - create_file_sids(&sbuf, &owner_sid, &group_sid); + create_file_sids(&fsp->fsp_name->st, &owner_sid, &group_sid); /* This is safe as nc_psd is discarded at fn exit. */ nc_psd->owner_sid = &owner_sid; nc_psd->group_sid = &group_sid; @@ -600,6 +697,26 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, psd = nc_psd; } + status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Get the full underlying sd, then hash. */ + status = SMB_VFS_NEXT_FGET_NT_ACL(handle, + fsp, + HASH_SECURITY_INFO, + &pdesc_next); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = hash_sd(pdesc_next, hash); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + #if 0 if ((security_info_sent & DACL_SECURITY_INFORMATION) && psd->dacl != NULL && @@ -620,11 +737,11 @@ static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp, if (DEBUGLEVEL >= 10) { DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, CONST_DISCARD(struct security_descriptor *,psd)); } - create_acl_blob(psd, &blob); + create_acl_blob(psd, &blob, hash); store_acl_blob_fsp(handle, fsp, &blob); return NT_STATUS_OK; diff --git a/source3/modules/vfs_afsacl.c b/source3/modules/vfs_afsacl.c index 55371c60f5..e6f43c9680 100644 --- a/source3/modules/vfs_afsacl.c +++ b/source3/modules/vfs_afsacl.c @@ -655,18 +655,17 @@ static size_t afs_to_nt_acl_common(struct afs_acl *afs_acl, static size_t afs_to_nt_acl(struct afs_acl *afs_acl, struct connection_struct *conn, - const char *name, + struct smb_filename *smb_fname, uint32 security_info, struct security_descriptor **ppdesc) { - SMB_STRUCT_STAT sbuf; - /* Get the stat struct for the owner info. */ - if(vfs_stat_smb_fname(conn, name, &sbuf) != 0) { + if(SMB_VFS_STAT(conn, smb_fname) != 0) { return 0; } - return afs_to_nt_acl_common(afs_acl, &sbuf, security_info, ppdesc); + return afs_to_nt_acl_common(afs_acl, &smb_fname->st, security_info, + ppdesc); } static size_t afs_fto_nt_acl(struct afs_acl *afs_acl, @@ -905,7 +904,7 @@ static NTSTATUS afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, ZERO_STRUCT(dir_acl); ZERO_STRUCT(file_acl); - name = talloc_strdup(talloc_tos(), fsp->fsp_name); + name = talloc_strdup(talloc_tos(), fsp->fsp_name->base_name); if (!name) { return NT_STATUS_NO_MEMORY; } @@ -925,7 +924,7 @@ static NTSTATUS afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, } if (!afs_get_afs_acl(name, &old_afs_acl)) { - DEBUG(3, ("Could not get old ACL of %s\n", fsp->fsp_name)); + DEBUG(3, ("Could not get old ACL of %s\n", fsp_str_dbg(fsp))); goto done; } @@ -941,7 +940,8 @@ static NTSTATUS afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, } free_afs_acl(&dir_acl); - if (!nt_to_afs_acl(fsp->fsp_name, security_info_sent, psd, + if (!nt_to_afs_acl(fsp->fsp_name->base_name, + security_info_sent, psd, nt_to_afs_dir_rights, &dir_acl)) goto done; } else { @@ -956,7 +956,8 @@ static NTSTATUS afs_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, } free_afs_acl(&file_acl); - if (!nt_to_afs_acl(fsp->fsp_name, security_info_sent, psd, + if (!nt_to_afs_acl(fsp->fsp_name->base_name, + security_info_sent, psd, nt_to_afs_file_rights, &file_acl)) goto done; } @@ -997,11 +998,11 @@ static NTSTATUS afsacl_fget_nt_acl(struct vfs_handle_struct *handle, struct afs_acl acl; size_t sd_size; - DEBUG(5, ("afsacl_fget_nt_acl: %s\n", fsp->fsp_name)); + DEBUG(5, ("afsacl_fget_nt_acl: %s\n", fsp_str_dbg(fsp))); sidpts = lp_parm_bool(SNUM(fsp->conn), "afsacl", "sidpts", False); - if (!afs_get_afs_acl(fsp->fsp_name, &acl)) { + if (!afs_get_afs_acl(fsp->fsp_name->base_name, &acl)) { return NT_STATUS_ACCESS_DENIED; } @@ -1018,6 +1019,8 @@ static NTSTATUS afsacl_get_nt_acl(struct vfs_handle_struct *handle, { struct afs_acl acl; size_t sd_size; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; DEBUG(5, ("afsacl_get_nt_acl: %s\n", name)); @@ -1027,8 +1030,16 @@ static NTSTATUS afsacl_get_nt_acl(struct vfs_handle_struct *handle, return NT_STATUS_ACCESS_DENIED; } - sd_size = afs_to_nt_acl(&acl, handle->conn, name, security_info, + status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + free_afs_acl(&acl); + return status; + } + + sd_size = afs_to_nt_acl(&acl, handle->conn, smb_fname, security_info, ppdesc); + TALLOC_FREE(smb_fname); free_afs_acl(&acl); diff --git a/source3/modules/vfs_aixacl2.c b/source3/modules/vfs_aixacl2.c index 5ebc3a12f8..01de33ed0b 100644 --- a/source3/modules/vfs_aixacl2.c +++ b/source3/modules/vfs_aixacl2.c @@ -162,7 +162,8 @@ static NTSTATUS aixjfs2_fget_nt_acl(vfs_handle_struct *handle, bool retryPosix = False; *ppdesc = NULL; - result = aixjfs2_get_nfs4_acl(fsp->fsp_name, &pacl, &retryPosix); + result = aixjfs2_get_nfs4_acl(fsp->fsp_name->base_name, &pacl, + &retryPosix); if (retryPosix) { DEBUG(10, ("retrying with posix acl...\n")); @@ -258,7 +259,7 @@ SMB_ACL_T aixjfs2_sys_acl_get_fd(vfs_handle_struct *handle, acl_type_t aixjfs2_type; aixjfs2_type.u64 = ACL_AIXC; - return aixjfs2_get_posix_acl(fsp->fsp_name, aixjfs2_type); + return aixjfs2_get_posix_acl(fsp->fsp_name->base_name, aixjfs2_type); } /* @@ -304,7 +305,7 @@ static bool aixjfs2_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) int rc; acl_type_t acltype; - DEBUG(10, ("jfs2_process_smbacl invoked on %s\n", fsp->fsp_name)); + DEBUG(10, ("jfs2_process_smbacl invoked on %s\n", fsp_str_dbg(fsp))); /* no need to be freed which is alloced with mem_ctx */ mem_ctx = talloc_tos(); @@ -353,7 +354,7 @@ static bool aixjfs2_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) /* won't set S_ISUID - the only one JFS2/NFS4 accepts */ rc = aclx_put( - fsp->fsp_name, + fsp->fsp_name->base_name, SET_ACL, /* set only the ACL, not mode bits */ acltype, /* not a pointer !!! */ jfs2acl, @@ -444,9 +445,10 @@ int aixjfs2_sys_acl_set_fd(vfs_handle_struct *handle, acl_type_t acl_type_info; int rc; - DEBUG(10, ("aixjfs2_sys_acl_set_fd invoked for %s", fsp->fsp_name)); + DEBUG(10, ("aixjfs2_sys_acl_set_fd invoked for %s", fsp_str_dbg(fsp))); - rc = aixjfs2_query_acl_support(fsp->fsp_name, ACL_AIXC, &acl_type_info); + rc = aixjfs2_query_acl_support(fsp->fsp_name->base_name, ACL_AIXC, + &acl_type_info); if (rc) { DEBUG(8, ("jfs2_set_nt_acl: AIXC support not found\n")); return -1; @@ -466,7 +468,7 @@ int aixjfs2_sys_acl_set_fd(vfs_handle_struct *handle, ); if (rc) { DEBUG(2, ("aclx_fput failed with %s for %s\n", - strerror(errno), fsp->fsp_name)); + strerror(errno), fsp_str_dbg(fsp))); return -1; } diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index cf2e27301d..dab3d78cec 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -237,7 +237,7 @@ static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mod result = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode); syslog(audit_syslog_priority(handle), "fchmod %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, + fsp->fsp_name->base_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -251,7 +251,7 @@ static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode); syslog(audit_syslog_priority(handle), "fchmod_acl %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, + fsp->fsp_name->base_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); diff --git a/source3/modules/vfs_cacheprime.c b/source3/modules/vfs_cacheprime.c index 71b850505a..3997dcbcfc 100644 --- a/source3/modules/vfs_cacheprime.c +++ b/source3/modules/vfs_cacheprime.c @@ -72,7 +72,7 @@ static bool prime_cache( DEBUG(module_debug, ("%s: doing readahead of %lld bytes at %lld for %s\n", MODULE, (long long)g_readsz, (long long)*last, - fsp->fsp_name)); + fsp_str_dbg(fsp))); nread = sys_pread(fsp->fh->fd, g_readbuf, g_readsz, *last); if (nread < 0) { diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c index 7e363b6be7..aa77da7cd7 100644 --- a/source3/modules/vfs_cap.c +++ b/source3/modules/vfs_cap.c @@ -53,7 +53,9 @@ static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr); } -static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp) +static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, + SMB_STRUCT_DIR *dirp, + SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_DIRENT *result; SMB_STRUCT_DIRENT *newdirent; @@ -334,7 +336,8 @@ static int cap_ntimes(vfs_handle_struct *handle, } -static bool cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath) +static int cap_symlink(vfs_handle_struct *handle, const char *oldpath, + const char *newpath) { char *capold = capencode(talloc_tos(), oldpath); char *capnew = capencode(talloc_tos(), newpath); @@ -346,7 +349,8 @@ static bool cap_symlink(vfs_handle_struct *handle, const char *oldpath, const ch return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew); } -static bool cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz) +static int cap_readlink(vfs_handle_struct *handle, const char *path, + char *buf, size_t bufsiz) { char *cappath = capencode(talloc_tos(), path); diff --git a/source3/modules/vfs_catia.c b/source3/modules/vfs_catia.c index 1fd101282c..3b691c0350 100644 --- a/source3/modules/vfs_catia.c +++ b/source3/modules/vfs_catia.c @@ -103,7 +103,8 @@ static SMB_STRUCT_DIR *catia_opendir(vfs_handle_struct *handle, } static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle, - SMB_STRUCT_DIR *dirp) + SMB_STRUCT_DIR *dirp, + SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_DIRENT *result = NULL; SMB_STRUCT_DIRENT *newdirent = NULL; diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index c4db8fa393..cdfd28c571 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -218,27 +218,17 @@ static int vfswrap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { - int result; - NTSTATUS status; - char *fname = NULL; + int result = -1; START_PROFILE(syscall_open); - /* - * XXX: Should an error be returned if there is a stream rather than - * trying to open a filename with a ':'? - */ - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; + if (smb_fname->stream_name) { + errno = ENOENT; + goto out; } - result = sys_open(fname, flags, mode); - - TALLOC_FREE(fname); - + result = sys_open(smb_fname->base_name, flags, mode); + out: END_PROFILE(syscall_open); return result; } @@ -562,23 +552,17 @@ static int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp) static int vfswrap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { - int result; - NTSTATUS status; - char *fname = NULL; + int result = -1; START_PROFILE(syscall_stat); - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; + if (smb_fname->stream_name) { + errno = ENOENT; + goto out; } - result = sys_stat(fname, &smb_fname->st); - - TALLOC_FREE(fname); - + result = sys_stat(smb_fname->base_name, &smb_fname->st); + out: END_PROFILE(syscall_stat); return result; } @@ -596,23 +580,17 @@ static int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUC static int vfswrap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { - int result; - NTSTATUS status; - char *fname = NULL; + int result = -1; START_PROFILE(syscall_lstat); - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; + if (smb_fname->stream_name) { + errno = ENOENT; + goto out; } - result = sys_lstat(fname, &smb_fname->st); - - TALLOC_FREE(fname); - + result = sys_lstat(smb_fname->base_name, &smb_fname->st); + out: END_PROFILE(syscall_lstat); return result; } @@ -866,7 +844,9 @@ static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fs uint64_t space_avail; uint64_t bsize,dfree,dsize; - space_avail = get_dfree_info(fsp->conn,fsp->fsp_name,false,&bsize,&dfree,&dsize); + space_avail = get_dfree_info(fsp->conn, + fsp->fsp_name->base_name, false, + &bsize, &dfree, &dsize); /* space_avail is 1k blocks */ if (space_avail == (uint64_t)-1 || ((uint64_t)space_to_write/1024 > space_avail) ) { @@ -1102,7 +1082,8 @@ static NTSTATUS vfswrap_notify_watch(vfs_handle_struct *vfs_handle, return NT_STATUS_OK; } -static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flags) +static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, + unsigned int flags) { #ifdef HAVE_CHFLAGS return chflags(path, flags); @@ -1113,7 +1094,7 @@ static int vfswrap_chflags(vfs_handle_struct *handle, const char *path, int flag } static struct file_id vfswrap_file_id_create(struct vfs_handle_struct *handle, - SMB_STRUCT_STAT *sbuf) + const SMB_STRUCT_STAT *sbuf) { struct file_id key; diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c index 53d1820c11..f6fc9256d0 100644 --- a/source3/modules/vfs_dirsort.c +++ b/source3/modules/vfs_dirsort.c @@ -113,7 +113,8 @@ static SMB_STRUCT_DIR *dirsort_opendir(vfs_handle_struct *handle, } static SMB_STRUCT_DIRENT *dirsort_readdir(vfs_handle_struct *handle, - SMB_STRUCT_DIR *dirp) + SMB_STRUCT_DIR *dirp, + SMB_STRUCT_STAT *sbuf) { struct dirsort_privates *data = NULL; time_t current_mtime; diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index 68b85516ea..c9d1862fa4 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -304,12 +304,12 @@ static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t mod if (lp_syslog() > 0) { syslog(audit_syslog_priority(handle), "fchmod %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, + fsp->fsp_name->base_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); } DEBUG(1, ("vfs_extd_audit: fchmod %s mode 0x%x %s %s", - fsp->fsp_name, (unsigned int)mode, + fsp_str_dbg(fsp), (unsigned int)mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : "")); @@ -324,12 +324,12 @@ static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, mode_t if (lp_syslog() > 0) { syslog(audit_syslog_priority(handle), "fchmod_acl %s mode 0x%x %s%s\n", - fsp->fsp_name, mode, + fsp->fsp_name->base_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); } DEBUG(1, ("vfs_extd_audit: fchmod_acl %s mode 0x%x %s %s", - fsp->fsp_name, (unsigned int)mode, + fsp_str_dbg(fsp), (unsigned int)mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : "")); diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index e8702aa2c8..76fbc8a8ae 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -419,6 +419,13 @@ static const char *smb_fname_str_do_log(const struct smb_filename *smb_fname) return fname; } +/** + * Return an fsp debug string using the do_log_ctx() + */ +static const char *fsp_str_do_log(const struct files_struct *fsp) +{ + return smb_fname_str_do_log(fsp->fsp_name); +} /* Free function for the private data. */ @@ -561,7 +568,7 @@ static int smb_full_audit_statvfs(struct vfs_handle_struct *handle, return result; } -static int smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle) +static uint32_t smb_full_audit_fs_capabilities(struct vfs_handle_struct *handle) { int result; @@ -736,7 +743,8 @@ static int smb_full_audit_close(vfs_handle_struct *handle, files_struct *fsp) result = SMB_VFS_NEXT_CLOSE(handle, fsp); - do_log(SMB_VFS_OP_CLOSE, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_CLOSE, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -748,7 +756,8 @@ static ssize_t smb_full_audit_read(vfs_handle_struct *handle, files_struct *fsp, result = SMB_VFS_NEXT_READ(handle, fsp, data, n); - do_log(SMB_VFS_OP_READ, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_READ, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -760,7 +769,8 @@ static ssize_t smb_full_audit_pread(vfs_handle_struct *handle, files_struct *fsp result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset); - do_log(SMB_VFS_OP_PREAD, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_PREAD, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -772,7 +782,8 @@ static ssize_t smb_full_audit_write(vfs_handle_struct *handle, files_struct *fsp result = SMB_VFS_NEXT_WRITE(handle, fsp, data, n); - do_log(SMB_VFS_OP_WRITE, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_WRITE, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -785,7 +796,8 @@ static ssize_t smb_full_audit_pwrite(vfs_handle_struct *handle, files_struct *fs result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset); - do_log(SMB_VFS_OP_PWRITE, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_PWRITE, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -798,7 +810,7 @@ static SMB_OFF_T smb_full_audit_lseek(vfs_handle_struct *handle, files_struct *f result = SMB_VFS_NEXT_LSEEK(handle, fsp, offset, whence); do_log(SMB_VFS_OP_LSEEK, (result != (ssize_t)-1), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -813,7 +825,7 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd, result = SMB_VFS_NEXT_SENDFILE(handle, tofd, fromfsp, hdr, offset, n); do_log(SMB_VFS_OP_SENDFILE, (result >= 0), handle, - "%s", fromfsp->fsp_name); + "%s", fsp_str_do_log(fromfsp)); return result; } @@ -828,7 +840,7 @@ static ssize_t smb_full_audit_recvfile(vfs_handle_struct *handle, int fromfd, result = SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, n); do_log(SMB_VFS_OP_RECVFILE, (result >= 0), handle, - "%s", tofsp->fsp_name); + "%s", fsp_str_do_log(tofsp)); return result; } @@ -854,7 +866,8 @@ static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp) result = SMB_VFS_NEXT_FSYNC(handle, fsp); - do_log(SMB_VFS_OP_FSYNC, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_FSYNC, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -879,7 +892,8 @@ static int smb_full_audit_fstat(vfs_handle_struct *handle, files_struct *fsp, result = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); - do_log(SMB_VFS_OP_FSTAT, (result >= 0), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_FSTAT, (result >= 0), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -897,7 +911,7 @@ static int smb_full_audit_lstat(vfs_handle_struct *handle, return result; } -static int smb_full_audit_get_alloc_size(vfs_handle_struct *handle, +static uint64_t smb_full_audit_get_alloc_size(vfs_handle_struct *handle, files_struct *fsp, const SMB_STRUCT_STAT *sbuf) { int result; @@ -942,7 +956,7 @@ static int smb_full_audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, result = SMB_VFS_NEXT_FCHMOD(handle, fsp, mode); do_log(SMB_VFS_OP_FCHMOD, (result >= 0), handle, - "%s|%o", fsp->fsp_name, mode); + "%s|%o", fsp_str_do_log(fsp), mode); return result; } @@ -968,7 +982,7 @@ static int smb_full_audit_fchown(vfs_handle_struct *handle, files_struct *fsp, result = SMB_VFS_NEXT_FCHOWN(handle, fsp, uid, gid); do_log(SMB_VFS_OP_FCHOWN, (result >= 0), handle, "%s|%ld|%ld", - fsp->fsp_name, (long int)uid, (long int)gid); + fsp_str_do_log(fsp), (long int)uid, (long int)gid); return result; } @@ -1032,7 +1046,7 @@ static int smb_full_audit_ftruncate(vfs_handle_struct *handle, files_struct *fsp result = SMB_VFS_NEXT_FTRUNCATE(handle, fsp, len); do_log(SMB_VFS_OP_FTRUNCATE, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1044,7 +1058,7 @@ static bool smb_full_audit_lock(vfs_handle_struct *handle, files_struct *fsp, result = SMB_VFS_NEXT_LOCK(handle, fsp, op, offset, count, type); - do_log(SMB_VFS_OP_LOCK, result, handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_LOCK, result, handle, "%s", fsp_str_do_log(fsp)); return result; } @@ -1058,7 +1072,7 @@ static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode); do_log(SMB_VFS_OP_KERNEL_FLOCK, (result >= 0), handle, "%s", - fsp->fsp_name); + fsp_str_do_log(fsp)); return result; } @@ -1071,7 +1085,7 @@ static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct result = SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype); do_log(SMB_VFS_OP_LINUX_SETLEASE, (result >= 0), handle, "%s", - fsp->fsp_name); + fsp_str_do_log(fsp)); return result; } @@ -1083,7 +1097,7 @@ static bool smb_full_audit_getlock(vfs_handle_struct *handle, files_struct *fsp, result = SMB_VFS_NEXT_GETLOCK(handle, fsp, poffset, pcount, ptype, ppid); - do_log(SMB_VFS_OP_GETLOCK, result, handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_GETLOCK, result, handle, "%s", fsp_str_do_log(fsp)); return result; } @@ -1256,7 +1270,7 @@ static NTSTATUS smb_full_audit_brl_lock_windows(struct vfs_handle_struct *handle blocking_lock, blr); do_log(SMB_VFS_OP_BRL_LOCK_WINDOWS, NT_STATUS_IS_OK(result), handle, - "%s:%llu-%llu. type=%d. blocking=%d", br_lck->fsp->fsp_name, + "%s:%llu-%llu. type=%d. blocking=%d", fsp_str_do_log(br_lck->fsp), plock->start, plock->size, plock->lock_type, blocking_lock ); return result; @@ -1273,7 +1287,7 @@ static bool smb_full_audit_brl_unlock_windows(struct vfs_handle_struct *handle, plock); do_log(SMB_VFS_OP_BRL_UNLOCK_WINDOWS, (result == 0), handle, - "%s:%llu-%llu:%d", br_lck->fsp->fsp_name, plock->start, + "%s:%llu-%llu:%d", fsp_str_do_log(br_lck->fsp), plock->start, plock->size, plock->lock_type); return result; @@ -1289,7 +1303,7 @@ static bool smb_full_audit_brl_cancel_windows(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_BRL_CANCEL_WINDOWS(handle, br_lck, plock, blr); do_log(SMB_VFS_OP_BRL_CANCEL_WINDOWS, (result == 0), handle, - "%s:%llu-%llu:%d", br_lck->fsp->fsp_name, plock->start, + "%s:%llu-%llu:%d", fsp_str_do_log(br_lck->fsp), plock->start, plock->size); return result; @@ -1304,7 +1318,7 @@ static bool smb_full_audit_strict_lock(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_STRICT_LOCK(handle, fsp, plock); do_log(SMB_VFS_OP_STRICT_LOCK, result, handle, - "%s:%llu-%llu:%d", fsp->fsp_name, plock->start, + "%s:%llu-%llu:%d", fsp_str_do_log(fsp), plock->start, plock->size); return result; @@ -1317,7 +1331,7 @@ static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle, SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock); do_log(SMB_VFS_OP_STRICT_UNLOCK, true, handle, - "%s:%llu-%llu:%d", fsp->fsp_name, plock->start, + "%s:%llu-%llu:%d", fsp_str_do_log(fsp), plock->start, plock->size); return; @@ -1332,7 +1346,7 @@ static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_stru result = SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc); do_log(SMB_VFS_OP_FGET_NT_ACL, NT_STATUS_IS_OK(result), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1360,7 +1374,8 @@ static NTSTATUS smb_full_audit_fset_nt_acl(vfs_handle_struct *handle, files_stru result = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd); - do_log(SMB_VFS_OP_FSET_NT_ACL, NT_STATUS_IS_OK(result), handle, "%s", fsp->fsp_name); + do_log(SMB_VFS_OP_FSET_NT_ACL, NT_STATUS_IS_OK(result), handle, "%s", + fsp_str_do_log(fsp)); return result; } @@ -1386,7 +1401,7 @@ static int smb_full_audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fs result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode); do_log(SMB_VFS_OP_FCHMOD_ACL, (result >= 0), handle, - "%s|%o", fsp->fsp_name, mode); + "%s|%o", fsp_str_do_log(fsp), mode); return result; } @@ -1475,7 +1490,7 @@ static SMB_ACL_T smb_full_audit_sys_acl_get_fd(vfs_handle_struct *handle, result = SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp); do_log(SMB_VFS_OP_SYS_ACL_GET_FD, (result != NULL), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1635,7 +1650,7 @@ static int smb_full_audit_sys_acl_set_fd(vfs_handle_struct *handle, files_struct result = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, theacl); do_log(SMB_VFS_OP_SYS_ACL_SET_FD, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1749,7 +1764,7 @@ static ssize_t smb_full_audit_fgetxattr(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, value, size); do_log(SMB_VFS_OP_FGETXATTR, (result >= 0), handle, - "%s|%s", fsp->fsp_name, name); + "%s|%s", fsp_str_do_log(fsp), name); return result; } @@ -1787,7 +1802,7 @@ static ssize_t smb_full_audit_flistxattr(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_FLISTXATTR(handle, fsp, list, size); do_log(SMB_VFS_OP_FLISTXATTR, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1829,7 +1844,7 @@ static int smb_full_audit_fremovexattr(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, name); do_log(SMB_VFS_OP_FREMOVEXATTR, (result >= 0), handle, - "%s|%s", fsp->fsp_name, name); + "%s|%s", fsp_str_do_log(fsp), name); return result; } @@ -1875,7 +1890,7 @@ static int smb_full_audit_fsetxattr(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, value, size, flags); do_log(SMB_VFS_OP_FSETXATTR, (result >= 0), handle, - "%s|%s", fsp->fsp_name, name); + "%s|%s", fsp_str_do_log(fsp), name); return result; } @@ -1886,7 +1901,7 @@ static int smb_full_audit_aio_read(struct vfs_handle_struct *handle, struct file result = SMB_VFS_NEXT_AIO_READ(handle, fsp, aiocb); do_log(SMB_VFS_OP_AIO_READ, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1897,7 +1912,7 @@ static int smb_full_audit_aio_write(struct vfs_handle_struct *handle, struct fil result = SMB_VFS_NEXT_AIO_WRITE(handle, fsp, aiocb); do_log(SMB_VFS_OP_AIO_WRITE, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1908,7 +1923,7 @@ static ssize_t smb_full_audit_aio_return(struct vfs_handle_struct *handle, struc result = SMB_VFS_NEXT_AIO_RETURN(handle, fsp, aiocb); do_log(SMB_VFS_OP_AIO_RETURN, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1919,7 +1934,7 @@ static int smb_full_audit_aio_cancel(struct vfs_handle_struct *handle, struct fi result = SMB_VFS_NEXT_AIO_CANCEL(handle, fsp, aiocb); do_log(SMB_VFS_OP_AIO_CANCEL, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1930,7 +1945,7 @@ static int smb_full_audit_aio_error(struct vfs_handle_struct *handle, struct fil result = SMB_VFS_NEXT_AIO_ERROR(handle, fsp, aiocb); do_log(SMB_VFS_OP_AIO_ERROR, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1941,7 +1956,7 @@ static int smb_full_audit_aio_fsync(struct vfs_handle_struct *handle, struct fil result = SMB_VFS_NEXT_AIO_FSYNC(handle, fsp, op, aiocb); do_log(SMB_VFS_OP_AIO_FSYNC, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1952,7 +1967,7 @@ static int smb_full_audit_aio_suspend(struct vfs_handle_struct *handle, struct f result = SMB_VFS_NEXT_AIO_SUSPEND(handle, fsp, aiocb, n, ts); do_log(SMB_VFS_OP_AIO_SUSPEND, (result >= 0), handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } @@ -1964,7 +1979,7 @@ static bool smb_full_audit_aio_force(struct vfs_handle_struct *handle, result = SMB_VFS_NEXT_AIO_FORCE(handle, fsp); do_log(SMB_VFS_OP_AIO_FORCE, result, handle, - "%s", fsp->fsp_name); + "%s", fsp_str_do_log(fsp)); return result; } diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index 47858cb352..cde80f0021 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -303,7 +303,7 @@ static NTSTATUS gpfsacl_fget_nt_acl(vfs_handle_struct *handle, int result; *ppdesc = NULL; - result = gpfs_get_nfs4_acl(fsp->fsp_name, &pacl); + result = gpfs_get_nfs4_acl(fsp->fsp_name->base_name, &pacl); if (result == 0) return smb_fget_nt_acl_nfs4(fsp, security_info, ppdesc, pacl); @@ -389,7 +389,7 @@ static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) "merge_writeappend", True)) { DEBUG(2, ("vfs_gpfs.c: file [%s]: ACE contains " "WRITE^APPEND, setting WRITE|APPEND\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); gace->aceMask |= ACE4_MASK_WRITE|ACE4_MASK_APPEND; } @@ -423,7 +423,8 @@ static bool gpfsacl_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) gacl->acl_nace++; } - ret = smbd_gpfs_putacl(fsp->fsp_name, GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl); + ret = smbd_gpfs_putacl(fsp->fsp_name->base_name, + GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl); if (ret != 0) { DEBUG(8, ("gpfs_putacl failed with %s\n", strerror(errno))); gpfs_dumpacl(8, gacl); @@ -439,12 +440,17 @@ static NTSTATUS gpfsacl_set_nt_acl_internal(files_struct *fsp, uint32 security_i struct gpfs_acl *acl; NTSTATUS result = NT_STATUS_ACCESS_DENIED; - acl = gpfs_getacl_alloc(fsp->fsp_name, 0); + acl = gpfs_getacl_alloc(fsp->fsp_name->base_name, 0); if (acl == NULL) return result; if (acl->acl_version&GPFS_ACL_VERSION_NFS4) { + if ((psd->type&SEC_DESC_DACL_PROTECTED)) { + DEBUG(2, ("Rejecting unsupported ACL with DACL_PROTECTED bit set\n")); + return NT_STATUS_NOT_SUPPORTED; + } + result = smb_set_nt_acl_nfs4( fsp, security_info_sent, psd, gpfsacl_process_smbacl); @@ -589,7 +595,8 @@ static SMB_ACL_T gpfsacl_sys_acl_get_file(vfs_handle_struct *handle, static SMB_ACL_T gpfsacl_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp) { - return gpfsacl_get_posix_acl(fsp->fsp_name, GPFS_ACL_TYPE_ACCESS); + return gpfsacl_get_posix_acl(fsp->fsp_name->base_name, + GPFS_ACL_TYPE_ACCESS); } static struct gpfs_acl *smb2gpfs_acl(const SMB_ACL_T pacl, @@ -702,7 +709,8 @@ static int gpfsacl_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl) { - return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name, SMB_ACL_TYPE_ACCESS, theacl); + return gpfsacl_sys_acl_set_file(handle, fsp->fsp_name->base_name, + SMB_ACL_TYPE_ACCESS, theacl); } static int gpfsacl_sys_acl_delete_def_file(vfs_handle_struct *handle, @@ -759,6 +767,8 @@ static int gpfsacl_emu_chmod(const char *path, mode_t mode) int i; files_struct fake_fsp; /* TODO: rationalize parametrization */ SMB4ACE_T *smbace; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; DEBUG(10, ("gpfsacl_emu_chmod invoked for %s mode %o\n", path, mode)); @@ -828,11 +838,19 @@ static int gpfsacl_emu_chmod(const char *path, mode_t mode) /* don't add complementary DENY ACEs here */ ZERO_STRUCT(fake_fsp); - fake_fsp.fsp_name = (char *)path; /* no file_new is needed here */ - + status = create_synthetic_smb_fname(talloc_tos(), path, NULL, NULL, + &fake_fsp.fsp_name); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } /* put the acl */ - if (gpfsacl_process_smbacl(&fake_fsp, pacl) == False) + if (gpfsacl_process_smbacl(&fake_fsp, pacl) == False) { + TALLOC_FREE(fake_fsp.fsp_name); return -1; + } + + TALLOC_FREE(fake_fsp.fsp_name); return 0; /* ok for [f]chmod */ } @@ -870,7 +888,7 @@ static int vfs_gpfs_fchmod(vfs_handle_struct *handle, files_struct *fsp, mode_t return 0; } - rc = gpfsacl_emu_chmod(fsp->fsp_name, mode); + rc = gpfsacl_emu_chmod(fsp->fsp_name->base_name, mode); if (rc == 1) return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode); return rc; diff --git a/source3/modules/vfs_hpuxacl.c b/source3/modules/vfs_hpuxacl.c index 35341a5c3e..32e8539202 100644 --- a/source3/modules/vfs_hpuxacl.c +++ b/source3/modules/vfs_hpuxacl.c @@ -201,23 +201,23 @@ SMB_ACL_T hpuxacl_sys_acl_get_fd(vfs_handle_struct *handle, DEBUG(10, ("redirecting call of hpuxacl_sys_acl_get_fd to " "hpuxacl_sys_acl_get_file (no facl syscall on HPUX).\n")); - return hpuxacl_sys_acl_get_file(handle, file_struct_p->fsp_name, - SMB_ACL_TYPE_ACCESS); + return hpuxacl_sys_acl_get_file(handle, + file_struct_p->fsp_name->base_name, + SMB_ACL_TYPE_ACCESS); } int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, - const char *name, + struct smb_filename *smb_fname, SMB_ACL_TYPE_T type, SMB_ACL_T theacl) { int ret = -1; - SMB_STRUCT_STAT s; HPUX_ACL_T hpux_acl = NULL; int count; DEBUG(10, ("hpuxacl_sys_acl_set_file called for file '%s'\n", - name)); + smb_fname_str_dbg(smb_fname))); if(hpux_acl_call_present() == False) { @@ -248,11 +248,11 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, * that has _not_ been specified in "type" from the file first * and concatenate it with the acl provided. */ - if (vfs_stat_smb_fname(handle->conn, name, &s) != 0) { + if (SMB_VFS_STAT(handle->conn, smb_fname) != 0) { DEBUG(10, ("Error in stat call: %s\n", strerror(errno))); goto done; } - if (S_ISDIR(s.st_ex_mode)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { HPUX_ACL_T other_acl; int other_count; SMB_ACL_TYPE_T other_type; @@ -261,7 +261,8 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS; DEBUGADD(10, ("getting acl from filesystem\n")); - if (!hpux_acl_get_file(name, &other_acl, &other_count)) { + if (!hpux_acl_get_file(smb_fname->base_name, &other_acl, + &other_count)) { DEBUG(10, ("error getting acl from directory\n")); goto done; } @@ -289,7 +290,8 @@ int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, } DEBUG(10, ("resulting acl is valid.\n")); - ret = acl(CONST_DISCARD(char *, name), ACL_SET, count, hpux_acl); + ret = acl(CONST_DISCARD(char *, smb_fname->base_name), ACL_SET, count, + hpux_acl); if (ret != 0) { DEBUG(0, ("ERROR calling acl: %s\n", strerror(errno))); } diff --git a/source3/modules/vfs_hpuxacl.h b/source3/modules/vfs_hpuxacl.h index 07b32d628c..9baed5790a 100644 --- a/source3/modules/vfs_hpuxacl.h +++ b/source3/modules/vfs_hpuxacl.h @@ -41,7 +41,7 @@ SMB_ACL_T hpuxacl_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp); int hpuxacl_sys_acl_set_file(vfs_handle_struct *handle, - const char *name, + struct smb_filename *smb_fname, SMB_ACL_TYPE_T type, SMB_ACL_T theacl); diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 1f300a055c..7c338e7268 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -406,8 +406,8 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle, static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) { int ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); - if (ret == 0 && shadow_copy2_match_name(fsp->fsp_name)) { - convert_sbuf(handle, fsp->fsp_name, sbuf); + if (ret == 0 && shadow_copy2_match_name(fsp->fsp_name->base_name)) { + convert_sbuf(handle, fsp->fsp_name->base_name, sbuf); } return ret; } @@ -549,7 +549,8 @@ static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname) SHADOW2_NEXT(RMDIR, (handle, name), int, -1); } -static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, int flags) +static int shadow_copy2_chflags(vfs_handle_struct *handle, const char *fname, + unsigned int flags) { SHADOW2_NEXT(CHFLAGS, (handle, name, flags), int, -1); } diff --git a/source3/modules/vfs_smb_traffic_analyzer.c b/source3/modules/vfs_smb_traffic_analyzer.c index a7fbeadbbe..6f7aee0e50 100644 --- a/source3/modules/vfs_smb_traffic_analyzer.c +++ b/source3/modules/vfs_smb_traffic_analyzer.c @@ -336,11 +336,11 @@ static ssize_t smb_traffic_analyzer_read(vfs_handle_struct *handle, \ ssize_t result; result = SMB_VFS_NEXT_READ(handle, fsp, data, n); - DEBUG(10, ("smb_traffic_analyzer_read: READ: %s\n", fsp->fsp_name )); + DEBUG(10, ("smb_traffic_analyzer_read: READ: %s\n", fsp_str_dbg(fsp))); smb_traffic_analyzer_send_data(handle, result, - fsp->fsp_name, + fsp->fsp_name->base_name, false); return result; } @@ -353,11 +353,12 @@ static ssize_t smb_traffic_analyzer_pread(vfs_handle_struct *handle, \ result = SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset); - DEBUG(10, ("smb_traffic_analyzer_pread: PREAD: %s\n", fsp->fsp_name )); + DEBUG(10, ("smb_traffic_analyzer_pread: PREAD: %s\n", + fsp_str_dbg(fsp))); smb_traffic_analyzer_send_data(handle, result, - fsp->fsp_name, + fsp->fsp_name->base_name, false); return result; @@ -370,11 +371,12 @@ static ssize_t smb_traffic_analyzer_write(vfs_handle_struct *handle, \ result = SMB_VFS_NEXT_WRITE(handle, fsp, data, n); - DEBUG(10, ("smb_traffic_analyzer_write: WRITE: %s\n", fsp->fsp_name )); + DEBUG(10, ("smb_traffic_analyzer_write: WRITE: %s\n", + fsp_str_dbg(fsp))); smb_traffic_analyzer_send_data(handle, result, - fsp->fsp_name, + fsp->fsp_name->base_name, true); return result; } @@ -386,11 +388,11 @@ static ssize_t smb_traffic_analyzer_pwrite(vfs_handle_struct *handle, \ result = SMB_VFS_NEXT_PWRITE(handle, fsp, data, n, offset); - DEBUG(10, ("smb_traffic_analyzer_pwrite: PWRITE: %s\n", fsp->fsp_name )); + DEBUG(10, ("smb_traffic_analyzer_pwrite: PWRITE: %s\n", fsp_str_dbg(fsp))); smb_traffic_analyzer_send_data(handle, result, - fsp->fsp_name, + fsp->fsp_name->base_name, true); return result; } diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c index eccc2379c9..c32c4f3190 100644 --- a/source3/modules/vfs_streams_xattr.c +++ b/source3/modules/vfs_streams_xattr.c @@ -128,27 +128,20 @@ static NTSTATUS streams_xattr_get_name(TALLOC_CTX *ctx, static bool streams_xattr_recheck(struct stream_io *sio) { NTSTATUS status; - struct smb_filename *smb_fname = NULL; char *xattr_name = NULL; if (sio->fsp->fsp_name == sio->fsp_name_ptr) { return true; } - status = create_synthetic_smb_fname_split(talloc_tos(), - sio->fsp->fsp_name, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return false; - } - - if (smb_fname->stream_name == NULL) { + if (sio->fsp->fsp_name->stream_name == NULL) { /* how can this happen */ errno = EINVAL; return false; } - status = streams_xattr_get_name(talloc_tos(), smb_fname->stream_name, + status = streams_xattr_get_name(talloc_tos(), + sio->fsp->fsp_name->stream_name, &xattr_name); if (!NT_STATUS_IS_OK(status)) { return false; @@ -159,10 +152,9 @@ static bool streams_xattr_recheck(struct stream_io *sio) sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp), xattr_name); sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(sio->handle, sio->fsp), - smb_fname->base_name); + sio->fsp->fsp_name->base_name); sio->fsp_name_ptr = sio->fsp->fsp_name; - TALLOC_FREE(smb_fname); TALLOC_FREE(xattr_name); if ((sio->xattr_name == NULL) || (sio->base == NULL)) { @@ -899,7 +891,8 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle, sio->xattr_name, ea.value.data, ea.value.length, 0); } else { - ret = SMB_VFS_SETXATTR(fsp->conn, fsp->base_fsp->fsp_name, + ret = SMB_VFS_SETXATTR(fsp->conn, + fsp->base_fsp->fsp_name->base_name, sio->xattr_name, ea.value.data, ea.value.length, 0); } @@ -963,8 +956,7 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n", - fsp->fsp_name, - (double)offset )); + fsp_str_dbg(fsp), (double)offset)); if (sio == NULL) { return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); @@ -1004,7 +996,8 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, sio->xattr_name, ea.value.data, ea.value.length, 0); } else { - ret = SMB_VFS_SETXATTR(fsp->conn, fsp->base_fsp->fsp_name, + ret = SMB_VFS_SETXATTR(fsp->conn, + fsp->base_fsp->fsp_name->base_name, sio->xattr_name, ea.value.data, ea.value.length, 0); } diff --git a/source3/modules/vfs_tsmsm.c b/source3/modules/vfs_tsmsm.c index 57807105f6..753b2bcd26 100644 --- a/source3/modules/vfs_tsmsm.c +++ b/source3/modules/vfs_tsmsm.c @@ -273,7 +273,7 @@ static ssize_t tsmsm_aio_return(struct vfs_handle_struct *handle, struct files_s if(result >= 0) { notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, - fsp->fsp_name); + fsp->fsp_name->base_name); } return result; @@ -307,7 +307,7 @@ static ssize_t tsmsm_pread(struct vfs_handle_struct *handle, struct files_struct */ notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, - fsp->fsp_name); + fsp->fsp_name->base_name); } return result; @@ -325,7 +325,7 @@ static ssize_t tsmsm_pwrite(struct vfs_handle_struct *handle, struct files_struc */ notify_fname(handle->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES, - fsp->fsp_name); + fsp->fsp_name->base_name); } return result; diff --git a/source3/modules/vfs_zfsacl.c b/source3/modules/vfs_zfsacl.c index a5b0490c8d..a92d5dae26 100644 --- a/source3/modules/vfs_zfsacl.c +++ b/source3/modules/vfs_zfsacl.c @@ -145,14 +145,14 @@ static bool zfs_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl) SMB_ASSERT(i == naces); /* store acl */ - if(acl(fsp->fsp_name, ACE_SETACL, naces, acebuf)) { + if(acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf)) { if(errno == ENOSYS) { DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not " "supported on the filesystem where the file " - "reside", fsp->fsp_name)); + "reside", fsp_str_dbg(fsp))); } else { - DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp->fsp_name, - strerror(errno))); + DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp_str_dbg(fsp), + strerror(errno))); } return 0; } @@ -180,7 +180,8 @@ static NTSTATUS zfsacl_fget_nt_acl(struct vfs_handle_struct *handle, SMB4ACL_T *pacl; NTSTATUS status; - status = zfs_get_nt_acl_common(fsp->fsp_name, security_info, &pacl); + status = zfs_get_nt_acl_common(fsp->fsp_name->base_name, security_info, + &pacl); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 848baeff3d..961e930728 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -82,6 +82,8 @@ static void terminate(void) /* If there was an async dns child - kill it. */ kill_async_dns_child(); + gencache_stabilize(); + pidfile_unlink(); exit(0); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 7e4371bf0b..dbbd6e327d 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -5142,6 +5142,9 @@ static char *lp_string(const char *s) #if 0 DEBUG(10, ("lp_string(%s)\n", s)); #endif + if (!s) { + return NULL; + } ret = talloc_sub_basic(ctx, get_current_username(), diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 4ed04e4e7a..0678181669 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1439,7 +1439,7 @@ static bool init_samu_from_buffer_v2(struct samu *sampass, uint8 *buf, uint32 bu } /* Change from V1 is addition of password history field. */ - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen) { uint8 *pw_hist = SMB_MALLOC_ARRAY(uint8, pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { @@ -1674,7 +1674,7 @@ static bool init_samu_from_buffer_v3(struct samu *sampass, uint8 *buf, uint32 bu } } - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen) { uint8 *pw_hist = (uint8 *)SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { @@ -1879,7 +1879,7 @@ static uint32 init_buffer_from_samu_v3 (uint8 **buf, struct samu *sampass, bool nt_pw_len = 0; } - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len); if (pwHistLen && nt_pw_hist && nt_pw_hist_len) { nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN; @@ -2085,7 +2085,7 @@ bool pdb_copy_sam_account(struct samu *dst, struct samu *src ) } /********************************************************************* - Update the bad password count checking the AP_RESET_COUNT_TIME + Update the bad password count checking the PDB_POLICY_RESET_COUNT_TIME *********************************************************************/ bool pdb_update_bad_password_count(struct samu *sampass, bool *updated) @@ -2102,7 +2102,7 @@ bool pdb_update_bad_password_count(struct samu *sampass, bool *updated) } become_root(); - res = pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime); + res = pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &resettime); unbecome_root(); if (!res) { @@ -2131,7 +2131,7 @@ bool pdb_update_bad_password_count(struct samu *sampass, bool *updated) } /********************************************************************* - Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION + Update the ACB_AUTOLOCK flag checking the PDB_POLICY_LOCK_ACCOUNT_DURATION *********************************************************************/ bool pdb_update_autolock_flag(struct samu *sampass, bool *updated) @@ -2147,7 +2147,7 @@ bool pdb_update_autolock_flag(struct samu *sampass, bool *updated) } become_root(); - res = pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration); + res = pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &duration); unbecome_root(); if (!res) { @@ -2199,7 +2199,7 @@ bool pdb_increment_bad_password_count(struct samu *sampass) /* Retrieve the account lockout policy */ become_root(); - ret = pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout); + ret = pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout); unbecome_root(); if ( !ret ) { DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n")); diff --git a/source3/passdb/pdb_ads.c b/source3/passdb/pdb_ads.c index eec63728ca..70d550042b 100644 --- a/source3/passdb/pdb_ads.c +++ b/source3/passdb/pdb_ads.c @@ -203,7 +203,7 @@ static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m, pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET); } if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) { - pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET); + pdb_set_kickoff_time(sam, tmp_time, PDB_SET); } str = tldap_talloc_single_attribute(entry, "displayName", @@ -250,7 +250,7 @@ static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m, DEBUG(10, ("Could not pull userAccountControl\n")); goto fail; } - pdb_set_acct_ctrl(sam, ads_uf2acb(n), PDB_SET); + pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET); if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) { if (blob.length != NT_HASH_LEN) { @@ -310,7 +310,7 @@ static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state, ret &= tldap_make_mod_fmt( existing, mem_ctx, pnum_mods, pmods, "userAccountControl", - "%d", ads_acb2uf(pdb_get_acct_ctrl(sam))); + "%d", ds_acb2uf(pdb_get_acct_ctrl(sam))); ret &= tldap_make_mod_fmt( existing, mem_ctx, pnum_mods, pmods, "homeDirectory", @@ -1682,7 +1682,7 @@ static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m, DEBUG(10, ("no samAccountType")); continue; } - lsa_attrs[i] = ads_atype_map(attr); + lsa_attrs[i] = ds_atype_map(attr); num_mapped += 1; } @@ -1706,16 +1706,18 @@ static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m, } static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m, - int policy_index, uint32 *value) + enum pdb_policy_type type, + uint32_t *value) { - return account_policy_get(policy_index, value) + return account_policy_get(type, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m, - int policy_index, uint32 value) + enum pdb_policy_type type, + uint32_t value) { - return account_policy_set(policy_index, value) + return account_policy_set(type, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -2022,7 +2024,9 @@ static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m, uint32 *num_domains, struct trustdom_info ***domains) { - return NT_STATUS_NOT_IMPLEMENTED; + *num_domains = 0; + *domains = NULL; + return NT_STATUS_OK; } static void pdb_ads_init_methods(struct pdb_methods *m) @@ -2111,7 +2115,7 @@ static void s3_tldap_debug(void *context, enum tldap_debug_level level, samba_level = 2; break; case TLDAP_DEBUG_TRACE: - samba_level = 10; + samba_level = 11; break; }; diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index f55b77f675..30775e49fe 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -88,7 +88,7 @@ time_t pdb_get_pass_can_change_time(const struct samu *sampass) pdb_get_init_flags(sampass, PDB_CANCHANGETIME) == PDB_CHANGED) return sampass->pass_can_change_time; - if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &allow)) + if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &allow)) allow = 0; /* in normal cases, just calculate it from policy */ @@ -112,7 +112,7 @@ time_t pdb_get_pass_must_change_time(const struct samu *sampass) if (sampass->acct_ctrl & ACB_PWNOEXP) return get_time_t_max(); - if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) + if (!pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &expire) || expire == (uint32)-1 || expire == 0) return get_time_t_max(); @@ -1013,7 +1013,7 @@ bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext) if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { uchar *pwhistory; uint32 pwHistLen; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen != 0){ uint32 current_history_len; /* We need to make sure we don't have a race condition here - the diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 465a6bf595..5d0b625da5 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -994,25 +994,25 @@ NTSTATUS pdb_lookup_names(const DOM_SID *domain_sid, } #endif -bool pdb_get_account_policy(int policy_index, uint32 *value) +bool pdb_get_account_policy(enum pdb_policy_type type, uint32_t *value) { struct pdb_methods *pdb = pdb_get_methods(); NTSTATUS status; become_root(); - status = pdb->get_account_policy(pdb, policy_index, value); + status = pdb->get_account_policy(pdb, type, value); unbecome_root(); return NT_STATUS_IS_OK(status); } -bool pdb_set_account_policy(int policy_index, uint32 value) +bool pdb_set_account_policy(enum pdb_policy_type type, uint32_t value) { struct pdb_methods *pdb = pdb_get_methods(); NTSTATUS status; become_root(); - status = pdb->set_account_policy(pdb, policy_index, value); + status = pdb->set_account_policy(pdb, type, value); unbecome_root(); return NT_STATUS_IS_OK(status); @@ -1174,14 +1174,14 @@ static NTSTATUS pdb_default_update_login_attempts (struct pdb_methods *methods, return NT_STATUS_OK; } -static NTSTATUS pdb_default_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value) +static NTSTATUS pdb_default_get_account_policy(struct pdb_methods *methods, enum pdb_policy_type type, uint32_t *value) { - return account_policy_get(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + return account_policy_get(type, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } -static NTSTATUS pdb_default_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value) +static NTSTATUS pdb_default_set_account_policy(struct pdb_methods *methods, enum pdb_policy_type type, uint32_t value) { - return account_policy_set(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; + return account_policy_set(type, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq_num) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 3579325769..1b1e22f2c8 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -336,7 +336,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state, const char **attr) { char *filter = NULL; - char *escape_user = escape_ldap_string_alloc(user); + char *escape_user = escape_ldap_string(talloc_tos(), user); int ret = -1; if (!escape_user) { @@ -350,7 +350,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state, filter = talloc_asprintf(talloc_tos(), "(&%s%s)", "(uid=%u)", get_objclass_filter(ldap_state->schema_ver)); if (!filter) { - SAFE_FREE(escape_user); + TALLOC_FREE(escape_user); return LDAP_NO_MEMORY; } /* @@ -360,7 +360,7 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state, filter = talloc_all_string_sub(talloc_tos(), filter, "%u", escape_user); - SAFE_FREE(escape_user); + TALLOC_FREE(escape_user); if (!filter) { return LDAP_NO_MEMORY; } @@ -902,7 +902,7 @@ static bool init_sam_from_ldap(struct ldapsam_privates *ldap_state, pwHistLen = 0; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen > 0){ uint8 *pwhist = NULL; int i; @@ -1327,7 +1327,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state, if (need_update(sampass, PDB_PWHISTORY)) { char *pwstr = NULL; uint32 pwHistLen = 0; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen); pwstr = SMB_MALLOC_ARRAY(char, 1024); if (!pwstr) { @@ -1404,7 +1404,7 @@ static bool init_ldap_from_sam (struct ldapsam_privates *ldap_state, uint16 badcount = pdb_get_bad_password_count(sampass); time_t badtime = pdb_get_bad_password_time(sampass); uint32 pol; - pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol); + pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &pol); DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n", (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime)); @@ -1701,6 +1701,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, char *utf8_password; char *utf8_dn; size_t converted_size; + int ret; if (!ldap_state->is_nds_ldap) { @@ -1732,14 +1733,31 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } if ((ber_printf (ber, "{") < 0) || - (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn) < 0) || - (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password) < 0) || - (ber_printf (ber, "n}") < 0)) { - DEBUG(0,("ldapsam_modify_entry: ber_printf returns a value <0\n")); - ber_free(ber,1); - TALLOC_FREE(utf8_dn); - TALLOC_FREE(utf8_password); - return NT_STATUS_UNSUCCESSFUL; + (ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, + utf8_dn) < 0)) { + DEBUG(0,("ldapsam_modify_entry: ber_printf returns a " + "value <0\n")); + ber_free(ber,1); + TALLOC_FREE(utf8_dn); + TALLOC_FREE(utf8_password); + return NT_STATUS_UNSUCCESSFUL; + } + + if ((utf8_password != NULL) && (*utf8_password != '\0')) { + ret = ber_printf(ber, "ts}", + LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, + utf8_password); + } else { + ret = ber_printf(ber, "}"); + } + + if (ret < 0) { + DEBUG(0,("ldapsam_modify_entry: ber_printf returns a " + "value <0\n")); + ber_free(ber,1); + TALLOC_FREE(utf8_dn); + TALLOC_FREE(utf8_password); + return NT_STATUS_UNSUCCESSFUL; } if ((rc = ber_flatten (ber, &bv))<0) { @@ -2120,18 +2138,18 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s /* does the entry already exist but without a samba attributes? we need to return the samba attributes here */ - escape_user = escape_ldap_string_alloc( username ); + escape_user = escape_ldap_string(talloc_tos(), username); filter = talloc_strdup(attr_list, "(uid=%u)"); if (!filter) { status = NT_STATUS_NO_MEMORY; goto fn_exit; } filter = talloc_all_string_sub(attr_list, filter, "%u", escape_user); + TALLOC_FREE(escape_user); if (!filter) { status = NT_STATUS_NO_MEMORY; goto fn_exit; } - SAFE_FREE(escape_user); rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr_list, &result); @@ -2278,7 +2296,6 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, struct s fn_exit: TALLOC_FREE(ctx); - SAFE_FREE(escape_user); if (result) { ldap_msgfree(result); } @@ -2528,7 +2545,7 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, const char *name) { char *filter = NULL; - char *escape_name = escape_ldap_string_alloc(name); + char *escape_name = escape_ldap_string(talloc_tos(), name); NTSTATUS status; if (!escape_name) { @@ -2540,11 +2557,11 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name) < 0) { - SAFE_FREE(escape_name); + TALLOC_FREE(escape_name); return NT_STATUS_NO_MEMORY; } - SAFE_FREE(escape_name); + TALLOC_FREE(escape_name); status = ldapsam_getgroup(methods, filter, map); SAFE_FREE(filter); return status; @@ -2665,20 +2682,19 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, for (memberuid = values; *memberuid != NULL; memberuid += 1) { char *escape_memberuid; - escape_memberuid = escape_ldap_string_alloc(*memberuid); + escape_memberuid = escape_ldap_string(talloc_tos(), + *memberuid); if (escape_memberuid == NULL) { ret = NT_STATUS_NO_MEMORY; goto done; } filter = talloc_asprintf_append_buffer(filter, "(uid=%s)", escape_memberuid); + TALLOC_FREE(escape_memberuid); if (filter == NULL) { - SAFE_FREE(escape_memberuid); ret = NT_STATUS_NO_MEMORY; goto done; } - - SAFE_FREE(escape_memberuid); } filter = talloc_asprintf_append_buffer(filter, "))"); @@ -2812,7 +2828,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, return NT_STATUS_INVALID_PARAMETER; } - escape_name = escape_ldap_string_alloc(pdb_get_username(user)); + escape_name = escape_ldap_string(talloc_tos(), pdb_get_username(user)); if (escape_name == NULL) return NT_STATUS_NO_MEMORY; @@ -2950,7 +2966,7 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, done: - SAFE_FREE(escape_name); + TALLOC_FREE(escape_name); return ret; } @@ -3764,7 +3780,7 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, } static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, - int policy_index, + enum pdb_policy_type type, uint32 value) { NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; @@ -3782,7 +3798,7 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, return NT_STATUS_INVALID_PARAMETER; } - policy_attr = get_account_policy_attr(policy_index); + policy_attr = get_account_policy_attr(type); if (policy_attr == NULL) { DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid " "policy\n")); @@ -3802,7 +3818,7 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, return ntstatus; } - if (!cache_account_policy_set(policy_index, value)) { + if (!cache_account_policy_set(type, value)) { DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to " "update local tdb cache\n")); return ntstatus; @@ -3812,14 +3828,15 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, } static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, - int policy_index, uint32 value) + enum pdb_policy_type type, + uint32_t value) { - return ldapsam_set_account_policy_in_ldap(methods, policy_index, + return ldapsam_set_account_policy_in_ldap(methods, type, value); } static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, - int policy_index, + enum pdb_policy_type type, uint32 *value) { NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; @@ -3841,10 +3858,10 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods return NT_STATUS_INVALID_PARAMETER; } - policy_attr = get_account_policy_attr(policy_index); + policy_attr = get_account_policy_attr(type); if (!policy_attr) { DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid " - "policy index: %d\n", policy_index)); + "policy index: %d\n", type)); return ntstatus; } @@ -3898,17 +3915,18 @@ out: Guenther */ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, - int policy_index, uint32 *value) + enum pdb_policy_type type, + uint32_t *value) { NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; - if (cache_account_policy_get(policy_index, value)) { + if (cache_account_policy_get(type, value)) { DEBUG(11,("ldapsam_get_account_policy: got valid value from " "cache\n")); return NT_STATUS_OK; } - ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, + ntstatus = ldapsam_get_account_policy_from_ldap(methods, type, value); if (NT_STATUS_IS_OK(ntstatus)) { goto update_cache; @@ -3919,27 +3937,27 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, #if 0 /* should we automagically migrate old tdb value here ? */ - if (account_policy_get(policy_index, value)) + if (account_policy_get(type, value)) goto update_ldap; DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying " - "default\n", policy_index)); + "default\n", type)); #endif - if (!account_policy_get_default(policy_index, value)) { + if (!account_policy_get_default(type, value)) { return ntstatus; } /* update_ldap: */ - ntstatus = ldapsam_set_account_policy(methods, policy_index, *value); + ntstatus = ldapsam_set_account_policy(methods, type, *value); if (!NT_STATUS_IS_OK(ntstatus)) { return ntstatus; } update_cache: - if (!cache_account_policy_set(policy_index, *value)) { + if (!cache_account_policy_set(type, *value)) { DEBUG(0,("ldapsam_get_account_policy: failed to update local " "tdb as a cache\n")); return NT_STATUS_UNSUCCESSFUL; @@ -4185,14 +4203,14 @@ static char *get_ldap_filter(TALLOC_CTX *mem_ctx, const char *username) goto done; } - escaped = escape_ldap_string_alloc(username); + escaped = escape_ldap_string(talloc_tos(), username); if (escaped == NULL) goto done; result = talloc_string_sub(mem_ctx, filter, "%u", username); done: SAFE_FREE(filter); - SAFE_FREE(escaped); + TALLOC_FREE(escaped); return result; } @@ -4994,10 +5012,10 @@ static NTSTATUS ldapsam_create_user(struct pdb_methods *my_methods, is_machine = True; } - username = escape_ldap_string_alloc(name); + username = escape_ldap_string(talloc_tos(), name); filter = talloc_asprintf(tmp_ctx, "(&(uid=%s)(objectClass=%s))", username, LDAP_OBJ_POSIXACCOUNT); - SAFE_FREE(username); + TALLOC_FREE(username); rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result); if (rc != LDAP_SUCCESS) { @@ -5270,10 +5288,10 @@ static NTSTATUS ldapsam_create_dom_group(struct pdb_methods *my_methods, gid_t gid = -1; int rc; - groupname = escape_ldap_string_alloc(name); + groupname = escape_ldap_string(talloc_tos(), name); filter = talloc_asprintf(tmp_ctx, "(&(cn=%s)(objectClass=%s))", groupname, LDAP_OBJ_POSIXGROUP); - SAFE_FREE(groupname); + TALLOC_FREE(groupname); rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, NULL, &result); if (rc != LDAP_SUCCESS) { @@ -5702,7 +5720,8 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods, return NT_STATUS_NO_MEMORY; } - escape_username = escape_ldap_string_alloc(pdb_get_username(sampass)); + escape_username = escape_ldap_string(talloc_tos(), + pdb_get_username(sampass)); if (escape_username== NULL) { return NT_STATUS_NO_MEMORY; } @@ -5715,7 +5734,7 @@ static NTSTATUS ldapsam_set_primary_group(struct pdb_methods *my_methods, LDAP_OBJ_POSIXACCOUNT, LDAP_OBJ_SAMBASAMACCOUNT); - SAFE_FREE(escape_username); + TALLOC_FREE(escape_username); if (filter == NULL) { return NT_STATUS_NO_MEMORY; diff --git a/source3/passdb/pdb_wbc_sam.c b/source3/passdb/pdb_wbc_sam.c index ec54d553d1..df80411a7a 100644 --- a/source3/passdb/pdb_wbc_sam.c +++ b/source3/passdb/pdb_wbc_sam.c @@ -167,12 +167,12 @@ done: return result; } -static NTSTATUS pdb_wbc_sam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value) +static NTSTATUS pdb_wbc_sam_get_account_policy(struct pdb_methods *methods, enum pdb_policy_type type, uint32_t *value) { return NT_STATUS_UNSUCCESSFUL; } -static NTSTATUS pdb_wbc_sam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value) +static NTSTATUS pdb_wbc_sam_set_account_policy(struct pdb_methods *methods, enum pdb_policy_type type, uint32_t value) { return NT_STATUS_UNSUCCESSFUL; } @@ -316,13 +316,12 @@ static NTSTATUS pdb_wbc_sam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map const char *name) { NTSTATUS result = NT_STATUS_OK; - char *user_name = NULL; - char *domain = NULL; + const char *domain = ""; DOM_SID sid; gid_t gid; enum lsa_SidType name_type; - if (!winbind_lookup_name(domain, user_name, &sid, &name_type)) { + if (!winbind_lookup_name(domain, name, &sid, &name_type)) { result = NT_STATUS_NO_SUCH_GROUP; goto done; } @@ -340,7 +339,7 @@ static NTSTATUS pdb_wbc_sam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map goto done; } - if (!_make_group_map(methods, domain, user_name, name_type, gid, &sid, map)) { + if (!_make_group_map(methods, domain, name, name_type, gid, &sid, map)) { result = NT_STATUS_NO_SUCH_GROUP; goto done; } diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index a8e175a684..9185fc84b1 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -58,6 +58,13 @@ NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn, return NT_STATUS_ACCESS_DENIED; /* No errno around here */ } + status = create_synthetic_smb_fname(fsp, + print_job_fname(lp_const_servicename(SNUM(conn)), jobid), NULL, + NULL, &fsp->fsp_name); + if (!NT_STATUS_IS_OK(status)) { + pjob_delete(lp_const_servicename(SNUM(conn)), jobid); + return status; + } /* setup a full fsp */ fsp->fh->fd = print_job_fd(lp_const_servicename(SNUM(conn)),jobid); GetTimeOfDay(&fsp->open_time); @@ -72,7 +79,6 @@ NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn, fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; - string_set(&fsp->fsp_name,print_job_fname(lp_const_servicename(SNUM(conn)),jobid)); fsp->wcp = NULL; SMB_VFS_FSTAT(fsp, psbuf); fsp->mode = psbuf->st_ex_mode; @@ -98,7 +104,7 @@ void print_fsp_end(files_struct *fsp, enum file_close_type close_type) } if (fsp->fsp_name) { - string_free(&fsp->fsp_name); + TALLOC_FREE(fsp->fsp_name); } if (!rap_to_pjobid(fsp->rap_print_jobid, NULL, &jobid)) { diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index e296d319e2..dec43ae741 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -2,6 +2,7 @@ * Unix SMB/CIFS implementation. * Virtual Windows Registry Layer * Copyright (C) Gerald Carter 2002-2005 + * Copyright (C) Michael Adam 2007-2009 * * 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 @@ -27,8 +28,16 @@ static struct db_context *regdb = NULL; static int regdb_refcount; -static bool regdb_key_exists(const char *key); +static bool regdb_key_exists(struct db_context *db, const char *key); static bool regdb_key_is_base_key(const char *key); +static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr); +static bool regdb_store_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr); +static int regdb_fetch_values_internal(struct db_context *db, const char* key, + struct regval_ctr *values); +static bool regdb_store_values_internal(struct db_context *db, const char *key, + struct regval_ctr *values); /* List the deepest path into the registry. All part components will be created.*/ @@ -94,7 +103,8 @@ static struct builtin_regkey_value builtin_registry_values[] = { * Initialize a key in the registry: * create each component key of the specified path. */ -static WERROR init_registry_key_internal(const char *add_path) +static WERROR init_registry_key_internal(struct db_context *db, + const char *add_path) { WERROR werr; TALLOC_CTX *frame = talloc_stackframe(); @@ -173,14 +183,20 @@ static WERROR init_registry_key_internal(const char *add_path) goto fail; } - regdb_fetch_keys(base, subkeys); + werr = regdb_fetch_keys_internal(db, base, subkeys); + if (!W_ERROR_IS_OK(werr) && + !W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) + { + goto fail; + } + if (*subkeyname) { werr = regsubkey_ctr_addkey(subkeys, subkeyname); if (!W_ERROR_IS_OK(werr)) { goto fail; } } - if (!regdb_store_keys( base, subkeys)) { + if (!regdb_store_keys_internal(db, base, subkeys)) { werr = WERR_CAN_NOT_COMPLETE; goto fail; } @@ -193,6 +209,20 @@ fail: return werr; } +struct init_registry_key_context { + const char *add_path; +}; + +static NTSTATUS init_registry_key_action(struct db_context *db, + void *private_data) +{ + struct init_registry_key_context *init_ctx = + (struct init_registry_key_context *)private_data; + + return werror_to_ntstatus(init_registry_key_internal( + db, init_ctx->add_path)); +} + /** * Initialize a key in the registry: * create each component key of the specified path, @@ -200,40 +230,104 @@ fail: */ WERROR init_registry_key(const char *add_path) { - WERROR werr; + struct init_registry_key_context init_ctx; - if (regdb_key_exists(add_path)) { + if (regdb_key_exists(regdb, add_path)) { return WERR_OK; } - if (regdb->transaction_start(regdb) != 0) { - DEBUG(0, ("init_registry_key: transaction_start failed\n")); - return WERR_REG_IO_FAILURE; - } + init_ctx.add_path = add_path; - werr = init_registry_key_internal(add_path); - if (!W_ERROR_IS_OK(werr)) { - goto fail; + return ntstatus_to_werror(dbwrap_trans_do(regdb, + init_registry_key_action, + &init_ctx)); +} + +/*********************************************************************** + Open the registry data in the tdb + ***********************************************************************/ + +static void regdb_ctr_add_value(struct regval_ctr *ctr, + struct builtin_regkey_value *value) +{ + UNISTR2 data; + + switch(value->type) { + case REG_DWORD: + regval_ctr_addvalue(ctr, value->valuename, REG_DWORD, + (char*)&value->data.dw_value, + sizeof(uint32)); + break; + + case REG_SZ: + init_unistr2(&data, value->data.string, UNI_STR_TERMINATE); + regval_ctr_addvalue(ctr, value->valuename, REG_SZ, + (char*)data.buffer, + data.uni_str_len*sizeof(uint16)); + break; + + default: + DEBUG(0, ("regdb_ctr_add_value: invalid value type in " + "registry values [%d]\n", value->type)); } +} - if (regdb->transaction_commit(regdb) != 0) { - DEBUG(0, ("init_registry_key: Could not commit transaction\n")); - return WERR_REG_IO_FAILURE; +static NTSTATUS init_registry_data_action(struct db_context *db, + void *private_data) +{ + NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + struct regval_ctr *values; + int i; + + /* loop over all of the predefined paths and add each component */ + + for (i=0; builtin_registry_paths[i] != NULL; i++) { + if (regdb_key_exists(db, builtin_registry_paths[i])) { + continue; + } + status = werror_to_ntstatus(init_registry_key_internal(db, + builtin_registry_paths[i])); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } } - return WERR_OK; + /* loop over all of the predefined values and add each component */ -fail: - if (regdb->transaction_cancel(regdb) != 0) { - smb_panic("init_registry_key: transaction_cancel failed\n"); + for (i=0; builtin_registry_values[i].path != NULL; i++) { + + values = TALLOC_ZERO_P(frame, struct regval_ctr); + if (values == NULL) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + regdb_fetch_values_internal(db, + builtin_registry_values[i].path, + values); + + /* preserve existing values across restarts. Only add new ones */ + + if (!regval_ctr_key_exists(values, + builtin_registry_values[i].valuename)) + { + regdb_ctr_add_value(values, + &builtin_registry_values[i]); + regdb_store_values_internal(db, + builtin_registry_values[i].path, + values); + } + TALLOC_FREE(values); } - return werr; -} + status = NT_STATUS_OK; -/*********************************************************************** - Open the registry data in the tdb - ***********************************************************************/ +done: + + TALLOC_FREE(frame); + return status; +} WERROR init_registry_data(void) { @@ -241,14 +335,13 @@ WERROR init_registry_data(void) TALLOC_CTX *frame = talloc_stackframe(); struct regval_ctr *values; int i; - UNISTR2 data; /* * First, check for the existence of the needed keys and values. * If all do already exist, we can save the writes. */ for (i=0; builtin_registry_paths[i] != NULL; i++) { - if (!regdb_key_exists(builtin_registry_paths[i])) { + if (!regdb_key_exists(regdb, builtin_registry_paths[i])) { goto do_init; } } @@ -260,7 +353,9 @@ WERROR init_registry_data(void) goto done; } - regdb_fetch_values(builtin_registry_values[i].path, values); + regdb_fetch_values_internal(regdb, + builtin_registry_values[i].path, + values); if (!regval_ctr_key_exists(values, builtin_registry_values[i].valuename)) { @@ -284,89 +379,9 @@ do_init: * transaction behaviour. */ - if (regdb->transaction_start(regdb) != 0) { - DEBUG(0, ("init_registry_data: tdb_transaction_start " - "failed\n")); - werr = WERR_REG_IO_FAILURE; - goto done; - } - - /* loop over all of the predefined paths and add each component */ - - for (i=0; builtin_registry_paths[i] != NULL; i++) { - if (regdb_key_exists(builtin_registry_paths[i])) { - continue; - } - werr = init_registry_key_internal(builtin_registry_paths[i]); - if (!W_ERROR_IS_OK(werr)) { - goto fail; - } - } - - /* loop over all of the predefined values and add each component */ - - for (i=0; builtin_registry_values[i].path != NULL; i++) { - - values = TALLOC_ZERO_P(frame, struct regval_ctr); - if (values == NULL) { - werr = WERR_NOMEM; - goto fail; - } - - regdb_fetch_values(builtin_registry_values[i].path, values); - - /* preserve existing values across restarts. Only add new ones */ - - if (!regval_ctr_key_exists(values, - builtin_registry_values[i].valuename)) - { - switch(builtin_registry_values[i].type) { - case REG_DWORD: - regval_ctr_addvalue(values, - builtin_registry_values[i].valuename, - REG_DWORD, - (char*)&builtin_registry_values[i].data.dw_value, - sizeof(uint32)); - break; - - case REG_SZ: - init_unistr2(&data, - builtin_registry_values[i].data.string, - UNI_STR_TERMINATE); - regval_ctr_addvalue(values, - builtin_registry_values[i].valuename, - REG_SZ, - (char*)data.buffer, - data.uni_str_len*sizeof(uint16)); - break; - - default: - DEBUG(0, ("init_registry_data: invalid value " - "type in builtin_registry_values " - "[%d]\n", - builtin_registry_values[i].type)); - } - regdb_store_values(builtin_registry_values[i].path, - values); - } - TALLOC_FREE(values); - } - - if (regdb->transaction_commit(regdb) != 0) { - DEBUG(0, ("init_registry_data: Could not commit " - "transaction\n")); - werr = WERR_REG_IO_FAILURE; - } else { - werr = WERR_OK; - } - - goto done; - -fail: - if (regdb->transaction_cancel(regdb) != 0) { - smb_panic("init_registry_data: tdb_transaction_cancel " - "failed\n"); - } + werr = ntstatus_to_werror(dbwrap_trans_do(regdb, + init_registry_data_action, + NULL)); done: TALLOC_FREE(frame); @@ -511,7 +526,8 @@ int regdb_get_seqnum(void) } -static WERROR regdb_delete_key_with_prefix(const char *keyname, +static WERROR regdb_delete_key_with_prefix(struct db_context *db, + const char *keyname, const char *prefix) { char *path; @@ -537,7 +553,7 @@ static WERROR regdb_delete_key_with_prefix(const char *keyname, goto done; } - werr = ntstatus_to_werror(dbwrap_delete_bystring(regdb, path)); + werr = ntstatus_to_werror(dbwrap_delete_bystring(db, path)); /* treat "not" found" as ok */ if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) { @@ -550,40 +566,40 @@ done: } -static WERROR regdb_delete_values(const char *keyname) +static WERROR regdb_delete_values(struct db_context *db, const char *keyname) { - return regdb_delete_key_with_prefix(keyname, REG_VALUE_PREFIX); + return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX); } -static WERROR regdb_delete_secdesc(const char *keyname) +static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname) { - return regdb_delete_key_with_prefix(keyname, REG_SECDESC_PREFIX); + return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX); } -static WERROR regdb_delete_subkeylist(const char *keyname) +static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname) { - return regdb_delete_key_with_prefix(keyname, NULL); + return regdb_delete_key_with_prefix(db, keyname, NULL); } -static WERROR regdb_delete_key_lists(const char *keyname) +static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname) { WERROR werr; - werr = regdb_delete_values(keyname); + werr = regdb_delete_values(db, keyname); if (!W_ERROR_IS_OK(werr)) { DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n", REG_VALUE_PREFIX, keyname, win_errstr(werr))); goto done; } - werr = regdb_delete_secdesc(keyname); + werr = regdb_delete_secdesc(db, keyname); if (!W_ERROR_IS_OK(werr)) { DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n", REG_SECDESC_PREFIX, keyname, win_errstr(werr))); goto done; } - werr = regdb_delete_subkeylist(keyname); + werr = regdb_delete_subkeylist(db, keyname); if (!W_ERROR_IS_OK(werr)) { DEBUG(1, (__location__ " Deleting %s failed: %s\n", keyname, win_errstr(werr))); @@ -600,33 +616,42 @@ done: fstrings ***********************************************************************/ -static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr) +static WERROR regdb_store_keys_internal2(struct db_context *db, + const char *key, + struct regsubkey_ctr *ctr) { TDB_DATA dbuf; uint8 *buffer = NULL; int i = 0; uint32 len, buflen; - bool ret = true; uint32 num_subkeys = regsubkey_ctr_numkeys(ctr); char *keyname = NULL; TALLOC_CTX *ctx = talloc_stackframe(); - NTSTATUS status; + WERROR werr; if (!key) { - return false; + werr = WERR_INVALID_PARAM; + goto done; } keyname = talloc_strdup(ctx, key); if (!keyname) { - return false; + werr = WERR_NOMEM; + goto done; } + keyname = normalize_reg_path(ctx, keyname); + if (!keyname) { + werr = WERR_NOMEM; + goto done; + } /* allocate some initial memory */ buffer = (uint8 *)SMB_MALLOC(1024); if (buffer == NULL) { - return false; + werr = WERR_NOMEM; + goto done; } buflen = 1024; len = 0; @@ -654,7 +679,7 @@ static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr DEBUG(0, ("regdb_store_keys: Failed to realloc " "memory of size [%u]\n", (unsigned int)(len+thistime)*2)); - ret = false; + werr = WERR_NOMEM; goto done; } buflen = (len+thistime)*2; @@ -663,7 +688,7 @@ static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr regsubkey_ctr_specific_key(ctr, i)); if (thistime2 != thistime) { DEBUG(0, ("tdb_pack failed\n")); - ret = false; + werr = WERR_CAN_NOT_COMPLETE; goto done; } } @@ -674,11 +699,9 @@ static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr dbuf.dptr = buffer; dbuf.dsize = len; - status = dbwrap_store_bystring(regdb, keyname, dbuf, TDB_REPLACE); - if (!NT_STATUS_IS_OK(status)) { - ret = false; - goto done; - } + werr = ntstatus_to_werror(dbwrap_store_bystring(db, keyname, dbuf, + TDB_REPLACE)); + W_ERROR_NOT_OK_GOTO_DONE(werr); /* * Delete a sorted subkey cache for regdb_key_exists, will be @@ -686,14 +709,22 @@ static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr */ keyname = talloc_asprintf(ctx, "%s/%s", REG_SORTED_SUBKEYS_PREFIX, keyname); - if (keyname != NULL) { - dbwrap_delete_bystring(regdb, keyname); + if (keyname == NULL) { + werr = WERR_NOMEM; + goto done; + } + + werr = ntstatus_to_werror(dbwrap_delete_bystring(db, keyname)); + + /* don't treat WERR_NOT_FOUND as an error here */ + if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) { + werr = WERR_OK; } done: TALLOC_FREE(ctx); SAFE_FREE(buffer); - return ret; + return werr; } /*********************************************************************** @@ -701,73 +732,37 @@ done: do not currently exist ***********************************************************************/ -bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) +struct regdb_store_keys_context { + const char *key; + struct regsubkey_ctr *ctr; +}; + +static NTSTATUS regdb_store_keys_action(struct db_context *db, + void *private_data) { - int num_subkeys, old_num_subkeys, i; + struct regdb_store_keys_context *store_ctx; + WERROR werr; + int num_subkeys, i; char *path = NULL; struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL; char *oldkeyname = NULL; - TALLOC_CTX *ctx = talloc_stackframe(); - WERROR werr; - - if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) { - goto fail; - } - - /* - * fetch a list of the old subkeys so we can determine if anything has - * changed - */ - - werr = regsubkey_ctr_init(ctx, &old_subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - return false; - } - - regdb_fetch_keys(key, old_subkeys); - - num_subkeys = regsubkey_ctr_numkeys(ctr); - old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys); - if ((num_subkeys && old_num_subkeys) && - (num_subkeys == old_num_subkeys)) { - - for (i = 0; i < num_subkeys; i++) { - if (strcmp(regsubkey_ctr_specific_key(ctr, i), - regsubkey_ctr_specific_key(old_subkeys, i)) - != 0) - { - break; - } - } - if (i == num_subkeys) { - /* - * Nothing changed, no point to even start a tdb - * transaction - */ - TALLOC_FREE(old_subkeys); - return true; - } - } - - TALLOC_FREE(old_subkeys); + TALLOC_CTX *mem_ctx = talloc_stackframe(); - if (regdb->transaction_start(regdb) != 0) { - DEBUG(0, ("regdb_store_keys: transaction_start failed\n")); - goto fail; - } + store_ctx = (struct regdb_store_keys_context *)private_data; /* * Re-fetch the old keys inside the transaction */ - werr = regsubkey_ctr_init(ctx, &old_subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - goto cancel; - } + werr = regsubkey_ctr_init(mem_ctx, &old_subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); - regdb_fetch_keys(key, old_subkeys); + werr = regdb_fetch_keys_internal(db, store_ctx->key, old_subkeys); + if (!W_ERROR_IS_OK(werr) && + !W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) + { + goto done; + } /* * Make the store operation as safe as possible without transactions: @@ -796,21 +791,22 @@ bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) for (i=0; i<num_subkeys; i++) { oldkeyname = regsubkey_ctr_specific_key(old_subkeys, i); - if (regsubkey_ctr_key_exists(ctr, oldkeyname)) { + if (regsubkey_ctr_key_exists(store_ctx->ctr, oldkeyname)) { /* * It's still around, don't delete */ - continue; } - path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname); + path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key, + oldkeyname); if (!path) { - goto cancel; + werr = WERR_NOMEM; + goto done; } - werr = regdb_delete_key_lists(path); - W_ERROR_NOT_OK_GOTO(werr, cancel); + werr = regdb_delete_key_lists(db, path); + W_ERROR_NOT_OK_GOTO_DONE(werr); TALLOC_FREE(path); } @@ -819,51 +815,51 @@ bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) /* (2) store the subkey list for the parent */ - if (!regdb_store_keys_internal(key, ctr) ) { + werr = regdb_store_keys_internal2(db, store_ctx->key, store_ctx->ctr); + if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("regdb_store_keys: Failed to store new subkey list " - "for parent [%s]\n", key)); - goto cancel; + "for parent [%s]: %s\n", store_ctx->key, + win_errstr(werr))); + goto done; } /* (3) now create records for any subkeys that don't already exist */ - num_subkeys = regsubkey_ctr_numkeys(ctr); + num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr); if (num_subkeys == 0) { - werr = regsubkey_ctr_init(ctx, &subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - goto cancel; - } + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); - if (!regdb_store_keys_internal(key, subkeys)) { + werr = regdb_store_keys_internal2(db, store_ctx->key, subkeys); + if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("regdb_store_keys: Failed to store " - "new record for key [%s]\n", key)); - goto cancel; + "new record for key [%s]: %s\n", + store_ctx->key, win_errstr(werr))); + goto done; } TALLOC_FREE(subkeys); - } for (i=0; i<num_subkeys; i++) { - path = talloc_asprintf(ctx, "%s/%s", - key, - regsubkey_ctr_specific_key(ctr, i)); + path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key, + regsubkey_ctr_specific_key(store_ctx->ctr, i)); if (!path) { - goto cancel; - } - werr = regsubkey_ctr_init(ctx, &subkeys); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0,("regdb_store_keys: talloc() failure!\n")); - goto cancel; + werr = WERR_NOMEM; + goto done; } + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); - if (regdb_fetch_keys( path, subkeys ) == -1) { + werr = regdb_fetch_keys_internal(db, path, subkeys); + if (!W_ERROR_IS_OK(werr)) { /* create a record with 0 subkeys */ - if (!regdb_store_keys_internal(path, subkeys)) { + werr = regdb_store_keys_internal2(db, path, subkeys); + if (!W_ERROR_IS_OK(werr)) { DEBUG(0,("regdb_store_keys: Failed to store " - "new record for key [%s]\n", path)); - goto cancel; + "new record for key [%s]: %s\n", path, + win_errstr(werr))); + goto done; } } @@ -871,23 +867,129 @@ bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) TALLOC_FREE(path); } - if (regdb->transaction_commit(regdb) != 0) { - DEBUG(0, ("regdb_store_keys: Could not commit transaction\n")); - goto fail; + werr = WERR_OK; + +done: + talloc_free(mem_ctx); + return werror_to_ntstatus(werr); +} + +static bool regdb_store_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr) +{ + int num_subkeys, old_num_subkeys, i; + struct regsubkey_ctr *old_subkeys = NULL; + TALLOC_CTX *ctx = talloc_stackframe(); + WERROR werr; + bool ret = false; + struct regdb_store_keys_context store_ctx; + + if (!regdb_key_is_base_key(key) && !regdb_key_exists(db, key)) { + goto done; } - TALLOC_FREE(ctx); - return true; + /* + * fetch a list of the old subkeys so we can determine if anything has + * changed + */ + + werr = regsubkey_ctr_init(ctx, &old_subkeys); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0,("regdb_store_keys: talloc() failure!\n")); + goto done; + } -cancel: - if (regdb->transaction_cancel(regdb) != 0) { - smb_panic("regdb_store_keys: transaction_cancel failed\n"); + werr = regdb_fetch_keys_internal(db, key, old_subkeys); + if (!W_ERROR_IS_OK(werr) && + !W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) + { + goto done; } -fail: + num_subkeys = regsubkey_ctr_numkeys(ctr); + old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys); + if ((num_subkeys && old_num_subkeys) && + (num_subkeys == old_num_subkeys)) { + + for (i = 0; i < num_subkeys; i++) { + if (strcmp(regsubkey_ctr_specific_key(ctr, i), + regsubkey_ctr_specific_key(old_subkeys, i)) + != 0) + { + break; + } + } + if (i == num_subkeys) { + /* + * Nothing changed, no point to even start a tdb + * transaction + */ + + ret = true; + goto done; + } + } + + TALLOC_FREE(old_subkeys); + + store_ctx.key = key; + store_ctx.ctr = ctr; + + werr = ntstatus_to_werror(dbwrap_trans_do(db, + regdb_store_keys_action, + &store_ctx)); + + ret = W_ERROR_IS_OK(werr); + +done: TALLOC_FREE(ctx); - return false; + return ret; +} + +bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr) +{ + return regdb_store_keys_internal(regdb, key, ctr); +} + +/** + * create a subkey of a given key + */ + +struct regdb_create_subkey_context { + const char *key; + const char *subkey; +}; + +static NTSTATUS regdb_create_subkey_action(struct db_context *db, + void *private_data) +{ + WERROR werr; + struct regdb_create_subkey_context *create_ctx; + struct regsubkey_ctr *subkeys; + TALLOC_CTX *mem_ctx = talloc_stackframe(); + + create_ctx = (struct regdb_create_subkey_context *)private_data; + + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_fetch_keys_internal(db, create_ctx->key, subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regsubkey_ctr_addkey(subkeys, create_ctx->subkey); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_store_keys_internal2(db, create_ctx->key, subkeys); + if (!W_ERROR_IS_OK(werr)) { + DEBUG(0, (__location__ " failed to store new subkey list for " + "parent key %s: %s\n", create_ctx->key, + win_errstr(werr))); + } + +done: + talloc_free(mem_ctx); + return werror_to_ntstatus(werr); } static WERROR regdb_create_subkey(const char *key, const char *subkey) @@ -895,8 +997,9 @@ static WERROR regdb_create_subkey(const char *key, const char *subkey) WERROR werr; struct regsubkey_ctr *subkeys; TALLOC_CTX *mem_ctx = talloc_stackframe(); + struct regdb_create_subkey_context create_ctx; - if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) { + if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) { werr = WERR_NOT_FOUND; goto done; } @@ -904,10 +1007,8 @@ static WERROR regdb_create_subkey(const char *key, const char *subkey) werr = regsubkey_ctr_init(mem_ctx, &subkeys); W_ERROR_NOT_OK_GOTO_DONE(werr); - if (regdb_fetch_keys(key, subkeys) < 0) { - werr = WERR_REG_IO_FAILURE; - goto done; - } + werr = regdb_fetch_keys_internal(regdb, key, subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); if (regsubkey_ctr_key_exists(subkeys, subkey)) { werr = WERR_OK; @@ -916,55 +1017,70 @@ static WERROR regdb_create_subkey(const char *key, const char *subkey) talloc_free(subkeys); - werr = regdb_transaction_start(); - W_ERROR_NOT_OK_GOTO_DONE(werr); + create_ctx.key = key; + create_ctx.subkey = subkey; - werr = regsubkey_ctr_init(mem_ctx, &subkeys); - W_ERROR_NOT_OK_GOTO(werr, cancel); + werr = ntstatus_to_werror(dbwrap_trans_do(regdb, + regdb_create_subkey_action, + &create_ctx)); - if (regdb_fetch_keys(key, subkeys) < 0) { - werr = WERR_REG_IO_FAILURE; - goto cancel; - } +done: + talloc_free(mem_ctx); + return werr; +} - werr = regsubkey_ctr_addkey(subkeys, subkey); - W_ERROR_NOT_OK_GOTO(werr, cancel); +/** + * create a subkey of a given key + */ - if (!regdb_store_keys_internal(key, subkeys)) { - DEBUG(0, (__location__ " failed to store new subkey list for " - "parent key %s\n", key)); - werr = WERR_REG_IO_FAILURE; - goto cancel; - } +struct regdb_delete_subkey_context { + const char *key; + const char *subkey; + const char *path; +}; - werr = regdb_transaction_commit(); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, (__location__ " failed to commit transaction: %s\n", - win_errstr(werr))); - } +static NTSTATUS regdb_delete_subkey_action(struct db_context *db, + void *private_data) +{ + WERROR werr; + struct regdb_delete_subkey_context *delete_ctx; + struct regsubkey_ctr *subkeys; + TALLOC_CTX *mem_ctx = talloc_stackframe(); - goto done; + delete_ctx = (struct regdb_delete_subkey_context *)private_data; + + werr = regdb_delete_key_lists(db, delete_ctx->path); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regsubkey_ctr_init(mem_ctx, &subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_fetch_keys_internal(db, delete_ctx->key, subkeys); + W_ERROR_NOT_OK_GOTO_DONE(werr); -cancel: - werr = regdb_transaction_cancel(); + werr = regsubkey_ctr_delkey(subkeys, delete_ctx->subkey); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + werr = regdb_store_keys_internal2(db, delete_ctx->key, subkeys); if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, (__location__ " failed to cancel transaction: %s\n", + DEBUG(0, (__location__ " failed to store new subkey_list for " + "parent key %s: %s\n", delete_ctx->key, win_errstr(werr))); } done: talloc_free(mem_ctx); - return werr; + return werror_to_ntstatus(werr); } static WERROR regdb_delete_subkey(const char *key, const char *subkey) { - WERROR werr, werr2; - struct regsubkey_ctr *subkeys; + WERROR werr; char *path; + struct regdb_delete_subkey_context delete_ctx; TALLOC_CTX *mem_ctx = talloc_stackframe(); - if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) { + if (!regdb_key_is_base_key(key) && !regdb_key_exists(regdb, key)) { werr = WERR_NOT_FOUND; goto done; } @@ -975,56 +1091,26 @@ static WERROR regdb_delete_subkey(const char *key, const char *subkey) goto done; } - if (!regdb_key_exists(path)) { + if (!regdb_key_exists(regdb, path)) { werr = WERR_OK; goto done; } - werr = regdb_transaction_start(); - W_ERROR_NOT_OK_GOTO_DONE(werr); - - werr = regdb_delete_key_lists(path); - W_ERROR_NOT_OK_GOTO(werr, cancel); - - werr = regsubkey_ctr_init(mem_ctx, &subkeys); - W_ERROR_NOT_OK_GOTO(werr, cancel); - - if (regdb_fetch_keys(key, subkeys) < 0) { - werr = WERR_REG_IO_FAILURE; - goto cancel; - } - - werr = regsubkey_ctr_delkey(subkeys, subkey); - W_ERROR_NOT_OK_GOTO(werr, cancel); + delete_ctx.key = key; + delete_ctx.subkey = subkey; + delete_ctx.path = path; - if (!regdb_store_keys_internal(key, subkeys)) { - DEBUG(0, (__location__ " failed to store new subkey_list for " - "parent key %s\n", key)); - werr = WERR_REG_IO_FAILURE; - goto cancel; - } - - werr = regdb_transaction_commit(); - if (!W_ERROR_IS_OK(werr)) { - DEBUG(0, (__location__ " failed to commit transaction: %s\n", - win_errstr(werr))); - } - - goto done; - -cancel: - werr2 = regdb_transaction_cancel(); - if (!W_ERROR_IS_OK(werr2)) { - DEBUG(0, (__location__ " failed to cancel transaction: %s\n", - win_errstr(werr2))); - } + werr = ntstatus_to_werror(dbwrap_trans_do(regdb, + regdb_delete_subkey_action, + &delete_ctx)); done: talloc_free(mem_ctx); return werr; } -static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key) +static TDB_DATA regdb_fetch_key_internal(struct db_context *db, + TALLOC_CTX *mem_ctx, const char *key) { char *path = NULL; TDB_DATA data; @@ -1034,7 +1120,7 @@ static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key) return make_tdb_data(NULL, 0); } - data = dbwrap_fetch_bystring(regdb, mem_ctx, path); + data = dbwrap_fetch_bystring(db, mem_ctx, path); TALLOC_FREE(path); return data; @@ -1091,7 +1177,7 @@ done: * parent_subkey_scanner. The code uses parse_record() to avoid a memcpy of * the potentially large subkey record. * - * The sorted subkey record is deleted in regdb_store_keys_internal and + * The sorted subkey record is deleted in regdb_store_keys_internal2 and * recreated on demand. */ @@ -1100,39 +1186,58 @@ static int cmp_keynames(const void *p1, const void *p2) return StrCaseCmp(*((char **)p1), *((char **)p2)); } -static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) +struct create_sorted_subkeys_context { + const char *key; + const char *sorted_keyname; +}; + +static NTSTATUS create_sorted_subkeys_action(struct db_context *db, + void *private_data) { char **sorted_subkeys; struct regsubkey_ctr *ctr; - bool result = false; NTSTATUS status; char *buf; char *p; - int i, res; + int i; size_t len; int num_subkeys; - WERROR werr; + struct create_sorted_subkeys_context *sorted_ctx; - if (regdb->transaction_start(regdb) != 0) { - DEBUG(0, ("create_sorted_subkeys: transaction_start " - "failed\n")); - return false; - } + sorted_ctx = (struct create_sorted_subkeys_context *)private_data; - werr = regsubkey_ctr_init(talloc_tos(), &ctr); - if (!W_ERROR_IS_OK(werr)) { - goto fail; + /* + * In this function, we only treat failing of the actual write to + * the db as a real error. All preliminary errors, at a stage when + * nothing has been written to the DB yet are treated as success + * to be committed (as an empty transaction). + * + * The reason is that this (disposable) call might be nested in other + * transactions. Doing a cancel here would destroy the possibility of + * a transaction_commit for transactions that we might be wrapped in. + */ + + status = werror_to_ntstatus(regsubkey_ctr_init(talloc_tos(), &ctr)); + if (!NT_STATUS_IS_OK(status)) { + /* don't treat this as an error */ + status = NT_STATUS_OK; + goto done; } - res = regdb_fetch_keys(key, ctr); - if (res == -1) { - goto fail; + status = werror_to_ntstatus(regdb_fetch_keys_internal(db, + sorted_ctx->key, + ctr)); + if (!NT_STATUS_IS_OK(status)) { + /* don't treat this as an error */ + status = NT_STATUS_OK; + goto done; } num_subkeys = regsubkey_ctr_numkeys(ctr); sorted_subkeys = talloc_array(ctr, char *, num_subkeys); if (sorted_subkeys == NULL) { - goto fail; + /* don't treat this as an error */ + goto done; } len = 4 + 4*num_subkeys; @@ -1141,7 +1246,8 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) sorted_subkeys[i] = talloc_strdup_upper(sorted_subkeys, regsubkey_ctr_specific_key(ctr, i)); if (sorted_subkeys[i] == NULL) { - goto fail; + /* don't treat this as an error */ + goto done; } len += strlen(sorted_subkeys[i])+1; } @@ -1150,7 +1256,8 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) buf = talloc_array(ctr, char, len); if (buf == NULL) { - goto fail; + /* don't treat this as an error */ + goto done; } p = buf + 4 + 4*num_subkeys; @@ -1164,38 +1271,28 @@ static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) } status = dbwrap_store_bystring( - regdb, sorted_keyname, make_tdb_data((uint8_t *)buf, len), + db, sorted_ctx->sorted_keyname, make_tdb_data((uint8_t *)buf, + len), TDB_REPLACE); - if (!NT_STATUS_IS_OK(status)) { - /* - * Don't use a "goto fail;" here, this would commit the broken - * transaction. See below for an explanation. - */ - if (regdb->transaction_cancel(regdb) == -1) { - DEBUG(0, ("create_sorted_subkeys: transaction_cancel " - "failed\n")); - } - TALLOC_FREE(ctr); - return false; - } - result = true; - fail: - /* - * We only get here via the "goto fail" when we did not write anything - * yet. Using transaction_commit even in a failure case is necessary - * because this (disposable) call might be nested in other - * transactions. Doing a cancel here would destroy the possibility of - * a transaction_commit for transactions that we might be wrapped in. - */ - if (regdb->transaction_commit(regdb) == -1) { - DEBUG(0, ("create_sorted_subkeys: transaction_start " - "failed\n")); - goto fail; - } +done: + talloc_free(ctr); + return status; +} - TALLOC_FREE(ctr); - return result; +static bool create_sorted_subkeys(const char *key, const char *sorted_keyname) +{ + NTSTATUS status; + struct create_sorted_subkeys_context sorted_ctx; + + sorted_ctx.key = key; + sorted_ctx.sorted_keyname = sorted_keyname; + + status = dbwrap_trans_do(regdb, + create_sorted_subkeys_action, + &sorted_ctx); + + return NT_STATUS_IS_OK(status); } struct scan_subkey_state { @@ -1241,7 +1338,8 @@ static int parent_subkey_scanner(TDB_DATA key, TDB_DATA data, return 0; } -static bool scan_parent_subkeys(const char *parent, const char *name) +static bool scan_parent_subkeys(struct db_context *db, const char *parent, + const char *name) { char *path = NULL; char *key = NULL; @@ -1268,8 +1366,8 @@ static bool scan_parent_subkeys(const char *parent, const char *name) } state.scanned = false; - res = regdb->parse_record(regdb, string_term_tdb_data(key), - parent_subkey_scanner, &state); + res = db->parse_record(db, string_term_tdb_data(key), + parent_subkey_scanner, &state); if (state.scanned) { result = state.found; @@ -1277,8 +1375,8 @@ static bool scan_parent_subkeys(const char *parent, const char *name) if (!create_sorted_subkeys(path, key)) { goto fail; } - res = regdb->parse_record(regdb, string_term_tdb_data(key), - parent_subkey_scanner, &state); + res = db->parse_record(db, string_term_tdb_data(key), + parent_subkey_scanner, &state); if ((res == 0) && (state.scanned)) { result = state.found; } @@ -1298,7 +1396,7 @@ static bool scan_parent_subkeys(const char *parent, const char *name) * The exeption of this are keys without a parent key, * i.e. the "base" keys (HKLM, HKCU, ...). */ -static bool regdb_key_exists(const char *key) +static bool regdb_key_exists(struct db_context *db, const char *key) { TALLOC_CTX *mem_ctx = talloc_stackframe(); TDB_DATA value; @@ -1322,11 +1420,11 @@ static bool regdb_key_exists(const char *key) p = strrchr(path, '/'); if (p == NULL) { /* this is a base key */ - value = regdb_fetch_key_internal(mem_ctx, path); + value = regdb_fetch_key_internal(db, mem_ctx, path); ret = (value.dptr != NULL); } else { *p = '\0'; - ret = scan_parent_subkeys(path, p+1); + ret = scan_parent_subkeys(db, path, p+1); } done: @@ -1340,35 +1438,36 @@ done: released by the caller. ***********************************************************************/ -int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr) +static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key, + struct regsubkey_ctr *ctr) { WERROR werr; - uint32 num_items; + uint32_t num_items; uint8 *buf; uint32 buflen, len; int i; fstring subkeyname; - int ret = -1; TALLOC_CTX *frame = talloc_stackframe(); TDB_DATA value; DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL")); - if (!regdb_key_exists(key)) { - goto done; - } + frame = talloc_stackframe(); - werr = regsubkey_ctr_set_seqnum(ctr, regdb_get_seqnum()); - if (!W_ERROR_IS_OK(werr)) { + if (!regdb_key_exists(db, key)) { + DEBUG(10, ("key [%s] not found\n", key)); + werr = WERR_NOT_FOUND; goto done; } - value = regdb_fetch_key_internal(frame, key); + werr = regsubkey_ctr_set_seqnum(ctr, db->get_seqnum(db)); + W_ERROR_NOT_OK_GOTO_DONE(werr); + + value = regdb_fetch_key_internal(db, frame, key); if (value.dptr == NULL) { DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n", key)); - ret = 0; goto done; } @@ -1376,22 +1475,37 @@ int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr) buflen = value.dsize; len = tdb_unpack( buf, buflen, "d", &num_items); + werr = regsubkey_ctr_reinit(ctr); + W_ERROR_NOT_OK_GOTO_DONE(werr); + for (i=0; i<num_items; i++) { len += tdb_unpack(buf+len, buflen-len, "f", subkeyname); werr = regsubkey_ctr_addkey(ctr, subkeyname); if (!W_ERROR_IS_OK(werr)) { DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey " "failed: %s\n", win_errstr(werr))); + num_items = 0; goto done; } } DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items)); - ret = num_items; done: TALLOC_FREE(frame); - return ret; + return werr; +} + +int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr) +{ + WERROR werr; + + werr = regdb_fetch_keys_internal(regdb, key, ctr); + if (!W_ERROR_IS_OK(werr)) { + return -1; + } + + return regsubkey_ctr_numkeys(ctr); } /**************************************************************************** @@ -1478,7 +1592,8 @@ static int regdb_pack_values(struct regval_ctr *values, uint8 *buf, int buflen) released by the caller. ***********************************************************************/ -int regdb_fetch_values(const char* key, struct regval_ctr *values) +static int regdb_fetch_values_internal(struct db_context *db, const char* key, + struct regval_ctr *values) { char *keystr = NULL; TALLOC_CTX *ctx = talloc_stackframe(); @@ -1487,7 +1602,7 @@ int regdb_fetch_values(const char* key, struct regval_ctr *values) DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key)); - if (!regdb_key_exists(key)) { + if (!regdb_key_exists(db, key)) { goto done; } @@ -1496,9 +1611,9 @@ int regdb_fetch_values(const char* key, struct regval_ctr *values) goto done; } - values->seqnum = regdb_get_seqnum(); + values->seqnum = db->get_seqnum(db); - value = regdb_fetch_key_internal(ctx, keystr); + value = regdb_fetch_key_internal(db, ctx, keystr); if (!value.dptr) { /* all keys have zero values by default */ @@ -1513,7 +1628,13 @@ done: return ret; } -bool regdb_store_values(const char *key, struct regval_ctr *values) +int regdb_fetch_values(const char* key, struct regval_ctr *values) +{ + return regdb_fetch_values_internal(regdb, key, values); +} + +static bool regdb_store_values_internal(struct db_context *db, const char *key, + struct regval_ctr *values) { TDB_DATA old_data, data; char *keystr = NULL; @@ -1524,7 +1645,7 @@ bool regdb_store_values(const char *key, struct regval_ctr *values) DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key)); - if (!regdb_key_exists(key)) { + if (!regdb_key_exists(db, key)) { goto done; } @@ -1552,7 +1673,7 @@ bool regdb_store_values(const char *key, struct regval_ctr *values) goto done; } - old_data = dbwrap_fetch_bystring(regdb, ctx, keystr); + old_data = dbwrap_fetch_bystring(db, ctx, keystr); if ((old_data.dptr != NULL) && (old_data.dsize == data.dsize) @@ -1562,7 +1683,7 @@ bool regdb_store_values(const char *key, struct regval_ctr *values) goto done; } - status = dbwrap_trans_store_bystring(regdb, keystr, data, TDB_REPLACE); + status = dbwrap_trans_store_bystring(db, keystr, data, TDB_REPLACE); result = NT_STATUS_IS_OK(status); @@ -1571,6 +1692,11 @@ done: return result; } +bool regdb_store_values(const char *key, struct regval_ctr *values) +{ + return regdb_store_values_internal(regdb, key, values); +} + static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key, struct security_descriptor **psecdesc) { @@ -1582,7 +1708,7 @@ static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key, DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key)); - if (!regdb_key_exists(key)) { + if (!regdb_key_exists(regdb, key)) { err = WERR_BADFILE; goto done; } @@ -1622,7 +1748,7 @@ static WERROR regdb_set_secdesc(const char *key, WERROR err = WERR_NOMEM; TDB_DATA tdbdata; - if (!regdb_key_exists(key)) { + if (!regdb_key_exists(regdb, key)) { err = WERR_BADFILE; goto done; } diff --git a/source3/registry/reg_backend_netlogon_params.c b/source3/registry/reg_backend_netlogon_params.c index 682c7fe9a5..6fc87efb1d 100644 --- a/source3/registry/reg_backend_netlogon_params.c +++ b/source3/registry/reg_backend_netlogon_params.c @@ -35,7 +35,7 @@ static int netlogon_params_fetch_values(const char *key, struct regval_ctr *regv { uint32 dwValue; - if (!pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue)) { + if (!pdb_get_account_policy(PDB_POLICY_REFUSE_MACHINE_PW_CHANGE, &dwValue)) { dwValue = 0; } diff --git a/source3/registry/reg_objects.c b/source3/registry/reg_objects.c index 5ae1cd8aa7..0c0455aada 100644 --- a/source3/registry/reg_objects.c +++ b/source3/registry/reg_objects.c @@ -63,6 +63,29 @@ WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr) return WERR_OK; } +/** + * re-initialize the list of subkeys (to the emtpy list) + * in an already allocated regsubkey_ctr + */ + +WERROR regsubkey_ctr_reinit(struct regsubkey_ctr *ctr) +{ + if (ctr == NULL) { + return WERR_INVALID_PARAM; + } + + talloc_free(ctr->subkeys_hash); + ctr->subkeys_hash = db_open_rbt(ctr); + W_ERROR_HAVE_NO_MEMORY(ctr->subkeys_hash); + + TALLOC_FREE(ctr->subkeys); + + ctr->num_subkeys = 0; + ctr->seqnum = 0; + + return WERR_OK; +} + WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum) { if (ctr == NULL) { @@ -89,7 +112,7 @@ static WERROR regsubkey_ctr_hash_keyname(struct regsubkey_ctr *ctr, { WERROR werr; - werr = ntstatus_to_werror(dbwrap_store_bystring(ctr->subkeys_hash, + werr = ntstatus_to_werror(dbwrap_store_bystring_upper(ctr->subkeys_hash, keyname, make_tdb_data((uint8 *)&idx, sizeof(idx)), @@ -107,7 +130,7 @@ static WERROR regsubkey_ctr_unhash_keyname(struct regsubkey_ctr *ctr, { WERROR werr; - werr = ntstatus_to_werror(dbwrap_delete_bystring(ctr->subkeys_hash, + werr = ntstatus_to_werror(dbwrap_delete_bystring_upper(ctr->subkeys_hash, keyname)); if (!W_ERROR_IS_OK(werr)) { DEBUG(1, ("error unhashing key '%s' in container: %s\n", @@ -127,7 +150,7 @@ static WERROR regsubkey_ctr_index_for_keyname(struct regsubkey_ctr *ctr, return WERR_INVALID_PARAM; } - data = dbwrap_fetch_bystring(ctr->subkeys_hash, ctr, keyname); + data = dbwrap_fetch_bystring_upper(ctr->subkeys_hash, ctr, keyname); if (data.dptr == NULL) { return WERR_NOT_FOUND; } diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 0f4829dec3..621ccf4bc9 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -637,42 +637,6 @@ bool prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) } /******************************************************************* - Stream a uint16* (allocate memory if unmarshalling) - ********************************************************************/ - -bool prs_pointer( const char *name, prs_struct *ps, int depth, - void *dta, size_t data_size, - bool (*prs_fn)(const char*, prs_struct*, int, void*) ) -{ - void ** data = (void **)dta; - uint32 data_p; - - /* output f000baaa to stream if the pointer is non-zero. */ - - data_p = *data ? 0xf000baaa : 0; - - if ( !prs_uint32("ptr", ps, depth, &data_p )) - return False; - - /* we're done if there is no data */ - - if ( !data_p ) - return True; - - if (UNMARSHALLING(ps)) { - if (data_size) { - if ( !(*data = PRS_ALLOC_MEM(ps, char, data_size)) ) - return False; - } else { - *data = NULL; - } - } - - return prs_fn(name, ps, depth, *data); -} - - -/******************************************************************* Stream a uint16. ********************************************************************/ @@ -784,36 +748,6 @@ bool prs_uint64(const char *name, prs_struct *ps, int depth, uint64 *data64) } /******************************************************************* - Stream a NTSTATUS - ********************************************************************/ - -bool prs_ntstatus(const char *name, prs_struct *ps, int depth, NTSTATUS *status) -{ - char *q = prs_mem_get(ps, sizeof(uint32)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) - *status = NT_STATUS(RIVAL(q,0)); - else - *status = NT_STATUS(IVAL(q,0)); - } else { - if (ps->bigendian_data) - RSIVAL(q,0,NT_STATUS_V(*status)); - else - SIVAL(q,0,NT_STATUS_V(*status)); - } - - DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, - nt_errstr(*status))); - - ps->data_offset += sizeof(uint32); - - return True; -} - -/******************************************************************* Stream a DCE error code ********************************************************************/ @@ -843,38 +777,6 @@ bool prs_dcerpc_status(const char *name, prs_struct *ps, int depth, NTSTATUS *st return True; } - -/******************************************************************* - Stream a WERROR - ********************************************************************/ - -bool prs_werror(const char *name, prs_struct *ps, int depth, WERROR *status) -{ - char *q = prs_mem_get(ps, sizeof(uint32)); - if (q == NULL) - return False; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) - *status = W_ERROR(RIVAL(q,0)); - else - *status = W_ERROR(IVAL(q,0)); - } else { - if (ps->bigendian_data) - RSIVAL(q,0,W_ERROR_V(*status)); - else - SIVAL(q,0,W_ERROR_V(*status)); - } - - DEBUGADD(5,("%s%04x %s: %s\n", tab_depth(5,depth), ps->data_offset, name, - win_errstr(*status))); - - ps->data_offset += sizeof(uint32); - - return True; -} - - /****************************************************************** Stream an array of uint8s. Length is number of uint8s. ********************************************************************/ @@ -952,60 +854,6 @@ bool prs_uint16s(bool charmode, const char *name, prs_struct *ps, int depth, uin } /****************************************************************** - Start using a function for streaming unicode chars. If unmarshalling, - output must be little-endian, if marshalling, input must be little-endian. - ********************************************************************/ - -static void dbg_rw_punival(bool charmode, const char *name, int depth, prs_struct *ps, - char *in_buf, char *out_buf, int len) -{ - int i; - - if (UNMARSHALLING(ps)) { - if (ps->bigendian_data) { - for (i = 0; i < len; i++) - SSVAL(out_buf,2*i,RSVAL(in_buf, 2*i)); - } else { - for (i = 0; i < len; i++) - SSVAL(out_buf, 2*i, SVAL(in_buf, 2*i)); - } - } else { - if (ps->bigendian_data) { - for (i = 0; i < len; i++) - RSSVAL(in_buf, 2*i, SVAL(out_buf,2*i)); - } else { - for (i = 0; i < len; i++) - SSVAL(in_buf, 2*i, SVAL(out_buf,2*i)); - } - } - - DEBUGADD(5,("%s%04x %s: ", tab_depth(5,depth), ps->data_offset, name)); - if (charmode) - print_asc(5, (unsigned char*)out_buf, 2*len); - else { - for (i = 0; i < len; i++) - DEBUGADD(5,("%04x ", out_buf[i])); - } - DEBUGADD(5,("\n")); -} - -/****************************************************************** - Stream a unistr. Always little endian. - ********************************************************************/ - -bool prs_uint16uni(bool charmode, const char *name, prs_struct *ps, int depth, uint16 *data16s, int len) -{ - char *q = prs_mem_get(ps, len * sizeof(uint16)); - if (q == NULL) - return False; - - dbg_rw_punival(charmode, name, depth, ps, q, (char *)data16s, len); - ps->data_offset += (len * sizeof(uint16)); - - return True; -} - -/****************************************************************** Stream an array of uint32s. Length is number of uint32s. ********************************************************************/ @@ -1216,172 +1064,6 @@ bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_ return True; } -bool prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str) -{ - size_t len; - char *tmp_str; - - if (UNMARSHALLING(ps)) { - len = strlen(&ps->data_p[ps->data_offset]); - } else { - len = strlen(*str); - } - - tmp_str = PRS_ALLOC_MEM(ps, char, len+1); - - if (tmp_str == NULL) { - return False; - } - - if (MARSHALLING(ps)) { - strncpy(tmp_str, *str, len); - } - - if (!prs_string(name, ps, depth, tmp_str, len+1)) { - return False; - } - - *str = tmp_str; - return True; -} - -/******************************************************************* - prs_uint16 wrapper. Call this and it sets up a pointer to where the - uint16 should be stored, or gets the size if reading. - ********************************************************************/ - -bool prs_uint16_pre(const char *name, prs_struct *ps, int depth, uint16 *data16, uint32 *offset) -{ - *offset = ps->data_offset; - if (UNMARSHALLING(ps)) { - /* reading. */ - return prs_uint16(name, ps, depth, data16); - } else { - char *q = prs_mem_get(ps, sizeof(uint16)); - if(q ==NULL) - return False; - ps->data_offset += sizeof(uint16); - } - return True; -} - -/******************************************************************* - prs_uint16 wrapper. call this and it retrospectively stores the size. - does nothing on reading, as that is already handled by ...._pre() - ********************************************************************/ - -bool prs_uint16_post(const char *name, prs_struct *ps, int depth, uint16 *data16, - uint32 ptr_uint16, uint32 start_offset) -{ - if (MARSHALLING(ps)) { - /* - * Writing - temporarily move the offset pointer. - */ - uint16 data_size = ps->data_offset - start_offset; - uint32 old_offset = ps->data_offset; - - ps->data_offset = ptr_uint16; - if(!prs_uint16(name, ps, depth, &data_size)) { - ps->data_offset = old_offset; - return False; - } - ps->data_offset = old_offset; - } else { - ps->data_offset = start_offset + (uint32)(*data16); - } - return True; -} - -/******************************************************************* - prs_uint32 wrapper. Call this and it sets up a pointer to where the - uint32 should be stored, or gets the size if reading. - ********************************************************************/ - -bool prs_uint32_pre(const char *name, prs_struct *ps, int depth, uint32 *data32, uint32 *offset) -{ - *offset = ps->data_offset; - if (UNMARSHALLING(ps) && (data32 != NULL)) { - /* reading. */ - return prs_uint32(name, ps, depth, data32); - } else { - ps->data_offset += sizeof(uint32); - } - return True; -} - -/******************************************************************* - prs_uint32 wrapper. call this and it retrospectively stores the size. - does nothing on reading, as that is already handled by ...._pre() - ********************************************************************/ - -bool prs_uint32_post(const char *name, prs_struct *ps, int depth, uint32 *data32, - uint32 ptr_uint32, uint32 data_size) -{ - if (MARSHALLING(ps)) { - /* - * Writing - temporarily move the offset pointer. - */ - uint32 old_offset = ps->data_offset; - ps->data_offset = ptr_uint32; - if(!prs_uint32(name, ps, depth, &data_size)) { - ps->data_offset = old_offset; - return False; - } - ps->data_offset = old_offset; - } - return True; -} - -/* useful function to store a structure in rpc wire format */ -int tdb_prs_store(TDB_CONTEXT *tdb, TDB_DATA kbuf, prs_struct *ps) -{ - TDB_DATA dbuf; - dbuf.dptr = (uint8 *)ps->data_p; - dbuf.dsize = prs_offset(ps); - return tdb_trans_store(tdb, kbuf, dbuf, TDB_REPLACE); -} - -/* useful function to fetch a structure into rpc wire format */ -int tdb_prs_fetch(TDB_CONTEXT *tdb, TDB_DATA kbuf, prs_struct *ps, TALLOC_CTX *mem_ctx) -{ - TDB_DATA dbuf; - - prs_init_empty(ps, mem_ctx, UNMARSHALL); - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - return -1; - - prs_give_memory(ps, (char *)dbuf.dptr, dbuf.dsize, True); - - return 0; -} - -/******************************************************************* - hash a stream. - ********************************************************************/ - -bool prs_hash1(prs_struct *ps, uint32 offset, int len) -{ - char *q; - - q = ps->data_p; - q = &q[offset]; - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("prs_hash1\n")); - dump_data(100, (uint8 *)ps->sess_key, 16); - dump_data(100, (uint8 *)q, len); -#endif - arcfour_crypt((uchar *) q, (const unsigned char *)ps->sess_key, len); - -#ifdef DEBUG_PASSWORD - dump_data(100, (uint8 *)q, len); -#endif - - return True; -} - /******************************************************************* Create a digest over the entire packet (including the data), and MD5 it with the session key. diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 324483b3ee..ace045cfa5 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -349,7 +349,9 @@ NTSTATUS _lsa_OpenPolicy2(pipes_struct *p, NTSTATUS status; /* Work out max allowed. */ - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); /* map the generic bits to the lsa policy ones */ se_map_generic(&des_access, &lsa_policy_mapping); @@ -503,6 +505,7 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p, const char *name; DOM_SID *sid = NULL; union lsa_PolicyInformation *info = NULL; + uint32_t acc_required = 0; if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) return NT_STATUS_INVALID_HANDLE; @@ -511,6 +514,47 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p, return NT_STATUS_INVALID_HANDLE; } + switch (r->in.level) { + case LSA_POLICY_INFO_AUDIT_LOG: + case LSA_POLICY_INFO_AUDIT_EVENTS: + acc_required = LSA_POLICY_VIEW_AUDIT_INFORMATION; + break; + case LSA_POLICY_INFO_DOMAIN: + acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION; + break; + case LSA_POLICY_INFO_PD: + acc_required = LSA_POLICY_GET_PRIVATE_INFORMATION; + break; + case LSA_POLICY_INFO_ACCOUNT_DOMAIN: + acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION; + break; + case LSA_POLICY_INFO_ROLE: + case LSA_POLICY_INFO_REPLICA: + acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION; + break; + case LSA_POLICY_INFO_QUOTA: + acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION; + break; + case LSA_POLICY_INFO_MOD: + case LSA_POLICY_INFO_AUDIT_FULL_SET: + /* according to MS-LSAD 3.1.4.4.3 */ + return NT_STATUS_INVALID_PARAMETER; + case LSA_POLICY_INFO_AUDIT_FULL_QUERY: + acc_required = LSA_POLICY_VIEW_AUDIT_INFORMATION; + break; + case LSA_POLICY_INFO_DNS: + case LSA_POLICY_INFO_DNS_INT: + case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN: + acc_required = LSA_POLICY_VIEW_LOCAL_INFORMATION; + break; + default: + break; + } + + if (!(handle->access & acc_required)) { + /* return NT_STATUS_ACCESS_DENIED; */ + } + info = TALLOC_ZERO_P(p->mem_ctx, union lsa_PolicyInformation); if (!info) { return NT_STATUS_NO_MEMORY; @@ -618,7 +662,8 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p, break; } break; - case LSA_POLICY_INFO_DNS: { + case LSA_POLICY_INFO_DNS: + case LSA_POLICY_INFO_DNS_INT: { struct pdb_domain_info *dominfo; if ((pdb_capabilities() & PDB_CAP_ADS) == 0) { @@ -657,6 +702,28 @@ NTSTATUS _lsa_QueryInfoPolicy(pipes_struct *p, } /*************************************************************************** + _lsa_QueryInfoPolicy2 + ***************************************************************************/ + +NTSTATUS _lsa_QueryInfoPolicy2(pipes_struct *p, + struct lsa_QueryInfoPolicy2 *r2) +{ + struct lsa_QueryInfoPolicy r; + + if ((pdb_capabilities() & PDB_CAP_ADS) == 0) { + p->rng_fault_state = True; + return NT_STATUS_NOT_IMPLEMENTED; + } + + ZERO_STRUCT(r); + r.in.handle = r2->in.handle; + r.in.level = r2->in.level; + r.out.info = r2->out.info; + + return _lsa_QueryInfoPolicy(p, &r); +} + +/*************************************************************************** _lsa_lookup_sids_internal ***************************************************************************/ @@ -1302,12 +1369,22 @@ NTSTATUS _lsa_DeleteObject(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } - status = privilege_delete_account(&info->sid); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("_lsa_DeleteObject: privilege_delete_account gave: %s\n", - nt_errstr(status))); + switch (info->type) { + case LSA_HANDLE_ACCOUNT_TYPE: + status = privilege_delete_account(&info->sid); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("_lsa_DeleteObject: privilege_delete_account gave: %s\n", + nt_errstr(status))); + return status; + } + break; + default: + return NT_STATUS_INVALID_HANDLE; } + close_policy_hnd(p, r->in.handle); + ZERO_STRUCTP(r->out.handle); + return status; } @@ -1560,8 +1637,12 @@ NTSTATUS _lsa_GetUserName(pipes_struct *p, NTSTATUS _lsa_CreateAccount(pipes_struct *p, struct lsa_CreateAccount *r) { + NTSTATUS status; struct lsa_info *handle; struct lsa_info *info; + uint32_t acc_granted; + struct security_descriptor *psd; + uint32_t sd_size; /* find the connection policy handle. */ if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle)) @@ -1573,12 +1654,26 @@ NTSTATUS _lsa_CreateAccount(pipes_struct *p, /* check if the user has enough rights */ - /* - * I don't know if it's the right one. not documented. - * but guessed with rpcclient. - */ - if (!(handle->access & LSA_POLICY_CREATE_ACCOUNT)) + if (!(handle->access & LSA_POLICY_CREATE_ACCOUNT)) { return NT_STATUS_ACCESS_DENIED; + } + + /* map the generic bits to the lsa policy ones */ + se_map_generic(&r->in.access_mask, &lsa_account_mapping); + + status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size, + &lsa_account_mapping, + r->in.sid, LSA_POLICY_ALL_ACCESS); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = access_check_object(psd, p->server_info->ptok, + NULL, 0, r->in.access_mask, + &acc_granted, "_lsa_CreateAccount"); + if (!NT_STATUS_IS_OK(status)) { + return status; + } if ( is_privileged_sid( r->in.sid ) ) return NT_STATUS_OBJECT_NAME_COLLISION; @@ -1591,7 +1686,7 @@ NTSTATUS _lsa_CreateAccount(pipes_struct *p, } info->sid = *r->in.sid; - info->access = r->in.access_mask; + info->access = acc_granted; info->type = LSA_HANDLE_ACCOUNT_TYPE; /* get a (unique) handle. open a policy on it. */ @@ -1628,7 +1723,9 @@ NTSTATUS _lsa_OpenAccount(pipes_struct *p, * handle - so don't check against policy handle. */ /* Work out max allowed. */ - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); /* map the generic bits to the lsa account ones */ se_map_generic(&des_access, &lsa_account_mapping); @@ -1913,6 +2010,51 @@ NTSTATUS _lsa_RemovePrivilegesFromAccount(pipes_struct *p, } /*************************************************************************** + _lsa_LookupPrivName + ***************************************************************************/ + +NTSTATUS _lsa_LookupPrivName(pipes_struct *p, + struct lsa_LookupPrivName *r) +{ + struct lsa_info *info = NULL; + const char *name; + struct lsa_StringLarge *lsa_name; + + /* find the connection policy handle. */ + if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info)) { + return NT_STATUS_INVALID_HANDLE; + } + + if (info->type != LSA_HANDLE_POLICY_TYPE) { + return NT_STATUS_INVALID_HANDLE; + } + + if (!(info->access & LSA_POLICY_VIEW_LOCAL_INFORMATION)) { + return NT_STATUS_ACCESS_DENIED; + } + + name = luid_to_privilege_name((LUID *)r->in.luid); + if (!name) { + return NT_STATUS_NO_SUCH_PRIVILEGE; + } + + lsa_name = TALLOC_ZERO_P(p->mem_ctx, struct lsa_StringLarge); + if (!lsa_name) { + return NT_STATUS_NO_MEMORY; + } + + lsa_name->string = talloc_strdup(lsa_name, name); + if (!lsa_name->string) { + TALLOC_FREE(lsa_name); + return NT_STATUS_NO_MEMORY; + } + + *r->out.name = lsa_name; + + return NT_STATUS_OK; +} + +/*************************************************************************** _lsa_QuerySecurity ***************************************************************************/ @@ -1943,19 +2085,9 @@ NTSTATUS _lsa_QuerySecurity(pipes_struct *p, return status; } - switch (r->in.sec_info) { - case 1: - /* SD contains only the owner */ - if((*r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) - return NT_STATUS_NO_MEMORY; - break; - case 4: - /* SD contains only the ACL */ - if((*r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd)) == NULL) - return NT_STATUS_NO_MEMORY; - break; - default: - return NT_STATUS_INVALID_LEVEL; + *r->out.sdbuf = make_sec_desc_buf(p->mem_ctx, sd_size, psd); + if (!*r->out.sdbuf) { + return NT_STATUS_NO_MEMORY; } return status; @@ -2242,18 +2374,79 @@ NTSTATUS _lsa_LookupPrivValue(pipes_struct *p, return NT_STATUS_OK; } +/*************************************************************************** + _lsa_EnumAccountsWithUserRight + ***************************************************************************/ + +NTSTATUS _lsa_EnumAccountsWithUserRight(pipes_struct *p, + struct lsa_EnumAccountsWithUserRight *r) +{ + NTSTATUS status; + struct lsa_info *info = NULL; + struct dom_sid *sids = NULL; + int num_sids = 0; + uint32_t i; + SE_PRIV mask; + + if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info)) { + return NT_STATUS_INVALID_HANDLE; + } + + if (info->type != LSA_HANDLE_POLICY_TYPE) { + return NT_STATUS_INVALID_HANDLE; + } + + if (!(info->access & LSA_POLICY_LOOKUP_NAMES)) { + return NT_STATUS_ACCESS_DENIED; + } + + if (!r->in.name || !r->in.name->string) { + return NT_STATUS_NO_SUCH_PRIVILEGE; + } + + if (!se_priv_from_name(r->in.name->string, &mask)) { + return NT_STATUS_NO_SUCH_PRIVILEGE; + } + + status = privilege_enum_sids(&mask, p->mem_ctx, + &sids, &num_sids); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + r->out.sids->num_sids = num_sids; + r->out.sids->sids = talloc_array(p->mem_ctx, struct lsa_SidPtr, + r->out.sids->num_sids); + + for (i=0; i < r->out.sids->num_sids; i++) { + r->out.sids->sids[i].sid = sid_dup_talloc(r->out.sids->sids, + &sids[i]); + if (!r->out.sids->sids[i].sid) { + TALLOC_FREE(r->out.sids->sids); + r->out.sids->num_sids = 0; + return NT_STATUS_NO_MEMORY; + } + } + + return NT_STATUS_OK; +} + +/*************************************************************************** + _lsa_Delete + ***************************************************************************/ + +NTSTATUS _lsa_Delete(pipes_struct *p, + struct lsa_Delete *r) +{ + return NT_STATUS_NOT_SUPPORTED; +} + /* * From here on the server routines are just dummy ones to make smbd link with * librpc/gen_ndr/srv_lsa.c. These routines are actually never called, we are * pulling the server stubs across one by one. */ -NTSTATUS _lsa_Delete(pipes_struct *p, struct lsa_Delete *r) -{ - p->rng_fault_state = True; - return NT_STATUS_NOT_IMPLEMENTED; -} - NTSTATUS _lsa_SetSecObj(pipes_struct *p, struct lsa_SetSecObj *r) { p->rng_fault_state = True; @@ -2308,18 +2501,6 @@ NTSTATUS _lsa_QuerySecret(pipes_struct *p, struct lsa_QuerySecret *r) return NT_STATUS_NOT_IMPLEMENTED; } -NTSTATUS _lsa_LookupPrivName(pipes_struct *p, struct lsa_LookupPrivName *r) -{ - p->rng_fault_state = True; - return NT_STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS _lsa_EnumAccountsWithUserRight(pipes_struct *p, struct lsa_EnumAccountsWithUserRight *r) -{ - p->rng_fault_state = True; - return NT_STATUS_NOT_IMPLEMENTED; -} - NTSTATUS _lsa_QueryTrustedDomainInfoBySid(pipes_struct *p, struct lsa_QueryTrustedDomainInfoBySid *r) { p->rng_fault_state = True; @@ -2350,24 +2531,6 @@ NTSTATUS _lsa_RetrievePrivateData(pipes_struct *p, struct lsa_RetrievePrivateDat return NT_STATUS_NOT_IMPLEMENTED; } -NTSTATUS _lsa_QueryInfoPolicy2(pipes_struct *p, - struct lsa_QueryInfoPolicy2 *r2) -{ - struct lsa_QueryInfoPolicy r; - - if ((pdb_capabilities() & PDB_CAP_ADS) == 0) { - p->rng_fault_state = True; - return NT_STATUS_NOT_IMPLEMENTED; - } - - ZERO_STRUCT(r); - r.in.handle = r2->in.handle; - r.in.level = r2->in.level; - r.out.info = r2->out.info; - - return _lsa_QueryInfoPolicy(p, &r); -} - NTSTATUS _lsa_SetInfoPolicy2(pipes_struct *p, struct lsa_SetInfoPolicy2 *r) { p->rng_fault_state = True; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 8560ee97c6..b27603f261 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -236,8 +236,9 @@ done: Map any MAXIMUM_ALLOWED_ACCESS request to a valid access set. ********************************************************************/ -void map_max_allowed_access(const NT_USER_TOKEN *token, - uint32_t *pacc_requested) +void map_max_allowed_access(const NT_USER_TOKEN *nt_token, + const struct unix_user_token *unix_token, + uint32_t *pacc_requested) { if (!((*pacc_requested) & MAXIMUM_ALLOWED_ACCESS)) { return; @@ -248,15 +249,15 @@ void map_max_allowed_access(const NT_USER_TOKEN *token, *pacc_requested = GENERIC_READ_ACCESS|GENERIC_EXECUTE_ACCESS; /* root gets anything. */ - if (geteuid() == sec_initial_uid()) { + if (unix_token->uid == sec_initial_uid()) { *pacc_requested |= GENERIC_ALL_ACCESS; return; } /* Full Access for 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ - if (is_sid_in_token(token, &global_sid_Builtin_Administrators) || - is_sid_in_token(token, &global_sid_Builtin_Account_Operators)) { + if (is_sid_in_token(nt_token, &global_sid_Builtin_Administrators) || + is_sid_in_token(nt_token, &global_sid_Builtin_Account_Operators)) { *pacc_requested |= GENERIC_ALL_ACCESS; return; } @@ -266,7 +267,7 @@ void map_max_allowed_access(const NT_USER_TOKEN *token, DOM_SID domadmin_sid; sid_copy( &domadmin_sid, get_global_sam_sid() ); sid_append_rid( &domadmin_sid, DOMAIN_GROUP_RID_ADMINS ); - if (is_sid_in_token(token, &domadmin_sid)) { + if (is_sid_in_token(nt_token, &domadmin_sid)) { *pacc_requested |= GENERIC_ALL_ACCESS; return; } @@ -550,7 +551,9 @@ NTSTATUS _samr_OpenDomain(pipes_struct *p, } /*check if access can be granted as requested by client. */ - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); make_samr_object_sd( p->mem_ctx, &psd, &sd_size, &dom_generic_mapping, NULL, 0 ); se_map_generic( &des_access, &dom_generic_mapping ); @@ -636,9 +639,9 @@ NTSTATUS _samr_GetUserPwInfo(pipes_struct *p, switch (sid_type) { case SID_NAME_USER: become_root(); - pdb_get_account_policy(AP_MIN_PASSWORD_LEN, + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &min_password_length); - pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, &password_properties); unbecome_root(); @@ -2076,19 +2079,19 @@ NTSTATUS _samr_ChangePasswordUser3(pipes_struct *p, /* AS ROOT !!! */ - pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &tmp); + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &tmp); dominfo->min_password_length = tmp; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &tmp); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &tmp); dominfo->password_history_length = tmp; - pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, &dominfo->password_properties); - pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp); u_expire = account_policy_temp; - pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp); u_min_age = account_policy_temp; /* !AS ROOT */ @@ -2260,8 +2263,9 @@ NTSTATUS _samr_OpenUser(pipes_struct *p, return NT_STATUS_NO_SUCH_USER; /* check if access can be granted as requested by client. */ - - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); se_map_generic(&des_access, &usr_generic_mapping); @@ -3301,19 +3305,19 @@ static NTSTATUS query_dom_info_1(TALLOC_CTX *mem_ctx, /* AS ROOT !!! */ - pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &account_policy_temp); r->min_password_length = account_policy_temp; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &account_policy_temp); r->password_history_length = account_policy_temp; - pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, &r->password_properties); - pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp); u_expire = account_policy_temp; - pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp); u_min_age = account_policy_temp; /* !AS ROOT */ @@ -3348,7 +3352,7 @@ static NTSTATUS query_dom_info_2(TALLOC_CTX *mem_ctx, r->num_groups = count_sam_groups(dinfo->disp_info); r->num_aliases = count_sam_aliases(dinfo->disp_info); - pdb_get_account_policy(AP_TIME_TO_LOGOUT, &u_logout); + pdb_get_account_policy(PDB_POLICY_TIME_TO_LOGOUT, &u_logout); unix_to_nt_time_abs(&r->force_logoff_time, u_logout); @@ -3385,7 +3389,7 @@ static NTSTATUS query_dom_info_3(TALLOC_CTX *mem_ctx, { uint32_t ul; - pdb_get_account_policy(AP_TIME_TO_LOGOUT, &ul); + pdb_get_account_policy(PDB_POLICY_TIME_TO_LOGOUT, &ul); u_logout = (time_t)ul; } @@ -3502,16 +3506,16 @@ static NTSTATUS query_dom_info_11(TALLOC_CTX *mem_ctx, become_root(); - pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &account_policy_temp); u_lock_duration = account_policy_temp; if (u_lock_duration != -1) { u_lock_duration *= 60; } - pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &account_policy_temp); u_reset_time = account_policy_temp * 60; - pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); r->lockout_threshold = account_policy_temp; /* !AS ROOT */ @@ -3537,16 +3541,16 @@ static NTSTATUS query_dom_info_12(TALLOC_CTX *mem_ctx, /* AS ROOT !!! */ - pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, &account_policy_temp); u_lock_duration = account_policy_temp; if (u_lock_duration != -1) { u_lock_duration *= 60; } - pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_RESET_COUNT_TIME, &account_policy_temp); u_reset_time = account_policy_temp * 60; - pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); + pdb_get_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); r->lockout_threshold = account_policy_temp; /* !AS ROOT */ @@ -3834,7 +3838,9 @@ NTSTATUS _samr_CreateUser2(pipes_struct *p, sid_compose(&sid, get_global_sam_sid(), *r->out.rid); - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW); @@ -3914,7 +3920,9 @@ NTSTATUS _samr_Connect(pipes_struct *p, was observed from a win98 client trying to enumerate users (when configured user level access control on shares) --jerry */ - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); se_map_generic( &des_access, &sam_generic_mapping ); @@ -3974,7 +3982,9 @@ NTSTATUS _samr_Connect2(pipes_struct *p, return NT_STATUS_ACCESS_DENIED; } - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &sam_generic_mapping, NULL, 0); se_map_generic(&des_access, &sam_generic_mapping); @@ -4187,7 +4197,9 @@ NTSTATUS _samr_OpenAlias(pipes_struct *p, /*check if access can be granted as requested by client. */ - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &ali_generic_mapping, NULL, 0); se_map_generic(&des_access,&ali_generic_mapping); @@ -6193,9 +6205,9 @@ NTSTATUS _samr_GetDomPwInfo(pipes_struct *p, } become_root(); - pdb_get_account_policy(AP_MIN_PASSWORD_LEN, + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &min_password_length); - pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, &password_properties); unbecome_root(); @@ -6237,7 +6249,9 @@ NTSTATUS _samr_OpenGroup(pipes_struct *p, } /*check if access can be granted as requested by client. */ - map_max_allowed_access(p->server_info->ptok, &des_access); + map_max_allowed_access(p->server_info->ptok, + &p->server_info->utok, + &des_access); make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &grp_generic_mapping, NULL, 0); se_map_generic(&des_access,&grp_generic_mapping); @@ -6362,14 +6376,14 @@ static NTSTATUS set_dom_info_1(TALLOC_CTX *mem_ctx, u_expire = nt_time_to_unix_abs((NTTIME *)&r->max_password_age); u_min_age = nt_time_to_unix_abs((NTTIME *)&r->min_password_age); - pdb_set_account_policy(AP_MIN_PASSWORD_LEN, + pdb_set_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, (uint32_t)r->min_password_length); - pdb_set_account_policy(AP_PASSWORD_HISTORY, + pdb_set_account_policy(PDB_POLICY_PASSWORD_HISTORY, (uint32_t)r->password_history_length); - pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + pdb_set_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, (uint32_t)r->password_properties); - pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (int)u_expire); - pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (int)u_min_age); + pdb_set_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, (int)u_expire); + pdb_set_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, (int)u_min_age); return NT_STATUS_OK; } @@ -6384,7 +6398,7 @@ static NTSTATUS set_dom_info_3(TALLOC_CTX *mem_ctx, u_logout = nt_time_to_unix_abs((NTTIME *)&r->force_logoff_time); - pdb_set_account_policy(AP_TIME_TO_LOGOUT, (int)u_logout); + pdb_set_account_policy(PDB_POLICY_TIME_TO_LOGOUT, (int)u_logout); return NT_STATUS_OK; } @@ -6404,9 +6418,9 @@ static NTSTATUS set_dom_info_12(TALLOC_CTX *mem_ctx, u_reset_time = nt_time_to_unix_abs((NTTIME *)&r->lockout_window)/60; - pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); - pdb_set_account_policy(AP_RESET_COUNT_TIME, (int)u_reset_time); - pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, + pdb_set_account_policy(PDB_POLICY_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); + pdb_set_account_policy(PDB_POLICY_RESET_COUNT_TIME, (int)u_reset_time); + pdb_set_account_policy(PDB_POLICY_BAD_ATTEMPT_LOCKOUT, (uint32_t)r->lockout_threshold); return NT_STATUS_OK; diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c index 69daa31e9c..1e5988af33 100644 --- a/source3/rpc_server/srv_samr_util.c +++ b/source3/rpc_server/srv_samr_util.c @@ -619,7 +619,7 @@ void copy_id21_to_sam_passwd(const char *log_prefix, uint32_t pwd_max_age = 0; time_t now = time(NULL); - pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &pwd_max_age); + pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &pwd_max_age); if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) { pwd_max_age = get_time_t_max(); diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 9d72168202..9dc1a26e3b 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -261,7 +261,7 @@ static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd) Delete a printer given a handle. ****************************************************************************/ -WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename ) +static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename) { char *cmd = lp_deleteprinter_cmd(); char *command = NULL; @@ -309,7 +309,9 @@ WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sh return WERR_BADFID; /* What to return here? */ /* go ahead and re-read the services immediately */ + become_root(); reload_services(false); + unbecome_root(); if ( lp_servicenumber( sharename ) < 0 ) return WERR_ACCESS_DENIED; @@ -5920,7 +5922,7 @@ static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum) /**************************************************************************** ****************************************************************************/ -WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri ) +static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri) { char *cmd = lp_addport_cmd(); char *command = NULL; @@ -6034,7 +6036,9 @@ bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEV } /* reload our services immediately */ + become_root(); reload_services(false); + unbecome_root(); numlines = 0; /* Get lines and convert them back to dos-codepage */ @@ -7316,7 +7320,7 @@ static WERROR fill_port_2(TALLOC_CTX *mem_ctx, wrapper around the enumer ports command ****************************************************************************/ -WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines ) +static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines) { char *cmd = lp_enumports_cmd(); char **qlines = NULL; diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 44acf4d647..b9d1ed6d73 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -540,11 +540,13 @@ static WERROR init_srv_share_info_ctr(pipes_struct *p, if (lp_browseable(snum) && lp_snum_ok(snum) && is_enumeration_allowed(p, snum) && (all_shares || !is_hidden_share(snum)) ) { - DEBUG(10, ("counting service %s\n", lp_servicename(snum))); + DEBUG(10, ("counting service %s\n", + lp_servicename(snum) ? lp_servicename(snum) : "(null)")); allowed[snum] = true; num_entries++; } else { - DEBUG(10, ("NOT counting service %s\n", lp_servicename(snum))); + DEBUG(10, ("NOT counting service %s\n", + lp_servicename(snum) ? lp_servicename(snum) : "(null)")); } } @@ -2070,8 +2072,7 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, conn, false, r->in.file, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(nt_status)) { werr = ntstatus_to_werror(nt_status); goto error_exit; @@ -2199,8 +2200,7 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, conn, false, r->in.file, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(nt_status)) { werr = ntstatus_to_werror(nt_status); goto error_exit; diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index ef3187579a..d7f8041779 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -1356,6 +1356,366 @@ static NTSTATUS cmd_lsa_del_priv(struct rpc_pipe_client *cli, return result; } +static NTSTATUS cmd_lsa_create_secret(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS status; + struct policy_handle handle, sec_handle; + struct lsa_String name; + + if (argc < 2) { + printf("Usage: %s name\n", argv[0]); + return NT_STATUS_OK; + } + + status = rpccli_lsa_open_policy2(cli, mem_ctx, + true, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + init_lsa_String(&name, argv[1]); + + status = rpccli_lsa_CreateSecret(cli, mem_ctx, + &handle, + name, + SEC_FLAG_MAXIMUM_ALLOWED, + &sec_handle); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + done: + if (is_valid_policy_hnd(&sec_handle)) { + rpccli_lsa_Close(cli, mem_ctx, &sec_handle); + } + if (is_valid_policy_hnd(&handle)) { + rpccli_lsa_Close(cli, mem_ctx, &handle); + } + + return status; +} + +static NTSTATUS cmd_lsa_delete_secret(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS status; + struct policy_handle handle, sec_handle; + struct lsa_String name; + + if (argc < 2) { + printf("Usage: %s name\n", argv[0]); + return NT_STATUS_OK; + } + + status = rpccli_lsa_open_policy2(cli, mem_ctx, + true, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + init_lsa_String(&name, argv[1]); + + status = rpccli_lsa_OpenSecret(cli, mem_ctx, + &handle, + name, + SEC_FLAG_MAXIMUM_ALLOWED, + &sec_handle); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = rpccli_lsa_DeleteObject(cli, mem_ctx, + &sec_handle); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + done: + if (is_valid_policy_hnd(&sec_handle)) { + rpccli_lsa_Close(cli, mem_ctx, &sec_handle); + } + if (is_valid_policy_hnd(&handle)) { + rpccli_lsa_Close(cli, mem_ctx, &handle); + } + + return status; +} + +static NTSTATUS cmd_lsa_query_secret(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS status; + struct policy_handle handle, sec_handle; + struct lsa_String name; + struct lsa_DATA_BUF_PTR new_val; + NTTIME new_mtime = 0; + struct lsa_DATA_BUF_PTR old_val; + NTTIME old_mtime = 0; + DATA_BLOB session_key; + DATA_BLOB new_blob = data_blob_null; + DATA_BLOB old_blob = data_blob_null; + char *new_secret, *old_secret; + + if (argc < 2) { + printf("Usage: %s name\n", argv[0]); + return NT_STATUS_OK; + } + + status = rpccli_lsa_open_policy2(cli, mem_ctx, + true, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + init_lsa_String(&name, argv[1]); + + status = rpccli_lsa_OpenSecret(cli, mem_ctx, + &handle, + name, + SEC_FLAG_MAXIMUM_ALLOWED, + &sec_handle); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + ZERO_STRUCT(new_val); + ZERO_STRUCT(old_val); + + status = rpccli_lsa_QuerySecret(cli, mem_ctx, + &sec_handle, + &new_val, + &new_mtime, + &old_val, + &old_mtime); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = cli_get_session_key(mem_ctx, cli, &session_key); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (new_val.buf) { + new_blob = data_blob_const(new_val.buf->data, new_val.buf->length); + } + if (old_val.buf) { + old_blob = data_blob_const(old_val.buf->data, old_val.buf->length); + } + + new_secret = sess_decrypt_string(mem_ctx, &new_blob, &session_key); + old_secret = sess_decrypt_string(mem_ctx, &old_blob, &session_key); + if (new_secret) { + d_printf("new secret: %s\n", new_secret); + } + if (old_secret) { + d_printf("old secret: %s\n", old_secret); + } + + done: + if (is_valid_policy_hnd(&sec_handle)) { + rpccli_lsa_Close(cli, mem_ctx, &sec_handle); + } + if (is_valid_policy_hnd(&handle)) { + rpccli_lsa_Close(cli, mem_ctx, &handle); + } + + return status; +} + +static NTSTATUS cmd_lsa_set_secret(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS status; + struct policy_handle handle, sec_handle; + struct lsa_String name; + struct lsa_DATA_BUF new_val; + struct lsa_DATA_BUF old_val; + DATA_BLOB enc_key; + DATA_BLOB session_key; + + if (argc < 3) { + printf("Usage: %s name secret\n", argv[0]); + return NT_STATUS_OK; + } + + status = rpccli_lsa_open_policy2(cli, mem_ctx, + true, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + init_lsa_String(&name, argv[1]); + + status = rpccli_lsa_OpenSecret(cli, mem_ctx, + &handle, + name, + SEC_FLAG_MAXIMUM_ALLOWED, + &sec_handle); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + ZERO_STRUCT(new_val); + ZERO_STRUCT(old_val); + + status = cli_get_session_key(mem_ctx, cli, &session_key); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + enc_key = sess_encrypt_string(argv[2], &session_key); + + new_val.length = enc_key.length; + new_val.size = enc_key.length; + new_val.data = enc_key.data; + + status = rpccli_lsa_SetSecret(cli, mem_ctx, + &sec_handle, + &new_val, + NULL); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + done: + if (is_valid_policy_hnd(&sec_handle)) { + rpccli_lsa_Close(cli, mem_ctx, &sec_handle); + } + if (is_valid_policy_hnd(&handle)) { + rpccli_lsa_Close(cli, mem_ctx, &handle); + } + + return status; +} + +static NTSTATUS cmd_lsa_retrieve_private_data(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS status; + struct policy_handle handle; + struct lsa_String name; + struct lsa_DATA_BUF *val; + DATA_BLOB session_key; + DATA_BLOB blob; + char *secret; + + if (argc < 2) { + printf("Usage: %s name\n", argv[0]); + return NT_STATUS_OK; + } + + status = rpccli_lsa_open_policy2(cli, mem_ctx, + true, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + init_lsa_String(&name, argv[1]); + + ZERO_STRUCT(val); + + status = rpccli_lsa_RetrievePrivateData(cli, mem_ctx, + &handle, + &name, + &val); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = cli_get_session_key(mem_ctx, cli, &session_key); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + if (val) { + blob = data_blob_const(val->data, val->length); + } + + secret = sess_decrypt_string(mem_ctx, &blob, &session_key); + if (secret) { + d_printf("secret: %s\n", secret); + } + + done: + if (is_valid_policy_hnd(&handle)) { + rpccli_lsa_Close(cli, mem_ctx, &handle); + } + + return status; +} + +static NTSTATUS cmd_lsa_store_private_data(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS status; + struct policy_handle handle; + struct lsa_String name; + struct lsa_DATA_BUF val; + DATA_BLOB session_key; + DATA_BLOB enc_key; + + if (argc < 3) { + printf("Usage: %s name secret\n", argv[0]); + return NT_STATUS_OK; + } + + status = rpccli_lsa_open_policy2(cli, mem_ctx, + true, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + init_lsa_String(&name, argv[1]); + + ZERO_STRUCT(val); + + status = cli_get_session_key(mem_ctx, cli, &session_key); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + enc_key = sess_encrypt_string(argv[2], &session_key); + + val.length = enc_key.length; + val.size = enc_key.length; + val.data = enc_key.data; + + status = rpccli_lsa_StorePrivateData(cli, mem_ctx, + &handle, + &name, + &val); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + done: + if (is_valid_policy_hnd(&handle)) { + rpccli_lsa_Close(cli, mem_ctx, &handle); + } + + return status; +} + /* List of commands exported by this module */ @@ -1384,6 +1744,12 @@ struct cmd_set lsarpc_commands[] = { { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" }, { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query LSA trusted domains info (given a SID)", "" }, { "getusername", RPC_RTYPE_NTSTATUS, cmd_lsa_get_username, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Get username", "" }, + { "createsecret", RPC_RTYPE_NTSTATUS, cmd_lsa_create_secret, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Create Secret", "" }, + { "deletesecret", RPC_RTYPE_NTSTATUS, cmd_lsa_delete_secret, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Delete Secret", "" }, + { "querysecret", RPC_RTYPE_NTSTATUS, cmd_lsa_query_secret, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Query Secret", "" }, + { "setsecret", RPC_RTYPE_NTSTATUS, cmd_lsa_set_secret, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Set Secret", "" }, + { "retrieveprivatedata", RPC_RTYPE_NTSTATUS, cmd_lsa_retrieve_private_data, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Retrieve Private Data", "" }, + { "storeprivatedata", RPC_RTYPE_NTSTATUS, cmd_lsa_store_private_data, NULL, &ndr_table_lsarpc.syntax_id, NULL, "Store Private Data", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index cbff69ff17..48f9df3cac 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -3430,6 +3430,48 @@ static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli, return werror; } +static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + WERROR result; + NTSTATUS status; + struct policy_handle handle, gdi_handle; + const char *printername; + struct spoolss_DevmodeContainer devmode_ctr; + + RPCCLIENT_PRINTERNAME(printername, cli, argv[1]); + + result = rpccli_spoolss_openprinter_ex(cli, mem_ctx, + printername, + SEC_FLAG_MAXIMUM_ALLOWED, + &handle); + if (!W_ERROR_IS_OK(result)) { + return result; + } + + ZERO_STRUCT(devmode_ctr); + + status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx, + &handle, + &gdi_handle, + &devmode_ctr, + &result); + if (!W_ERROR_IS_OK(result)) { + goto done; + } + + done: + if (is_valid_policy_hnd(&gdi_handle)) { + rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL); + } + if (is_valid_policy_hnd(&handle)) { + rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL); + } + + return result; +} + /* List of commands exported by this module */ struct cmd_set spoolss_commands[] = { @@ -3469,6 +3511,7 @@ struct cmd_set spoolss_commands[] = { { "enumprocs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors", "" }, { "enumprocdatatypes", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" }, { "enummonitors", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" }, + { "createprinteric", RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic, &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" }, { NULL } }; diff --git a/source3/script/tests/test_smbtorture_s3.sh b/source3/script/tests/test_smbtorture_s3.sh index c577ed18d4..602433bd91 100755 --- a/source3/script/tests/test_smbtorture_s3.sh +++ b/source3/script/tests/test_smbtorture_s3.sh @@ -21,6 +21,9 @@ incdir=`dirname $0` . $incdir/test_functions.sh } +SMB_CONF_PATH="$CONFFILE" +export SMB_CONF_PATH + tests="FDPASS LOCK1 LOCK2 LOCK3 LOCK4 LOCK5 LOCK6 LOCK7" #tests="$tests UNLINK BROWSE ATTR TRANS2 MAXFID TORTURE " tests="$tests UNLINK BROWSE ATTR TRANS2 TORTURE " @@ -29,6 +32,7 @@ tests="$tests DIR DIR1 TCON TCONDEV RW1 RW2 RW3" tests="$tests OPEN XCOPY RENAME DELETE PROPERTIES W2K" tests="$tests TCON2 IOCTL CHKPATH FDSESS LOCAL-SUBSTITUTE CHAIN1" tests="$tests GETADDRINFO POSIX UID-REGRESSION-TEST SHORTNAME-TEST" +tests="$tests LOCAL-BASE64 LOCAL-GENCACHE" skipped1="RANDOMIPC NEGNOWAIT NBENCH ERRMAPEXTRACT TRANS2SCAN NTTRANSSCAN" skipped2="DENY1 DENY2 OPENATTR CASETABLE EATEST" diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c6f700f17a..ed415c5e13 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -188,7 +188,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " "offset %.0f, len = %u (mid = %u)\n", - fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, + fsp_str_dbg(fsp), (double)startpos, (unsigned int)smb_maxcnt, (unsigned int)aio_ex->req->mid )); outstanding_aio_calls++; @@ -241,7 +241,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, DEBUG(10,("schedule_aio_write_and_X: failed to schedule " "aio_write for file %s, offset %.0f, len = %u " "(mid = %u)\n", - fsp->fsp_name, (double)startpos, + fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite, (unsigned int)req->mid )); return False; @@ -300,14 +300,14 @@ bool schedule_aio_write_and_X(connection_struct *conn, "failed."); } DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " - "behind for file %s\n", fsp->fsp_name )); + "behind for file %s\n", fsp_str_dbg(fsp))); } outstanding_aio_calls++; DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file " "%s, offset %.0f, len = %u (mid = %u) " "outstanding_aio_calls = %d\n", - fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, + fsp_str_dbg(fsp), (double)startpos, (unsigned int)numtowrite, (unsigned int)aio_ex->req->mid, outstanding_aio_calls )); return True; @@ -341,7 +341,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) DEBUG( 3,( "handle_aio_read_complete: file %s nread == -1. " "Error = %s\n", - aio_ex->fsp->fsp_name, strerror(errno) )); + fsp_str_dbg(aio_ex->fsp), strerror(errno))); ret = errno; ERROR_NT(map_nt_error_from_unix(ret)); @@ -359,7 +359,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) DEBUG( 3, ( "handle_aio_read_complete file %s max=%d " "nread=%d\n", - aio_ex->fsp->fsp_name, + fsp_str_dbg(aio_ex->fsp), (int)aio_ex->acb.aio_nbytes, (int)nread ) ); } @@ -374,7 +374,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) DEBUG(10,("handle_aio_read_complete: scheduled aio_read completed " "for file %s, offset %.0f, len = %u\n", - aio_ex->fsp->fsp_name, (double)aio_ex->acb.aio_offset, + fsp_str_dbg(aio_ex->fsp), (double)aio_ex->acb.aio_offset, (unsigned int)nread )); return ret; @@ -399,13 +399,13 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(5,("handle_aio_write_complete: " "aio_write_behind failed ! File %s " "is corrupt ! Error %s\n", - fsp->fsp_name, strerror(errno) )); + fsp_str_dbg(fsp), strerror(errno))); ret = errno; } else { DEBUG(0,("handle_aio_write_complete: " "aio_write_behind failed ! File %s " "is corrupt ! Wanted %u bytes but " - "only wrote %d\n", fsp->fsp_name, + "only wrote %d\n", fsp_str_dbg(fsp), (unsigned int)numtowrite, (int)nwritten )); ret = EIO; @@ -413,7 +413,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) } else { DEBUG(10,("handle_aio_write_complete: " "aio_write_behind completed for file %s\n", - fsp->fsp_name )); + fsp_str_dbg(fsp))); } return 0; } @@ -424,7 +424,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) if(nwritten == -1) { DEBUG( 3,( "handle_aio_write: file %s wanted %u bytes. " "nwritten == %d. Error = %s\n", - fsp->fsp_name, (unsigned int)numtowrite, + fsp_str_dbg(fsp), (unsigned int)numtowrite, (int)nwritten, strerror(errno) )); /* If errno is ECANCELED then don't return anything to the @@ -456,7 +456,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ERRHRD, ERRdiskfull); srv_set_message(outbuf,0,0,true); DEBUG(5,("handle_aio_write: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); } aio_ex->fsp->fh->pos = aio_ex->acb.aio_offset + nwritten; @@ -472,7 +472,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) DEBUG(10,("handle_aio_write_complete: scheduled aio_write completed " "for file %s, offset %.0f, requested %u, written = %u\n", - fsp->fsp_name, (double)aio_ex->acb.aio_offset, + fsp_str_dbg(fsp), (double)aio_ex->acb.aio_offset, (unsigned int)numtowrite, (unsigned int)nwritten )); return ret; @@ -496,7 +496,7 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { DEBUG(10,( "handle_aio_completed: operation mid %u still in " "process for file %s\n", - aio_ex->req->mid, aio_ex->fsp->fsp_name )); + aio_ex->req->mid, fsp_str_dbg(aio_ex->fsp))); return False; } diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 4c61428692..e752194ca5 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -202,7 +202,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n", (unsigned int)blr->expire_time.tv_sec, (unsigned int)blr->expire_time.tv_usec, lock_timeout, - blr->fsp->fnum, blr->fsp->fsp_name )); + blr->fsp->fnum, fsp_str_dbg(blr->fsp))); return True; } @@ -418,8 +418,9 @@ static bool process_lockingX(struct blocking_lock_record *blr) * Success - we got all the locks. */ - DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", - fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); + DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d " + "num_locks=%d\n", fsp_str_dbg(fsp), fsp->fnum, + (unsigned int)locktype, num_locks)); reply_lockingX_success(blr); return True; @@ -442,7 +443,7 @@ static bool process_lockingX(struct blocking_lock_record *blr) DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ Waiting....\n", - blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); + blr->lock_num, num_locks, fsp_str_dbg(fsp), fsp->fnum)); return False; } @@ -533,7 +534,7 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo DEBUG(10, ("remove_pending_lock_requests_by_fid - removing " "request type %d for file %s fnum = %d\n", - blr->req->cmd, fsp->fsp_name, fsp->fnum)); + blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum)); blr_cancelled = blocking_lock_cancel(fsp, blr->lock_pid, @@ -583,7 +584,7 @@ void remove_pending_lock_requests_by_mid(int mid) if (br_lck) { DEBUG(10, ("remove_pending_lock_requests_by_mid - " "removing request type %d for file %s fnum " - "= %d\n", blr->req->cmd, fsp->fsp_name, + "= %d\n", blr->req->cmd, fsp_str_dbg(fsp), fsp->fnum )); brl_lock_cancel(br_lck, @@ -703,7 +704,7 @@ void process_blocking_lock_queue(void) DEBUG(5,("process_blocking_lock_queue: " "pending lock fnum = %d for file %s " "timed out.\n", blr->fsp->fnum, - blr->fsp->fsp_name )); + fsp_str_dbg(blr->fsp))); brl_lock_cancel(br_lck, blr->lock_pid, diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 2eb09d176d..64f988f1f7 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -1024,7 +1024,7 @@ static bool check_passwd_history(struct samu *sampass, const char *plaintext) int i; uint32 pwHisLen, curr_pwHisLen; - pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { return False; } @@ -1107,7 +1107,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw * denies machines to change the password. * * Should we deny also SRVTRUST and/or DOMSTRUST ? .SSS. */ if (pdb_get_acct_ctrl(hnd) & ACB_WSTRUST) { - if (pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &refuse) && refuse) { + if (pdb_get_account_policy(PDB_POLICY_REFUSE_MACHINE_PW_CHANGE, &refuse) && refuse) { DEBUG(1, ("Machine %s cannot change password now, " "denied by Refuse Machine Password Change policy\n", username)); @@ -1130,7 +1130,7 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCOUNT_RESTRICTION; } - if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { + if (pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); diff --git a/source3/smbd/close.c b/source3/smbd/close.c index a0672f3949..788b0a7cec 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -36,90 +36,99 @@ static NTSTATUS check_magic(struct files_struct *fsp) TALLOC_CTX *ctx = NULL; const char *p; struct connection_struct *conn = fsp->conn; + char *fname = NULL; + NTSTATUS status; if (!*lp_magicscript(SNUM(conn))) { return NT_STATUS_OK; } - DEBUG(5,("checking magic for %s\n",fsp->fsp_name)); + DEBUG(5,("checking magic for %s\n", fsp_str_dbg(fsp))); + + ctx = talloc_stackframe(); - if (!(p = strrchr_m(fsp->fsp_name,'/'))) { - p = fsp->fsp_name; + fname = fsp->fsp_name->base_name; + + if (!(p = strrchr_m(fname,'/'))) { + p = fname; } else { p++; } if (!strequal(lp_magicscript(SNUM(conn)),p)) { - return NT_STATUS_OK; + status = NT_STATUS_OK; + goto out; } - ctx = talloc_stackframe(); - if (*lp_magicoutput(SNUM(conn))) { magic_output = lp_magicoutput(SNUM(conn)); } else { magic_output = talloc_asprintf(ctx, "%s.out", - fsp->fsp_name); + fname); } if (!magic_output) { - TALLOC_FREE(ctx); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto out; } /* Ensure we don't depend on user's PATH. */ - p = talloc_asprintf(ctx, "./%s", fsp->fsp_name); + p = talloc_asprintf(ctx, "./%s", fname); if (!p) { - TALLOC_FREE(ctx); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto out; } - if (chmod(fsp->fsp_name,0755) == -1) { - TALLOC_FREE(ctx); - return map_nt_error_from_unix(errno); + if (chmod(fname, 0755) == -1) { + status = map_nt_error_from_unix(errno); + goto out; } ret = smbrun(p,&tmp_fd); DEBUG(3,("Invoking magic command %s gave %d\n", p,ret)); - unlink(fsp->fsp_name); + unlink(fname); if (ret != 0 || tmp_fd == -1) { if (tmp_fd != -1) { close(tmp_fd); } - TALLOC_FREE(ctx); - return NT_STATUS_UNSUCCESSFUL; + status = NT_STATUS_UNSUCCESSFUL; + goto out; } outfd = open(magic_output, O_CREAT|O_EXCL|O_RDWR, 0600); if (outfd == -1) { int err = errno; close(tmp_fd); - TALLOC_FREE(ctx); - return map_nt_error_from_unix(err); + status = map_nt_error_from_unix(err); + goto out; } if (sys_fstat(tmp_fd,&st) == -1) { int err = errno; close(tmp_fd); close(outfd); - TALLOC_FREE(ctx); - return map_nt_error_from_unix(err); + status = map_nt_error_from_unix(err); + goto out; } if (transfer_file(tmp_fd,outfd,(SMB_OFF_T)st.st_ex_size) == (SMB_OFF_T)-1) { int err = errno; close(tmp_fd); close(outfd); - TALLOC_FREE(ctx); - return map_nt_error_from_unix(err); + status = map_nt_error_from_unix(err); + goto out; } close(tmp_fd); if (close(outfd) == -1) { - TALLOC_FREE(ctx); - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } + + status = NT_STATUS_OK; + + out: TALLOC_FREE(ctx); - return NT_STATUS_OK; + return status; } /**************************************************************************** @@ -261,18 +270,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, bool delete_file = false; bool changed_user = false; struct share_mode_lock *lck = NULL; - struct smb_filename *smb_fname = NULL; - char *fname = NULL; NTSTATUS status = NT_STATUS_OK; int ret; struct file_id id; - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - /* * Lock the share entries, and determine if we should delete * on close. If so delete whilst the lock is still in effect. @@ -284,7 +285,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (lck == NULL) { DEBUG(0, ("close_remove_share_mode: Could not get share mode " - "lock for file %s\n", smb_fname_str_dbg(smb_fname))); + "lock for file %s\n", fsp_str_dbg(fsp))); status = NT_STATUS_INVALID_PARAMETER; goto done; } @@ -296,7 +297,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (!del_share_mode(lck, fsp)) { DEBUG(0, ("close_remove_share_mode: Could not delete share " "entry for file %s\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); } if (fsp->initial_delete_on_close && (lck->delete_token == NULL)) { @@ -354,7 +355,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, */ DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " - "- deleting file.\n", smb_fname_str_dbg(smb_fname))); + "- deleting file.\n", fsp_str_dbg(fsp))); /* * Don't try to update the write time when we delete the file @@ -366,7 +367,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. " "Change user to uid %u\n", - smb_fname_str_dbg(smb_fname), + fsp_str_dbg(fsp), (unsigned int)lck->delete_token->uid)); if (!push_sec_ctx()) { @@ -387,30 +388,30 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, hasn't been renamed. */ if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(conn, smb_fname); + ret = SMB_VFS_LSTAT(conn, fsp->fsp_name); } else { - ret = SMB_VFS_STAT(conn, smb_fname); + ret = SMB_VFS_STAT(conn, fsp->fsp_name); } if (ret != 0) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and stat failed with error %s\n", - smb_fname_str_dbg(smb_fname), strerror(errno))); + fsp_str_dbg(fsp), strerror(errno))); /* * Don't save the errno here, we ignore this error */ goto done; } - id = vfs_file_id_from_sbuf(conn, &smb_fname->st); + id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st); if (!file_id_equal(&fsp->file_id, &id)) { DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and dev and/or inode does not match\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, " "stat file_id %s\n", - smb_fname_str_dbg(smb_fname), + fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), file_id_string_tos(&id))); /* @@ -420,9 +421,9 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } if ((conn->fs_capabilities & FILE_NAMED_STREAMS) - && !is_ntfs_stream_smb_fname(smb_fname)) { + && !is_ntfs_stream_smb_fname(fsp->fsp_name)) { - status = delete_all_streams(conn, smb_fname->base_name); + status = delete_all_streams(conn, fsp->fsp_name->base_name); if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("delete_all_streams failed: %s\n", @@ -432,7 +433,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } - if (SMB_VFS_UNLINK(conn, smb_fname) != 0) { + if (SMB_VFS_UNLINK(conn, fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may * have had the file open with delete on close set and @@ -443,21 +444,14 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. Delete on close " "was set and unlink failed with error %s\n", - smb_fname_str_dbg(smb_fname), strerror(errno))); + fsp_str_dbg(fsp), strerror(errno))); status = map_nt_error_from_unix(errno); } - status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - goto done; - } - notify_fname(conn, NOTIFY_ACTION_REMOVED, FILE_NOTIFY_CHANGE_FILE_NAME, - fname); - - TALLOC_FREE(fname); + fsp->fsp_name->base_name); /* As we now have POSIX opens which can unlink * with other open files we may have taken @@ -476,7 +470,6 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } TALLOC_FREE(lck); - TALLOC_FREE(smb_fname); return status; } @@ -499,7 +492,6 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts) static NTSTATUS update_write_time_on_close(struct files_struct *fsp) { - struct smb_filename *smb_fname = NULL; struct smb_file_time ft; NTSTATUS status; int ret = -1; @@ -514,43 +506,32 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) fsp->close_write_time = timespec_current(); } - /* XXX: Remove when fsp->fsp_name is converted to smb_filename. */ - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { - ret = SMB_VFS_FSTAT(fsp, &smb_fname->st); + ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); } else { if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(fsp->conn, smb_fname); + ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name); } else { - ret = SMB_VFS_STAT(fsp->conn, smb_fname); + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); } } if (ret == -1) { - status = map_nt_error_from_unix(errno); - goto out; + return map_nt_error_from_unix(errno); } - if (!VALID_STAT(smb_fname->st)) { + if (!VALID_STAT(fsp->fsp_name->st)) { /* if it doesn't seem to be a real file */ - status = NT_STATUS_OK; - goto out; + return NT_STATUS_OK; } ft.mtime = fsp->close_write_time; - status = smb_set_file_time(fsp->conn, fsp, smb_fname, &ft, true); + status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, true); if (!NT_STATUS_IS_OK(status)) { - goto out; + return status; } - out: - TALLOC_FREE(smb_fname); return status; } @@ -647,7 +628,7 @@ static NTSTATUS close_normal_file(struct smb_request *req, files_struct *fsp, status = ntstatus_keeperror(status, tmp); DEBUG(2,("%s closed file %s (numopen=%d) %s\n", - conn->server_info->unix_name,fsp->fsp_name, + conn->server_info->unix_name, fsp_str_dbg(fsp), conn->num_files_open - 1, nt_errstr(status) )); @@ -663,16 +644,9 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, enum file_close_type close_type) { struct share_mode_lock *lck = NULL; - struct smb_filename *smb_dname = NULL; bool delete_dir = False; NTSTATUS status = NT_STATUS_OK; - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - NULL, &smb_dname); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - /* * NT can set delete_on_close of the last open * reference to a directory also. @@ -683,14 +657,14 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, if (lck == NULL) { DEBUG(0, ("close_directory: Could not get share mode lock for " - "%s\n", smb_fname_str_dbg(smb_dname))); + "%s\n", fsp_str_dbg(fsp))); status = NT_STATUS_INVALID_PARAMETER; goto out; } if (!del_share_mode(lck, fsp)) { DEBUG(0, ("close_directory: Could not delete share entry for " - "%s\n", smb_fname_str_dbg(smb_dname))); + "%s\n", fsp_str_dbg(fsp))); } if (fsp->initial_delete_on_close) { @@ -704,7 +678,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, become_user(fsp->conn, fsp->vuid); became_user = True; } - send_stat_cache_delete_message(fsp->fsp_name); + send_stat_cache_delete_message(fsp->fsp_name->base_name); set_delete_on_close_lck(lck, True, ¤t_user.ut); if (became_user) { unbecome_user(); @@ -747,11 +721,12 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, TALLOC_FREE(lck); - status = rmdir_internals(talloc_tos(), fsp->conn, smb_dname); + status = rmdir_internals(talloc_tos(), fsp->conn, + fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - " "deleting directory returned %s.\n", - smb_fname_str_dbg(smb_dname), nt_errstr(status))); + fsp_str_dbg(fsp), nt_errstr(status))); /* unbecome user. */ pop_sec_ctx(); @@ -774,7 +749,7 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Could not close dir! fname=%s, fd=%d, err=%d=%s\n", - smb_fname_str_dbg(smb_dname), fsp->fh->fd, errno, + fsp_str_dbg(fsp), fsp->fh->fd, errno, strerror(errno))); } @@ -786,7 +761,6 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, out: TALLOC_FREE(lck); - TALLOC_FREE(smb_dname); return status; } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index ca926aa33c..bd0c7df959 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -448,8 +448,8 @@ static bool get_stat_dos_flags(connection_struct *conn, if (S_ISDIR(smb_fname->st.st_ex_mode)) *dosmode |= aDIR; - *dosmode |= set_sparse_flag(smb_fname->st); - *dosmode |= set_link_read_only_flag(smb_fname->st); + *dosmode |= set_sparse_flag(&smb_fname->st); + *dosmode |= set_link_read_only_flag(&smb_fname->st); return true; } @@ -845,7 +845,7 @@ bool update_write_time(struct files_struct *fsp) } notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name); + FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name); return true; } diff --git a/source3/smbd/error.c b/source3/smbd/error.c index ce22f86414..874efa2a0b 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -136,33 +136,3 @@ void reply_openerror(struct smb_request *req, NTSTATUS status) reply_nterror(req, status); } } - -void reply_unix_error(struct smb_request *req, uint8 defclass, uint32 defcode, - NTSTATUS defstatus, int line, const char *file) -{ - int eclass=defclass; - int ecode=defcode; - NTSTATUS ntstatus = defstatus; - int i=0; - - TALLOC_FREE(req->outbuf); - reply_outbuf(req, 0, 0); - - if (errno != 0) { - DEBUG(3,("unix_error_packet: error string = %s\n", - strerror(errno))); - - while (unix_dos_nt_errmap[i].dos_class != 0) { - if (unix_dos_nt_errmap[i].unix_error == errno) { - eclass = unix_dos_nt_errmap[i].dos_class; - ecode = unix_dos_nt_errmap[i].dos_code; - ntstatus = unix_dos_nt_errmap[i].nt_error; - break; - } - i++; - } - } - - error_packet_set((char *)req->outbuf, eclass, ecode, ntstatus, - line, file); -} diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c index ef54398bc4..743d88f360 100644 --- a/source3/smbd/fake_file.c +++ b/source3/smbd/fake_file.c @@ -71,23 +71,32 @@ static struct fake_file_handle *init_fake_file_handle(enum FAKE_FILE_TYPE type) Does this name match a fake filename ? ****************************************************************************/ -enum FAKE_FILE_TYPE is_fake_file(const char *fname) +enum FAKE_FILE_TYPE is_fake_file(const struct smb_filename *smb_fname) { #ifdef HAVE_SYS_QUOTAS int i; + char *fname = NULL; + NTSTATUS status; #endif - if (!fname) { + if (!smb_fname) { return FAKE_FILE_TYPE_NONE; } #ifdef HAVE_SYS_QUOTAS + status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + return FAKE_FILE_TYPE_NONE; + } + for (i=0;fake_files[i].name!=NULL;i++) { if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) { DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname)); + TALLOC_FREE(fname); return fake_files[i].type; } } + TALLOC_FREE(fname); #endif return FAKE_FILE_TYPE_NONE; @@ -101,7 +110,7 @@ enum FAKE_FILE_TYPE is_fake_file(const char *fname) NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn, uint16_t current_vuid, enum FAKE_FILE_TYPE fake_file_type, - const char *fname, + const struct smb_filename *smb_fname, uint32 access_mask, files_struct **result) { @@ -112,7 +121,8 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn, if (conn->server_info->utok.uid != 0) { DEBUG(3, ("open_fake_file_shared: access_denied to " "service[%s] file[%s] user[%s]\n", - lp_servicename(SNUM(conn)), fname, + lp_servicename(SNUM(conn)), + smb_fname_str_dbg(smb_fname), conn->server_info->unix_name)); return NT_STATUS_ACCESS_DENIED; @@ -124,7 +134,8 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn, } DEBUG(5,("open_fake_file_shared: fname = %s, FID = %d, access_mask = 0x%x\n", - fname, fsp->fnum, (unsigned int)access_mask)); + smb_fname_str_dbg(smb_fname), fsp->fnum, + (unsigned int)access_mask)); fsp->conn = conn; fsp->fh->fd = -1; @@ -132,8 +143,12 @@ NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn, fsp->fh->pos = -1; fsp->can_lock = False; /* Should this be true ? - No, JRA */ fsp->access_mask = access_mask; - string_set(&fsp->fsp_name,fname); - + status = fsp_set_smb_fname(fsp, smb_fname); + if (!NT_STATUS_IS_OK(status)) { + file_free(req, fsp); + return NT_STATUS_NO_MEMORY; + } + fsp->fake_file_handle = init_fake_file_handle(fake_file_type); if (fsp->fake_file_handle==NULL) { diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index d8fee1db06..7d0a552956 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -33,7 +33,6 @@ bool can_access_file_acl(struct connection_struct *conn, NTSTATUS status; uint32_t access_granted; struct security_descriptor *secdesc = NULL; - char *fname = NULL; bool ret; if (conn->server_info->utok.uid == 0 || conn->admin_user) { @@ -41,13 +40,7 @@ bool can_access_file_acl(struct connection_struct *conn, return true; } - status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - ret = false; - goto out; - } - - status = SMB_VFS_GET_NT_ACL(conn, fname, + status = SMB_VFS_GET_NT_ACL(conn, smb_fname->base_name, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), @@ -62,7 +55,6 @@ bool can_access_file_acl(struct connection_struct *conn, access_mask, &access_granted); ret = NT_STATUS_IS_OK(status); out: - TALLOC_FREE(fname); TALLOC_FREE(secdesc); return ret; } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 0c13b845df..bd609d3e86 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -57,6 +57,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) /* you can't read from print files */ if (fsp->print_file) { + errno = EBADF; return -1; } @@ -102,7 +103,7 @@ tryagain: } DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", - fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret)); fsp->fh->pos += ret; fsp->fh->position_information = fsp->fh->pos; @@ -135,7 +136,7 @@ static ssize_t real_write_file(struct smb_request *req, } DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", - fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + fsp_str_dbg(fsp), (double)pos, (unsigned long)n, (long)ret)); if (ret != -1) { fsp->fh->pos += ret; @@ -163,8 +164,9 @@ static int wcp_file_size_change(files_struct *fsp) wcp->file_size = wcp->offset + wcp->data_size; ret = SMB_VFS_FTRUNCATE(fsp, wcp->file_size); if (ret == -1) { - DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f error %s\n", - fsp->fsp_name, (double)wcp->file_size, strerror(errno) )); + DEBUG(0,("wcp_file_size_change (%s): ftruncate of size %.0f " + "error %s\n", fsp_str_dbg(fsp), + (double)wcp->file_size, strerror(errno))); } return ret; } @@ -178,7 +180,7 @@ static void update_write_time_handler(struct event_context *ctx, /* Remove the timed event handler. */ TALLOC_FREE(fsp->update_write_time_event); - DEBUG(5, ("Update write time on %s\n", fsp->fsp_name)); + DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp))); /* change the write time if not already changed by someone else */ update_write_time(fsp); @@ -243,7 +245,8 @@ void trigger_write_time_update_immediate(struct files_struct *fsp) } TALLOC_FREE(fsp->update_write_time_event); - DEBUG(5, ("Update write time immediate on %s\n", fsp->fsp_name)); + DEBUG(5, ("Update write time immediate on %s\n", + fsp_str_dbg(fsp))); fsp->update_write_time_triggered = true; @@ -284,28 +287,17 @@ ssize_t write_file(struct smb_request *req, } if (!fsp->modified) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - fsp->modified = True; - status = create_synthetic_smb_fname_split(talloc_tos(), - fsp->fsp_name, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; - } - - if (SMB_VFS_FSTAT(fsp, &smb_fname->st) == 0) { + if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == 0) { int dosmode; trigger_write_time_update(fsp); - dosmode = dos_mode(fsp->conn, smb_fname); + dosmode = dos_mode(fsp->conn, fsp->fsp_name); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { - file_set_dosmode(fsp->conn, smb_fname, - dosmode | aARCH, NULL, false); + file_set_dosmode(fsp->conn, fsp->fsp_name, + dosmode | aARCH, NULL, false); } /* @@ -315,11 +307,10 @@ ssize_t write_file(struct smb_request *req, if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { setup_write_cache(fsp, - smb_fname->st.st_ex_size); + fsp->fsp_name->st.st_ex_size); wcp = fsp->wcp; } } - TALLOC_FREE(smb_fname); } #ifdef WITH_PROFILE @@ -381,8 +372,10 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", return total_written; } - DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", - fsp->fsp_name, fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); + DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f " + "wcp->data_size=%u\n", fsp_str_dbg(fsp), fsp->fh->fd, + (double)pos, (unsigned int)n, (double)wcp->offset, + (unsigned int)wcp->data_size)); fsp->fh->pos = pos + n; @@ -827,7 +820,8 @@ void delete_write_cache(files_struct *fsp) SAFE_FREE(wcp->data); SAFE_FREE(fsp->wcp); - DEBUG(10,("delete_write_cache: File %s deleted write cache\n", fsp->fsp_name )); + DEBUG(10,("delete_write_cache: File %s deleted write cache\n", + fsp_str_dbg(fsp))); } /**************************************************************************** @@ -870,7 +864,7 @@ static bool setup_write_cache(files_struct *fsp, SMB_OFF_T file_size) allocated_write_caches++; DEBUG(10,("setup_write_cache: File %s allocated write cache size %lu\n", - fsp->fsp_name, (unsigned long)wcp->alloc_size )); + fsp_str_dbg(fsp), (unsigned long)wcp->alloc_size)); return True; } @@ -887,7 +881,7 @@ void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size) char *msg; if (asprintf(&msg, "set_filelen_write_cache: size change " "on file %s with write cache size = %lu\n", - fsp->fsp_name, + fsp->fsp_name->base_name, (unsigned long)fsp->wcp->data_size) != -1) { smb_panic(msg); } else { @@ -969,7 +963,13 @@ NTSTATUS sync_file(connection_struct *conn, files_struct *fsp, bool write_throug int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) { if (fsp->fh->fd == -1) { - return vfs_stat_smb_fname(fsp->conn, fsp->fsp_name, pst); + int ret; + + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); + if (ret != -1) { + *pst = fsp->fsp_name->st; + } + return ret; } else { return SMB_VFS_FSTAT(fsp, pst); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 29ebc37d1a..09f9a418bd 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -80,201 +80,6 @@ static NTSTATUS determine_path_error(const char *name, } } -/** - * XXX: This is temporary and there should be no callers of this outside of - * this file once smb_filename is plumbed through all path based operations. - * The one legitimate caller currently is smb_fname_str_dbg(), which this - * could be made static for. - */ -NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, const struct smb_filename *smb_fname, - char **full_name) -{ - if (smb_fname->stream_name) { - *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name, - smb_fname->stream_name); - } else { - *full_name = talloc_strdup(ctx, smb_fname->base_name); - } - - if (!*full_name) { - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -/** - * There are actually legitimate callers of this such as functions that - * enumerate streams using the SMB_VFS_STREAMINFO interface and then want to - * operate on each stream. - */ -NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, - const char *stream_name, - const SMB_STRUCT_STAT *psbuf, - struct smb_filename **smb_fname_out) -{ - struct smb_filename smb_fname_loc; - - ZERO_STRUCT(smb_fname_loc); - - /* Setup the base_name/stream_name. */ - smb_fname_loc.base_name = CONST_DISCARD(char *, base_name); - smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name); - - /* Copy the psbuf if one was given. */ - if (psbuf) - smb_fname_loc.st = *psbuf; - - /* Let copy_smb_filename() do the heavy lifting. */ - return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out); -} - -/** - * XXX: This is temporary and there should be no callers of this once - * smb_filename is plumbed through all path based operations. - */ -NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx, - const char *fname, - const SMB_STRUCT_STAT *psbuf, - struct smb_filename **smb_fname_out) -{ - NTSTATUS status; - const char *stream_name = NULL; - char *base_name = NULL; - - if (!lp_posix_pathnames()) { - stream_name = strchr_m(fname, ':'); - } - - /* Setup the base_name/stream_name. */ - if (stream_name) { - base_name = talloc_strndup(ctx, fname, - PTR_DIFF(stream_name, fname)); - } else { - base_name = talloc_strdup(ctx, fname); - } - - if (!base_name) { - return NT_STATUS_NO_MEMORY; - } - - status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf, - smb_fname_out); - TALLOC_FREE(base_name); - return status; -} - -/** - * XXX: This is temporary and there should be no callers of this once - * smb_filename is plumbed through all path based operations. - */ -int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf) -{ - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - int ret; - - status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; - } - - ret = SMB_VFS_STAT(conn, smb_fname); - if (ret != -1) { - *psbuf = smb_fname->st; - } - - TALLOC_FREE(smb_fname); - return ret; -} - -/** - * XXX: This is temporary and there should be no callers of this once - * smb_filename is plumbed through all path based operations. - */ -int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, - SMB_STRUCT_STAT *psbuf) -{ - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - int ret; - - status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; - } - - ret = SMB_VFS_LSTAT(conn, smb_fname); - if (ret != -1) { - *psbuf = smb_fname->st; - } - - TALLOC_FREE(smb_fname); - return ret; -} - -/** - * Return a string using the debug_ctx() - */ -const char *smb_fname_str_dbg(const struct smb_filename *smb_fname) -{ - char *fname = NULL; - NTSTATUS status; - - if (smb_fname == NULL) { - return ""; - } - status = get_full_smb_filename(debug_ctx(), smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - return ""; - } - return fname; -} - -NTSTATUS copy_smb_filename(TALLOC_CTX *ctx, - const struct smb_filename *smb_fname_in, - struct smb_filename **smb_fname_out) -{ - - *smb_fname_out = talloc_zero(ctx, struct smb_filename); - if (*smb_fname_out == NULL) { - return NT_STATUS_NO_MEMORY; - } - - if (smb_fname_in->base_name) { - (*smb_fname_out)->base_name = - talloc_strdup(*smb_fname_out, smb_fname_in->base_name); - if (!(*smb_fname_out)->base_name) - goto no_mem_err; - } - - if (smb_fname_in->stream_name) { - (*smb_fname_out)->stream_name = - talloc_strdup(*smb_fname_out, smb_fname_in->stream_name); - if (!(*smb_fname_out)->stream_name) - goto no_mem_err; - } - - if (smb_fname_in->original_lcomp) { - (*smb_fname_out)->original_lcomp = - talloc_strdup(*smb_fname_out, smb_fname_in->original_lcomp); - if (!(*smb_fname_out)->original_lcomp) - goto no_mem_err; - } - - (*smb_fname_out)->st = smb_fname_in->st; - return NT_STATUS_OK; - - no_mem_err: - TALLOC_FREE(*smb_fname_out); - return NT_STATUS_NO_MEMORY; -} - /**************************************************************************** This routine is called to convert names from the dos namespace to unix namespace. It needs to handle any case conversions, mangling, format changes, @@ -312,23 +117,21 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, struct smb_filename **smb_fname_out, uint32_t ucf_flags) { - SMB_STRUCT_STAT st; struct smb_filename *smb_fname = NULL; char *start, *end; char *dirpath = NULL; - char *name = NULL; char *stream = NULL; bool component_was_mangled = False; bool name_has_wildcard = False; bool posix_pathnames = false; bool allow_wcard_last_component = ucf_flags & UCF_ALLOW_WCARD_LCOMP; bool save_last_component = ucf_flags & UCF_SAVE_LCOMP; - NTSTATUS result; + NTSTATUS status; int ret = -1; *smb_fname_out = NULL; - smb_fname = talloc_zero(talloc_tos(), struct smb_filename); + smb_fname = talloc_zero(ctx, struct smb_filename); if (smb_fname == NULL) { return NT_STATUS_NO_MEMORY; } @@ -338,10 +141,10 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, filename - so don't convert them */ if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) { - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } - *smb_fname_out = smb_fname; - return NT_STATUS_OK; + goto done; } DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path)); @@ -369,15 +172,16 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, */ if (!*orig_path) { - if (!(name = talloc_strdup(ctx,"."))) { - return NT_STATUS_NO_MEMORY; + if (!(smb_fname->base_name = talloc_strdup(smb_fname, "."))) { + status = NT_STATUS_NO_MEMORY; + goto err; } - if (vfs_stat_smb_fname(conn,name,&st) == 0) { - smb_fname->st = st; - } else { - return map_nt_error_from_unix(errno); + if (SMB_VFS_STAT(conn, smb_fname) != 0) { + status = map_nt_error_from_unix(errno); + goto err; } - DEBUG(5,("conversion finished \"\" -> %s\n",name)); + DEBUG(5, ("conversion finished \"\" -> %s\n", + smb_fname->base_name)); goto done; } @@ -385,17 +189,19 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, orig_path[1] == '\0')) { /* Start of pathname can't be "." only. */ if (orig_path[1] == '\0' || orig_path[2] == '\0') { - result = NT_STATUS_OBJECT_NAME_INVALID; + status = NT_STATUS_OBJECT_NAME_INVALID; } else { - result =determine_path_error( - &orig_path[2], allow_wcard_last_component); + status =determine_path_error(&orig_path[2], + allow_wcard_last_component); } - return result; + goto err; } - if (!(name = talloc_strdup(ctx, orig_path))) { + /* Start with the full orig_path as given by the caller. */ + if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) { DEBUG(0, ("talloc_strdup failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } /* @@ -409,7 +215,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) { - strnorm(name, lp_defaultcase(SNUM(conn))); + strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn))); } /* @@ -417,44 +223,60 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, */ if(save_last_component) { - end = strrchr_m(name, '/'); + end = strrchr_m(smb_fname->base_name, '/'); if (end) { - smb_fname->original_lcomp = talloc_strdup(ctx, + smb_fname->original_lcomp = talloc_strdup(smb_fname, end + 1); } else { - smb_fname->original_lcomp = talloc_strdup(ctx, name); + smb_fname->original_lcomp = + talloc_strdup(smb_fname, smb_fname->base_name); + } + if (smb_fname->original_lcomp == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err; } } posix_pathnames = lp_posix_pathnames(); - /* Strip off the stream. Should we use any of the other stream parsing - * at this point? Also, should we set the is_stream bit? */ + /* + * Strip off the stream, and add it back when we're done with the + * base_name. + */ if (!posix_pathnames) { - stream = strchr_m(name, ':'); + stream = strchr_m(smb_fname->base_name, ':'); if (stream != NULL) { - char *tmp = talloc_strdup(ctx, stream); + char *tmp = talloc_strdup(smb_fname, stream); if (tmp == NULL) { - TALLOC_FREE(name); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } + /* + * Since this is actually pointing into + * smb_fname->base_name this truncates base_name. + */ *stream = '\0'; stream = tmp; } } - start = name; + start = smb_fname->base_name; - /* If we're providing case insentive semantics or + /* + * If we're providing case insentive semantics or * the underlying filesystem is case insensitive, * then a case-normalized hit in the stat-cache is * authoratitive. JRA. + * + * Note: We're only checking base_name. The stream_name will be + * added and verified in build_stream_path(). */ - if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) && - stat_cache_lookup(conn, &name, &dirpath, &start, &st)) { - smb_fname->st = st; + if((!conn->case_sensitive || !(conn->fs_capabilities & + FILE_CASE_SENSITIVE_SEARCH)) && + stat_cache_lookup(conn, &smb_fname->base_name, &dirpath, &start, + &smb_fname->st)) { goto done; } @@ -465,43 +287,46 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) { DEBUG(0, ("talloc_strdup failed\n")); - TALLOC_FREE(name); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } /* - * stat the name - if it exists then we are all done! + * stat the name - if it exists then we can add the stream back (if + * there was one) and be done! */ if (posix_pathnames) { - ret = vfs_lstat_smb_fname(conn,name,&st); + ret = SMB_VFS_LSTAT(conn, smb_fname); } else { - ret = vfs_stat_smb_fname(conn,name,&st); + ret = SMB_VFS_STAT(conn, smb_fname); } if (ret == 0) { /* Ensure we catch all names with in "/." this is disallowed under Windows. */ - const char *p = strstr(name, "/."); /* mb safe. */ + const char *p = strstr(smb_fname->base_name, "/."); /*mb safe*/ if (p) { if (p[2] == '/') { /* Error code within a pathname. */ - result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; goto fail; } else if (p[2] == '\0') { /* Error code at the end of a pathname. */ - result = NT_STATUS_OBJECT_NAME_INVALID; + status = NT_STATUS_OBJECT_NAME_INVALID; goto fail; } } - stat_cache_add(orig_path, name, conn->case_sensitive); - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); - smb_fname->st = st; + /* Add the path (not including the stream) to the cache. */ + stat_cache_add(orig_path, smb_fname->base_name, + conn->case_sensitive); + DEBUG(5,("conversion of base_name finished %s -> %s\n", + orig_path, smb_fname->base_name)); goto done; } DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", - name, dirpath, start)); + smb_fname->base_name, dirpath, start)); /* * A special case - if we don't have any mangling chars and are case @@ -509,8 +334,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * won't help. */ - if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) && - !mangle_is_mangled(name, conn->params)) { + if ((conn->case_sensitive || !(conn->fs_capabilities & + FILE_CASE_SENSITIVE_SEARCH)) && + !mangle_is_mangled(smb_fname->base_name, conn->params)) { goto done; } @@ -549,11 +375,12 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, if (save_last_component) { TALLOC_FREE(smb_fname->original_lcomp); - smb_fname->original_lcomp = talloc_strdup(ctx, + smb_fname->original_lcomp = talloc_strdup(smb_fname, end ? end + 1 : start); if (!smb_fname->original_lcomp) { DEBUG(0, ("talloc failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } } @@ -562,9 +389,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, if (ISDOT(start)) { if (!end) { /* Error code at the end of a pathname. */ - result = NT_STATUS_OBJECT_NAME_INVALID; + status = NT_STATUS_OBJECT_NAME_INVALID; } else { - result = determine_path_error(end+1, + status = determine_path_error(end+1, allow_wcard_last_component); } goto fail; @@ -577,13 +404,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, /* Wildcard not valid anywhere. */ if (name_has_wildcard && !allow_wcard_last_component) { - result = NT_STATUS_OBJECT_NAME_INVALID; + status = NT_STATUS_OBJECT_NAME_INVALID; goto fail; } /* Wildcards never valid within a pathname. */ if (name_has_wildcard && end) { - result = NT_STATUS_OBJECT_NAME_INVALID; + status = NT_STATUS_OBJECT_NAME_INVALID; goto fail; } @@ -592,9 +419,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, */ if (posix_pathnames) { - ret = vfs_lstat_smb_fname(conn,name, &st); + ret = SMB_VFS_LSTAT(conn, smb_fname); } else { - ret = vfs_stat_smb_fname(conn,name, &st); + ret = SMB_VFS_STAT(conn, smb_fname); } if (ret == 0) { @@ -602,7 +429,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * It exists. it must either be a directory or this must * be the last part of the path for it to be OK. */ - if (end && !S_ISDIR(st.st_ex_mode)) { + if (end && !S_ISDIR(smb_fname->st.st_ex_mode)) { /* * An intermediate part of the name isn't * a directory. @@ -617,25 +444,15 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * applications depend on the difference between * these two errors. */ - result = NT_STATUS_OBJECT_PATH_NOT_FOUND; + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; goto fail; } - if (!end) { - /* - * We just scanned for, and found the end of - * the path. We must return the valid stat - * struct. JRA. - */ - - smb_fname->st = st; - } - } else { char *found_name = NULL; /* Stat failed - ensure we don't use it. */ - SET_STAT_INVALID(st); + SET_STAT_INVALID(smb_fname->st); /* * Reset errno so we can detect @@ -681,11 +498,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, if (errno == ENOENT || errno == ENOTDIR || errno == ELOOP) { - result = + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { - result = + status = map_nt_error_from_unix(errno); } goto fail; @@ -706,10 +523,10 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, */ if (errno == ENOTDIR || errno == ELOOP) { - result = + status = NT_STATUS_OBJECT_PATH_NOT_FOUND; } else { - result = + status = map_nt_error_from_unix(errno); } goto fail; @@ -741,12 +558,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, &unmangled, conn->params)) { char *tmp; - size_t start_ofs = start - name; + size_t start_ofs = + start - smb_fname->base_name; if (*dirpath != '\0') { - tmp = talloc_asprintf(ctx, - "%s/%s", dirpath, - unmangled); + tmp = talloc_asprintf( + smb_fname, "%s/%s", + dirpath, unmangled); TALLOC_FREE(unmangled); } else { @@ -754,11 +572,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } - TALLOC_FREE(name); - name = tmp; - start = name + start_ofs; + TALLOC_FREE(smb_fname->base_name); + smb_fname->base_name = tmp; + start = + smb_fname->base_name + start_ofs; end = start + strlen(start); } @@ -773,46 +593,50 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, */ if (end) { char *tmp; - size_t start_ofs = start - name; + size_t start_ofs = + start - smb_fname->base_name; if (*dirpath != '\0') { - tmp = talloc_asprintf(ctx, + tmp = talloc_asprintf(smb_fname, "%s/%s/%s", dirpath, found_name, end+1); } else { - tmp = talloc_asprintf(ctx, + tmp = talloc_asprintf(smb_fname, "%s/%s", found_name, end+1); } if (tmp == NULL) { DEBUG(0, ("talloc_asprintf failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } - TALLOC_FREE(name); - name = tmp; - start = name + start_ofs; + TALLOC_FREE(smb_fname->base_name); + smb_fname->base_name = tmp; + start = smb_fname->base_name + start_ofs; end = start + strlen(found_name); *end = '\0'; } else { char *tmp; - size_t start_ofs = start - name; + size_t start_ofs = + start - smb_fname->base_name; if (*dirpath != '\0') { - tmp = talloc_asprintf(ctx, + tmp = talloc_asprintf(smb_fname, "%s/%s", dirpath, found_name); } else { - tmp = talloc_strdup(ctx, + tmp = talloc_strdup(smb_fname, found_name); } if (tmp == NULL) { DEBUG(0, ("talloc failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } - TALLOC_FREE(name); - name = tmp; - start = name + start_ofs; + TALLOC_FREE(smb_fname->base_name); + smb_fname->base_name = tmp; + start = smb_fname->base_name + start_ofs; /* * We just scanned for, and found the end of @@ -821,17 +645,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, */ if (posix_pathnames) { - ret = vfs_lstat_smb_fname(conn,name, - &st); + ret = SMB_VFS_LSTAT(conn, smb_fname); } else { - ret = vfs_stat_smb_fname(conn,name, - &st); + ret = SMB_VFS_STAT(conn, smb_fname); } - if (ret == 0) { - smb_fname->st = st; - } else { - SET_STAT_INVALID(st); + if (ret != 0) { + SET_STAT_INVALID(smb_fname->st); } } @@ -844,12 +664,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * We should never provide different behaviors * depending on DEVELOPER!!! */ - if (VALID_STAT(st)) { + if (VALID_STAT(smb_fname->st)) { bool delete_pending; - get_file_infos(vfs_file_id_from_sbuf(conn, &st), + get_file_infos(vfs_file_id_from_sbuf(conn, + &smb_fname->st), &delete_pending, NULL); if (delete_pending) { - result = NT_STATUS_DELETE_PENDING; + status = NT_STATUS_DELETE_PENDING; goto fail; } } @@ -864,7 +685,8 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, "%s/%s", dirpath, start); if (!tmp) { DEBUG(0, ("talloc_asprintf failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } TALLOC_FREE(dirpath); dirpath = tmp; @@ -873,15 +695,15 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, TALLOC_FREE(dirpath); if (!(dirpath = talloc_strdup(ctx,start))) { DEBUG(0, ("talloc_strdup failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } } /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. + * Cache the dirpath thus far. Don't cache a name with mangled + * or wildcard components as this can change the size. */ - if(!component_was_mangled && !name_has_wildcard) { stat_cache_add(orig_path, dirpath, conn->case_sensitive); @@ -896,29 +718,30 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } /* - * Don't cache a name with mangled or wildcard components - * as this can change the size. + * Cache the full path. Don't cache a name with mangled or wildcard + * components as this can change the size. */ if(!component_was_mangled && !name_has_wildcard) { - stat_cache_add(orig_path, name, conn->case_sensitive); + stat_cache_add(orig_path, smb_fname->base_name, + conn->case_sensitive); } /* * The name has been resolved. */ - DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); + DEBUG(5,("conversion finished %s -> %s\n", orig_path, + smb_fname->base_name)); done: - smb_fname->base_name = name; - + /* Add back the stream if one was stripped off originally. */ if (stream != NULL) { smb_fname->stream_name = stream; /* Check path now that the base_name has been converted. */ - result = build_stream_path(ctx, conn, orig_path, smb_fname); - if (!NT_STATUS_IS_OK(result)) { + status = build_stream_path(ctx, conn, orig_path, smb_fname); + if (!NT_STATUS_IS_OK(status)) { goto fail; } } @@ -928,20 +751,23 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, fail: DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start)); if (*dirpath != '\0') { - smb_fname->base_name = talloc_asprintf(ctx, "%s/%s", dirpath, - start); + smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s", + dirpath, start); } else { - smb_fname->base_name = talloc_strdup(ctx, start); + smb_fname->base_name = talloc_strdup(smb_fname, start); } if (!smb_fname->base_name) { DEBUG(0, ("talloc_asprintf failed\n")); - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto err; } *smb_fname_out = smb_fname; - TALLOC_FREE(name); TALLOC_FREE(dirpath); - return result; + return status; + err: + TALLOC_FREE(smb_fname); + return status; } /**************************************************************************** @@ -1137,6 +963,7 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, struct stream_struct *streams = NULL; if (SMB_VFS_STAT(conn, smb_fname) == 0) { + DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname))); return NT_STATUS_OK; } @@ -1183,21 +1010,16 @@ static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, TALLOC_FREE(smb_fname->stream_name); - smb_fname->stream_name = talloc_strdup(mem_ctx, streams[i].name); + smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name); + if (smb_fname->stream_name == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } SET_STAT_INVALID(smb_fname->st); if (SMB_VFS_STAT(conn, smb_fname) == 0) { - char *result = NULL; - - status = get_full_smb_filename(mem_ctx, smb_fname, &result); - if (!NT_STATUS_IS_OK(status)) { - status = NT_STATUS_NO_MEMORY; - goto fail; - } - - stat_cache_add(orig_path, result, conn->case_sensitive); - TALLOC_FREE(result); + DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname))); } status = NT_STATUS_OK; fail: @@ -1213,8 +1035,7 @@ NTSTATUS filename_convert(TALLOC_CTX *ctx, connection_struct *conn, bool dfs_path, const char *name_in, - struct smb_filename **pp_smb_fname, - char **pp_name) + struct smb_filename **pp_smb_fname) { NTSTATUS status; char *fname = NULL; @@ -1241,22 +1062,15 @@ NTSTATUS filename_convert(TALLOC_CTX *ctx, return status; } - status = get_full_smb_filename(ctx, *pp_smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - status = check_name(conn, fname); + status = check_name(conn, (*pp_smb_fname)->base_name); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("filename_convert: check_name failed " "for name %s with %s\n", - fname, + smb_fname_str_dbg(*pp_smb_fname), nt_errstr(status) )); + TALLOC_FREE(*pp_smb_fname); return status; } - if (pp_name != NULL) { - *pp_name = fname; - } return status; } diff --git a/source3/smbd/filename_util.c b/source3/smbd/filename_util.c new file mode 100644 index 0000000000..867709a373 --- /dev/null +++ b/source3/smbd/filename_util.c @@ -0,0 +1,206 @@ +/* + Unix SMB/CIFS implementation. + Filename utility functions. + Copyright (C) Tim Prouty 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "includes.h" + +/** + * XXX: This is temporary and there should be no callers of this outside of + * this file once smb_filename is plumbed through all path based operations. + * The one legitimate caller currently is smb_fname_str_dbg(), which this + * could be made static for. + */ +NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx, + const struct smb_filename *smb_fname, + char **full_name) +{ + if (smb_fname->stream_name) { + /* stream_name must always be NULL if there is no stream. */ + SMB_ASSERT(smb_fname->stream_name[0] != '\0'); + + *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name, + smb_fname->stream_name); + } else { + *full_name = talloc_strdup(ctx, smb_fname->base_name); + } + + if (!*full_name) { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + +/** + * There are actually legitimate callers of this such as functions that + * enumerate streams using the SMB_VFS_STREAMINFO interface and then want to + * operate on each stream. + */ +NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, + const char *stream_name, + const SMB_STRUCT_STAT *psbuf, + struct smb_filename **smb_fname_out) +{ + struct smb_filename smb_fname_loc; + + ZERO_STRUCT(smb_fname_loc); + + /* Setup the base_name/stream_name. */ + smb_fname_loc.base_name = CONST_DISCARD(char *, base_name); + smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name); + + /* Copy the psbuf if one was given. */ + if (psbuf) + smb_fname_loc.st = *psbuf; + + /* Let copy_smb_filename() do the heavy lifting. */ + return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out); +} + +/** + * XXX: This is temporary and there should be no callers of this once + * smb_filename is plumbed through all path based operations. + */ +NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx, + const char *fname, + const SMB_STRUCT_STAT *psbuf, + struct smb_filename **smb_fname_out) +{ + NTSTATUS status; + const char *stream_name = NULL; + char *base_name = NULL; + + if (!lp_posix_pathnames()) { + stream_name = strchr_m(fname, ':'); + } + + /* Setup the base_name/stream_name. */ + if (stream_name) { + base_name = talloc_strndup(ctx, fname, + PTR_DIFF(stream_name, fname)); + } else { + base_name = talloc_strdup(ctx, fname); + } + + if (!base_name) { + return NT_STATUS_NO_MEMORY; + } + + status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf, + smb_fname_out); + TALLOC_FREE(base_name); + return status; +} + +/** + * Return a string using the debug_ctx() + */ +const char *smb_fname_str_dbg(const struct smb_filename *smb_fname) +{ + char *fname = NULL; + NTSTATUS status; + + if (smb_fname == NULL) { + return ""; + } + status = get_full_smb_filename(debug_ctx(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + return ""; + } + return fname; +} + +/** + * Return a debug string using the debug_ctx(). This can only be called from + * DEBUG() macros due to the debut_ctx(). + */ +const char *fsp_str_dbg(const struct files_struct *fsp) +{ + return smb_fname_str_dbg(fsp->fsp_name); +} + +NTSTATUS copy_smb_filename(TALLOC_CTX *ctx, + const struct smb_filename *smb_fname_in, + struct smb_filename **smb_fname_out) +{ + /* stream_name must always be NULL if there is no stream. */ + if (smb_fname_in->stream_name) { + SMB_ASSERT(smb_fname_in->stream_name[0] != '\0'); + } + + *smb_fname_out = talloc_zero(ctx, struct smb_filename); + if (*smb_fname_out == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (smb_fname_in->base_name) { + (*smb_fname_out)->base_name = + talloc_strdup(*smb_fname_out, smb_fname_in->base_name); + if (!(*smb_fname_out)->base_name) + goto no_mem_err; + } + + if (smb_fname_in->stream_name) { + (*smb_fname_out)->stream_name = + talloc_strdup(*smb_fname_out, smb_fname_in->stream_name); + if (!(*smb_fname_out)->stream_name) + goto no_mem_err; + } + + if (smb_fname_in->original_lcomp) { + (*smb_fname_out)->original_lcomp = + talloc_strdup(*smb_fname_out, smb_fname_in->original_lcomp); + if (!(*smb_fname_out)->original_lcomp) + goto no_mem_err; + } + + (*smb_fname_out)->st = smb_fname_in->st; + return NT_STATUS_OK; + + no_mem_err: + TALLOC_FREE(*smb_fname_out); + return NT_STATUS_NO_MEMORY; +} + +/**************************************************************************** + Simple check to determine if the filename is a stream. + ***************************************************************************/ +bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) +{ + /* stream_name must always be NULL if there is no stream. */ + if (smb_fname->stream_name) { + SMB_ASSERT(smb_fname->stream_name[0] != '\0'); + } + + if (lp_posix_pathnames()) { + return false; + } + + return smb_fname->stream_name; +} + +/**************************************************************************** + Returns true if the filename's stream == "::$DATA" + ***************************************************************************/ +bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname) +{ + if (!is_ntfs_stream_smb_fname(smb_fname)) { + return false; + } + + return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0; +} diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 0e6dd7e457..a170f774fe 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -44,6 +44,7 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, { int i; files_struct *fsp; + NTSTATUS status; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to @@ -65,21 +66,26 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, return NT_STATUS_TOO_MANY_OPENED_FILES; } - fsp = SMB_MALLOC_P(files_struct); + /* + * Make a child of the connection_struct as an fsp can't exist + * indepenedent of a connection. + */ + fsp = talloc_zero(conn, struct files_struct); if (!fsp) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(fsp); - - fsp->fh = SMB_MALLOC_P(struct fd_handle); + /* + * This can't be a child of fsp because the file_handle can be ref'd + * when doing a dos/fcb open, which will then share the file_handle + * across multiple fsps. + */ + fsp->fh = talloc_zero(conn, struct fd_handle); if (!fsp->fh) { - SAFE_FREE(fsp); + TALLOC_FREE(fsp); return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(fsp->fh); - fsp->fh->ref_count = 1; fsp->fh->fd = -1; @@ -95,8 +101,18 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, fsp->fnum = i + FILE_HANDLE_OFFSET; SMB_ASSERT(fsp->fnum < 65536); - string_set(&fsp->fsp_name,""); - + /* + * Create an smb_filename with "" for the base_name. There are very + * few NULL checks, so make sure it's initialized with something. to + * be safe until an audit can be done. + */ + status = create_synthetic_smb_fname(fsp, "", NULL, NULL, + &fsp->fsp_name); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(fsp); + TALLOC_FREE(fsp->fh); + } + DLIST_ADD(Files, fsp); DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", @@ -236,8 +252,9 @@ void file_dump_open_table(void) files_struct *fsp; for (fsp=Files;fsp;fsp=fsp->next,count++) { - DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n", - count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id, + DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, " + "fileid=%s\n", count, fsp->fnum, fsp_str_dbg(fsp), + fsp->fh->fd, (unsigned long)fsp->fh->gen_id, file_id_string_tos(&fsp->file_id))); } } @@ -283,8 +300,10 @@ files_struct *file_find_dif(struct file_id id, unsigned long gen_id) if ((fsp->fh->fd == -1) && (fsp->oplock_type != NO_OPLOCK) && (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { - DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \ -oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, + DEBUG(0,("file_find_dif: file %s file_id = " + "%s, gen = %u oplock_type = %u is a " + "stat open with oplock type !\n", + fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), (unsigned int)fsp->fh->gen_id, (unsigned int)fsp->oplock_type )); @@ -385,10 +404,11 @@ bool file_find_subpath(files_struct *dir_fsp) { files_struct *fsp; size_t dlen; - char *d_fullname = talloc_asprintf(talloc_tos(), - "%s/%s", - dir_fsp->conn->connectpath, - dir_fsp->fsp_name); + char *d_fullname; + + d_fullname = talloc_asprintf(talloc_tos(), "%s/%s", + dir_fsp->conn->connectpath, + dir_fsp->fsp_name->base_name); if (!d_fullname) { return false; @@ -406,7 +426,7 @@ bool file_find_subpath(files_struct *dir_fsp) d1_fullname = talloc_asprintf(talloc_tos(), "%s/%s", fsp->conn->connectpath, - fsp->fsp_name); + fsp->fsp_name->base_name); if (strnequal(d_fullname, d1_fullname, dlen)) { TALLOC_FREE(d_fullname); @@ -444,12 +464,10 @@ void file_free(struct smb_request *req, files_struct *fsp) { DLIST_REMOVE(Files, fsp); - string_free(&fsp->fsp_name); - TALLOC_FREE(fsp->fake_file_handle); if (fsp->fh->ref_count == 1) { - SAFE_FREE(fsp->fh); + TALLOC_FREE(fsp->fh); } else { fsp->fh->ref_count--; } @@ -495,7 +513,8 @@ void file_free(struct smb_request *req, files_struct *fsp) information */ ZERO_STRUCTP(fsp); - SAFE_FREE(fsp); + /* fsp->fsp_name is a talloc child and is free'd automatically. */ + TALLOC_FREE(fsp); } /**************************************************************************** @@ -541,11 +560,11 @@ files_struct *file_fsp(struct smb_request *req, uint16 fid) Duplicate the file handle part for a DOS or FCB open. ****************************************************************************/ -void dup_file_fsp(struct smb_request *req, files_struct *from, +NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from, uint32 access_mask, uint32 share_access, uint32 create_options, files_struct *to) { - SAFE_FREE(to->fh); + TALLOC_FREE(to->fh); to->fh = from->fh; to->fh->ref_count++; @@ -570,5 +589,25 @@ void dup_file_fsp(struct smb_request *req, files_struct *from, to->modified = from->modified; to->is_directory = from->is_directory; to->aio_write_behind = from->aio_write_behind; - string_set(&to->fsp_name,from->fsp_name); + return fsp_set_smb_fname(to, from->fsp_name); +} + +/** + * The only way that the fsp->fsp_name field should ever be set. + */ +NTSTATUS fsp_set_smb_fname(struct files_struct *fsp, + const struct smb_filename *smb_fname_in) +{ + NTSTATUS status; + struct smb_filename *smb_fname_new; + + status = copy_smb_filename(fsp, smb_fname_in, &smb_fname_new); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + TALLOC_FREE(fsp->fsp_name); + fsp->fsp_name = smb_fname_new; + + return NT_STATUS_OK; } diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index 15550ed455..317304a86d 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -153,4 +153,9 @@ void smbd_init_globals(void) ZERO_STRUCT(conn_ctx_stack); ZERO_STRUCT(sec_ctx_stack); + + smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection); + if (!smbd_server_conn) { + exit_server("failed to create smbd_server_connection"); + } } diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 3d195c84f0..434204b60d 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -168,6 +168,56 @@ NTSTATUS smb2_signing_check_pdu(DATA_BLOB session_key, const struct iovec *vector, int count); +struct smbd_lock_element { + uint32_t smbpid; + enum brl_type brltype; + uint64_t offset; + uint64_t count; +}; + +NTSTATUS smbd_do_locking(struct smb_request *req, + files_struct *fsp, + uint8_t type, + int32_t timeout, + uint16_t num_ulocks, + struct smbd_lock_element *ulocks, + uint16_t num_locks, + struct smbd_lock_element *locks, + bool *async); + +NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + files_struct *fsp, + const struct smb_filename *smb_fname, + bool delete_pending, + struct timespec write_time_ts, + bool ms_dfs_link, + struct ea_list *ea_list, + int lock_data_count, + char *lock_data, + uint16_t flags2, + unsigned int max_data_bytes, + char **ppdata, + unsigned int *pdata_size); + +NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, + struct smb_request *req, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + files_struct *fsp, + struct smb_filename *smb_fname, + char **ppdata, int total_data, + int *ret_data_size); + +NTSTATUS smbd_do_qfsinfo(connection_struct *conn, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + uint16_t flags2, + unsigned int max_data_bytes, + char **ppdata, + int *ret_data_len); + void smbd_server_connection_terminate_ex(struct smbd_server_connection *sconn, const char *reason, const char *location); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 1067dab074..96a411dd70 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -454,7 +454,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, } DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)\n", - subcommand, fsp->fsp_name, pnum)); + subcommand, fsp_str_dbg(fsp), pnum)); DEBUG(10, ("api_fd_reply: p:%p max_trans_reply: %d\n", fsp, mdrcnt)); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d40b8a8902..2b63eb1743 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -411,7 +411,6 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, char **pp_link_target, SMB_STRUCT_STAT *sbufp) { - SMB_STRUCT_STAT st; int referral_len = 0; #if defined(HAVE_BROKEN_READLINK) char link_target_buf[PATH_MAX]; @@ -420,6 +419,8 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, #endif size_t bufsize = 0; char *link_target = NULL; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; if (pp_link_target) { bufsize = 1024; @@ -433,21 +434,28 @@ static bool is_msdfs_link_internal(TALLOC_CTX *ctx, link_target = link_target_buf; } - if (sbufp == NULL) { - sbufp = &st; + status = create_synthetic_smb_fname(talloc_tos(), path, NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + goto err; } - if (vfs_lstat_smb_fname(conn, path, sbufp) != 0) { + if (SMB_VFS_LSTAT(conn, smb_fname) != 0) { DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n", path)); + TALLOC_FREE(smb_fname); goto err; } - - if (!S_ISLNK(sbufp->st_ex_mode)) { + if (!S_ISLNK(smb_fname->st.st_ex_mode)) { DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n", path)); + TALLOC_FREE(smb_fname); goto err; } + if (sbufp != NULL) { + *sbufp = smb_fname->st; + } + TALLOC_FREE(smb_fname); referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1); if (referral_len == -1) { diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ded888c021..8f37923865 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -182,7 +182,7 @@ void change_notify_reply(connection_struct *conn, static void notify_callback(void *private_data, const struct notify_event *e) { files_struct *fsp = (files_struct *)private_data; - DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name)); + DEBUG(10, ("notify_callback called for %s\n", fsp_str_dbg(fsp))); notify_fsp(fsp, e->action, e->path); } @@ -200,8 +200,9 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return NT_STATUS_NO_MEMORY; } + /* Do notify operations on the base_name. */ if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath, - fsp->fsp_name) == -1) { + fsp->fsp_name->base_name) == -1) { DEBUG(0, ("asprintf failed\n")); TALLOC_FREE(fsp->notify); return NT_STATUS_NO_MEMORY; @@ -236,7 +237,7 @@ NTSTATUS change_notify_add_request(struct smb_request *req, struct smbd_server_connection *sconn = smbd_server_conn; DEBUG(10, ("change_notify_add_request: Adding request for %s: " - "max_param = %d\n", fsp->fsp_name, (int)max_param)); + "max_param = %d\n", fsp_str_dbg(fsp), (int)max_param)); if (!(request = talloc(NULL, struct notify_change_request)) || !(map = talloc(request, struct notify_mid_map))) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index b65af26eca..43212dc800 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -272,30 +272,6 @@ void send_nt_replies(connection_struct *conn, } /**************************************************************************** - Simple check to determine if the filename is a stream. - ***************************************************************************/ -bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) -{ - if (lp_posix_pathnames()) { - return false; - } - - return smb_fname->stream_name; -} - -/**************************************************************************** - Returns true if the filename's stream == "::$DATA" - ***************************************************************************/ -bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname) -{ - if (!is_ntfs_stream_smb_fname(smb_fname)) { - return false; - } - - return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0; -} - -/**************************************************************************** Reply to an NT create and X call on a pipe ****************************************************************************/ @@ -502,8 +478,7 @@ void reply_ntcreate_and_X(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -794,7 +769,7 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, security_acl_map_generic(psd->sacl, &file_generic_mapping); if (DEBUGLEVEL >= 10) { - DEBUG(10,("set_sd for file %s\n", fsp->fsp_name )); + DEBUG(10,("set_sd for file %s\n", fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, psd); } @@ -992,8 +967,7 @@ static void call_nt_transact_create(connection_struct *conn, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1341,8 +1315,7 @@ void reply_ntrename(struct smb_request *req) if (req->wct < 4) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBntrename); - return; + goto out; } attrs = SVAL(req->vwv+0, 0); @@ -1353,14 +1326,12 @@ void reply_ntrename(struct smb_request *req) &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBntrename); - return; + goto out; } if (ms_has_wild(oldname)) { reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD); - END_PROFILE(SMBntrename); - return; + goto out; } p++; @@ -1368,55 +1339,83 @@ void reply_ntrename(struct smb_request *req) &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBntrename); - return; + goto out; } - status = filename_convert(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - oldname, - &smb_fname_old, - &oldname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - END_PROFILE(SMBntrename); - return; - } - reply_nterror(req, status); - END_PROFILE(SMBntrename); - return; + /* The newname must begin with a ':' if the oldname contains a ':'. */ + if (strchr_m(oldname, ':') && (newname[0] != ':')) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto out; } - status = filename_convert(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - newname, - &smb_fname_new, - &newname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - END_PROFILE(SMBntrename); - return; + /* rename_internals() calls unix_convert(), so don't call it here. */ + if (rename_type != RENAME_FLAG_RENAME) { + status = filename_convert(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + oldname, + &smb_fname_old); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + goto out; + } + reply_nterror(req, status); + goto out; } - reply_nterror(req, status); - END_PROFILE(SMBntrename); - return; - } - /* The new name must begin with a ':' if the old name is a stream. */ - if (is_ntfs_stream_smb_fname(smb_fname_old) && (newname[0] != ':')) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBntrename); - return; - } + status = filename_convert(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + newname, + &smb_fname_new); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, + NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + goto out; + } + reply_nterror(req, status); + goto out; + } - DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); + DEBUG(3,("reply_ntrename: %s -> %s\n", + smb_fname_str_dbg(smb_fname_old), + smb_fname_str_dbg(smb_fname_new))); + } switch(rename_type) { case RENAME_FLAG_RENAME: + status = resolve_dfspath(ctx, conn, + (req->flags2 & + FLAGS2_DFS_PATHNAMES), + oldname, &oldname); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("resolve_dfspath failed for name %s " + "with %s\n", oldname, + nt_errstr(status))); + reply_nterror(req, status); + goto out; + } + + status = resolve_dfspath(ctx, conn, + (req->flags2 & + FLAGS2_DFS_PATHNAMES), + newname, &newname); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("resolve_dfspath failed for name %s " + "with %s\n", newname, + nt_errstr(status))); + reply_nterror(req, status); + goto out; + } + + DEBUG(3,("reply_ntrename: %s -> %s\n", oldname, + newname)); + status = rename_internals(ctx, conn, req, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard, DELETE_ACCESS); @@ -1454,17 +1453,15 @@ void reply_ntrename(struct smb_request *req) if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - END_PROFILE(SMBntrename); - return; + goto out; } reply_nterror(req, status); - END_PROFILE(SMBntrename); - return; + goto out; } reply_outbuf(req, 0, 0); - + out: END_PROFILE(SMBntrename); return; } @@ -1523,7 +1520,7 @@ static void call_nt_transact_notify_change(connection_struct *conn, DEBUG(3,("call_nt_transact_notify_change: notify change " "called on %s, filter = %s, recursive = %d\n", - fsp->fsp_name, filter_string, recursive)); + fsp_str_dbg(fsp), filter_string, recursive)); TALLOC_FREE(filter_string); } @@ -1626,7 +1623,7 @@ static void call_nt_transact_rename(connection_struct *conn, send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0); DEBUG(3,("nt transact rename from = %s, to = %s ignored!\n", - fsp->fsp_name, new_name)); + fsp_str_dbg(fsp), new_name)); return; } @@ -1684,8 +1681,9 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, security_info_wanted = IVAL(params,4); - DEBUG(3,("call_nt_transact_query_security_desc: file = %s, info_wanted = 0x%x\n", fsp->fsp_name, - (unsigned int)security_info_wanted )); + DEBUG(3,("call_nt_transact_query_security_desc: file = %s, " + "info_wanted = 0x%x\n", fsp_str_dbg(fsp), + (unsigned int)security_info_wanted)); params = nttrans_realloc(ppparams, 4); if(params == NULL) { @@ -1722,7 +1720,8 @@ static void call_nt_transact_query_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); if (DEBUGLEVEL >= 10) { - DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name)); + DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", + fsp_str_dbg(fsp))); NDR_PRINT_DEBUG(security_descriptor, psd); } @@ -1796,8 +1795,8 @@ static void call_nt_transact_set_security_desc(connection_struct *conn, security_info_sent = IVAL(params,4); - DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, - (unsigned int)security_info_sent )); + DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", + fsp_str_dbg(fsp), (unsigned int)security_info_sent)); if (data_count == 0) { reply_doserror(req, ERRDOS, ERRnoaccess); @@ -2021,7 +2020,7 @@ static void call_nt_transact_ioctl(connection_struct *conn, cur_pdata+=12; DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n", - shadow_data->num_volumes,fsp->fsp_name)); + shadow_data->num_volumes, fsp_str_dbg(fsp))); if (labels && shadow_data->labels) { for (i=0;i<shadow_data->num_volumes;i++) { srvstr_push(pdata, req->flags2, diff --git a/source3/smbd/open.c b/source3/smbd/open.c index e01350f2bf..87cab1966b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -94,6 +94,7 @@ static NTSTATUS check_open_rights(struct connection_struct *conn, "on %s: %s\n", smb_fname_str_dbg(smb_fname), nt_errstr(status))); + TALLOC_FREE(sd); return status; } @@ -218,13 +219,13 @@ void change_file_owner_to_parent(connection_struct *conn, if (ret == -1) { DEBUG(0,("change_file_owner_to_parent: failed to fchown " "file %s to parent directory uid %u. Error " - "was %s\n", fsp->fsp_name, + "was %s\n", fsp_str_dbg(fsp), (unsigned int)smb_fname_parent->st.st_ex_uid, strerror(errno) )); } DEBUG(10,("change_file_owner_to_parent: changed new file %s to " - "parent directory uid %u.\n", fsp->fsp_name, + "parent directory uid %u.\n", fsp_str_dbg(fsp), (unsigned int)smb_fname_parent->st.st_ex_uid)); TALLOC_FREE(smb_fname_parent); @@ -349,7 +350,6 @@ static NTSTATUS open_file(files_struct *fsp, uint32 access_mask, /* client requested access mask. */ uint32 open_access_mask) /* what we're actually using in the open. */ { - char *path = NULL; NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -434,7 +434,7 @@ static NTSTATUS open_file(files_struct *fsp, * wildcard characters are allowed in stream names * only test the basefilename */ - wild = fsp->base_fsp->fsp_name; + wild = fsp->base_fsp->fsp_name->base_name; } else { wild = smb_fname->base_name; } @@ -614,16 +614,13 @@ static NTSTATUS open_file(files_struct *fsp, conn->case_sensitive)) { fsp->aio_write_behind = True; } - - status = get_full_smb_filename(talloc_tos(), smb_fname, - &path); + status = fsp_set_smb_fname(fsp, smb_fname); if (!NT_STATUS_IS_OK(status)) { + fd_close(fsp); + errno = map_errno_from_nt_status(status); return status; } - string_set(&fsp->fsp_name, path); - TALLOC_FREE(path); - fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", @@ -795,7 +792,8 @@ static void validate_my_share_entries(int num, str = talloc_asprintf(talloc_tos(), "validate_my_share_entries: " "file %s, oplock_type = 0x%x, op_type = 0x%x\n", - fsp->fsp_name, (unsigned int)fsp->oplock_type, + fsp->fsp_name->base_name, + (unsigned int)fsp->oplock_type, (unsigned int)share_entry->op_type ); smb_panic(str); } @@ -1029,7 +1027,7 @@ static bool delay_for_oplocks(struct share_mode_lock *lck, } DEBUG(10,("delay_for_oplocks: oplock type 0x%x on file %s\n", - fsp->oplock_type, fsp->fsp_name)); + fsp->oplock_type, fsp_str_dbg(fsp))); /* No delay. */ return false; @@ -1152,13 +1150,6 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, uint32 create_options) { files_struct *fsp; - char *fname = NULL; - NTSTATUS status; - - status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } DEBUG(5,("fcb_or_dos_open: attempting old open semantics for " "file %s.\n", smb_fname_str_dbg(smb_fname))); @@ -1168,7 +1159,7 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, " "vuid = %u, file_pid = %u, private_options = 0x%x " - "access_mask = 0x%x\n", fsp->fsp_name, + "access_mask = 0x%x\n", fsp_str_dbg(fsp), fsp->fh->fd, (unsigned int)fsp->vuid, (unsigned int)fsp->file_pid, (unsigned int)fsp->fh->private_options, @@ -1180,7 +1171,9 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && (fsp->access_mask & FILE_WRITE_DATA) && - strequal(fsp->fsp_name, fname)) { + strequal(fsp->fsp_name->base_name, smb_fname->base_name) && + strequal(fsp->fsp_name->stream_name, + smb_fname->stream_name)) { DEBUG(10,("fcb_or_dos_open: file match\n")); break; } @@ -1198,17 +1191,16 @@ NTSTATUS fcb_or_dos_open(struct smb_request *req, } /* We need to duplicate this fsp. */ - dup_file_fsp(req, fsp, access_mask, share_access, - create_options, fsp_to_dup_into); - - return NT_STATUS_OK; + return dup_file_fsp(req, fsp, access_mask, share_access, + create_options, fsp_to_dup_into); } /**************************************************************************** Open a file with a share mode - old openX method - map into NTCreate. ****************************************************************************/ -bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func, +bool map_open_params_to_ntcreate(const struct smb_filename *smb_fname, + int deny_mode, int open_func, uint32 *paccess_mask, uint32 *pshare_mode, uint32 *pcreate_disposition, @@ -1221,7 +1213,8 @@ bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, " "open_func = 0x%x\n", - fname, (unsigned int)deny_mode, (unsigned int)open_func )); + smb_fname_str_dbg(smb_fname), (unsigned int)deny_mode, + (unsigned int)open_func )); /* Create the NT compatible access_mask. */ switch (GET_OPENX_MODE(deny_mode)) { @@ -1295,7 +1288,7 @@ bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func case DENY_DOS: create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS; - if (is_executable(fname)) { + if (is_executable(smb_fname->base_name)) { share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; } else { if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) { @@ -1320,7 +1313,7 @@ bool map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, " "share_mode = 0x%x, create_disposition = 0x%x, " "create_options = 0x%x\n", - fname, + smb_fname_str_dbg(smb_fname), (unsigned int)access_mask, (unsigned int)share_mode, (unsigned int)create_disposition, @@ -2611,8 +2604,10 @@ static NTSTATUS open_directory(connection_struct *conn, fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False; - - string_set(&fsp->fsp_name, smb_dname->base_name); + status = fsp_set_smb_fname(fsp, smb_dname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } mtimespec = smb_dname->st.st_ex_mtime; @@ -2730,6 +2725,11 @@ void msg_file_was_renamed(struct messaging_context *msg, bn_len = strlen(base_name); stream_name = sharepath + sp_len + 1 + bn_len + 1; + /* stream_name must always be NULL if there is no stream. */ + if (stream_name[0] == '\0') { + stream_name = NULL; + } + status = create_synthetic_smb_fname(talloc_tos(), base_name, stream_name, NULL, &smb_fname); if (!NT_STATUS_IS_OK(status)) { @@ -2743,18 +2743,14 @@ void msg_file_was_renamed(struct messaging_context *msg, for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) { if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) { - char *newname = NULL; DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n", - fsp->fnum, fsp->fsp_name, + fsp->fnum, fsp_str_dbg(fsp), smb_fname_str_dbg(smb_fname))); - status = get_full_smb_filename(talloc_tos(), - smb_fname, &newname); + status = fsp_set_smb_fname(fsp, smb_fname); if (!NT_STATUS_IS_OK(status)) { goto out; } - string_set(&fsp->fsp_name, newname); - TALLOC_FREE(newname); } else { /* TODO. JRA. */ /* Now we have the complete path we can work out if this is @@ -2765,7 +2761,7 @@ void msg_file_was_renamed(struct messaging_context *msg, fsp->conn->connectpath, sharepath, fsp->fnum, - fsp->fsp_name, + fsp_str_dbg(fsp), smb_fname_str_dbg(smb_fname))); } } @@ -2926,7 +2922,7 @@ NTSTATUS open_streams_for_delete(connection_struct *conn, } DEBUG(10, ("Closing stream # %d, %s\n", i, - streams[i]->fsp_name)); + fsp_str_dbg(streams[i]))); close_file(NULL, streams[i], NORMAL_CLOSE); } @@ -3326,6 +3322,11 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, dir_fsp = file_fsp(req, root_dir_fid); + if (is_ntfs_stream_smb_fname(dir_fsp->fsp_name)) { + status = NT_STATUS_INVALID_HANDLE; + goto out; + } + if (dir_fsp == NULL) { status = NT_STATUS_INVALID_HANDLE; goto out; @@ -3354,7 +3355,7 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, goto out; } - if (ISDOT(dir_fsp->fsp_name)) { + if (ISDOT(dir_fsp->fsp_name->base_name)) { /* * We're at the toplevel dir, the final file name * must not contain ./, as this is filtered out @@ -3367,7 +3368,7 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, goto out; } } else { - size_t dir_name_len = strlen(dir_fsp->fsp_name); + size_t dir_name_len = strlen(dir_fsp->fsp_name->base_name); /* * Copy in the base directory name. @@ -3379,7 +3380,7 @@ NTSTATUS get_relative_fid_filename(connection_struct *conn, status = NT_STATUS_NO_MEMORY; goto out; } - memcpy(parent_fname, dir_fsp->fsp_name, + memcpy(parent_fname, dir_fsp->fsp_name->base_name, dir_name_len+1); /* @@ -3463,16 +3464,9 @@ NTSTATUS create_file_default(connection_struct *conn, */ if (is_ntfs_stream_smb_fname(smb_fname)) { - char *fname = NULL; enum FAKE_FILE_TYPE fake_file_type; - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } - - fake_file_type = is_fake_file(fname); + fake_file_type = is_fake_file(smb_fname); if (fake_file_type != FAKE_FILE_TYPE_NONE) { @@ -3488,9 +3482,8 @@ NTSTATUS create_file_default(connection_struct *conn, * close it */ status = open_fake_file(req, conn, req->vuid, - fake_file_type, fname, + fake_file_type, smb_fname, access_mask, &fsp); - TALLOC_FREE(fname); if (!NT_STATUS_IS_OK(status)) { goto fail; } @@ -3498,7 +3491,6 @@ NTSTATUS create_file_default(connection_struct *conn, ZERO_STRUCT(smb_fname->st); goto done; } - TALLOC_FREE(fname); if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) { status = NT_STATUS_OBJECT_NAME_NOT_FOUND; diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index e9b2a6cf95..dd8d5372fb 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -81,7 +81,7 @@ bool set_file_oplock(files_struct *fsp, int oplock_type) DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, " "tv_sec = %x, tv_usec = %x\n", - fsp->fsp_name, file_id_string_tos(&fsp->file_id), + fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, (int)fsp->open_time.tv_sec, (int)fsp->open_time.tv_usec )); @@ -158,14 +158,15 @@ bool remove_oplock(files_struct *fsp) NULL); if (lck == NULL) { DEBUG(0,("remove_oplock: failed to lock share entry for " - "file %s\n", fsp->fsp_name )); + "file %s\n", fsp_str_dbg(fsp))); return False; } ret = remove_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("remove_oplock: failed to remove share oplock for " "file %s fnum %d, %s\n", - fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id))); + fsp_str_dbg(fsp), fsp->fnum, + file_id_string_tos(&fsp->file_id))); } release_file_oplock(fsp); TALLOC_FREE(lck); @@ -184,14 +185,15 @@ bool downgrade_oplock(files_struct *fsp) NULL); if (lck == NULL) { DEBUG(0,("downgrade_oplock: failed to lock share entry for " - "file %s\n", fsp->fsp_name )); + "file %s\n", fsp_str_dbg(fsp))); return False; } ret = downgrade_share_oplock(lck, fsp); if (!ret) { DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " "for file %s fnum %d, file_id %s\n", - fsp->fsp_name, fsp->fnum, file_id_string_tos(&fsp->file_id))); + fsp_str_dbg(fsp), fsp->fnum, + file_id_string_tos(&fsp->file_id))); } downgrade_file_oplock(fsp); @@ -294,7 +296,8 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f if(fsp->oplock_type == NO_OPLOCK) { if( DEBUGLVL( 3 ) ) { - dbgtext( "initial_break_processing: file %s ", fsp->fsp_name ); + dbgtext( "initial_break_processing: file %s ", + fsp_str_dbg(fsp)); dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n", file_id_string_tos(&id), fsp->fh->gen_id ); dbgtext( "Allowing break to succeed regardless.\n" ); @@ -314,7 +317,8 @@ static void oplock_timeout_handler(struct event_context *ctx, /* Remove the timed event handler. */ TALLOC_FREE(fsp->oplock_timeout); - DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", fsp->fsp_name)); + DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n", + fsp_str_dbg(fsp))); global_client_failed_oplock_break = True; remove_oplock(fsp); reply_to_oplock_break_requests(fsp); @@ -375,7 +379,7 @@ void break_level2_to_none_async(files_struct *fsp) DEBUG(10,("process_oplock_async_level2_break_message: sending break " "to none message for fid %d, file %s\n", fsp->fnum, - fsp->fsp_name)); + fsp_str_dbg(fsp))); /* Now send a break to none message to our client. */ break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); @@ -506,7 +510,7 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx, !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { DEBUG(3, ("Already downgraded oplock on %s: %s\n", file_id_string_tos(&fsp->file_id), - fsp->fsp_name)); + fsp_str_dbg(fsp))); /* We just send the same message back. */ messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE, (uint8 *)data->data, @@ -740,7 +744,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp, NULL); if (lck == NULL) { DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " - "share mode entry for file %s.\n", fsp->fsp_name )); + "share mode entry for file %s.\n", fsp_str_dbg(fsp))); return; } diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index 89b8e0f7b5..dd32177988 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -212,7 +212,8 @@ static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx, DEBUG(0,("irix_set_kernel_oplock: Unable to get " "kernel oplock on file %s, file_id %s " "gen_id = %ul. Error was %s\n", - fsp->fsp_name, file_id_string_tos(&fsp->file_id), + fsp_str_dbg(fsp), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) )); } else { @@ -220,7 +221,7 @@ static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx, "file %s, fd = %d, file_id = %s, " "gen_id = %ul. Another process had the file " "open.\n", - fsp->fsp_name, fsp->fh->fd, + fsp_str_dbg(fsp), fsp->fh->fd, file_id_string_tos(&fsp->file_id), fsp->fh->gen_id )); } @@ -229,7 +230,7 @@ static bool irix_set_kernel_oplock(struct kernel_oplocks *_ctx, DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s " "gen_id = %ul\n", - fsp->fsp_name, file_id_string_tos(&fsp->file_id), + fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id)); return True; @@ -250,7 +251,8 @@ static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx, int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1); dbgtext("irix_release_kernel_oplock: file %s, file_id = %s" "gen_id = %ul, has kernel oplock state " - "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id), + "of %x.\n", fsp_str_dbg(fsp), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, state ); } @@ -263,7 +265,8 @@ static void irix_release_kernel_oplock(struct kernel_oplocks *_ctx, "removing kernel oplock on file " ); dbgtext("%s, file_id = %s gen_id = %ul. " "Error was %s\n", - fsp->fsp_name, file_id_string_tos(&fsp->file_id), + fsp_str_dbg(fsp), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) ); } diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 273fbfdc01..b4a5495e4b 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -111,7 +111,7 @@ static bool linux_set_kernel_oplock(struct kernel_oplocks *ctx, if ( SMB_VFS_LINUX_SETLEASE(fsp, F_WRLCK) == -1) { DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, " "fd = %d, file_id = %s. (%s)\n", - fsp->fsp_name, fsp->fh->fd, + fsp_str_dbg(fsp), fsp->fh->fd, file_id_string_tos(&fsp->file_id), strerror(errno))); return False; @@ -119,7 +119,7 @@ static bool linux_set_kernel_oplock(struct kernel_oplocks *ctx, DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, " "file_id = %s gen_id = %lu\n", - fsp->fsp_name, file_id_string_tos(&fsp->file_id), + fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id)); return True; @@ -140,7 +140,8 @@ static void linux_release_kernel_oplock(struct kernel_oplocks *ctx, int state = fcntl(fsp->fh->fd, F_GETLEASE, 0); dbgtext("linux_release_kernel_oplock: file %s, file_id = %s " "gen_id = %lu has kernel oplock state " - "of %x.\n", fsp->fsp_name, file_id_string_tos(&fsp->file_id), + "of %x.\n", fsp_str_dbg(fsp), + file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, state ); } @@ -152,7 +153,7 @@ static void linux_release_kernel_oplock(struct kernel_oplocks *ctx, dbgtext("linux_release_kernel_oplock: Error when " "removing kernel oplock on file " ); dbgtext("%s, file_id = %s, gen_id = %lu. " - "Error was %s\n", fsp->fsp_name, + "Error was %s\n", fsp_str_dbg(fsp), file_id_string_tos(&fsp->file_id), fsp->fh->gen_id, strerror(errno) ); } diff --git a/source3/smbd/oplock_onefs.c b/source3/smbd/oplock_onefs.c index d359f9c6f2..a73100abdf 100644 --- a/source3/smbd/oplock_onefs.c +++ b/source3/smbd/oplock_onefs.c @@ -60,29 +60,30 @@ struct onefs_callback_record { struct onefs_callback_record *callback_recs; /** - * Convert a onefs_callback_record to a string. + * Convert a onefs_callback_record to a debug string using the dbg_ctx(). */ -static char *onefs_callback_record_str_static(const struct onefs_callback_record *r) +const char *onefs_cb_record_str_dbg(const struct onefs_callback_record *r) { - static fstring result; + char *result; if (r == NULL) { - fstrcpy(result, "NULL callback record"); + result = talloc_strdup(dbg_ctx(), "NULL callback record"); return result; } switch (r->state) { case ONEFS_OPEN_FILE: - fstr_sprintf(result, "cb record %llu for file %s", - r->id, r->data.fsp->fsp_name); - break; + result = talloc_asprintf(dbg_ctx(), "cb record %llu for file " + "%s", r->id, + fsp_str_dbg(r->data.fsp)); case ONEFS_WAITING_FOR_OPLOCK: - fstr_sprintf(result, "cb record %llu for pending mid %d", - r->id, (int)r->data.mid); + result = talloc_asprintf(dbg_ctx(), "cb record %llu for " + "pending mid %d", r->id, + (int)r->data.mid); break; default: - fstr_sprintf(result, "cb record %llu unknown state %d", - r->id, r->state); + result = talloc_asprintf(dbg_ctx(), "cb record %llu unknown " + "state %d", r->id, r->state); break; } @@ -102,7 +103,7 @@ static void debug_cb_records(const char *fn) DEBUG(10, ("cb records (%s):\n", fn)); for (rec = callback_recs; rec; rec = rec->next) { - DEBUGADD(10, ("%s\n", onefs_callback_record_str_static(rec))); + DEBUGADD(10, ("%s\n", onefs_cb_record_dbg_str(rec))); } } @@ -127,7 +128,7 @@ static struct onefs_callback_record *onefs_find_cb(uint64_t id, for (rec = callback_recs; rec; rec = rec->next) { if (rec->id == id) { DEBUG(10, ("found %s\n", - onefs_callback_record_str_static(rec))); + onefs_cb_record_dbg_str(rec))); break; } } @@ -139,7 +140,7 @@ static struct onefs_callback_record *onefs_find_cb(uint64_t id, if (rec->state != expected_state) { DEBUG(0, ("Expected cb type %d, got %s", expected_state, - onefs_callback_record_str_static(rec))); + onefs_cb_record_dbg_str(rec))); SMB_ASSERT(0); return NULL; } @@ -299,7 +300,7 @@ static void oplock_break_to_none_handler(uint64_t id) } DEBUG(10, ("oplock_break_to_none_handler called for file %s\n", - cb->data.fsp->fsp_name)); + cb->data.fsp_str_dbg(fsp))); init_share_mode_entry(&sme, cb, FORCE_OPLOCK_BREAK_TO_NONE); share_mode_entry_to_message(msg, &sme); @@ -336,7 +337,7 @@ static void oplock_break_to_level_two_handler(uint64_t id) } DEBUG(10, ("oplock_break_to_level_two_handler called for file %s\n", - cb->data.fsp->fsp_name)); + cb->data.fsp_str_dbg(fsp))); init_share_mode_entry(&sme, cb, LEVEL_II_OPLOCK); share_mode_entry_to_message(msg, &sme); @@ -377,7 +378,7 @@ static void oplock_revoked_handler(uint64_t id) SMB_ASSERT(fsp->oplock_timeout == NULL); DEBUG(0,("Level 1 oplock break failed for file %s. Forcefully " - "revoking oplock\n", fsp->fsp_name)); + "revoking oplock\n", fsp_str_dbg(fsp))); global_client_failed_oplock_break = True; remove_oplock(fsp); @@ -413,7 +414,7 @@ static void semlock_available_handler(uint64_t id) char *msg; if (asprintf(&msg, "Semlock available on an open that wasn't " "deferred: %s\n", - onefs_callback_record_str_static(cb)) != -1) { + onefs_cb_record_dbg_str(cb)) != -1) { smb_panic(msg); } smb_panic("Semlock available on an open that wasn't " @@ -457,7 +458,7 @@ static void semlock_async_failure_handler(uint64_t id) char *msg; if (asprintf(&msg, "Semlock failure on an open that wasn't " "deferred: %s\n", - onefs_callback_record_str_static(cb)) != -1) { + onefs_cb_record_dbg_str(cb)) != -1) { smb_panic(msg); } smb_panic("Semlock failure on an open that wasn't deferred\n"); @@ -501,7 +502,7 @@ static void onefs_release_kernel_oplock(struct kernel_oplocks *_ctx, enum oplock_type oplock = onefs_samba_oplock_to_oplock(oplock_type); DEBUG(10, ("onefs_release_kernel_oplock: Releasing %s to type %s\n", - fsp->fsp_name, onefs_oplock_str(oplock))); + fsp_str_dbg(fsp), onefs_oplock_str(oplock))); if (fsp->fh->fd == -1) { DEBUG(1, ("no fd\n")); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 928ef0169e..b1a749736d 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -428,27 +428,30 @@ bool user_in_netgroup(struct smbd_server_connection *sconn, if (innetgr(ngname, NULL, user, sconn->smb1.sessions.my_yp_domain)) { DEBUG(5,("user_in_netgroup: Found\n")); return true; - } else { + } - /* - * Ok, innetgr is case sensitive. Try once more with lowercase - * just in case. Attempt to fix #703. JRA. - */ + /* + * Ok, innetgr is case sensitive. Try once more with lowercase + * just in case. Attempt to fix #703. JRA. + */ + fstrcpy(lowercase_user, user); + strlower_m(lowercase_user); - fstrcpy(lowercase_user, user); - strlower_m(lowercase_user); + if (strcmp(user,lowercase_user) == 0) { + /* user name was already lower case! */ + return false; + } - DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", - lowercase_user, - sconn->smb1.sessions.my_yp_domain? - sconn->smb1.sessions.my_yp_domain:"(ANY)", - ngname)); + DEBUG(5,("looking for user %s of domain %s in netgroup %s\n", + lowercase_user, + sconn->smb1.sessions.my_yp_domain? + sconn->smb1.sessions.my_yp_domain:"(ANY)", + ngname)); - if (innetgr(ngname, NULL, lowercase_user, - sconn->smb1.sessions.my_yp_domain)) { - DEBUG(5,("user_in_netgroup: Found\n")); - return true; - } + if (innetgr(ngname, NULL, lowercase_user, + sconn->smb1.sessions.my_yp_domain)) { + DEBUG(5,("user_in_netgroup: Found\n")); + return true; } #endif /* HAVE_NETGROUP */ return false; diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 7ae7435646..091db09987 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -37,6 +37,7 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name, { struct connection_struct *conn = smb_req->conn; struct files_struct *fsp; + struct smb_filename *smb_fname = NULL; NTSTATUS status; status = file_new(smb_req, conn, &fsp); @@ -50,7 +51,19 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name, fsp->vuid = smb_req->vuid; fsp->can_lock = false; fsp->access_mask = FILE_READ_DATA | FILE_WRITE_DATA; - string_set(&fsp->fsp_name, name); + + status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + file_free(smb_req, fsp); + return status; + } + status = fsp_set_smb_fname(fsp, smb_fname); + TALLOC_FREE(smb_fname); + if (!NT_STATUS_IS_OK(status)) { + file_free(smb_req, fsp); + return status; + } status = np_open(NULL, name, conn->client_address, conn->server_info, &fsp->fake_file_handle); @@ -179,7 +192,7 @@ void reply_pipe_write(struct smb_request *req) data = req->buf + 3; DEBUG(6, ("reply_pipe_write: %x name: %s len: %d\n", (int)fsp->fnum, - fsp->fsp_name, (int)state->numtowrite)); + fsp_str_dbg(fsp), (int)state->numtowrite)); subreq = np_write_send(state, smbd_event_context(), fsp->fake_file_handle, data, state->numtowrite); @@ -203,8 +216,14 @@ static void pipe_write_done(struct tevent_req *subreq) status = np_write_recv(subreq, &nwritten); TALLOC_FREE(subreq); - if ((nwritten == 0 && state->numtowrite != 0) || (nwritten < 0)) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + if (nwritten < 0) { + reply_nterror(req, status); + goto send; + } + + /* Looks bogus to me now. Needs to be removed ? JRA. */ + if ((nwritten == 0 && state->numtowrite != 0)) { + reply_doserror(req, ERRDOS, ERRnoaccess); goto send; } @@ -269,7 +288,7 @@ void reply_pipe_write_and_X(struct smb_request *req) == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); DEBUG(6, ("reply_pipe_write_and_X: %x name: %s len: %d\n", - (int)fsp->fnum, fsp->fsp_name, (int)state->numtowrite)); + (int)fsp->fnum, fsp_str_dbg(fsp), (int)state->numtowrite)); data = (uint8_t *)smb_base(req->inbuf) + smb_doff; @@ -283,7 +302,7 @@ void reply_pipe_write_and_X(struct smb_request *req) DEBUG(0,("reply_pipe_write_and_X: start of message " "set and not enough data sent.(%u)\n", (unsigned int)state->numtowrite )); - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; } @@ -313,8 +332,15 @@ static void pipe_write_andx_done(struct tevent_req *subreq) status = np_write_recv(subreq, &nwritten); TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status) || (nwritten != state->numtowrite)) { - reply_unixerror(req, ERRDOS,ERRnoaccess); + + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto done; + } + + /* Looks bogus to me now. Is this error message correct ? JRA. */ + if (nwritten != state->numtowrite) { + reply_doserror(req, ERRDOS,ERRnoaccess); goto done; } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 76eee9b56a..0a3b0dff75 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -256,15 +256,16 @@ static void store_inheritance_attributes(files_struct *fsp, ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, store_size, 0); } else { - ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME, - pai_buf, store_size, 0); + ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name, + SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, store_size, 0); } SAFE_FREE(pai_buf); DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n", (unsigned int)sd_type, - fsp->fsp_name)); + fsp_str_dbg(fsp))); if (ret == -1 && !no_acl_syscall_error(errno)) { DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) )); @@ -599,8 +600,10 @@ static struct pai_val *fload_inherited_info(files_struct *fsp) ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME, pai_buf, pai_buf_size); } else { - ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME, - pai_buf, pai_buf_size); + ret = SMB_VFS_GETXATTR(fsp->conn, + fsp->fsp_name->base_name, + SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); } if (ret == -1) { @@ -618,7 +621,8 @@ static struct pai_val *fload_inherited_info(files_struct *fsp) } } while (ret == -1); - DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name)); + DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", + (unsigned long)ret, fsp_str_dbg(fsp))); if (ret == -1) { /* No attribute or not supported. */ @@ -637,8 +641,7 @@ static struct pai_val *fload_inherited_info(files_struct *fsp) if (paiv) { DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n", - (unsigned int)paiv->sd_type, - fsp->fsp_name)); + (unsigned int)paiv->sd_type, fsp_str_dbg(fsp))); } SAFE_FREE(pai_buf); @@ -1727,8 +1730,12 @@ static bool create_canon_ace_lists(files_struct *fsp, got_dir_allow = True; if ((current_ace->attr == DENY_ACE) && got_dir_allow) { - DEBUG(0,("create_canon_ace_lists: malformed ACL in inheritable ACL ! \ -Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); + DEBUG(0,("create_canon_ace_lists: " + "malformed ACL in " + "inheritable ACL! Deny entry " + "after Allow entry. Failing " + "to set on file %s.\n", + fsp_str_dbg(fsp))); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -1785,8 +1792,10 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); got_file_allow = True; if ((current_ace->attr == DENY_ACE) && got_file_allow) { - DEBUG(0,("create_canon_ace_lists: malformed ACL in file ACL ! \ -Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); + DEBUG(0,("create_canon_ace_lists: malformed " + "ACL in file ACL ! Deny entry after " + "Allow entry. Failing to set on file " + "%s.\n", fsp_str_dbg(fsp))); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); return False; @@ -2169,17 +2178,8 @@ static mode_t create_default_mode(files_struct *fsp, bool interitable_mode) mode_t mode; if (interitable_mode) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - status = create_synthetic_smb_fname_split(talloc_tos(), - fsp->fsp_name, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return 0; - } - mode = unix_mode(fsp->conn, FILE_ATTRIBUTE_ARCHIVE, smb_fname, - NULL); + mode = unix_mode(fsp->conn, FILE_ATTRIBUTE_ARCHIVE, + fsp->fsp_name, NULL); } else { mode = S_IRUSR; } @@ -2602,14 +2602,9 @@ static bool set_canon_ace_list(files_struct *fsp, SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); bool needs_mask = False; mode_t mask_perms = 0; - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - psbuf, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - goto fail; - } + /* Use the psbuf that was passed in. */ + fsp->fsp_name->st = *psbuf; #if defined(POSIX_ACL_NEEDS_MASK) /* HP-UX always wants to have a mask (called "class" there). */ @@ -2767,7 +2762,7 @@ static bool set_canon_ace_list(files_struct *fsp, */ if(default_ace || fsp->is_directory || fsp->fh->fd == -1) { - if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname->base_name, + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name->base_name, the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support @@ -2777,17 +2772,17 @@ static bool set_canon_ace_list(files_struct *fsp, *pacl_set_support = False; } - if (acl_group_override(conn, smb_fname)) { + if (acl_group_override(conn, fsp->fsp_name)) { int sret; DEBUG(5,("set_canon_ace_list: acl group " "control on and current user in file " "%s primary group.\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); become_root(); sret = SMB_VFS_SYS_ACL_SET_FILE(conn, - smb_fname->base_name, the_acl_type, + fsp->fsp_name->base_name, the_acl_type, the_acl); unbecome_root(); if (sret == 0) { @@ -2801,8 +2796,7 @@ static bool set_canon_ace_list(files_struct *fsp, "file %s (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", - smb_fname_str_dbg(smb_fname), - strerror(errno))); + fsp_str_dbg(fsp), strerror(errno))); goto fail; } } @@ -2816,13 +2810,13 @@ static bool set_canon_ace_list(files_struct *fsp, *pacl_set_support = False; } - if (acl_group_override(conn, smb_fname)) { + if (acl_group_override(conn, fsp->fsp_name)) { int sret; DEBUG(5,("set_canon_ace_list: acl group " "control on and current user in file " "%s primary group.\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); become_root(); sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl); @@ -2836,8 +2830,7 @@ static bool set_canon_ace_list(files_struct *fsp, DEBUG(2,("set_canon_ace_list: " "sys_acl_set_file failed for file %s " "(%s).\n", - smb_fname_str_dbg(smb_fname), - strerror(errno) )); + fsp_str_dbg(fsp), strerror(errno))); goto fail; } } @@ -2850,7 +2843,6 @@ static bool set_canon_ace_list(files_struct *fsp, if (the_acl != NULL) { SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); } - TALLOC_FREE(smb_fname); return ret; } @@ -2906,8 +2898,9 @@ static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file mode_t or_bits; if (ace_count != 3) { - DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \ -posix perms.\n", fsp->fsp_name )); + DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE " + "entries for file %s to convert to posix perms.\n", + fsp_str_dbg(fsp))); return False; } @@ -2921,8 +2914,8 @@ posix perms.\n", fsp->fsp_name )); } if (!owner_ace || !group_ace || !other_ace) { - DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get standard entries for file %s.\n", - fsp->fsp_name )); + DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get " + "standard entries for file %s.\n", fsp_str_dbg(fsp))); return False; } @@ -2956,9 +2949,10 @@ posix perms.\n", fsp->fsp_name )); *posix_perms = (((*posix_perms) & and_bits)|or_bits); - DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n", - (int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms, - fsp->fsp_name )); + DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o " + "to perm=0%o for file %s.\n", (int)owner_ace->perms, + (int)group_ace->perms, (int)other_ace->perms, + (int)*posix_perms, fsp_str_dbg(fsp))); return True; } @@ -3351,11 +3345,12 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, *ppdesc = NULL; - DEBUG(10,("posix_fget_nt_acl: called for file %s\n", fsp->fsp_name )); + DEBUG(10,("posix_fget_nt_acl: called for file %s\n", + fsp_str_dbg(fsp))); /* can it happen that fsp_name == NULL ? */ if (fsp->is_directory || fsp->fh->fd == -1) { - return posix_get_nt_acl(fsp->conn, fsp->fsp_name, + return posix_get_nt_acl(fsp->conn, fsp->fsp_name->base_name, security_info, ppdesc); } @@ -3369,40 +3364,53 @@ NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info, pal = fload_inherited_info(fsp); - return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name, &sbuf, pal, - posix_acl, NULL, security_info, ppdesc); + return posix_get_nt_acl_common(fsp->conn, fsp->fsp_name->base_name, + &sbuf, pal, posix_acl, NULL, + security_info, ppdesc); } NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, uint32_t security_info, SEC_DESC **ppdesc) { - SMB_STRUCT_STAT sbuf; SMB_ACL_T posix_acl = NULL; SMB_ACL_T def_acl = NULL; struct pai_val *pal; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; *ppdesc = NULL; DEBUG(10,("posix_get_nt_acl: called for file %s\n", name )); + status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* Get the stat struct for the owner info. */ - if(vfs_stat_smb_fname(conn, name, &sbuf) != 0) { - return map_nt_error_from_unix(errno); + if(SMB_VFS_STAT(conn, smb_fname) != 0) { + status = map_nt_error_from_unix(errno); + goto out; } /* Get the ACL from the path. */ posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_ACCESS); /* If it's a directory get the default POSIX ACL. */ - if(S_ISDIR(sbuf.st_ex_mode)) { + if(S_ISDIR(smb_fname->st.st_ex_mode)) { def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, name, SMB_ACL_TYPE_DEFAULT); def_acl = free_empty_sys_acl(conn, def_acl); } pal = load_inherited_info(conn, name); - return posix_get_nt_acl_common(conn, name, &sbuf, pal, posix_acl, - def_acl, security_info, ppdesc); + status = posix_get_nt_acl_common(conn, name, &smb_fname->st, pal, + posix_acl, def_acl, security_info, + ppdesc); + out: + TALLOC_FREE(smb_fname); + return status; } /**************************************************************************** @@ -3514,7 +3522,8 @@ NTSTATUS append_parent_acl(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - if (!parent_dirname(mem_ctx, fsp->fsp_name, &parent_name, NULL)) { + if (!parent_dirname(mem_ctx, fsp->fsp_name->base_name, &parent_name, + NULL)) { return NT_STATUS_NO_MEMORY; } @@ -3596,7 +3605,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, "ignoring non container " "inherit flags %u on ACE with sid %s " "from parent %s\n", - fsp->fsp_name, + fsp_str_dbg(fsp), (unsigned int)se->flags, sid_string_dbg(&se->trustee), parent_name)); @@ -3609,7 +3618,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, "ignoring non object " "inherit flags %u on ACE with sid %s " "from parent %s\n", - fsp->fsp_name, + fsp_str_dbg(fsp), (unsigned int)se->flags, sid_string_dbg(&se->trustee), parent_name)); @@ -3633,7 +3642,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, DEBUG(10,("append_parent_acl: path %s " "ignoring ACE with protected sid %s " "from parent %s\n", - fsp->fsp_name, + fsp_str_dbg(fsp), sid_string_dbg(&se->trustee), parent_name)); continue; @@ -3671,7 +3680,7 @@ NTSTATUS append_parent_acl(files_struct *fsp, DEBUG(10,("append_parent_acl: path %s " "inheriting ACE with sid %s " "from parent %s\n", - fsp->fsp_name, + fsp_str_dbg(fsp), sid_string_dbg(&se->trustee), parent_name)); } @@ -3707,21 +3716,13 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC bool set_acl_as_root = false; bool acl_set_support = false; bool ret = false; - struct smb_filename *smb_fname = NULL; - - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } DEBUG(10,("set_nt_acl: called for file %s\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); if (!CAN_WRITE(conn)) { DEBUG(10,("set acl rejected on read-only share\n")); - status = NT_STATUS_MEDIA_WRITE_PROTECTED; - goto out; + return NT_STATUS_MEDIA_WRITE_PROTECTED; } /* @@ -3729,19 +3730,17 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC */ if(fsp->is_directory || fsp->fh->fd == -1) { - if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) { - status = map_nt_error_from_unix(errno); - goto out; + if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name) != 0) { + return map_nt_error_from_unix(errno); } } else { - if(SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) { - status = map_nt_error_from_unix(errno); - goto out; + if(SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { + return map_nt_error_from_unix(errno); } } /* Save the original element we check against. */ - orig_mode = smb_fname->st.st_ex_mode; + orig_mode = fsp->fsp_name->st.st_ex_mode; /* * Unpack the user/group/world id's. @@ -3749,7 +3748,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { - goto out; + return status; } /* @@ -3758,24 +3757,22 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC * Noticed by Simo. */ - if (((user != (uid_t)-1) && (smb_fname->st.st_ex_uid != user)) || - (( grp != (gid_t)-1) && (smb_fname->st.st_ex_gid != grp))) { + if (((user != (uid_t)-1) && (fsp->fsp_name->st.st_ex_uid != user)) || + (( grp != (gid_t)-1) && (fsp->fsp_name->st.st_ex_gid != grp))) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", - smb_fname_str_dbg(smb_fname), (unsigned int)user, - (unsigned int)grp )); + fsp_str_dbg(fsp), (unsigned int)user, + (unsigned int)grp)); - if(try_chown(fsp->conn, smb_fname, user, grp) == -1) { + if(try_chown(fsp->conn, fsp->fsp_name, user, grp) == -1) { DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error " - "= %s.\n", smb_fname_str_dbg(smb_fname), + "= %s.\n", fsp_str_dbg(fsp), (unsigned int)user, (unsigned int)grp, strerror(errno))); if (errno == EPERM) { - status = NT_STATUS_INVALID_OWNER; - goto out; + return NT_STATUS_INVALID_OWNER; } - status = map_nt_error_from_unix(errno); - goto out; + return map_nt_error_from_unix(errno); } /* @@ -3784,25 +3781,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC */ if(fsp->is_directory) { - if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) { - status = map_nt_error_from_unix(errno); - goto out; + if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name) != 0) { + return map_nt_error_from_unix(errno); } } else { int sret; if(fsp->fh->fd == -1) - sret = SMB_VFS_STAT(fsp->conn, smb_fname); + sret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name); else - sret = SMB_VFS_FSTAT(fsp, &smb_fname->st); + sret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st); if(sret != 0) return map_nt_error_from_unix(errno); } /* Save the original element we check against. */ - orig_mode = smb_fname->st.st_ex_mode; + orig_mode = fsp->fsp_name->st.st_ex_mode; /* If we successfully chowned, we know we must * be able to set the acl, so do it as root. @@ -3810,24 +3806,22 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC set_acl_as_root = true; } - create_file_sids(&smb_fname->st, &file_owner_sid, &file_grp_sid); + create_file_sids(&fsp->fsp_name->st, &file_owner_sid, &file_grp_sid); - acl_perms = unpack_canon_ace(fsp, &smb_fname->st, &file_owner_sid, + acl_perms = unpack_canon_ace(fsp, &fsp->fsp_name->st, &file_owner_sid, &file_grp_sid, &file_ace_list, &dir_ace_list, security_info_sent, psd); /* Ignore W2K traverse DACL set. */ if (!file_ace_list && !dir_ace_list) { - status = NT_STATUS_OK; - goto out; + return NT_STATUS_OK; } if (!acl_perms) { DEBUG(3,("set_nt_acl: cannot set permissions\n")); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = NT_STATUS_ACCESS_DENIED; - goto out; + return NT_STATUS_ACCESS_DENIED; } /* @@ -3837,8 +3831,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) { free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = NT_STATUS_OK; - goto out; + return NT_STATUS_OK; } /* @@ -3851,18 +3844,17 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC become_root(); } ret = set_canon_ace_list(fsp, file_ace_list, false, - &smb_fname->st, &acl_set_support); + &fsp->fsp_name->st, &acl_set_support); if (set_acl_as_root) { unbecome_root(); } if (acl_set_support && ret == false) { DEBUG(3,("set_nt_acl: failed to set file acl on file " - "%s (%s).\n", smb_fname_str_dbg(smb_fname), + "%s (%s).\n", fsp_str_dbg(fsp), strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = map_nt_error_from_unix(errno); - goto out; + return map_nt_error_from_unix(errno); } } @@ -3872,7 +3864,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC become_root(); } ret = set_canon_ace_list(fsp, dir_ace_list, true, - &smb_fname->st, + &fsp->fsp_name->st, &acl_set_support); if (set_acl_as_root) { unbecome_root(); @@ -3880,12 +3872,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (ret == false) { DEBUG(3,("set_nt_acl: failed to set default " "acl on directory %s (%s).\n", - smb_fname_str_dbg(smb_fname), - strerror(errno) )); + fsp_str_dbg(fsp), strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = map_nt_error_from_unix(errno); - goto out; + return map_nt_error_from_unix(errno); } } else { int sret = -1; @@ -3898,23 +3888,23 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC become_root(); } sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, - smb_fname->base_name); + fsp->fsp_name->base_name); if (set_acl_as_root) { unbecome_root(); } if (sret == -1) { - if (acl_group_override(conn, smb_fname)) { + if (acl_group_override(conn, fsp->fsp_name)) { DEBUG(5,("set_nt_acl: acl group " "control on and current user " "in file %s primary group. " "Override delete_def_acl\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); become_root(); sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE( conn, - smb_fname->base_name); + fsp->fsp_name->base_name); unbecome_root(); } @@ -3922,8 +3912,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = map_nt_error_from_unix(errno); - goto out; + return map_nt_error_from_unix(errno); } } } @@ -3954,52 +3943,48 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC free_canon_ace_list(dir_ace_list); DEBUG(3,("set_nt_acl: failed to convert file acl to " "posix permissions for file %s.\n", - smb_fname_str_dbg(smb_fname))); - status = NT_STATUS_ACCESS_DENIED; - goto out; + fsp_str_dbg(fsp))); + return NT_STATUS_ACCESS_DENIED; } if (orig_mode != posix_perms) { int sret = -1; DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", - smb_fname_str_dbg(smb_fname), - (unsigned int)posix_perms)); + fsp_str_dbg(fsp), (unsigned int)posix_perms)); if (set_acl_as_root) { become_root(); } - sret = SMB_VFS_CHMOD(conn, smb_fname->base_name, + sret = SMB_VFS_CHMOD(conn, fsp->fsp_name->base_name, posix_perms); if (set_acl_as_root) { unbecome_root(); } if(sret == -1) { - if (acl_group_override(conn, smb_fname)) { + if (acl_group_override(conn, fsp->fsp_name)) { DEBUG(5,("set_nt_acl: acl group " "control on and current user " "in file %s primary group. " "Override chmod\n", - smb_fname_str_dbg(smb_fname))); + fsp_str_dbg(fsp))); become_root(); - sret = - SMB_VFS_CHMOD(conn, - smb_fname->base_name, - posix_perms); + sret = SMB_VFS_CHMOD(conn, + fsp->fsp_name->base_name, + posix_perms); unbecome_root(); } if (sret == -1) { DEBUG(3,("set_nt_acl: chmod %s, 0%o " "failed. Error = %s.\n", - smb_fname_str_dbg(smb_fname), + fsp_str_dbg(fsp), (unsigned int)posix_perms, strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = map_nt_error_from_unix(errno); - goto out; + return map_nt_error_from_unix(errno); } } } @@ -4008,10 +3993,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - status = NT_STATUS_OK; - out: - TALLOC_FREE(smb_fname); - return status; + return NT_STATUS_OK; } /**************************************************************************** @@ -4614,6 +4596,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) connection_struct *conn; files_struct finfo; struct fd_handle fh; + NTSTATUS status; conn = TALLOC_ZERO_P(ctx, connection_struct); if (conn == NULL) { @@ -4644,16 +4627,24 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) finfo.conn = conn; finfo.fh = &fh; finfo.fh->fd = -1; - finfo.fsp_name = CONST_DISCARD(char *,fname); + + status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, NULL, + &finfo.fsp_name); + if (!NT_STATUS_IS_OK(status)) { + conn_free_internal( conn ); + return NULL; + } if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); + TALLOC_FREE(finfo.fsp_name); conn_free_internal( conn ); return NULL; } ret_sd = dup_sec_desc( ctx, psd ); + TALLOC_FREE(finfo.fsp_name); conn_free_internal( conn ); return ret_sd; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index b26bc150db..c2065caf79 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2015,11 +2015,6 @@ void smbd_process(void) TALLOC_CTX *frame = talloc_stackframe(); char remaddr[INET6_ADDRSTRLEN]; - smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection); - if (!smbd_server_conn) { - exit_server("failed to create smbd_server_connection"); - } - if (lp_maxprotocol() == PROTOCOL_SMB2 && lp_security() != SEC_SHARE) { smbd_server_conn->allow_smb2 = true; diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 1fd4e50ea6..76d32a2f98 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -856,6 +856,7 @@ void reply_tcon_and_X(struct smb_request *req) END_PROFILE(SMBtconX); + req->tid = conn->cnum; chain_reply(req); return; } @@ -993,8 +994,7 @@ void reply_checkpath(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1090,8 +1090,7 @@ void reply_getatr(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1106,7 +1105,7 @@ void reply_getatr(struct smb_request *req) DEBUG(3,("reply_getatr: stat of %s failed (%s)\n", smb_fname_str_dbg(smb_fname), strerror(errno))); - reply_unixerror(req, ERRDOS,ERRbadfile); + reply_nterror(req, map_nt_error_from_unix(errno)); goto out; } @@ -1192,8 +1191,7 @@ void reply_setatr(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1220,7 +1218,7 @@ void reply_setatr(struct smb_request *req) ft.mtime = convert_time_t_to_timespec(mtime); status = smb_set_file_time(conn, NULL, smb_fname, &ft, true); if (!NT_STATUS_IS_OK(status)) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, status); goto out; } @@ -1232,7 +1230,7 @@ void reply_setatr(struct smb_request *req) if (file_set_dosmode(conn, smb_fname, mode, NULL, false) != 0) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); goto out; } } @@ -1258,7 +1256,7 @@ void reply_dskattr(struct smb_request *req) START_PROFILE(SMBdskattr); if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) { - reply_unixerror(req, ERRHRD, ERRgeneral); + reply_nterror(req, map_nt_error_from_unix(errno)); END_PROFILE(SMBdskattr); return; } @@ -1342,6 +1340,7 @@ void reply_search(struct smb_request *req) char *path = NULL; const char *mask = NULL; char *directory = NULL; + struct smb_filename *smb_fname = NULL; char *fname = NULL; SMB_OFF_T size; uint32 mode; @@ -1366,14 +1365,12 @@ void reply_search(struct smb_request *req) if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBsearch); - return; + goto out; } if (lp_posix_pathnames()) { reply_unknown_new(req, req->cmd); - END_PROFILE(SMBsearch); - return; + goto out; } /* If we were called as SMBffirst then we must expect close. */ @@ -1389,8 +1386,7 @@ void reply_search(struct smb_request *req) &nt_status, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; + goto out; } p++; @@ -1400,8 +1396,6 @@ void reply_search(struct smb_request *req) /* dirtype &= ~aDIR; */ if (status_len == 0) { - struct smb_filename *smb_fname = NULL; - nt_status = resolve_dfspath_wcard(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, path, @@ -1411,35 +1405,25 @@ void reply_search(struct smb_request *req) if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); - END_PROFILE(SMBsearch); - return; + goto out; } reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; + goto out; } nt_status = unix_convert(ctx, conn, path, &smb_fname, UCF_ALLOW_WCARD_LCOMP); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; + goto out; } - nt_status = get_full_smb_filename(ctx, smb_fname, &directory); - TALLOC_FREE(smb_fname); - if (!NT_STATUS_IS_OK(nt_status)) { - reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; - } + directory = smb_fname->base_name; nt_status = check_name(conn, directory); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; + goto out; } p = strrchr_m(directory,'/'); @@ -1454,8 +1438,7 @@ void reply_search(struct smb_request *req) if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; + goto out; } memset((char *)status,'\0',21); @@ -1472,8 +1455,7 @@ void reply_search(struct smb_request *req) &conn->dirptr); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; + goto out; } dptr_num = dptr_dnum(conn->dirptr); } else { @@ -1513,8 +1495,7 @@ void reply_search(struct smb_request *req) if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)), 0,aVOLID,0,!allow_long_path_components)) { reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; + goto out; } dptr_fill(buf+12,dptr_num); if (dptr_zero(buf+12) && (status_len==0)) { @@ -1526,8 +1507,7 @@ void reply_search(struct smb_request *req) data_blob_const(buf, sizeof(buf))) == -1) { reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; + goto out; } } else { unsigned int i; @@ -1566,8 +1546,7 @@ void reply_search(struct smb_request *req) convert_timespec_to_time_t(date), !allow_long_path_components)) { reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; + goto out; } if (!dptr_fill(buf+12,dptr_num)) { break; @@ -1576,8 +1555,7 @@ void reply_search(struct smb_request *req) data_blob_const(buf, sizeof(buf))) == -1) { reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; + goto out; } numentries++; } @@ -1604,8 +1582,7 @@ void reply_search(struct smb_request *req) if ((numentries == 0) && !mask_contains_wcard) { reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles); - END_PROFILE(SMBsearch); - return; + goto out; } SSVAL(req->outbuf,smb_vwv0,numentries); @@ -1637,7 +1614,8 @@ void reply_search(struct smb_request *req) dirtype, numentries, maxentries )); - + out: + TALLOC_FREE(smb_fname); END_PROFILE(SMBsearch); return; } @@ -1746,8 +1724,7 @@ void reply_open(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -1759,10 +1736,10 @@ void reply_open(struct smb_request *req) goto out; } - if (!map_open_params_to_ntcreate( - smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN, - &access_mask, &share_mode, &create_disposition, - &create_options)) { + if (!map_open_params_to_ntcreate(smb_fname, deny_mode, + OPENX_FILE_EXISTS_OPEN, &access_mask, + &share_mode, &create_disposition, + &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); goto out; } @@ -1811,7 +1788,8 @@ void reply_open(struct smb_request *req) mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); if (fattr & aDIR) { - DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name)); + DEBUG(3,("attempt to open a directory %s\n", + fsp_str_dbg(fsp))); close_file(req, fsp, ERROR_CLOSE); reply_doserror(req, ERRDOS,ERRnoaccess); goto out; @@ -1916,8 +1894,7 @@ void reply_open_and_X(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -1929,9 +1906,10 @@ void reply_open_and_X(struct smb_request *req) goto out; } - if (!map_open_params_to_ntcreate( - smb_fname->base_name, deny_mode, smb_ofun, &access_mask, - &share_mode, &create_disposition, &create_options)) { + if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun, + &access_mask, &share_mode, + &create_disposition, + &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); goto out; } @@ -2076,6 +2054,7 @@ void reply_ulogoffX(struct smb_request *req) DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) ); END_PROFILE(SMBulogoffX); + req->vuid = UID_FIELD_INVALID; chain_reply(req); } @@ -2124,8 +2103,7 @@ void reply_mknew(struct smb_request *req) conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -2257,8 +2235,7 @@ void reply_ctemp(struct smb_request *req) status = filename_convert(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2271,7 +2248,7 @@ void reply_ctemp(struct smb_request *req) tmpfd = mkstemp(smb_fname->base_name); if (tmpfd == -1) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); goto out; } @@ -2311,9 +2288,9 @@ void reply_ctemp(struct smb_request *req) SSVAL(req->outbuf,smb_vwv0,fsp->fnum); /* the returned filename is relative to the directory */ - s = strrchr_m(fsp->fsp_name, '/'); + s = strrchr_m(fsp->fsp_name->base_name, '/'); if (!s) { - s = fsp->fsp_name; + s = fsp->fsp_name->base_name; } else { s++; } @@ -2339,8 +2316,8 @@ void reply_ctemp(struct smb_request *req) CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } - DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) ); - DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name, + DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp))); + DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp), fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode)); out: TALLOC_FREE(smb_fname); @@ -2355,22 +2332,13 @@ void reply_ctemp(struct smb_request *req) static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, uint16 dirtype, SMB_STRUCT_STAT *pst) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; uint32 fmode; if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - pst, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - fmode = dos_mode(conn, smb_fname); - TALLOC_FREE(smb_fname); + fmode = dos_mode(conn, fsp->fsp_name); if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; } @@ -2646,18 +2614,23 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname->st))) { + TALLOC_CTX *frame = talloc_stackframe(); + if (!is_visible_file(conn, fname_dir, dname, &smb_fname->st, true)) { + TALLOC_FREE(frame); continue; } /* Quick check for "." and ".." */ if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(frame); continue; } if(!mask_match(dname, fname_mask, conn->case_sensitive)) { + TALLOC_FREE(frame); continue; } @@ -2669,23 +2642,28 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, if (!smb_fname->base_name) { TALLOC_FREE(dir_hnd); status = NT_STATUS_NO_MEMORY; + TALLOC_FREE(frame); goto out; } status = check_name(conn, smb_fname->base_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(frame); goto out; } status = do_unlink(conn, req, smb_fname, dirtype); if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); continue; } count++; DEBUG(3,("unlink_internals: successful unlink [%s]\n", smb_fname->base_name)); + + TALLOC_FREE(frame); } TALLOC_FREE(dir_hnd); } @@ -2854,7 +2832,7 @@ static void sendfile_short_send(files_struct *fsp, if (nread < headersize) { DEBUG(0,("sendfile_short_send: sendfile failed to send " "header for file %s (%s). Terminating\n", - fsp->fsp_name, strerror(errno) )); + fsp_str_dbg(fsp), strerror(errno))); exit_server_cleanly("sendfile_short_send failed"); } @@ -2868,7 +2846,7 @@ static void sendfile_short_send(files_struct *fsp, } DEBUG(0,("sendfile_short_send: filling truncated file %s " - "with zeros !\n", fsp->fsp_name)); + "with zeros !\n", fsp_str_dbg(fsp))); while (nread < smb_maxcnt) { /* @@ -2963,15 +2941,19 @@ static void send_file_readbraw(connection_struct *conn, DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n")); if (fake_sendfile(fsp, startpos, nread) == -1) { - DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(0,("send_file_readbraw: " + "fake_sendfile failed for " + "file %s (%s).\n", + fsp_str_dbg(fsp), + strerror(errno))); exit_server_cleanly("send_file_readbraw fake_sendfile failed"); } return; } - DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(0,("send_file_readbraw: sendfile failed for " + "file %s (%s). Terminating\n", + fsp_str_dbg(fsp), strerror(errno))); exit_server_cleanly("send_file_readbraw sendfile failed"); } else if (sendfile_read == 0) { /* @@ -2983,7 +2965,7 @@ static void send_file_readbraw(connection_struct *conn, */ DEBUG(3, ("send_file_readbraw: sendfile sent zero " "bytes falling back to the normal read: " - "%s\n", fsp->fsp_name)); + "%s\n", fsp_str_dbg(fsp))); goto normal_readbraw; } @@ -3269,7 +3251,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); END_PROFILE(SMBlockread); return; } @@ -3363,7 +3345,7 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", nread = read_file(fsp,data,startpos,numtoread); if (nread < 0) { - reply_unixerror(req, ERRDOS,ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); goto strict_unlock; } @@ -3425,9 +3407,10 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, SMB_STRUCT_STAT sbuf; ssize_t nread = -1; struct lock_struct lock; + int saved_errno = 0; if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); return; } @@ -3494,8 +3477,11 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, nread = fake_sendfile(fsp, startpos, smb_maxcnt); if (nread == -1) { - DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(0,("send_file_readX: " + "fake_sendfile failed for " + "file %s (%s).\n", + fsp_str_dbg(fsp), + strerror(errno))); exit_server_cleanly("send_file_readX: fake_sendfile failed"); } DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n", @@ -3504,8 +3490,9 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, goto strict_unlock; } - DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(0,("send_file_readX: sendfile failed for file " + "%s (%s). Terminating\n", fsp_str_dbg(fsp), + strerror(errno))); exit_server_cleanly("send_file_readX sendfile failed"); } else if (nread == 0) { /* @@ -3517,7 +3504,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, */ DEBUG(3, ("send_file_readX: sendfile sent zero bytes " "falling back to the normal read: %s\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); goto normal_read; } @@ -3547,14 +3534,16 @@ normal_read: /* Send out the header. */ if (write_data(smbd_server_fd(), (char *)headerbuf, sizeof(headerbuf)) != sizeof(headerbuf)) { - DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(0,("send_file_readX: write_data failed for file " + "%s (%s). Terminating\n", fsp_str_dbg(fsp), + strerror(errno))); exit_server_cleanly("send_file_readX sendfile failed"); } nread = fake_sendfile(fsp, startpos, smb_maxcnt); if (nread == -1) { - DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(0,("send_file_readX: fake_sendfile failed for " + "file %s (%s).\n", fsp_str_dbg(fsp), + strerror(errno))); exit_server_cleanly("send_file_readX: fake_sendfile failed"); } goto strict_unlock; @@ -3565,11 +3554,12 @@ nosendfile_read: reply_outbuf(req, 12, smb_maxcnt); nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt); + saved_errno = errno; SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); if (nread < 0) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(saved_errno)); return; } @@ -3810,7 +3800,7 @@ void reply_writebraw(struct smb_request *req) (int)nwritten, (int)write_through)); if (nwritten < (ssize_t)numtowrite) { - reply_unixerror(req, ERRHRD, ERRdiskfull); + reply_doserror(req, ERRHRD, ERRdiskfull); error_to_writebrawerr(req); goto strict_unlock; } @@ -3879,7 +3869,7 @@ void reply_writebraw(struct smb_request *req) nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite); if (nwritten == -1) { TALLOC_FREE(buf); - reply_unixerror(req, ERRHRD, ERRdiskfull); + reply_nterror(req, map_nt_error_from_unix(errno)); error_to_writebrawerr(req); goto strict_unlock; } @@ -3900,7 +3890,7 @@ void reply_writebraw(struct smb_request *req) status = sync_file(conn, fsp, write_through); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); reply_nterror(req, status); error_to_writebrawerr(req); goto strict_unlock; @@ -3958,6 +3948,7 @@ void reply_writeunlock(struct smb_request *req) NTSTATUS status = NT_STATUS_OK; files_struct *fsp; struct lock_struct lock; + int saved_errno = 0; START_PROFILE(SMBwriteunlock); @@ -4003,18 +3994,24 @@ void reply_writeunlock(struct smb_request *req) nwritten = 0; } else { nwritten = write_file(req,fsp,data,startpos,numtowrite); + saved_errno = errno; } status = sync_file(conn, fsp, False /* write through */); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); reply_nterror(req, status); goto strict_unlock; } - if(((nwritten < numtowrite) && (numtowrite != 0))||(nwritten < 0)) { - reply_unixerror(req, ERRHRD, ERRdiskfull); + if(nwritten < 0) { + reply_nterror(req, map_nt_error_from_unix(saved_errno)); + goto strict_unlock; + } + + if((nwritten < numtowrite) && (numtowrite != 0)) { + reply_doserror(req, ERRHRD, ERRdiskfull); goto strict_unlock; } @@ -4065,6 +4062,7 @@ void reply_write(struct smb_request *req) files_struct *fsp; struct lock_struct lock; NTSTATUS status; + int saved_errno = 0; START_PROFILE(SMBwrite); @@ -4136,13 +4134,18 @@ void reply_write(struct smb_request *req) status = sync_file(conn, fsp, False); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_write: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); reply_nterror(req, status); goto strict_unlock; } - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { - reply_unixerror(req, ERRHRD, ERRdiskfull); + if(nwritten < 0) { + reply_nterror(req, map_nt_error_from_unix(saved_errno)); + goto strict_unlock; + } + + if((nwritten == 0) && (numtowrite != 0)) { + reply_doserror(req, ERRHRD, ERRdiskfull); goto strict_unlock; } @@ -4389,8 +4392,13 @@ void reply_write_and_X(struct smb_request *req) nwritten = write_file(req,fsp,data,startpos,numtowrite); } - if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { - reply_unixerror(req, ERRHRD, ERRdiskfull); + if(nwritten < 0) { + reply_nterror(req, map_nt_error_from_unix(errno)); + goto strict_unlock; + } + + if((nwritten == 0) && (numtowrite != 0)) { + reply_doserror(req, ERRHRD, ERRdiskfull); goto strict_unlock; } @@ -4409,7 +4417,7 @@ void reply_write_and_X(struct smb_request *req) status = sync_file(conn, fsp, write_through); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); reply_nterror(req, status); goto strict_unlock; } @@ -4484,8 +4492,8 @@ void reply_lseek(struct smb_request *req) SMB_STRUCT_STAT sbuf; if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) { - reply_unixerror(req, ERRDOS, - ERRnoaccess); + reply_nterror(req, + map_nt_error_from_unix(errno)); END_PROFILE(SMBlseek); return; } @@ -4497,7 +4505,7 @@ void reply_lseek(struct smb_request *req) } if(res == -1) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); END_PROFILE(SMBlseek); return; } @@ -4545,7 +4553,7 @@ void reply_flush(struct smb_request *req) NTSTATUS status = sync_file(conn, fsp, True); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("reply_flush: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status) )); + fsp_str_dbg(fsp), nt_errstr(status))); reply_nterror(req, status); END_PROFILE(SMBflush); return; @@ -4713,8 +4721,8 @@ void reply_writeclose(struct smb_request *req) */ if (numtowrite) { - DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n", - fsp->fsp_name )); + DEBUG(3,("reply_writeclose: zero length write doesn't close " + "file %s\n", fsp_str_dbg(fsp))); close_status = close_file(req, fsp, NORMAL_CLOSE); } @@ -5197,7 +5205,7 @@ void reply_printwrite(struct smb_request *req) data = (const char *)req->buf + 3; if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) { - reply_unixerror(req, ERRHRD, ERRdiskfull); + reply_nterror(req, map_nt_error_from_unix(errno)); END_PROFILE(SMBsplwr); return; } @@ -5232,8 +5240,7 @@ void reply_mkdir(struct smb_request *req) status = filename_convert(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, - &smb_dname, - NULL); + &smb_dname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5540,8 +5547,7 @@ void reply_rmdir(struct smb_request *req) status = filename_convert(ctx, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, - &smb_dname, - NULL); + &smb_dname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5711,7 +5717,6 @@ static void rename_open_files(connection_struct *conn, { files_struct *fsp; bool did_rename = False; - char *fname_dst = NULL; NTSTATUS status; for(fsp = file_find_di_first(lck->id); fsp; @@ -5725,17 +5730,13 @@ static void rename_open_files(connection_struct *conn, } DEBUG(10, ("rename_open_files: renaming file fnum %d " "(file_id %s) from %s -> %s\n", fsp->fnum, - file_id_string_tos(&fsp->file_id), fsp->fsp_name, + file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp), smb_fname_str_dbg(smb_fname_dst))); - status = get_full_smb_filename(talloc_tos(), smb_fname_dst, - &fname_dst); - if (!NT_STATUS_IS_OK(status)) { - return; + status = fsp_set_smb_fname(fsp, smb_fname_dst); + if (NT_STATUS_IS_OK(status)) { + did_rename = True; } - string_set(&fsp->fsp_name, fname_dst); - did_rename = True; - TALLOC_FREE(fname_dst); } if (!did_rename) { @@ -5790,9 +5791,6 @@ static void notify_rename(connection_struct *conn, bool is_dir, { char *parent_dir_src = NULL; char *parent_dir_dst = NULL; - char *fname_src = NULL; - char *fname_dst = NULL; - NTSTATUS status; uint32 mask; mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME @@ -5805,24 +5803,17 @@ static void notify_rename(connection_struct *conn, bool is_dir, goto out; } - status = get_full_smb_filename(talloc_tos(), smb_fname_src, - &fname_src); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - status = get_full_smb_filename(talloc_tos(), smb_fname_dst, - &fname_dst); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - if (strcmp(parent_dir_src, parent_dir_dst) == 0) { - notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, fname_src); - notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, fname_dst); + notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, + smb_fname_src->base_name); + notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, + smb_fname_dst->base_name); } else { - notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, fname_src); - notify_fname(conn, NOTIFY_ACTION_ADDED, mask, fname_dst); + notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, + smb_fname_src->base_name); + notify_fname(conn, NOTIFY_ACTION_ADDED, mask, + smb_fname_dst->base_name); } /* this is a strange one. w2k3 gives an additional event for @@ -5832,13 +5823,11 @@ static void notify_rename(connection_struct *conn, bool is_dir, notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_ATTRIBUTES |FILE_NOTIFY_CHANGE_CREATION, - fname_dst); + smb_fname_dst->base_name); } out: TALLOC_FREE(parent_dir_src); TALLOC_FREE(parent_dir_dst); - TALLOC_FREE(fname_src); - TALLOC_FREE(fname_dst); } /**************************************************************************** @@ -5867,17 +5856,12 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, } /* Make a copy of the src and dst smb_fname structs */ - status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst); + status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src); if (!NT_STATUS_IS_OK(status)) { goto out; } - /* - * This will be replaced with copy_smb_filename() when fsp->fsp_name - * is converted to store an smb_filename struct. - */ - status = create_synthetic_smb_fname_split(ctx, fsp->fsp_name, NULL, - &smb_fname_src); + status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst); if (!NT_STATUS_IS_OK(status)) { goto out; } @@ -6635,8 +6619,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, if (!target_is_directory && count) { new_create_disposition = FILE_OPEN; } else { - if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name, - 0, ofun, NULL, NULL, + if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun, + NULL, NULL, &new_create_disposition, NULL)) { status = NT_STATUS_INVALID_PARAMETER; @@ -6756,7 +6740,6 @@ void reply_copy(struct smb_request *req) const char *p; int count=0; int error = ERRnoaccess; - int err = 0; int tid2; int ofun; int flags; @@ -7059,13 +7042,6 @@ void reply_copy(struct smb_request *req) } if (count == 0) { - if(err) { - /* Error on close... */ - errno = err; - reply_unixerror(req, ERRHRD, ERRgeneral); - goto out; - } - reply_doserror(req, ERRDOS, error); goto out; } @@ -7223,6 +7199,205 @@ uint64_t get_lock_offset(const uint8_t *data, int data_offset, return offset; } +NTSTATUS smbd_do_locking(struct smb_request *req, + files_struct *fsp, + uint8_t type, + int32_t timeout, + uint16_t num_ulocks, + struct smbd_lock_element *ulocks, + uint16_t num_locks, + struct smbd_lock_element *locks, + bool *async) +{ + connection_struct *conn = req->conn; + int i; + NTSTATUS status = NT_STATUS_OK; + + *async = false; + + /* Data now points at the beginning of the list + of smb_unlkrng structs */ + for(i = 0; i < (int)num_ulocks; i++) { + struct smbd_lock_element *e = &ulocks[i]; + + DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for " + "pid %u, file %s\n", + (double)e->offset, + (double)e->count, + (unsigned int)e->smbpid, + fsp_str_dbg(fsp))); + + if (e->brltype != UNLOCK_LOCK) { + /* this can only happen with SMB2 */ + return NT_STATUS_INVALID_PARAMETER; + } + + status = do_unlock(smbd_messaging_context(), + fsp, + e->smbpid, + e->count, + e->offset, + WINDOWS_LOCK); + + DEBUG(10, ("smbd_do_locking: unlock returned %s\n", + nt_errstr(status))); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + /* Setup the timeout in seconds. */ + + if (!lp_blocking_locks(SNUM(conn))) { + timeout = 0; + } + + /* Data now points at the beginning of the list + of smb_lkrng structs */ + + for(i = 0; i < (int)num_locks; i++) { + struct smbd_lock_element *e = &locks[i]; + + DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid " + "%u, file %s timeout = %d\n", + (double)e->offset, + (double)e->count, + (unsigned int)e->smbpid, + fsp_str_dbg(fsp), + (int)timeout)); + + if (type & LOCKING_ANDX_CANCEL_LOCK) { + struct blocking_lock_record *blr = NULL; + + if (lp_blocking_locks(SNUM(conn))) { + + /* Schedule a message to ourselves to + remove the blocking lock record and + return the right error. */ + + blr = blocking_lock_cancel(fsp, + e->smbpid, + e->offset, + e->count, + WINDOWS_LOCK, + type, + NT_STATUS_FILE_LOCK_CONFLICT); + if (blr == NULL) { + return NT_STATUS_DOS( + ERRDOS, + ERRcancelviolation); + } + } + /* Remove a matching pending lock. */ + status = do_lock_cancel(fsp, + e->smbpid, + e->count, + e->offset, + WINDOWS_LOCK, + blr); + } else { + bool blocking_lock = timeout ? true : false; + bool defer_lock = false; + struct byte_range_lock *br_lck; + uint32_t block_smbpid; + + br_lck = do_lock(smbd_messaging_context(), + fsp, + e->smbpid, + e->count, + e->offset, + e->brltype, + WINDOWS_LOCK, + blocking_lock, + &status, + &block_smbpid, + NULL); + + if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { + /* Windows internal resolution for blocking locks seems + to be about 200ms... Don't wait for less than that. JRA. */ + if (timeout != -1 && timeout < lp_lock_spin_time()) { + timeout = lp_lock_spin_time(); + } + defer_lock = true; + } + + /* This heuristic seems to match W2K3 very well. If a + lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT + it pretends we asked for a timeout of between 150 - 300 milliseconds as + far as I can tell. Replacement for do_lock_spin(). JRA. */ + + if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock && + NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) { + defer_lock = true; + timeout = lp_lock_spin_time(); + } + + if (br_lck && defer_lock) { + /* + * A blocking lock was requested. Package up + * this smb into a queued request and push it + * onto the blocking lock queue. + */ + if(push_blocking_lock_request(br_lck, + req, + fsp, + timeout, + i, + e->smbpid, + e->brltype, + WINDOWS_LOCK, + e->offset, + e->count, + block_smbpid)) { + TALLOC_FREE(br_lck); + *async = true; + return NT_STATUS_OK; + } + } + + TALLOC_FREE(br_lck); + } + + if (!NT_STATUS_IS_OK(status)) { + break; + } + } + + /* If any of the above locks failed, then we must unlock + all of the previous locks (X/Open spec). */ + + if (num_locks != 0 && !NT_STATUS_IS_OK(status)) { + + if (type & LOCKING_ANDX_CANCEL_LOCK) { + i = -1; /* we want to skip the for loop */ + } + + /* + * Ensure we don't do a remove on the lock that just failed, + * as under POSIX rules, if we have a lock already there, we + * will delete it (and we shouldn't) ..... + */ + for(i--; i >= 0; i--) { + struct smbd_lock_element *e = &locks[i]; + + do_unlock(smbd_messaging_context(), + fsp, + e->smbpid, + e->count, + e->offset, + WINDOWS_LOCK); + } + return status; + } + + DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n", + fsp->fnum, (unsigned int)type, num_locks, num_ulocks)); + + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a lockingX request. ****************************************************************************/ @@ -7235,14 +7410,15 @@ void reply_lockingX(struct smb_request *req) unsigned char oplocklevel; uint16 num_ulocks; uint16 num_locks; - uint64_t count = 0, offset = 0; - uint32 lock_pid; int32 lock_timeout; int i; const uint8_t *data; bool large_file_format; bool err; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + struct smbd_lock_element *ulocks; + struct smbd_lock_element *locks; + bool async = false; START_PROFILE(SMBlockingX); @@ -7304,7 +7480,8 @@ void reply_lockingX(struct smb_request *req) DEBUG(5,("reply_lockingX: Error : oplock break from " "client for fnum = %d (oplock=%d) and no " "oplock granted on this file (%s).\n", - fsp->fnum, fsp->oplock_type, fsp->fsp_name)); + fsp->fnum, fsp->oplock_type, + fsp_str_dbg(fsp))); /* if this is a pure oplock break request then don't * send a reply */ @@ -7327,7 +7504,7 @@ void reply_lockingX(struct smb_request *req) if (!result) { DEBUG(0, ("reply_lockingX: error in removing " - "oplock on file %s\n", fsp->fsp_name)); + "oplock on file %s\n", fsp_str_dbg(fsp))); /* Hmmm. Is this panic justified? */ smb_panic("internal tdb error"); } @@ -7355,12 +7532,27 @@ void reply_lockingX(struct smb_request *req) return; } + ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks); + if (ulocks == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBlockingX); + return; + } + + locks = talloc_array(req, struct smbd_lock_element, num_locks); + if (locks == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBlockingX); + return; + } + /* Data now points at the beginning of the list of smb_unlkrng structs */ for(i = 0; i < (int)num_ulocks; i++) { - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); + ulocks[i].smbpid = get_lock_pid(data, i, large_file_format); + ulocks[i].count = get_lock_count(data, i, large_file_format); + ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err); + ulocks[i].brltype = UNLOCK_LOCK; /* * There is no error code marked "stupid client bug".... :-). @@ -7370,32 +7562,6 @@ void reply_lockingX(struct smb_request *req) reply_doserror(req, ERRDOS, ERRnoaccess); return; } - - DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for " - "pid %u, file %s\n", (double)offset, (double)count, - (unsigned int)lock_pid, fsp->fsp_name )); - - status = do_unlock(smbd_messaging_context(), - fsp, - lock_pid, - count, - offset, - WINDOWS_LOCK); - - DEBUG(10, ("reply_lockingX: unlock returned %s\n", - nt_errstr(status))); - - if (NT_STATUS_V(status)) { - END_PROFILE(SMBlockingX); - reply_nterror(req, status); - return; - } - } - - /* Setup the timeout in seconds. */ - - if (!lp_blocking_locks(SNUM(conn))) { - lock_timeout = 0; } /* Now do any requested locks */ @@ -7405,11 +7571,23 @@ void reply_lockingX(struct smb_request *req) of smb_lkrng structs */ for(i = 0; i < (int)num_locks; i++) { - enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ? - READ_LOCK:WRITE_LOCK); - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); + locks[i].smbpid = get_lock_pid(data, i, large_file_format); + locks[i].count = get_lock_count(data, i, large_file_format); + locks[i].offset = get_lock_offset(data, i, large_file_format, &err); + + if (locktype & LOCKING_ANDX_SHARED_LOCK) { + if (locktype & LOCKING_ANDX_CANCEL_LOCK) { + locks[i].brltype = PENDING_READ_LOCK; + } else { + locks[i].brltype = READ_LOCK; + } + } else { + if (locktype & LOCKING_ANDX_CANCEL_LOCK) { + locks[i].brltype = PENDING_WRITE_LOCK; + } else { + locks[i].brltype = WRITE_LOCK; + } + } /* * There is no error code marked "stupid client bug".... :-). @@ -7419,154 +7597,22 @@ void reply_lockingX(struct smb_request *req) reply_doserror(req, ERRDOS, ERRnoaccess); return; } - - DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid " - "%u, file %s timeout = %d\n", (double)offset, - (double)count, (unsigned int)lock_pid, - fsp->fsp_name, (int)lock_timeout )); - - if (locktype & LOCKING_ANDX_CANCEL_LOCK) { - struct blocking_lock_record *blr = NULL; - - if (lp_blocking_locks(SNUM(conn))) { - - /* Schedule a message to ourselves to - remove the blocking lock record and - return the right error. */ - - blr = blocking_lock_cancel(fsp, - lock_pid, - offset, - count, - WINDOWS_LOCK, - locktype, - NT_STATUS_FILE_LOCK_CONFLICT); - if (blr == NULL) { - END_PROFILE(SMBlockingX); - reply_nterror( - req, - NT_STATUS_DOS( - ERRDOS, - ERRcancelviolation)); - return; - } - } - /* Remove a matching pending lock. */ - status = do_lock_cancel(fsp, - lock_pid, - count, - offset, - WINDOWS_LOCK, - blr); - } else { - bool blocking_lock = lock_timeout ? True : False; - bool defer_lock = False; - struct byte_range_lock *br_lck; - uint32 block_smbpid; - - br_lck = do_lock(smbd_messaging_context(), - fsp, - lock_pid, - count, - offset, - lock_type, - WINDOWS_LOCK, - blocking_lock, - &status, - &block_smbpid, - NULL); - - if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) { - /* Windows internal resolution for blocking locks seems - to be about 200ms... Don't wait for less than that. JRA. */ - if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) { - lock_timeout = lp_lock_spin_time(); - } - defer_lock = True; - } - - /* This heuristic seems to match W2K3 very well. If a - lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT - it pretends we asked for a timeout of between 150 - 300 milliseconds as - far as I can tell. Replacement for do_lock_spin(). JRA. */ - - if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock && - NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) { - defer_lock = True; - lock_timeout = lp_lock_spin_time(); - } - - if (br_lck && defer_lock) { - /* - * A blocking lock was requested. Package up - * this smb into a queued request and push it - * onto the blocking lock queue. - */ - if(push_blocking_lock_request(br_lck, - req, - fsp, - lock_timeout, - i, - lock_pid, - lock_type, - WINDOWS_LOCK, - offset, - count, - block_smbpid)) { - TALLOC_FREE(br_lck); - END_PROFILE(SMBlockingX); - return; - } - } - - TALLOC_FREE(br_lck); - } - - if (NT_STATUS_V(status)) { - break; - } } - /* If any of the above locks failed, then we must unlock - all of the previous locks (X/Open spec). */ - if (num_locks != 0 && !NT_STATUS_IS_OK(status)) { - - if (locktype & LOCKING_ANDX_CANCEL_LOCK) { - i = -1; /* we want to skip the for loop */ - } - - /* - * Ensure we don't do a remove on the lock that just failed, - * as under POSIX rules, if we have a lock already there, we - * will delete it (and we shouldn't) ..... - */ - for(i--; i >= 0; i--) { - lock_pid = get_lock_pid( data, i, large_file_format); - count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, - &err); - - /* - * There is no error code marked "stupid client - * bug".... :-). - */ - if(err) { - END_PROFILE(SMBlockingX); - reply_doserror(req, ERRDOS, ERRnoaccess); - return; - } - - do_unlock(smbd_messaging_context(), - fsp, - lock_pid, - count, - offset, - WINDOWS_LOCK); - } + status = smbd_do_locking(req, fsp, + locktype, lock_timeout, + num_ulocks, ulocks, + num_locks, locks, + &async); + if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBlockingX); reply_nterror(req, status); return; } + if (async) { + END_PROFILE(SMBlockingX); + return; + } reply_outbuf(req, 2, 0); @@ -7615,7 +7661,6 @@ void reply_readbs(struct smb_request *req) void reply_setattrE(struct smb_request *req) { connection_struct *conn = req->conn; - struct smb_filename *smb_fname = NULL; struct smb_file_time ft; files_struct *fsp; NTSTATUS status; @@ -7635,14 +7680,6 @@ void reply_setattrE(struct smb_request *req) goto out; } - /* XXX: Remove when fsp->fsp_name is converted to smb_filename. */ - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - /* * Convert the DOS times into unix times. */ @@ -7663,7 +7700,7 @@ void reply_setattrE(struct smb_request *req) /* Ensure we have a valid stat struct for the source. */ if (fsp->fh->fd != -1) { - if (SMB_VFS_FSTAT(fsp, &smb_fname->st) == -1) { + if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); goto out; @@ -7672,9 +7709,9 @@ void reply_setattrE(struct smb_request *req) int ret = -1; if (fsp->posix_open) { - ret = SMB_VFS_LSTAT(conn, smb_fname); + ret = SMB_VFS_LSTAT(conn, fsp->fsp_name); } else { - ret = SMB_VFS_STAT(conn, smb_fname); + ret = SMB_VFS_STAT(conn, fsp->fsp_name); } if (ret == -1) { status = map_nt_error_from_unix(errno); @@ -7683,7 +7720,7 @@ void reply_setattrE(struct smb_request *req) } } - status = smb_set_file_time(conn, fsp, smb_fname, &ft, true); + status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true); if (!NT_STATUS_IS_OK(status)) { reply_doserror(req, ERRDOS, ERRnoaccess); goto out; @@ -7743,8 +7780,6 @@ void reply_getattrE(struct smb_request *req) int mode; files_struct *fsp; struct timespec create_ts; - struct smb_filename *smb_fname = NULL; - NTSTATUS status; START_PROFILE(SMBgetattrE); @@ -7764,21 +7799,14 @@ void reply_getattrE(struct smb_request *req) /* Do an fstat on this file */ if(fsp_stat(fsp, &sbuf)) { - reply_unixerror(req, ERRDOS, ERRnoaccess); + reply_nterror(req, map_nt_error_from_unix(errno)); END_PROFILE(SMBgetattrE); return; } - status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, - &sbuf, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - END_PROFILE(SMBgetattrE); - return; - } + fsp->fsp_name->st = sbuf; - mode = dos_mode(conn, smb_fname); - TALLOC_FREE(smb_fname); + mode = dos_mode(conn, fsp->fsp_name); /* * Convert the times into dos times. Set create diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 6951fac171..4b1c803d75 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -94,6 +94,7 @@ static void smb_conf_updated(struct messaging_context *msg, { DEBUG(10,("smb_conf_updated: Got message saying smb.conf was " "updated. Reloading.\n")); + change_to_root_user(); reload_services(False); } @@ -868,6 +869,7 @@ static void exit_server_common(enum server_exit_reason how, if (am_parent) { pidfile_unlink(); } + gencache_stabilize(); } /* if we had any open SMB connections when we exited then we diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 0124b2b047..a043288bc9 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -182,8 +182,8 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir) if (do_chdir && vfs_ChDir(conn,conn->connectpath) != 0 && vfs_ChDir(conn,conn->origpath) != 0) { - DEBUG(0,("chdir (%s) failed\n", - conn->connectpath)); + DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n", + conn->connectpath, strerror(errno))); return(False); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 3988105fa4..2d2e5141ee 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1807,6 +1807,7 @@ void reply_sesssetup_and_X(struct smb_request *req) SSVAL(req->outbuf,smb_uid,sess_vuid); SSVAL(req->inbuf,smb_uid,sess_vuid); + req->vuid = sess_vuid; if (!sconn->smb1.sessions.done_sesssetup) { sconn->smb1.sessions.max_send = diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c index 6724e5cc15..acb5da7751 100644 --- a/source3/smbd/smb2_close.c +++ b/source3/smbd/smb2_close.c @@ -107,11 +107,6 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req, return NT_STATUS_NO_MEMORY; } - /* If it's an IPC, pass off the pipe handler. */ - if (IS_IPC(conn)) { - return NT_STATUS_NOT_IMPLEMENTED; - } - fsp = file_fsp(smbreq, (uint16_t)in_file_id_volatile); if (fsp == NULL) { return NT_STATUS_FILE_CLOSED; @@ -126,7 +121,7 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req, status = close_file(smbreq, fsp, NORMAL_CLOSE); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n", - fsp->fsp_name, nt_errstr(status))); + fsp_str_dbg(fsp), nt_errstr(status))); return status; } diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index bdff1939e5..b455f82d80 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -259,7 +259,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, files_struct *result; int info; SMB_STRUCT_STAT sbuf; - struct smb_filename *smb_fname = NULL; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_create_state); @@ -316,6 +315,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, } info = FILE_WAS_CREATED; } else { + struct smb_filename *smb_fname = NULL; + /* these are ignored for SMB2 */ in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */ in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */ @@ -324,10 +325,10 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, smbreq->conn, smbreq->flags2 & FLAGS2_DFS_PATHNAMES, in_name, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); + TALLOC_FREE(smb_fname); goto out; } @@ -348,19 +349,11 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, &info); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); + TALLOC_FREE(smb_fname); goto out; } sbuf = smb_fname->st; - } - - if (!smb_fname) { - status = create_synthetic_smb_fname_split(talloc_tos(), - result->fsp_name, - &sbuf, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - goto out; - } + TALLOC_FREE(smb_fname); } smb2req->compat_chain_fsp = smbreq->chain_fsp; @@ -379,7 +372,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, state->out_allocation_size = sbuf.st_ex_blksize * sbuf.st_ex_blocks; state->out_end_of_file = sbuf.st_ex_size; state->out_file_attributes = dos_mode(result->conn, - smb_fname); + result->fsp_name); if (state->out_file_attributes == 0) { state->out_file_attributes = FILE_ATTRIBUTE_NORMAL; } @@ -387,7 +380,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, tevent_req_done(req); out: - TALLOC_FREE(smb_fname); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c index 8ce683923b..1d3ae2eb06 100644 --- a/source3/smbd/smb2_flush.c +++ b/source3/smbd/smb2_flush.c @@ -176,7 +176,7 @@ static struct tevent_req *smbd_smb2_flush_send(TALLOC_CTX *mem_ctx, status = sync_file(smbreq->conn, fsp, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("smbd_smb2_flush: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status))); + fsp_str_dbg(fsp), nt_errstr(status))); tevent_req_nterror(req, status); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c index ba725fdec9..5a6e3d7ecb 100644 --- a/source3/smbd/smb2_getinfo.c +++ b/source3/smbd/smb2_getinfo.c @@ -233,7 +233,177 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED); + if (IS_IPC(conn)) { + tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); + return tevent_req_post(req, ev); + } + + switch (in_info_type) { + case 0x01:/* SMB2_GETINFO_FILE */ + { + uint16_t file_info_level; + char *data = NULL; + unsigned int data_size = 0; + bool delete_pending = false; + struct timespec write_time_ts; + struct file_id fileid; + struct ea_list *ea_list = NULL; + int lock_data_count = 0; + char *lock_data = NULL; + bool ms_dfs_link = false; + NTSTATUS status; + + ZERO_STRUCT(write_time_ts); + + switch (in_file_info_class) { + case 0x0F:/* RAW_FILEINFO_SMB2_ALL_EAS */ + file_info_level = 0xFF00 | in_file_info_class; + break; + + case 0x12:/* RAW_FILEINFO_SMB2_ALL_INFORMATION */ + file_info_level = 0xFF00 | in_file_info_class; + break; + + default: + /* the levels directly map to the passthru levels */ + file_info_level = in_file_info_class + 1000; + break; + } + + if (fsp->fake_file_handle) { + /* + * This is actually for the QUOTA_FAKE_FILE --metze + */ + + /* We know this name is ok, it's already passed the checks. */ + + } else if (fsp && (fsp->is_directory || fsp->fh->fd == -1)) { + /* + * This is actually a QFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + + if (INFO_LEVEL_IS_UNIX(file_info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn, fsp->fsp_name)) { + DEBUG(3,("smbd_smb2_getinfo_send: " + "SMB_VFS_LSTAT of %s failed " + "(%s)\n", fsp_str_dbg(fsp), + strerror(errno))); + status = map_nt_error_from_unix(errno); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + } else if (SMB_VFS_STAT(conn, fsp->fsp_name)) { + DEBUG(3,("smbd_smb2_getinfo_send: " + "SMB_VFS_STAT of %s failed (%s)\n", + fsp_str_dbg(fsp), + strerror(errno))); + status = map_nt_error_from_unix(errno); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + + fileid = vfs_file_id_from_sbuf(conn, + &fsp->fsp_name->st); + get_file_infos(fileid, &delete_pending, &write_time_ts); + } else { + /* + * Original code - this is an open file. + */ + + if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { + DEBUG(3, ("smbd_smb2_getinfo_send: " + "fstat of fnum %d failed (%s)\n", + fsp->fnum, strerror(errno))); + status = map_nt_error_from_unix(errno); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + fileid = vfs_file_id_from_sbuf(conn, + &fsp->fsp_name->st); + get_file_infos(fileid, &delete_pending, &write_time_ts); + } + + status = smbd_do_qfilepathinfo(conn, state, + file_info_level, + fsp, + fsp->fsp_name, + delete_pending, + write_time_ts, + ms_dfs_link, + ea_list, + lock_data_count, + lock_data, + STR_UNICODE, + in_output_buffer_length, + &data, + &data_size); + if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(data); + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { + status = NT_STATUS_INVALID_INFO_CLASS; + } + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + if (data_size > 0) { + state->out_output_buffer = data_blob_talloc(state, + data, + data_size); + SAFE_FREE(data); + if (tevent_req_nomem(state->out_output_buffer.data, req)) { + return tevent_req_post(req, ev); + } + } + SAFE_FREE(data); + break; + } + + case 0x02:/* SMB2_GETINFO_FS */ + { + uint16_t file_info_level; + char *data = NULL; + int data_size = 0; + NTSTATUS status; + + /* the levels directly map to the passthru levels */ + file_info_level = in_file_info_class + 1000; + + status = smbd_do_qfsinfo(conn, state, + file_info_level, + STR_UNICODE, + in_output_buffer_length, + &data, + &data_size); + if (!NT_STATUS_IS_OK(status)) { + SAFE_FREE(data); + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { + status = NT_STATUS_INVALID_INFO_CLASS; + } + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + if (data_size > 0) { + state->out_output_buffer = data_blob_talloc(state, + data, + data_size); + SAFE_FREE(data); + if (tevent_req_nomem(state->out_output_buffer.data, req)) { + return tevent_req_post(req, ev); + } + } + SAFE_FREE(data); + break; + } + + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + tevent_req_done(req); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c index 3ffe053481..121b4eb24d 100644 --- a/source3/smbd/smb2_lock.c +++ b/source3/smbd/smb2_lock.c @@ -31,6 +31,7 @@ struct smbd_smb2_lock_element { static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, + uint32_t in_smbpid, uint64_t in_file_id_volatile, uint16_t in_lock_count, struct smbd_smb2_lock_element *in_locks); @@ -41,15 +42,17 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req) { const uint8_t *inhdr; const uint8_t *inbody; - int i = req->current_idx; + const int i = req->current_idx; size_t expected_body_size = 0x30; size_t body_size; + uint32_t in_smbpid; uint16_t in_lock_count; uint64_t in_file_id_persistent; uint64_t in_file_id_volatile; struct smbd_smb2_lock_element *in_locks; struct tevent_req *subreq; const uint8_t *lock_buffer; + uint16_t l; inhdr = (const uint8_t *)req->in.vector[i+0].iov_base; if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) { @@ -63,8 +66,10 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } + in_smbpid = IVAL(inhdr, SMB2_HDR_PID); + in_lock_count = CVAL(inbody, 0x02); - /* 0x04 4 bytes reserved */ + /* 0x04 - 4 bytes reserved */ in_file_id_persistent = BVAL(inbody, 0x08); in_file_id_volatile = BVAL(inbody, 0x10); @@ -88,19 +93,21 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req) return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); } - i = 0; + l = 0; lock_buffer = inbody + 0x18; - in_locks[i].offset = BVAL(lock_buffer, 0x00); - in_locks[i].length = BVAL(lock_buffer, 0x08); - in_locks[i].flags = BVAL(lock_buffer, 0x10); + in_locks[l].offset = BVAL(lock_buffer, 0x00); + in_locks[l].length = BVAL(lock_buffer, 0x08); + in_locks[l].flags = IVAL(lock_buffer, 0x10); + /* 0x14 - 4 reserved bytes */ lock_buffer = (const uint8_t *)req->in.vector[i+2].iov_base; - for (i=1; i < in_lock_count; i++) { - in_locks[i].offset = BVAL(lock_buffer, 0x00); - in_locks[i].length = BVAL(lock_buffer, 0x08); - in_locks[i].flags = BVAL(lock_buffer, 0x10); + for (l=1; l < in_lock_count; l++) { + in_locks[l].offset = BVAL(lock_buffer, 0x00); + in_locks[l].length = BVAL(lock_buffer, 0x08); + in_locks[l].flags = IVAL(lock_buffer, 0x10); + /* 0x14 - 4 reserved bytes */ lock_buffer += 0x18; } @@ -108,6 +115,7 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req) subreq = smbd_smb2_lock_send(req, req->conn->smb2.event_ctx, req, + in_smbpid, in_file_id_volatile, in_lock_count, in_locks); @@ -172,6 +180,7 @@ struct smbd_smb2_lock_state { static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_smb2_request *smb2req, + uint32_t in_smbpid, uint64_t in_file_id_volatile, uint16_t in_lock_count, struct smbd_smb2_lock_element *in_locks) @@ -181,6 +190,12 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, struct smb_request *smbreq; connection_struct *conn = smb2req->tcon->compat_conn; files_struct *fsp; + int32_t timeout = -1; + bool isunlock = false; + uint16_t i; + struct smbd_lock_element *locks; + NTSTATUS status; + bool async = false; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_lock_state); @@ -211,7 +226,150 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED); + locks = talloc_array(state, struct smbd_lock_element, in_lock_count); + if (locks == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return tevent_req_post(req, ev); + } + + switch (in_locks[0].flags) { + case SMB2_LOCK_FLAG_SHARED: + case SMB2_LOCK_FLAG_EXCLUSIVE: + if (in_lock_count > 1) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + timeout = -1; + break; + + case SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY: + case SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY: + timeout = 0; + break; + + case SMB2_LOCK_FLAG_UNLOCK: + /* only the first lock gives the UNLOCK bit - see + MS-SMB2 3.3.5.14 */ + isunlock = true; + timeout = 0; + break; + + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + for (i=0; i<in_lock_count; i++) { + uint64_t max_count; + bool invalid = false; + + switch (in_locks[i].flags) { + case SMB2_LOCK_FLAG_SHARED: + case SMB2_LOCK_FLAG_EXCLUSIVE: + if (i > 0) { + tevent_req_nterror(req, + NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + if (isunlock) { + tevent_req_nterror(req, + NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + break; + + case SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY: + case SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY: + if (isunlock) { + tevent_req_nterror(req, + NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + break; + + case SMB2_LOCK_FLAG_UNLOCK: + if (!isunlock) { + tevent_req_nterror(req, + NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + break; + + default: + if (isunlock) { + /* + * is the first element was a UNLOCK + * we need to deferr the error response + * to the backend, because we need to process + * all unlock elements before + */ + invalid = true; + break; + } + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + locks[i].smbpid = in_smbpid; + locks[i].offset = in_locks[i].offset; + locks[i].count = in_locks[i].length; + + if (in_locks[i].flags & SMB2_LOCK_FLAG_EXCLUSIVE) { + locks[i].brltype = WRITE_LOCK; + } else if (in_locks[i].flags & SMB2_LOCK_FLAG_SHARED) { + locks[i].brltype = READ_LOCK; + } else if (invalid) { + /* + * this is an invalid UNLOCK element + * and the backend needs to test for + * brltype != UNLOCK_LOCK and return + * NT_STATUS_INVALID_PARAMER + */ + locks[i].brltype = READ_LOCK; + } else { + locks[i].brltype = UNLOCK_LOCK; + } + + max_count = UINT64_MAX - locks[i].offset; + if (locks[i].count > max_count) { + tevent_req_nterror(req, NT_STATUS_INVALID_LOCK_RANGE); + return tevent_req_post(req, ev); + } + } + + if (isunlock) { + status = smbd_do_locking(smbreq, fsp, + 0, + timeout, + in_lock_count, + locks, + 0, + NULL, + &async); + } else { + status = smbd_do_locking(smbreq, fsp, + 0, + timeout, + 0, + NULL, + in_lock_count, + locks, + &async); + } + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_LOCK_CONFLICT)) { + status = NT_STATUS_LOCK_NOT_GRANTED; + } + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + + if (async) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return tevent_req_post(req, ev); + } + + tevent_req_done(req); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c index 7ab93ce574..f6d83aeeed 100644 --- a/source3/smbd/smb2_notify.c +++ b/source3/smbd/smb2_notify.c @@ -231,7 +231,7 @@ static struct tevent_req *smbd_smb2_notify_send(TALLOC_CTX *mem_ctx, DEBUG(3,("smbd_smb2_notify_send: notify change " "called on %s, filter = %s, recursive = %d\n", - fsp->fsp_name, filter_string, recursive)); + fsp_str_dbg(fsp), filter_string, recursive)); TALLOC_FREE(filter_string); } diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c index c9f281f73e..42993511ec 100644 --- a/source3/smbd/smb2_read.c +++ b/source3/smbd/smb2_read.c @@ -281,13 +281,13 @@ static struct tevent_req *smbd_smb2_read_send(TALLOC_CTX *mem_ctx, if (nread < 0) { DEBUG(5,("smbd_smb2_read: read_file[%s] nread[%lld]\n", - fsp->fsp_name, (long long)nread)); + fsp_str_dbg(fsp), (long long)nread)); tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); return tevent_req_post(req, ev); } if (nread == 0 && in_length != 0) { DEBUG(5,("smbd_smb2_read: read_file[%s] end of file\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); tevent_req_nterror(req, NT_STATUS_END_OF_FILE); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 43afb1b901..204e57d860 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1339,7 +1339,7 @@ static int smbd_smb2_request_next_vector(struct tstream_context *stream, if (invalid) { /* the caller should check this */ - body_size = 0; + body_size = 2; } if ((body_size % 2) != 0) { @@ -1376,7 +1376,7 @@ static int smbd_smb2_request_next_vector(struct tstream_context *stream, */ memcpy(body, hdr + SMB2_HDR_BODY, 2); vector[0].iov_base = body + 2; - vector[0].iov_len = req->in.vector[idx].iov_len - 2; + vector[0].iov_len = body_size - 2; vector[1] = req->in.vector[idx+1]; diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c index 110ce6c64a..08c4a7f5bf 100644 --- a/source3/smbd/smb2_setinfo.c +++ b/source3/smbd/smb2_setinfo.c @@ -200,7 +200,123 @@ static struct tevent_req *smbd_smb2_setinfo_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } - tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED); + if (IS_IPC(conn)) { + tevent_req_nterror(req, NT_STATUS_NOT_SUPPORTED); + return tevent_req_post(req, ev); + } + + switch (in_info_type) { + case 0x01:/* SMB2_SETINFO_FILE */ + { + uint16_t file_info_level; + char *data; + int data_size; + int ret_size = 0; + NTSTATUS status; + + + file_info_level = in_file_info_class + 1000; + if (file_info_level == SMB_FILE_RENAME_INFORMATION) { + file_info_level = 0xFF00 + in_file_info_class; + } + + if (fsp->is_directory || fsp->fh->fd == -1) { + /* + * This is actually a SETFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + if (INFO_LEVEL_IS_UNIX(file_info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn, fsp->fsp_name)) { + DEBUG(3,("smbd_smb2_setinfo_send: " + "SMB_VFS_LSTAT of %s failed " + "(%s)\n", fsp_str_dbg(fsp), + strerror(errno))); + status = map_nt_error_from_unix(errno); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + } else { + if (SMB_VFS_STAT(conn, fsp->fsp_name) != 0) { + DEBUG(3,("smbd_smb2_setinfo_send: " + "fileinfo of %s failed (%s)\n", + fsp_str_dbg(fsp), + strerror(errno))); + status = map_nt_error_from_unix(errno); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + } + } else if (fsp->print_file) { + /* + * Doing a DELETE_ON_CLOSE should cancel a print job. + */ + if ((file_info_level == SMB_SET_FILE_DISPOSITION_INFO) + && in_input_buffer.length >= 1 + && CVAL(in_input_buffer.data,0)) { + fsp->fh->private_options |= FILE_DELETE_ON_CLOSE; + + DEBUG(3,("smbd_smb2_setinfo_send: " + "Cancelling print job (%s)\n", + fsp_str_dbg(fsp))); + + tevent_req_done(req); + return tevent_req_post(req, ev); + } else { + tevent_req_nterror(req, + NT_STATUS_OBJECT_PATH_INVALID); + return tevent_req_post(req, ev); + } + } else { + /* + * Original code - this is an open file. + */ + + if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) != 0) { + DEBUG(3,("smbd_smb2_setinfo_send: fstat " + "of fnum %d failed (%s)\n", fsp->fnum, + strerror(errno))); + status = map_nt_error_from_unix(errno); + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + } + + data = NULL; + data_size = in_input_buffer.length; + if (data_size > 0) { + data = (char *)SMB_MALLOC_ARRAY(char, data_size); + if (tevent_req_nomem(data, req)) { + + } + memcpy(data, in_input_buffer.data, data_size); + } + + status = smbd_do_setfilepathinfo(conn, smbreq, state, + file_info_level, + fsp, + fsp->fsp_name, + &data, + data_size, + &ret_size); + SAFE_FREE(data); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_LEVEL)) { + status = NT_STATUS_INVALID_INFO_CLASS; + } + tevent_req_nterror(req, status); + return tevent_req_post(req, ev); + } + break; + } + + default: + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); + } + + tevent_req_done(req); return tevent_req_post(req, ev); } diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c index 31460a01a1..f1606be623 100644 --- a/source3/smbd/smb2_write.c +++ b/source3/smbd/smb2_write.c @@ -272,14 +272,14 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx, if (((nwritten == 0) && (in_data.length != 0)) || (nwritten < 0)) { DEBUG(5,("smbd_smb2_write: write_file[%s] disk full\n", - fsp->fsp_name)); + fsp_str_dbg(fsp))); SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); tevent_req_nterror(req, NT_STATUS_DISK_FULL); return tevent_req_post(req, ev); } DEBUG(3,("smbd_smb2_write: fnum=[%d/%s] length=%d offset=%d wrote=%d\n", - fsp->fnum, fsp->fsp_name, (int)in_data.length, + fsp->fnum, fsp_str_dbg(fsp), (int)in_data.length, (int)in_offset, (int)nwritten)); if (in_flags & 0x00000001) { @@ -289,7 +289,7 @@ static struct tevent_req *smbd_smb2_write_send(TALLOC_CTX *mem_ctx, status = sync_file(conn, fsp, write_through); if (!NT_STATUS_IS_OK(status)) { DEBUG(5,("smbd_smb2_write: sync_file for %s returned %s\n", - fsp->fsp_name, nt_errstr(status))); + fsp_str_dbg(fsp), nt_errstr(status))); SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock); tevent_req_nterror(req, status); return tevent_req_post(req, ev); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index daed9f8225..da52cc05d4 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -175,6 +175,8 @@ bool stat_cache_lookup(connection_struct *conn, DATA_BLOB data_val; char *name; TALLOC_CTX *ctx = talloc_tos(); + struct smb_filename *smb_fname = NULL; + NTSTATUS status; *pp_dirpath = NULL; *pp_start = *pp_name; @@ -274,14 +276,25 @@ bool stat_cache_lookup(connection_struct *conn, "-> [%s]\n", chk_name, translated_path )); DO_PROFILE_INC(statcache_hits); - if (vfs_stat_smb_fname(conn, translated_path, pst) != 0) { + status = create_synthetic_smb_fname(talloc_tos(), translated_path, + NULL, NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(chk_name); + TALLOC_FREE(translated_path); + return false; + } + + if (SMB_VFS_STAT(conn, smb_fname) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ memcache_delete(smbd_memcache(), STAT_CACHE, data_blob_const(chk_name, strlen(chk_name))); TALLOC_FREE(chk_name); TALLOC_FREE(translated_path); + TALLOC_FREE(smb_fname); return False; } + *pst = smb_fname->st; + TALLOC_FREE(smb_fname); if (!sizechanged) { memcpy(*pp_name, translated_path, diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 4bf27863bd..856fd9432d 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -367,6 +367,69 @@ static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned in return ret_data_size; } +static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx, + char *pdata, + unsigned int total_data_size, + unsigned int *ret_data_size, + connection_struct *conn, + struct ea_list *ea_list) +{ + uint8_t *p = (uint8_t *)pdata; + uint8_t *last_start = NULL; + + *ret_data_size = 0; + + if (!lp_ea_support(SNUM(conn))) { + return NT_STATUS_NO_EAS_ON_FILE; + } + + for (; ea_list; ea_list = ea_list->next) { + size_t dos_namelen; + fstring dos_ea_name; + size_t this_size; + + if (last_start) { + SIVAL(last_start, 0, PTR_DIFF(p, last_start)); + } + last_start = p; + + push_ascii_fstring(dos_ea_name, ea_list->ea.name); + dos_namelen = strlen(dos_ea_name); + if (dos_namelen > 255 || dos_namelen == 0) { + return NT_STATUS_INTERNAL_ERROR; + } + if (ea_list->ea.value.length > 65535) { + return NT_STATUS_INTERNAL_ERROR; + } + + this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length; + + if (ea_list->next) { + size_t pad = 4 - (this_size % 4); + this_size += pad; + } + + if (this_size > total_data_size) { + return NT_STATUS_INFO_LENGTH_MISMATCH; + } + + /* We know we have room. */ + SIVAL(p, 0x00, 0); /* next offset */ + SCVAL(p, 0x04, ea_list->ea.flags); + SCVAL(p, 0x05, dos_namelen); + SSVAL(p, 0x06, ea_list->ea.value.length); + fstrcpy((char *)(p+0x08), dos_ea_name); + memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length); + + total_data_size -= this_size; + p += this_size; + } + + *ret_data_size = PTR_DIFF(p, pdata); + DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size)); + return NT_STATUS_OK; +} + static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname) { size_t total_ea_len = 0; @@ -408,17 +471,13 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname, struct ea_list *ea_list) { char *fname = NULL; - NTSTATUS status; if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; } - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + /* For now setting EAs on streams isn't supported. */ + fname = smb_fname->base_name; for (;ea_list; ea_list = ea_list->next) { int ret; @@ -439,8 +498,9 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, if (ea_list->ea.value.length == 0) { /* Remove the attribute. */ if (fsp && (fsp->fh->fd != -1)) { - DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); + DEBUG(10,("set_ea: deleting ea name %s on " + "file %s by file descriptor.\n", + unix_ea_name, fsp_str_dbg(fsp))); ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name); } else { DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", @@ -457,8 +517,9 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, #endif } else { if (fsp && (fsp->fh->fd != -1)) { - DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); + DEBUG(10,("set_ea: setting ea name %s on file " + "%s by file descriptor.\n", + unix_ea_name, fsp_str_dbg(fsp))); ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name, ea_list->ea.value.data, ea_list->ea.value.length, 0); } else { @@ -963,8 +1024,7 @@ static void call_trans2open(connection_struct *conn, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, - &smb_fname, - NULL); + &smb_fname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -981,12 +1041,10 @@ static void call_trans2open(connection_struct *conn, goto out; } - if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode, - open_ofun, - &access_mask, - &share_mode, - &create_disposition, - &create_options)) { + if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun, + &access_mask, &share_mode, + &create_disposition, + &create_options)) { reply_doserror(req, ERRDOS, ERRbadaccess); goto out; } @@ -1085,7 +1143,8 @@ static void call_trans2open(connection_struct *conn, SIVAL(params,20,inode); SSVAL(params,24,0); /* Padding. */ if (flags & 8) { - uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name); + uint32 ea_size = estimate_ea_size(conn, fsp, + fsp->fsp_name->base_name); SIVAL(params, 26, ea_size); } else { SIVAL(params, 26, 0); @@ -1976,7 +2035,7 @@ static void call_trans2findfirst(connection_struct *conn, if (total_params < 13) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } dirtype = SVAL(params,0); @@ -2014,12 +2073,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", ask_sharemode = false; if (!lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + goto out; } break; default: reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + goto out; } srvstr_get_path_wcard(ctx, params, req->flags2, &directory, @@ -2027,7 +2086,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", STR_TERMINATE, &ntstatus, &mask_contains_wcard); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); - return; + goto out; } ntstatus = resolve_dfspath_wcard(ctx, conn, @@ -2039,32 +2098,27 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath); - return; + goto out; } reply_nterror(req, ntstatus); - return; + goto out; } ntstatus = unix_convert(ctx, conn, directory, &smb_dname, (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP)); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); - return; + goto out; } mask = smb_dname->original_lcomp; - ntstatus = get_full_smb_filename(ctx, smb_dname, &directory); - TALLOC_FREE(smb_dname); - if (!NT_STATUS_IS_OK(ntstatus)) { - reply_nterror(req, ntstatus); - return; - } + directory = smb_dname->base_name; ntstatus = check_name(conn, directory); if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); - return; + goto out; } p = strrchr_m(directory,'/'); @@ -2074,14 +2128,14 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", mask = talloc_strdup(ctx,"*"); if (!mask) { reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + goto out; } mask_contains_wcard = True; } directory = talloc_strdup(talloc_tos(), "./"); if (!directory) { reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + goto out; } } else { *p = 0; @@ -2094,7 +2148,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", if (total_data < 4) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } ea_size = IVAL(pdata,0); @@ -2102,19 +2156,19 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } if (!lp_ea_support(SNUM(conn))) { reply_doserror(req, ERRDOS, ERReasnotsupported); - return; + goto out; } /* Pull out the list of names. */ ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4); if (!ea_list) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } } @@ -2122,7 +2176,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); if(*ppdata == NULL ) { reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + goto out; } pdata = *ppdata; data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1; @@ -2131,7 +2185,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd *pparams = (char *)SMB_REALLOC(*pparams, 10); if (*pparams == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + goto out; } params = *pparams; @@ -2150,7 +2204,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (!NT_STATUS_IS_OK(ntstatus)) { reply_nterror(req, ntstatus); - return; + goto out; } dptr_num = dptr_dnum(conn->dirptr); @@ -2233,11 +2287,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd dptr_close(&dptr_num); if (Protocol < PROTOCOL_NT1) { reply_doserror(req, ERRDOS, ERRnofiles); - return; + goto out; } else { reply_botherror(req, NT_STATUS_NO_SUCH_FILE, ERRDOS, ERRbadfile); - return; + goto out; } } @@ -2276,7 +2330,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd char mangled_name[13]; name_to_8_3(mask, mangled_name, True, conn->params); } - + out: + TALLOC_FREE(smb_dname); return; } @@ -2624,67 +2679,54 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info) "%s", samba_version_string()); } -/**************************************************************************** - Reply to a TRANS2_QFSINFO (query filesystem info). -****************************************************************************/ - -static void call_trans2qfsinfo(connection_struct *conn, - struct smb_request *req, - char **pparams, int total_params, - char **ppdata, int total_data, - unsigned int max_data_bytes) +NTSTATUS smbd_do_qfsinfo(connection_struct *conn, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + uint16_t flags2, + unsigned int max_data_bytes, + char **ppdata, + int *ret_data_len) { char *pdata, *end_data; - char *params = *pparams; - uint16 info_level; - int data_len, len; - SMB_STRUCT_STAT st; + int data_len = 0, len; const char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); uint32 additional_flags = 0; - - if (total_params < 2) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - info_level = SVAL(params,0); + struct smb_filename *smb_fname_dot = NULL; + SMB_STRUCT_STAT st; + NTSTATUS status; if (IS_IPC(conn)) { if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { - DEBUG(0,("call_trans2qfsinfo: not an allowed " + DEBUG(0,("smbd_do_qfsinfo: not an allowed " "info level (0x%x) on IPC$.\n", (unsigned int)info_level)); - reply_nterror(req, NT_STATUS_ACCESS_DENIED); - return; + return NT_STATUS_ACCESS_DENIED; } } - if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) { - if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { - DEBUG(0,("call_trans2qfsinfo: encryption required " - "and info level 0x%x sent.\n", - (unsigned int)info_level)); - exit_server_cleanly("encryption required " - "on connection"); - return; - } - } + DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level)); - DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); + status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL, + &smb_fname_dot); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - if(vfs_stat_smb_fname(conn,".",&st)!=0) { - DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); - reply_doserror(req, ERRSRV, ERRinvdevice); - return; + if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) { + DEBUG(2,("stat of . failed (%s)\n", strerror(errno))); + TALLOC_FREE(smb_fname_dot); + return map_nt_error_from_unix(errno); } + st = smb_fname_dot->st; + TALLOC_FREE(smb_fname_dot); + *ppdata = (char *)SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if (*ppdata == NULL ) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + if (*ppdata == NULL) { + return NT_STATUS_NO_MEMORY; } pdata = *ppdata; @@ -2697,8 +2739,7 @@ static void call_trans2qfsinfo(connection_struct *conn, uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 18; if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) { - reply_unixerror(req, ERRHRD, ERRgeneral); - return; + return map_nt_error_from_unix(errno); } block_size = lp_block_size(snum); @@ -2717,7 +2758,7 @@ static void call_trans2qfsinfo(connection_struct *conn, bytes_per_sector = 512; sectors_per_unit = bsize/bytes_per_sector; - DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \ + DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit, (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); @@ -2743,13 +2784,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u * the pushed string. The change here was adding the STR_TERMINATE. JRA. */ len = srvstr_push( - pdata, req->flags2, + pdata, flags2, pdata+l2_vol_szVolLabel, vname, PTR_DIFF(end_data, pdata+l2_vol_szVolLabel), STR_NOALIGN|STR_TERMINATE); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; - DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", + DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n", (unsigned)convert_timespec_to_time_t(st.st_ex_ctime), len, vname)); break; @@ -2776,7 +2817,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it and will think we can't do long filenames */ - len = srvstr_push(pdata, req->flags2, pdata+12, fstype, + len = srvstr_push(pdata, flags2, pdata+12, fstype, PTR_DIFF(end_data, pdata+12), STR_UNICODE); SIVAL(pdata,8,len); @@ -2785,7 +2826,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u case SMB_QUERY_FS_LABEL_INFO: case SMB_FS_LABEL_INFORMATION: - len = srvstr_push(pdata, req->flags2, pdata+4, vname, + len = srvstr_push(pdata, flags2, pdata+4, vname, PTR_DIFF(end_data, pdata+4), 0); data_len = 4 + len; SIVAL(pdata,0,len); @@ -2802,13 +2843,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u (str_checksum(get_local_machine_name())<<16)); /* Max label len is 32 characters. */ - len = srvstr_push(pdata, req->flags2, pdata+18, vname, + len = srvstr_push(pdata, flags2, pdata+18, vname, PTR_DIFF(end_data, pdata+18), STR_UNICODE); SIVAL(pdata,12,len); data_len = 18+len; - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", + DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", (int)strlen(vname),vname, lp_servicename(snum))); break; @@ -2818,8 +2859,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) { - reply_unixerror(req, ERRHRD, ERRgeneral); - return; + return map_nt_error_from_unix(errno); } block_size = lp_block_size(snum); if (bsize < block_size) { @@ -2836,7 +2876,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u } bytes_per_sector = 512; sectors_per_unit = bsize/bytes_per_sector; - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \ + DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit, (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); SBIG_UINT(pdata,0,dsize); @@ -2851,8 +2891,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) { - reply_unixerror(req, ERRHRD, ERRgeneral); - return; + return map_nt_error_from_unix(errno); } block_size = lp_block_size(snum); if (bsize < block_size) { @@ -2869,7 +2908,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } bytes_per_sector = 512; sectors_per_unit = bsize/bytes_per_sector; - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \ + DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit, (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree)); SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */ @@ -2922,24 +2961,23 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned fsp.fnum = -1; /* access check */ - if (conn->server_info->utok.uid != 0) { + if (conn->server_info->utok.uid != sec_initial_uid()) { DEBUG(0,("set_user_quota: access_denied " "service [%s] user [%s]\n", lp_servicename(SNUM(conn)), conn->server_info->unix_name)); - reply_doserror(req, ERRDOS, ERRnoaccess); - return; + return NT_STATUS_ACCESS_DENIED; } if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - reply_doserror(req, ERRSRV, ERRerror); - return; + return map_nt_error_from_unix(errno); } data_len = 48; - DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn)))); + DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n", + lp_servicename(SNUM(conn)))); /* Unknown1 24 NULL bytes*/ SBIG_UINT(pdata,0,(uint64_t)0); @@ -2990,8 +3028,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int encrypt_caps = 0; if (!lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } switch (conn->encrypt_level) { @@ -3036,8 +3073,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned vfs_statvfs_struct svfs; if (!lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } rc = SMB_VFS_STATVFS(conn, ".", &svfs); @@ -3052,16 +3088,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SBIG_UINT(pdata,32,svfs.TotalFileNodes); SBIG_UINT(pdata,40,svfs.FreeFileNodes); SBIG_UINT(pdata,48,svfs.FsIdentifier); - DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n")); + DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n")); #ifdef EOPNOTSUPP } else if (rc == EOPNOTSUPP) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; #endif /* EOPNOTSUPP */ } else { DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - reply_doserror(req, ERRSRV, ERRerror); - return; + return NT_STATUS_DOS(ERRSRV, ERRerror); } break; } @@ -3073,13 +3107,11 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int i; if (!lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } if (max_data_bytes < 40) { - reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL); - return; + return NT_STATUS_BUFFER_TOO_SMALL; } /* We ARE guest if global_sid_Builtin_Guests is @@ -3193,12 +3225,59 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned } /* drop through */ default: - reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return NT_STATUS_INVALID_LEVEL; + } + + *ret_data_len = data_len; + return NT_STATUS_OK; +} + +/**************************************************************************** + Reply to a TRANS2_QFSINFO (query filesystem info). +****************************************************************************/ + +static void call_trans2qfsinfo(connection_struct *conn, + struct smb_request *req, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) +{ + char *params = *pparams; + uint16_t info_level; + int data_len = 0; + NTSTATUS status; + + if (total_params < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + info_level = SVAL(params,0); + + if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) { + if (info_level != SMB_QUERY_CIFS_UNIX_INFO) { + DEBUG(0,("call_trans2qfsinfo: encryption required " + "and info level 0x%x sent.\n", + (unsigned int)info_level)); + exit_server_cleanly("encryption required " + "on connection"); return; + } } + DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); + + status = smbd_do_qfsinfo(conn, req, + info_level, + req->flags2, + max_data_bytes, + ppdata, &data_len); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } - send_trans2_replies(conn, req, params, 0, pdata, data_len, + send_trans2_replies(conn, req, params, 0, *ppdata, data_len, max_data_bytes); DEBUG( 4, ( "%s info_level = %d\n", @@ -3369,12 +3448,12 @@ cap_low = 0x%x, cap_high = 0x%x\n", ZERO_STRUCT(quotas); /* access check */ - if ((conn->server_info->utok.uid != 0) + if ((conn->server_info->utok.uid != sec_initial_uid()) ||!CAN_WRITE(conn)) { DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", lp_servicename(SNUM(conn)), conn->server_info->unix_name)); - reply_doserror(req, ERRSRV, ERRaccess); + reply_nterror(req, NT_STATUS_ACCESS_DENIED); return; } @@ -3443,7 +3522,7 @@ cap_low = 0x%x, cap_high = 0x%x\n", /* now set the quotas */ if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); - reply_doserror(req, ERRSRV, ERRerror); + reply_nterror(req, map_nt_error_from_unix(errno)); return; } @@ -3878,296 +3957,55 @@ static void call_trans2qpipeinfo(connection_struct *conn, return; } -/**************************************************************************** - Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by - file name or file id). -****************************************************************************/ - -static void call_trans2qfilepathinfo(connection_struct *conn, - struct smb_request *req, - unsigned int tran_call, - char **pparams, int total_params, - char **ppdata, int total_data, - unsigned int max_data_bytes) +NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + files_struct *fsp, + const struct smb_filename *smb_fname, + bool delete_pending, + struct timespec write_time_ts, + bool ms_dfs_link, + struct ea_list *ea_list, + int lock_data_count, + char *lock_data, + uint16_t flags2, + unsigned int max_data_bytes, + char **ppdata, + unsigned int *pdata_size) { - char *params = *pparams; char *pdata = *ppdata; char *dstart, *dend; - uint16 info_level; - int mode=0; - int nlink; - SMB_OFF_T file_size=0; - uint64_t allocation_size=0; - unsigned int data_size = 0; - unsigned int param_size = 2; + unsigned int data_size; + struct timespec create_time_ts, mtime_ts, atime_ts; + time_t create_time, mtime, atime; SMB_STRUCT_STAT sbuf; - char *dos_fname = NULL; - char *fname = NULL; - struct smb_filename *smb_fname = NULL; - char *fullpathname; - char *base_name; char *p; - SMB_OFF_T pos = 0; - bool delete_pending = False; - int len; - time_t create_time, mtime, atime; - struct timespec create_time_ts, mtime_ts, atime_ts; - struct timespec write_time_ts; - files_struct *fsp = NULL; - struct file_id fileid; - struct ea_list *ea_list = NULL; - char *lock_data = NULL; - bool ms_dfs_link = false; - TALLOC_CTX *ctx = talloc_tos(); - NTSTATUS status = NT_STATUS_OK; - - if (!params) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - ZERO_STRUCT(write_time_ts); - - if (tran_call == TRANSACT2_QFILEINFO) { - if (total_params < 4) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - if (IS_IPC(conn)) { - call_trans2qpipeinfo(conn, req, tran_call, - pparams, total_params, - ppdata, total_data, - max_data_bytes); - return; - } - - fsp = file_fsp(req, SVAL(params,0)); - info_level = SVAL(params,2); - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; - } - - /* Initial check for valid fsp ptr. */ - if (!check_fsp_open(conn, req, fsp)) { - return; - } - - fname = talloc_strdup(talloc_tos(),fsp->fsp_name); - if (!fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - status = create_synthetic_smb_fname_split(talloc_tos(), fname, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - if(fsp->fake_file_handle) { - /* - * This is actually for the QUOTA_FAKE_FILE --metze - */ - - /* We know this name is ok, it's already passed the checks. */ - - } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) { - /* - * This is actually a QFILEINFO on a directory - * handle (returned from an NT SMB). NT5.0 seems - * to do this call. JRA. - */ - - if (INFO_LEVEL_IS_UNIX(info_level)) { - /* Always do lstat for UNIX calls. */ - if (SMB_VFS_LSTAT(conn, smb_fname)) { - DEBUG(3,("call_trans2qfilepathinfo: " - "SMB_VFS_LSTAT of %s failed " - "(%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req,ERRDOS,ERRbadpath); - return; - } - } else if (SMB_VFS_STAT(conn, smb_fname)) { - DEBUG(3,("call_trans2qfilepathinfo: " - "SMB_VFS_STAT of %s failed (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadpath); - return; - } - - fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, &delete_pending, &write_time_ts); - } else { - /* - * Original code - this is an open file. - */ - if (!check_fsp(conn, req, fsp)) { - return; - } - - if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) { - DEBUG(3, ("fstat of fnum %d failed (%s)\n", - fsp->fnum, strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadfid); - return; - } - pos = fsp->fh->position_information; - fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, &delete_pending, &write_time_ts); - } - - } else { - /* qpathinfo */ - if (total_params < 7) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - info_level = SVAL(params,0); - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; - } - - srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6], - total_params - 6, - STR_TERMINATE, &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - status = filename_convert(ctx, - conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, - NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - return; - } - reply_nterror(req, status); - return; - } - - /* If this is a stream, check if there is a delete_pending. */ - if ((conn->fs_capabilities & FILE_NAMED_STREAMS) - && is_ntfs_stream_smb_fname(smb_fname)) { - struct smb_filename *smb_fname_base = NULL; - - /* Create an smb_filename with stream_name == NULL. */ - status = - create_synthetic_smb_fname(talloc_tos(), - smb_fname->base_name, - NULL, NULL, - &smb_fname_base); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - if (INFO_LEVEL_IS_UNIX(info_level)) { - /* Always do lstat for UNIX calls. */ - if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) { - DEBUG(3,("call_trans2qfilepathinfo: " - "SMB_VFS_LSTAT of %s failed " - "(%s)\n", - smb_fname_str_dbg(smb_fname_base), - strerror(errno))); - TALLOC_FREE(smb_fname_base); - reply_unixerror(req,ERRDOS,ERRbadpath); - return; - } - } else { - if (SMB_VFS_STAT(conn, smb_fname_base) != 0) { - DEBUG(3,("call_trans2qfilepathinfo: " - "fileinfo of %s failed " - "(%s)\n", - smb_fname_str_dbg(smb_fname_base), - strerror(errno))); - TALLOC_FREE(smb_fname_base); - reply_unixerror(req,ERRDOS,ERRbadpath); - return; - } - } - - fileid = vfs_file_id_from_sbuf(conn, - &smb_fname_base->st); - TALLOC_FREE(smb_fname_base); - get_file_infos(fileid, &delete_pending, NULL); - if (delete_pending) { - reply_nterror(req, NT_STATUS_DELETE_PENDING); - return; - } - } - - if (INFO_LEVEL_IS_UNIX(info_level)) { - /* Always do lstat for UNIX calls. */ - if (SMB_VFS_LSTAT(conn, smb_fname)) { - DEBUG(3,("call_trans2qfilepathinfo: " - "SMB_VFS_LSTAT of %s failed (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadpath); - return; - } - - } else if (!VALID_STAT(smb_fname->st) && - SMB_VFS_STAT(conn, smb_fname) && - (info_level != SMB_INFO_IS_NAME_VALID)) { - ms_dfs_link = check_msdfs_link(conn, fname, - &smb_fname->st); - - if (!ms_dfs_link) { - DEBUG(3,("call_trans2qfilepathinfo: " - "SMB_VFS_STAT of %s failed (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadpath); - return; - } - } - - fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, &delete_pending, &write_time_ts); - if (delete_pending) { - reply_nterror(req, NT_STATUS_DELETE_PENDING); - return; - } - } + char *fname; + char *base_name; + char *dos_fname; + int mode; + int nlink; + NTSTATUS status; + uint64_t file_size = 0; + uint64_t pos = 0; + uint64_t allocation_size = 0; + uint64_t file_index = 0; + uint32_t access_mask = 0; - /* Set sbuf for use below. */ sbuf = smb_fname->st; if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } - DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", - fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); + status = get_full_smb_filename(mem_ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } - p = strrchr_m(smb_fname->base_name,'/'); - if (!p) - base_name = smb_fname->base_name; - else - base_name = p+1; + DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n", + smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1, + info_level, max_data_bytes)); if (ms_dfs_link) { mode = dos_mode_msdfs(conn, smb_fname); @@ -4187,102 +4025,15 @@ static void call_trans2qfilepathinfo(connection_struct *conn, nlink -= 1; } - fullpathname = fname; - if (!(mode & aDIR)) - file_size = get_file_size_stat(&sbuf); - - /* Pull out any data sent here before we realloc. */ - switch (info_level) { - case SMB_INFO_QUERY_EAS_FROM_LIST: - { - /* Pull any EA list from the data portion. */ - uint32 ea_size; - - if (total_data < 4) { - reply_nterror( - req, NT_STATUS_INVALID_PARAMETER); - return; - } - ea_size = IVAL(pdata,0); - - if (total_data > 0 && ea_size != total_data) { - DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ -total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); - reply_nterror( - req, NT_STATUS_INVALID_PARAMETER); - return; - } - - if (!lp_ea_support(SNUM(conn))) { - reply_doserror(req, ERRDOS, - ERReasnotsupported); - return; - } - - /* Pull out the list of names. */ - ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4); - if (!ea_list) { - reply_nterror( - req, NT_STATUS_INVALID_PARAMETER); - return; - } - break; - } - - case SMB_QUERY_POSIX_LOCK: - { - if (fsp == NULL || fsp->fh->fd == -1) { - reply_nterror(req, NT_STATUS_INVALID_HANDLE); - return; - } - - if (total_data != POSIX_LOCK_DATA_SIZE) { - reply_nterror( - req, NT_STATUS_INVALID_PARAMETER); - return; - } - - /* Copy the lock range data. */ - lock_data = (char *)TALLOC_MEMDUP( - ctx, pdata, total_data); - if (!lock_data) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - } - default: - break; - } - - *pparams = (char *)SMB_REALLOC(*pparams,2); - if (*pparams == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - params = *pparams; - SSVAL(params,0,0); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); - if (*ppdata == NULL ) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + if (*ppdata == NULL) { + return NT_STATUS_NO_MEMORY; } pdata = *ppdata; dstart = pdata; dend = dstart + data_size - 1; - allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); - - if (!fsp) { - /* Do we have this path open ? */ - files_struct *fsp1; - fileid = vfs_file_id_from_sbuf(conn, &sbuf); - fsp1 = file_find_di_first(fileid); - if (fsp1 && fsp1->initial_allocation_size) { - allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf); - } - } - if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) { update_stat_ex_mtime(&sbuf, write_time_ts); } @@ -4301,28 +4052,67 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd mtime = convert_timespec_to_time_t(mtime_ts); atime = convert_timespec_to_time_t(atime_ts); + p = strrchr_m(smb_fname->base_name,'/'); + if (!p) + base_name = smb_fname->base_name; + else + base_name = p+1; + /* NT expects the name to be in an exact form of the *full* filename. See the trans2 torture test */ if (ISDOT(base_name)) { - dos_fname = talloc_strdup(ctx, "\\"); + dos_fname = talloc_strdup(mem_ctx, "\\"); if (!dos_fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } } else { - dos_fname = talloc_asprintf(ctx, + dos_fname = talloc_asprintf(mem_ctx, "\\%s", fname); if (!dos_fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } string_replace(dos_fname, '/', '\\'); } + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf); + + if (!fsp) { + /* Do we have this path open ? */ + files_struct *fsp1; + struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf); + fsp1 = file_find_di_first(fileid); + if (fsp1 && fsp1->initial_allocation_size) { + allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf); + } + } + + if (!(mode & aDIR)) { + file_size = get_file_size_stat(&sbuf); + } + + if (fsp) { + pos = fsp->fh->position_information; + } + + if (fsp) { + access_mask = fsp->access_mask; + } else { + /* GENERIC_EXECUTE mapping from Windows */ + access_mask = 0x12019F; + } + + /* This should be an index number - looks like + dev/ino to me :-) + + I think this causes us to fail the IFSKIT + BasicFileInformationTest. -tpot */ + file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */ + file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */ + switch (info_level) { case SMB_INFO_STANDARD: - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n")); data_size = 22; srv_put_dos_date2(pdata,l1_fdateCreation,create_time); srv_put_dos_date2(pdata,l1_fdateLastAccess,atime); @@ -4335,7 +4125,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_INFO_QUERY_EA_SIZE: { unsigned int ea_size = estimate_ea_size(conn, fsp, fname); - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n")); data_size = 26; srv_put_dos_date2(pdata,0,create_time); srv_put_dos_date2(pdata,4,atime); @@ -4348,14 +4138,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } case SMB_INFO_IS_NAME_VALID: - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n")); - if (tran_call == TRANSACT2_QFILEINFO) { + DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n")); + if (fsp) { /* os/2 needs this ? really ?*/ - reply_doserror(req, ERRDOS, ERRbadfunc); - return; + return NT_STATUS_DOS(ERRDOS, ERRbadfunc); } + /* This is only reached for qpathinfo */ data_size = 0; - param_size = 0; break; case SMB_INFO_QUERY_EAS_FROM_LIST: @@ -4363,9 +4152,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd size_t total_ea_len = 0; struct ea_list *ea_file_list = NULL; - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); - ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len); + ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { @@ -4374,7 +4163,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd break; } - data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list); + data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list); break; } @@ -4383,16 +4172,45 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd /* We have data_size bytes to put EA's into. */ size_t total_ea_len = 0; - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); - ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len); + ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); if (!ea_list || (total_ea_len > data_size)) { data_size = 4; SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ break; } - data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list); + data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list); + break; + } + + case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/ + { + /* We have data_size bytes to put EA's into. */ + size_t total_ea_len = 0; + struct ea_list *ea_file_list = NULL; + + DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n")); + + /*TODO: add filtering and index handling */ + + ea_file_list = get_ea_list_from_file(mem_ctx, + conn, fsp, + fname, + &total_ea_len); + if (!ea_file_list) { + return NT_STATUS_NO_EAS_ON_FILE; + } + + status = fill_ea_chained_buffer(mem_ctx, + pdata, + data_size, + &data_size, + conn, ea_file_list); + if (!NT_STATUS_IS_OK(status)) { + return status; + } break; } @@ -4400,10 +4218,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_BASIC_INFO: if (info_level == SMB_QUERY_FILE_BASIC_INFO) { - DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n")); data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */ } else { - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n")); data_size = 40; SIVAL(pdata,36,0); } @@ -4424,7 +4242,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_FILE_STANDARD_INFORMATION: case SMB_QUERY_FILE_STANDARD_INFO: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n")); data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); @@ -4438,7 +4256,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_EA_INFO: { unsigned int ea_size = estimate_ea_size(conn, fsp, fname); - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n")); data_size = 4; SIVAL(pdata,0,ea_size); break; @@ -4448,15 +4266,14 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_ALT_NAME_INFO: case SMB_FILE_ALTERNATE_NAME_INFORMATION: { + int len; char mangled_name[13]; - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n")); if (!name_to_8_3(base_name,mangled_name, True,conn->params)) { - reply_nterror( - req, - NT_STATUS_NO_MEMORY); + return NT_STATUS_NO_MEMORY; } - len = srvstr_push(dstart, req->flags2, + len = srvstr_push(dstart, flags2, pdata+4, mangled_name, PTR_DIFF(dend, pdata+4), STR_UNICODE); @@ -4466,28 +4283,31 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } case SMB_QUERY_FILE_NAME_INFO: + { + int len; /* this must be *exactly* right for ACLs on mapped drives to work */ - len = srvstr_push(dstart, req->flags2, + len = srvstr_push(dstart, flags2, pdata+4, dos_fname, PTR_DIFF(dend, pdata+4), STR_UNICODE); - DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n")); data_size = 4 + len; SIVAL(pdata,0,len); break; + } case SMB_FILE_ALLOCATION_INFORMATION: case SMB_QUERY_FILE_ALLOCATION_INFO: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,allocation_size); break; case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_QUERY_FILE_END_OF_FILEINFO: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,file_size); break; @@ -4495,8 +4315,9 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_ALL_INFO: case SMB_FILE_ALL_INFORMATION: { + int len; unsigned int ea_size = estimate_ea_size(conn, fsp, fname); - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n")); put_long_date_timespec(pdata,create_time_ts); put_long_date_timespec(pdata+8,atime_ts); put_long_date_timespec(pdata+16,mtime_ts); /* write time */ @@ -4513,7 +4334,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 24; SIVAL(pdata,0,ea_size); pdata += 4; /* EA info */ - len = srvstr_push(dstart, req->flags2, + len = srvstr_push(dstart, flags2, pdata+4, dos_fname, PTR_DIFF(dend, pdata+4), STR_UNICODE); @@ -4522,27 +4343,52 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = PTR_DIFF(pdata,(*ppdata)); break; } - case SMB_FILE_INTERNAL_INFORMATION: - /* This should be an index number - looks like - dev/ino to me :-) - I think this causes us to fail the IFSKIT - BasicFileInformationTest. -tpot */ + case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/ + { + int len; + unsigned int ea_size = estimate_ea_size(conn, fsp, fname); + DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n")); + put_long_date_timespec(pdata+0x00,create_time_ts); + put_long_date_timespec(pdata+0x08,atime_ts); + put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */ + put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */ + SIVAL(pdata, 0x20, mode); + SIVAL(pdata, 0x24, 0); /* padding. */ + SBVAL(pdata, 0x28, allocation_size); + SBVAL(pdata, 0x30, file_size); + SIVAL(pdata, 0x38, nlink); + SCVAL(pdata, 0x3C, delete_pending); + SCVAL(pdata, 0x3D, (mode&aDIR)?1:0); + SSVAL(pdata, 0x3E, 0); /* padding */ + SBVAL(pdata, 0x40, file_index); + SIVAL(pdata, 0x48, ea_size); + SIVAL(pdata, 0x4C, access_mask); + SBVAL(pdata, 0x50, pos); + SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */ + SIVAL(pdata, 0x5C, 0); /* No alignment needed. */ + + pdata += 0x60; + + len = srvstr_push(dstart, flags2, + pdata+4, dos_fname, + PTR_DIFF(dend, pdata+4), + STR_UNICODE); + SIVAL(pdata,0,len); + pdata += 4 + len; + data_size = PTR_DIFF(pdata,(*ppdata)); + break; + } + case SMB_FILE_INTERNAL_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); - SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */ - SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */ + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n")); + SBVAL(pdata, 0, file_index); data_size = 8; break; case SMB_FILE_ACCESS_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n")); - if (fsp) { - SIVAL(pdata,0,fsp->access_mask); - } else { - /* GENERIC_EXECUTE mapping from Windows */ - SIVAL(pdata,0,0x12019F); - } + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n")); + SIVAL(pdata, 0, access_mask); data_size = 4; break; @@ -4551,32 +4397,32 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd { size_t byte_len; byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False); - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n")); SIVAL(pdata,0,byte_len); data_size = 4 + byte_len; break; } case SMB_FILE_DISPOSITION_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n")); data_size = 1; SCVAL(pdata,0,delete_pending); break; case SMB_FILE_POSITION_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n")); data_size = 8; SOFF_T(pdata,0,pos); break; case SMB_FILE_MODE_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n")); SIVAL(pdata,0,mode); data_size = 4; break; case SMB_FILE_ALIGNMENT_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n")); SIVAL(pdata,0,0); /* No alignment needed. */ data_size = 4; break; @@ -4594,7 +4440,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd unsigned int num_streams; struct stream_struct *streams; - DEBUG(10,("call_trans2qfilepathinfo: " + DEBUG(10,("smbd_do_qfilepathinfo: " "SMB_FILE_STREAM_INFORMATION\n")); status = SMB_VFS_STREAMINFO( @@ -4604,8 +4450,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("could not get stream info: %s\n", nt_errstr(status))); - reply_nterror(req, status); - return; + return status; } status = marshall_stream_info(num_streams, streams, @@ -4615,8 +4460,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("marshall_stream_info failed: %s\n", nt_errstr(status))); - reply_nterror(req, status); - return; + return status; } TALLOC_FREE(streams); @@ -4625,7 +4469,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } case SMB_QUERY_COMPRESSION_INFO: case SMB_FILE_COMPRESSION_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n")); SOFF_T(pdata,0,file_size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ @@ -4633,7 +4477,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd break; case SMB_FILE_NETWORK_OPEN_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n")); put_long_date_timespec(pdata,create_time_ts); put_long_date_timespec(pdata+8,atime_ts); put_long_date_timespec(pdata+16,mtime_ts); /* write time */ @@ -4646,7 +4490,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd break; case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n")); SIVAL(pdata,0,mode); SIVAL(pdata,4,0); data_size = 8; @@ -4663,7 +4507,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd { int i; - DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC ")); + DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC ")); for (i=0; i<100; i++) DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); @@ -4679,7 +4523,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd { int i; - DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 ")); + DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 ")); for (i=0; i<100; i++) DEBUG(4,("%d=%x, ",i, (*ppdata)[i])); @@ -4690,33 +4534,28 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_QUERY_FILE_UNIX_LINK: { - char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1); + int len; + char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1); if (!buffer) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + return NT_STATUS_NO_MEMORY; } - DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); + DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n")); #ifdef S_ISLNK if(!S_ISLNK(sbuf.st_ex_mode)) { - reply_unixerror(req, ERRSRV, - ERRbadlink); - return; + return NT_STATUS_DOS(ERRSRV, ERRbadlink); } #else - reply_unixerror(req, ERRDOS, ERRbadlink); - return; + return NT_STATUS_DOS(ERRDOS, ERRbadlink); #endif - len = SMB_VFS_READLINK(conn,fullpathname, + len = SMB_VFS_READLINK(conn,fname, buffer, PATH_MAX); if (len == -1) { - reply_unixerror(req, ERRDOS, - ERRnoaccess); - return; + return map_nt_error_from_unix(errno); } buffer[len] = 0; - len = srvstr_push(dstart, req->flags2, + len = srvstr_push(dstart, flags2, pdata, buffer, PTR_DIFF(dend, pdata), STR_TERMINATE); @@ -4741,17 +4580,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } if (file_acl == NULL && no_acl_syscall_error(errno)) { - DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n", + DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n", fname )); - reply_nterror( - req, - NT_STATUS_NOT_IMPLEMENTED); - return; + return NT_STATUS_NOT_IMPLEMENTED; } if (S_ISDIR(sbuf.st_ex_mode)) { if (fsp && fsp->is_directory) { - def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + def_acl = + SMB_VFS_SYS_ACL_GET_FILE( + conn, + fsp->fsp_name->base_name, + SMB_ACL_TYPE_DEFAULT); } else { def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT); } @@ -4762,7 +4602,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd num_def_acls = count_acl_entries(conn, def_acl); if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) { - DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n", + DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n", data_size, (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) )); @@ -4772,10 +4612,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - reply_nterror( - req, - NT_STATUS_BUFFER_TOO_SMALL); - return; + return NT_STATUS_BUFFER_TOO_SMALL; } SSVAL(pdata,0,SMB_POSIX_ACL_VERSION); @@ -4788,9 +4625,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - reply_nterror( - req, NT_STATUS_INTERNAL_ERROR); - return; + return NT_STATUS_INTERNAL_ERROR; } if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) { if (file_acl) { @@ -4799,10 +4634,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd if (def_acl) { SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl); } - reply_nterror( - req, - NT_STATUS_INTERNAL_ERROR); - return; + return NT_STATUS_INTERNAL_ERROR; } if (file_acl) { @@ -4824,10 +4656,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd uint32 lock_pid; enum brl_type lock_type; - if (total_data != POSIX_LOCK_DATA_SIZE) { - reply_nterror( - req, NT_STATUS_INVALID_PARAMETER); - return; + /* We need an open file with a real fd for this. */ + if (!fsp || fsp->is_directory || fsp->fh->fd == -1) { + return NT_STATUS_INVALID_LEVEL; + } + + if (lock_data_count != POSIX_LOCK_DATA_SIZE) { + return NT_STATUS_INVALID_PARAMETER; } switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { @@ -4840,10 +4675,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case POSIX_LOCK_TYPE_UNLOCK: default: /* There's no point in asking for an unlock... */ - reply_nterror( - req, - NT_STATUS_INVALID_PARAMETER); - return; + return NT_STATUS_INVALID_PARAMETER; } lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET); @@ -4888,15 +4720,393 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE); SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK); } else { - reply_nterror(req, status); - return; + return status; } break; } default: + return NT_STATUS_INVALID_LEVEL; + } + + *pdata_size = data_size; + return NT_STATUS_OK; +} + +/**************************************************************************** + Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by + file name or file id). +****************************************************************************/ + +static void call_trans2qfilepathinfo(connection_struct *conn, + struct smb_request *req, + unsigned int tran_call, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) +{ + char *params = *pparams; + char *pdata = *ppdata; + uint16 info_level; + unsigned int data_size = 0; + unsigned int param_size = 2; + struct smb_filename *smb_fname = NULL; + bool delete_pending = False; + struct timespec write_time_ts; + files_struct *fsp = NULL; + struct file_id fileid; + struct ea_list *ea_list = NULL; + int lock_data_count = 0; + char *lock_data = NULL; + bool ms_dfs_link = false; + NTSTATUS status = NT_STATUS_OK; + + if (!params) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + ZERO_STRUCT(write_time_ts); + + if (tran_call == TRANSACT2_QFILEINFO) { + if (total_params < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + if (IS_IPC(conn)) { + call_trans2qpipeinfo(conn, req, tran_call, + pparams, total_params, + ppdata, total_data, + max_data_bytes); + return; + } + + fsp = file_fsp(req, SVAL(params,0)); + info_level = SVAL(params,2); + + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); + + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; + } + + /* Initial check for valid fsp ptr. */ + if (!check_fsp_open(conn, req, fsp)) { + return; + } + + status = copy_smb_filename(talloc_tos(), fsp->fsp_name, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + if(fsp->fake_file_handle) { + /* + * This is actually for the QUOTA_FAKE_FILE --metze + */ + + /* We know this name is ok, it's already passed the checks. */ + + } else if(fsp->is_directory || fsp->fh->fd == -1) { + /* + * This is actually a QFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn, smb_fname)) { + DEBUG(3,("call_trans2qfilepathinfo: " + "SMB_VFS_LSTAT of %s failed " + "(%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + } else if (SMB_VFS_STAT(conn, smb_fname)) { + DEBUG(3,("call_trans2qfilepathinfo: " + "SMB_VFS_STAT of %s failed (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + + fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); + get_file_infos(fileid, &delete_pending, &write_time_ts); + } else { + /* + * Original code - this is an open file. + */ + if (!check_fsp(conn, req, fsp)) { + return; + } + + if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) { + DEBUG(3, ("fstat of fnum %d failed (%s)\n", + fsp->fnum, strerror(errno))); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); + get_file_infos(fileid, &delete_pending, &write_time_ts); + } + + } else { + char *fname = NULL; + + /* qpathinfo */ + if (total_params < 7) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + info_level = SVAL(params,0); + + DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); + + if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + + srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6], + total_params - 6, + STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + status = filename_convert(req, + conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; + } + reply_nterror(req, status); + return; + } + + /* If this is a stream, check if there is a delete_pending. */ + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && is_ntfs_stream_smb_fname(smb_fname)) { + struct smb_filename *smb_fname_base = NULL; + + /* Create an smb_filename with stream_name == NULL. */ + status = + create_synthetic_smb_fname(talloc_tos(), + smb_fname->base_name, + NULL, NULL, + &smb_fname_base); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) { + DEBUG(3,("call_trans2qfilepathinfo: " + "SMB_VFS_LSTAT of %s failed " + "(%s)\n", + smb_fname_str_dbg(smb_fname_base), + strerror(errno))); + TALLOC_FREE(smb_fname_base); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + } else { + if (SMB_VFS_STAT(conn, smb_fname_base) != 0) { + DEBUG(3,("call_trans2qfilepathinfo: " + "fileinfo of %s failed " + "(%s)\n", + smb_fname_str_dbg(smb_fname_base), + strerror(errno))); + TALLOC_FREE(smb_fname_base); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + } + + fileid = vfs_file_id_from_sbuf(conn, + &smb_fname_base->st); + TALLOC_FREE(smb_fname_base); + get_file_infos(fileid, &delete_pending, NULL); + if (delete_pending) { + reply_nterror(req, NT_STATUS_DELETE_PENDING); + return; + } + } + + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn, smb_fname)) { + DEBUG(3,("call_trans2qfilepathinfo: " + "SMB_VFS_LSTAT of %s failed (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + + } else if (!VALID_STAT(smb_fname->st) && + SMB_VFS_STAT(conn, smb_fname) && + (info_level != SMB_INFO_IS_NAME_VALID)) { + ms_dfs_link = check_msdfs_link(conn, + smb_fname->base_name, + &smb_fname->st); + + if (!ms_dfs_link) { + DEBUG(3,("call_trans2qfilepathinfo: " + "SMB_VFS_STAT of %s failed (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + } + + fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); + get_file_infos(fileid, &delete_pending, &write_time_ts); + if (delete_pending) { + reply_nterror(req, NT_STATUS_DELETE_PENDING); + return; + } + } + + DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d " + "total_data=%d\n", smb_fname_str_dbg(smb_fname), + fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); + + /* Pull out any data sent here before we realloc. */ + switch (info_level) { + case SMB_INFO_QUERY_EAS_FROM_LIST: + { + /* Pull any EA list from the data portion. */ + uint32 ea_size; + + if (total_data < 4) { + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; + } + ea_size = IVAL(pdata,0); + + if (total_data > 0 && ea_size != total_data) { + DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; + } + + if (!lp_ea_support(SNUM(conn))) { + reply_doserror(req, ERRDOS, + ERReasnotsupported); + return; + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4); + if (!ea_list) { + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; + } + break; + } + + case SMB_QUERY_POSIX_LOCK: + { + if (fsp == NULL || fsp->fh->fd == -1) { + reply_nterror(req, NT_STATUS_INVALID_HANDLE); + return; + } + + if (total_data != POSIX_LOCK_DATA_SIZE) { + reply_nterror( + req, NT_STATUS_INVALID_PARAMETER); + return; + } + + /* Copy the lock range data. */ + lock_data = (char *)TALLOC_MEMDUP( + req, pdata, total_data); + if (!lock_data) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + lock_data_count = total_data; + } + default: + break; + } + + *pparams = (char *)SMB_REALLOC(*pparams,2); + if (*pparams == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + params = *pparams; + SSVAL(params,0,0); + + /* + * draft-leach-cifs-v1-spec-02.txt + * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path + * says: + * + * The requested information is placed in the Data portion of the + * transaction response. For the information levels greater than 0x100, + * the transaction response has 1 parameter word which should be + * ignored by the client. + * + * However Windows only follows this rule for the IS_NAME_VALID call. + */ + switch (info_level) { + case SMB_INFO_IS_NAME_VALID: + param_size = 0; + break; + } + + if ((info_level & 0xFF00) == 0xFF00) { + /* + * We use levels that start with 0xFF00 + * internally to represent SMB2 specific levels + */ + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + + status = smbd_do_qfilepathinfo(conn, req, info_level, + fsp, smb_fname, + delete_pending, write_time_ts, + ms_dfs_link, ea_list, + lock_data_count, lock_data, + req->flags2, max_data_bytes, + ppdata, &data_size); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; } send_trans2_replies(conn, req, params, param_size, *ppdata, data_size, @@ -4915,8 +5125,6 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, const struct smb_filename *smb_fname_old, const struct smb_filename *smb_fname_new) { - char *oldname = NULL; - char *newname = NULL; NTSTATUS status = NT_STATUS_OK; /* source must already exist. */ @@ -4934,25 +5142,22 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, return NT_STATUS_FILE_IS_A_DIRECTORY; } - status = get_full_smb_filename(ctx, smb_fname_new, &newname); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - status = get_full_smb_filename(ctx, smb_fname_old, &oldname); - if (!NT_STATUS_IS_OK(status)) { - goto out; + /* Setting a hardlink to/from a stream isn't currently supported. */ + if (is_ntfs_stream_smb_fname(smb_fname_old) || + is_ntfs_stream_smb_fname(smb_fname_new)) { + return NT_STATUS_INVALID_PARAMETER; } - DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname )); + DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", + smb_fname_old->base_name, smb_fname_new->base_name)); - if (SMB_VFS_LINK(conn,oldname,newname) != 0) { + if (SMB_VFS_LINK(conn, smb_fname_old->base_name, + smb_fname_new->base_name) != 0) { status = map_nt_error_from_unix(errno); DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n", - nt_errstr(status), newname, oldname)); + nt_errstr(status), smb_fname_old->base_name, + smb_fname_new->base_name)); } - out: - TALLOC_FREE(newname); - TALLOC_FREE(oldname); return status; } @@ -5317,8 +5522,9 @@ static NTSTATUS smb_file_position_information(connection_struct *conn, } #endif /* LARGE_SMB_OFF_T */ - DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n", - fsp->fsp_name, (double)position_information )); + DEBUG(10,("smb_file_position_information: Set file position " + "information for file %s to %.0f\n", fsp_str_dbg(fsp), + (double)position_information)); fsp->fh->position_information = position_information; return NT_STATUS_OK; } @@ -5351,10 +5557,10 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn, struct smb_request *req, const char *pdata, int total_data, - const char *fname) + const struct smb_filename *smb_fname) { char *link_target = NULL; - const char *newname = fname; + const char *newname = smb_fname->base_name; NTSTATUS status = NT_STATUS_OK; TALLOC_CTX *ctx = talloc_tos(); @@ -5454,8 +5660,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, oldname, - &smb_fname_old, - NULL); + &smb_fname_old); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -5529,8 +5734,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, /* Create an smb_fname to call rename_internals_fsp() with. */ status = create_synthetic_smb_fname(talloc_tos(), - fsp->base_fsp->fsp_name, - newname, NULL, &smb_fname); + fsp->base_fsp->fsp_name->base_name, newname, NULL, + &smb_fname); if (!NT_STATUS_IS_OK(status)) { goto out; } @@ -5547,7 +5752,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, /* Create a char * to call rename_internals() with. */ base_name = talloc_asprintf(ctx, "%s%s", - fsp->base_fsp->fsp_name, + fsp->base_fsp->fsp_name->base_name, newname); if (!base_name) { status = NT_STATUS_NO_MEMORY; @@ -5604,13 +5809,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn, } if (fsp) { - DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", - fsp->fnum, fsp->fsp_name, base_name )); + DEBUG(10,("smb_file_rename_information: " + "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", + fsp->fnum, fsp_str_dbg(fsp), base_name)); status = rename_internals_fsp(conn, fsp, smb_fname, 0, overwrite); } else { - DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n", - fname, base_name )); + DEBUG(10,("smb_file_rename_information: " + "SMB_FILE_RENAME_INFORMATION %s -> %s\n", + fname, base_name)); status = rename_internals(ctx, conn, req, fname, base_name, 0, overwrite, False, dest_has_wcard, FILE_WRITE_ATTRIBUTES); @@ -5629,8 +5836,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { uint16 posix_acl_version; uint16 num_file_acls; @@ -5665,18 +5871,20 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, } DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n", - fname ? fname : fsp->fsp_name, + smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp), (unsigned int)num_file_acls, (unsigned int)num_def_acls)); - if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE)) { + if (valid_file_acls && !set_unix_posix_acl(conn, fsp, + smb_fname->base_name, num_file_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE)) { return map_nt_error_from_unix(errno); } - if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls, - pdata + SMB_POSIX_ACL_HEADER_SIZE + - (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { + if (valid_def_acls && !set_unix_posix_default_acl(conn, + smb_fname->base_name, &smb_fname->st, num_def_acls, + pdata + SMB_POSIX_ACL_HEADER_SIZE + + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) { return map_nt_error_from_unix(errno); } return NT_STATUS_OK; @@ -5752,7 +5960,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn, DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u," "lock_pid = %u, count = %.0f, offset = %.0f\n", - fsp->fsp_name, + fsp_str_dbg(fsp), (unsigned int)lock_type, (unsigned int)lock_pid, (double)count, @@ -6444,11 +6652,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, struct smb_request *req, char **ppdata, int total_data, - const char *fname, - SMB_STRUCT_STAT *psbuf, + struct smb_filename *smb_fname, int *pdata_return_size) { - struct smb_filename *smb_fname; NTSTATUS status = NT_STATUS_OK; uint32 raw_unixmode = 0; uint32 mod_unixmode = 0; @@ -6465,7 +6671,8 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, raw_unixmode = IVAL(pdata,8); /* Next 4 bytes are not yet defined. */ - status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode); + status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode, + PERM_NEW_DIR, &unixmode); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6473,13 +6680,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS; DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n", - fname, (unsigned int)unixmode )); - - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + smb_fname_str_dbg(smb_fname), (unsigned int)unixmode)); status = SMB_VFS_CREATE_FILE( conn, /* conn */ @@ -6498,9 +6699,6 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, &fsp, /* result */ &info); /* pinfo */ - *psbuf = smb_fname->st; - TALLOC_FREE(smb_fname); - if (NT_STATUS_IS_OK(status)) { close_file(req, fsp, NORMAL_CLOSE); } @@ -6531,12 +6729,14 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn, case SMB_QUERY_FILE_UNIX_BASIC: SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); SSVAL(pdata,10,0); /* Padding. */ - store_file_unix_basic(conn, pdata + 12, fsp, psbuf); + store_file_unix_basic(conn, pdata + 12, fsp, + &smb_fname->st); break; case SMB_QUERY_FILE_UNIX_INFO2: SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); SSVAL(pdata,10,0); /* Padding. */ - store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); + store_file_unix_basic_info2(conn, pdata + 12, fsp, + &smb_fname->st); break; default: SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); @@ -6555,11 +6755,9 @@ static NTSTATUS smb_posix_open(connection_struct *conn, struct smb_request *req, char **ppdata, int total_data, - const char *fname, - SMB_STRUCT_STAT *psbuf, + struct smb_filename *smb_fname, int *pdata_return_size) { - struct smb_filename *smb_fname = NULL; bool extended_oplock_granted = False; char *pdata = *ppdata; uint32 flags = 0; @@ -6592,8 +6790,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn, return smb_posix_mkdir(conn, req, ppdata, total_data, - fname, - psbuf, + smb_fname, pdata_return_size); } @@ -6632,11 +6829,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn, raw_unixmode = IVAL(pdata,8); /* Next 4 bytes are not yet defined. */ - status = unix_perms_from_wire(conn, - psbuf, - raw_unixmode, - VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE, - &unixmode); + status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode, + (VALID_STAT(smb_fname->st) ? + PERM_EXISTING_FILE : PERM_NEW_FILE), + &unixmode); if (!NT_STATUS_IS_OK(status)) { return status; @@ -6655,16 +6851,10 @@ static NTSTATUS smb_posix_open(connection_struct *conn, } DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n", - fname, + smb_fname_str_dbg(smb_fname), (unsigned int)wire_open_mode, (unsigned int)unixmode )); - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ @@ -6683,9 +6873,6 @@ static NTSTATUS smb_posix_open(connection_struct *conn, &fsp, /* result */ &info); /* pinfo */ - *psbuf = smb_fname->st; - TALLOC_FREE(smb_fname); - if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6738,12 +6925,14 @@ static NTSTATUS smb_posix_open(connection_struct *conn, case SMB_QUERY_FILE_UNIX_BASIC: SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC); SSVAL(pdata,10,0); /* padding. */ - store_file_unix_basic(conn, pdata + 12, fsp, psbuf); + store_file_unix_basic(conn, pdata + 12, fsp, + &smb_fname->st); break; case SMB_QUERY_FILE_UNIX_INFO2: SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2); SSVAL(pdata,10,0); /* padding. */ - store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf); + store_file_unix_basic_info2(conn, pdata + 12, fsp, + &smb_fname->st); break; default: SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED); @@ -6826,7 +7015,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, NULL); if (lck == NULL) { DEBUG(0, ("smb_posix_unlink: Could not get share mode " - "lock for file %s\n", fsp->fsp_name)); + "lock for file %s\n", fsp_str_dbg(fsp))); close_file(req, fsp, NORMAL_CLOSE); return NT_STATUS_INVALID_PARAMETER; } @@ -6867,200 +7056,42 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, return close_file(req, fsp, NORMAL_CLOSE); } -/**************************************************************************** - Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). -****************************************************************************/ - -static void call_trans2setfilepathinfo(connection_struct *conn, - struct smb_request *req, - unsigned int tran_call, - char **pparams, int total_params, - char **ppdata, int total_data, - unsigned int max_data_bytes) +NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn, + struct smb_request *req, + TALLOC_CTX *mem_ctx, + uint16_t info_level, + files_struct *fsp, + struct smb_filename *smb_fname, + char **ppdata, int total_data, + int *ret_data_size) { - char *params = *pparams; char *pdata = *ppdata; - uint16 info_level; - SMB_STRUCT_STAT sbuf; char *fname = NULL; - struct smb_filename *smb_fname = NULL; - files_struct *fsp = NULL; NTSTATUS status = NT_STATUS_OK; int data_return_size = 0; - TALLOC_CTX *ctx = talloc_tos(); - - if (!params) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - if (tran_call == TRANSACT2_SETFILEINFO) { - if (total_params < 4) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - fsp = file_fsp(req, SVAL(params,0)); - /* Basic check for non-null fsp. */ - if (!check_fsp_open(conn, req, fsp)) { - return; - } - info_level = SVAL(params,2); - - fname = talloc_strdup(talloc_tos(),fsp->fsp_name); - if (!fname) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - status = create_synthetic_smb_fname_split(talloc_tos(), fname, - NULL, &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - if(fsp->is_directory || fsp->fh->fd == -1) { - /* - * This is actually a SETFILEINFO on a directory - * handle (returned from an NT SMB). NT5.0 seems - * to do this call. JRA. - */ - if (INFO_LEVEL_IS_UNIX(info_level)) { - /* Always do lstat for UNIX calls. */ - if (SMB_VFS_LSTAT(conn, smb_fname)) { - DEBUG(3,("call_trans2setfilepathinfo: " - "SMB_VFS_LSTAT of %s failed " - "(%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req,ERRDOS,ERRbadpath); - return; - } - } else { - if (SMB_VFS_STAT(conn, smb_fname) != 0) { - DEBUG(3,("call_trans2setfilepathinfo: " - "fileinfo of %s failed (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req,ERRDOS,ERRbadpath); - return; - } - } - } else if (fsp->print_file) { - /* - * Doing a DELETE_ON_CLOSE should cancel a print job. - */ - if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { - fsp->fh->private_options |= FILE_DELETE_ON_CLOSE; - - DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name )); - SSVAL(params,0,0); - send_trans2_replies(conn, req, params, 2, - *ppdata, 0, - max_data_bytes); - return; - } else { - reply_unixerror(req, ERRDOS, ERRbadpath); - return; - } - } else { - /* - * Original code - this is an open file. - */ - if (!check_fsp(conn, req, fsp)) { - return; - } - - if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) { - DEBUG(3,("call_trans2setfilepathinfo: fstat " - "of fnum %d failed (%s)\n", fsp->fnum, - strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadfid); - return; - } - } - } else { - /* set path info */ - if (total_params < 7) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - info_level = SVAL(params,0); - srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6], - total_params - 6, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - status = filename_convert(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - fname, - &smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, - NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - return; - } - reply_nterror(req, status); - return; - } - - if (INFO_LEVEL_IS_UNIX(info_level)) { - /* - * For CIFS UNIX extensions the target name may not exist. - */ - - /* Always do lstat for UNIX calls. */ - SMB_VFS_LSTAT(conn, smb_fname); - - } else if (!VALID_STAT(smb_fname->st) && - SMB_VFS_STAT(conn, smb_fname)) { - DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of " - "%s failed (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno))); - reply_unixerror(req, ERRDOS, ERRbadpath); - return; - } - } - - /* Set sbuf for use below. */ - sbuf = smb_fname->st; + *ret_data_size = 0; if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } if (!CAN_WRITE(conn)) { /* Allow POSIX opens. The open path will deny * any non-readonly opens. */ if (info_level != SMB_POSIX_PATH_OPEN) { - reply_doserror(req, ERRSRV, ERRaccess); - return; + return NT_STATUS_DOS(ERRSRV, ERRaccess); } } - DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", - tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); - - /* Realloc the parameter size */ - *pparams = (char *)SMB_REALLOC(*pparams,2); - if (*pparams == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + status = get_full_smb_filename(mem_ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + return status; } - params = *pparams; - SSVAL(params,0,0); + DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d " + "totdata=%d\n", smb_fname_str_dbg(smb_fname), + fsp ? fsp->fnum : -1, info_level, total_data)); switch (info_level) { @@ -7186,22 +7217,20 @@ static void call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_UNIX_LINK: { - if (tran_call != TRANSACT2_SETPATHINFO) { + if (fsp) { /* We must have a pathname for this. */ - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } status = smb_set_file_unix_link(conn, req, pdata, - total_data, fname); + total_data, smb_fname); break; } case SMB_SET_FILE_UNIX_HLINK: { - if (tran_call != TRANSACT2_SETPATHINFO || smb_fname == NULL) { + if (fsp) { /* We must have a pathname for this. */ - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } status = smb_set_file_unix_hlink(conn, req, pdata, total_data, @@ -7224,17 +7253,15 @@ static void call_trans2setfilepathinfo(connection_struct *conn, pdata, total_data, fsp, - fname, - &sbuf); + smb_fname); break; } #endif case SMB_SET_POSIX_LOCK: { - if (tran_call != TRANSACT2_SETFILEINFO) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + if (!fsp) { + return NT_STATUS_INVALID_LEVEL; } status = smb_set_posix_lock(conn, req, pdata, total_data, fsp); @@ -7243,27 +7270,24 @@ static void call_trans2setfilepathinfo(connection_struct *conn, case SMB_POSIX_PATH_OPEN: { - if (tran_call != TRANSACT2_SETPATHINFO) { + if (fsp) { /* We must have a pathname for this. */ - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } status = smb_posix_open(conn, req, ppdata, total_data, - fname, - &sbuf, + smb_fname, &data_return_size); break; } case SMB_POSIX_PATH_UNLINK: { - if (tran_call != TRANSACT2_SETPATHINFO) { + if (fsp) { /* We must have a pathname for this. */ - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; + return NT_STATUS_INVALID_LEVEL; } status = smb_posix_unlink(conn, req, @@ -7274,10 +7298,196 @@ static void call_trans2setfilepathinfo(connection_struct *conn, } default: - reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return NT_STATUS_INVALID_LEVEL; + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *ret_data_size = data_return_size; + return NT_STATUS_OK; +} + +/**************************************************************************** + Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname). +****************************************************************************/ + +static void call_trans2setfilepathinfo(connection_struct *conn, + struct smb_request *req, + unsigned int tran_call, + char **pparams, int total_params, + char **ppdata, int total_data, + unsigned int max_data_bytes) +{ + char *params = *pparams; + char *pdata = *ppdata; + uint16 info_level; + struct smb_filename *smb_fname = NULL; + files_struct *fsp = NULL; + NTSTATUS status = NT_STATUS_OK; + int data_return_size = 0; + + if (!params) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + if (tran_call == TRANSACT2_SETFILEINFO) { + if (total_params < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + fsp = file_fsp(req, SVAL(params,0)); + /* Basic check for non-null fsp. */ + if (!check_fsp_open(conn, req, fsp)) { + return; + } + info_level = SVAL(params,2); + + status = copy_smb_filename(talloc_tos(), fsp->fsp_name, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + if(fsp->is_directory || fsp->fh->fd == -1) { + /* + * This is actually a SETFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* Always do lstat for UNIX calls. */ + if (SMB_VFS_LSTAT(conn, smb_fname)) { + DEBUG(3,("call_trans2setfilepathinfo: " + "SMB_VFS_LSTAT of %s failed " + "(%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, map_nt_error_from_unix(errno)); + return; + } + } else { + if (SMB_VFS_STAT(conn, smb_fname) != 0) { + DEBUG(3,("call_trans2setfilepathinfo: " + "fileinfo of %s failed (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, map_nt_error_from_unix(errno)); + return; + } + } + } else if (fsp->print_file) { + /* + * Doing a DELETE_ON_CLOSE should cancel a print job. + */ + if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) { + fsp->fh->private_options |= FILE_DELETE_ON_CLOSE; + + DEBUG(3,("call_trans2setfilepathinfo: " + "Cancelling print job (%s)\n", + fsp_str_dbg(fsp))); + + SSVAL(params,0,0); + send_trans2_replies(conn, req, params, 2, + *ppdata, 0, + max_data_bytes); + return; + } else { + reply_doserror(req, ERRDOS, ERRbadpath); + return; + } + } else { + /* + * Original code - this is an open file. + */ + if (!check_fsp(conn, req, fsp)) { + return; + } + + if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) { + DEBUG(3,("call_trans2setfilepathinfo: fstat " + "of fnum %d failed (%s)\n", fsp->fnum, + strerror(errno))); + reply_nterror(req, map_nt_error_from_unix(errno)); + return; + } + } + } else { + char *fname = NULL; + + /* set path info */ + if (total_params < 7) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; + } + + info_level = SVAL(params,0); + srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6], + total_params - 6, STR_TERMINATE, + &status); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + status = filename_convert(req, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + fname, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; + } + reply_nterror(req, status); + return; + } + + if (INFO_LEVEL_IS_UNIX(info_level)) { + /* + * For CIFS UNIX extensions the target name may not exist. + */ + + /* Always do lstat for UNIX calls. */ + SMB_VFS_LSTAT(conn, smb_fname); + + } else if (!VALID_STAT(smb_fname->st) && + SMB_VFS_STAT(conn, smb_fname)) { + DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of " + "%s failed (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + reply_nterror(req, map_nt_error_from_unix(errno)); + return; + } + } + + DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d " + "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname), + fsp ? fsp->fnum : -1, info_level,total_data)); + + /* Realloc the parameter size */ + *pparams = (char *)SMB_REALLOC(*pparams,2); + if (*pparams == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; } + params = *pparams; + SSVAL(params,0,0); + + status = smbd_do_setfilepathinfo(conn, req, req, + info_level, + fsp, + smb_fname, + ppdata, total_data, + &data_return_size); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ @@ -7301,7 +7511,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn, return; } - SSVAL(params,0,0); send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size, max_data_bytes); @@ -7349,8 +7558,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req, conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, - &smb_dname, - NULL); + &smb_dname); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 2b4124bf7b..cd78c7962e 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -487,10 +487,12 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) * Actually try and commit the space on disk.... */ - DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", fsp->fsp_name, (double)len )); + DEBUG(10,("vfs_allocate_file_space: file %s, len %.0f\n", + fsp_str_dbg(fsp), (double)len)); if (((SMB_OFF_T)len) < 0) { - DEBUG(0,("vfs_allocate_file_space: %s negative len requested.\n", fsp->fsp_name )); + DEBUG(0,("vfs_allocate_file_space: %s negative len " + "requested.\n", fsp_str_dbg(fsp))); errno = EINVAL; return -1; } @@ -505,8 +507,9 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) if (len < (uint64_t)st.st_ex_size) { /* Shrink - use ftruncate. */ - DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current size %.0f\n", - fsp->fsp_name, (double)st.st_ex_size )); + DEBUG(10,("vfs_allocate_file_space: file %s, shrink. Current " + "size %.0f\n", fsp_str_dbg(fsp), + (double)st.st_ex_size)); contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_ALLOC_SHRINK); @@ -530,13 +533,16 @@ int vfs_allocate_file_space(files_struct *fsp, uint64_t len) len -= st.st_ex_size; len /= 1024; /* Len is now number of 1k blocks needed. */ - space_avail = get_dfree_info(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + space_avail = get_dfree_info(conn, fsp->fsp_name->base_name, false, + &bsize, &dfree, &dsize); if (space_avail == (uint64_t)-1) { return -1; } - DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", - fsp->fsp_name, (double)st.st_ex_size, (double)len, (double)space_avail )); + DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, " + "needed blocks = %.0f, space avail = %.0f\n", + fsp_str_dbg(fsp), (double)st.st_ex_size, (double)len, + (double)space_avail)); if (len > space_avail) { errno = ENOSPC; @@ -558,14 +564,15 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_SET_FILE_LEN); - DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); + DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", + fsp_str_dbg(fsp), (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); if ((ret = SMB_VFS_FTRUNCATE(fsp, len)) != -1) { set_filelen_write_cache(fsp, len); notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_ATTRIBUTES, - fsp->fsp_name); + fsp->fsp_name->base_name); } contend_level2_oplocks_end(fsp, LEVEL2_CONTEND_SET_FILE_LEN); @@ -600,8 +607,10 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) return 0; } - DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to len %.0f (%.0f bytes)\n", - fsp->fsp_name, (double)st.st_ex_size, (double)len, (double)(len - st.st_ex_size))); + DEBUG(10,("vfs_fill_sparse: write zeros in file %s from len %.0f to " + "len %.0f (%.0f bytes)\n", fsp_str_dbg(fsp), + (double)st.st_ex_size, (double)len, + (double)(len - st.st_ex_size))); contend_level2_oplocks_begin(fsp, LEVEL2_CONTEND_FILL_SPARSE); @@ -625,8 +634,9 @@ int vfs_fill_sparse(files_struct *fsp, SMB_OFF_T len) pwrite_ret = SMB_VFS_PWRITE(fsp, sparse_buf, curr_write_size, offset + total); if (pwrite_ret == -1) { - DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file %s failed with error %s\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(10,("vfs_fill_sparse: SMB_VFS_PWRITE for file " + "%s failed with error %s\n", + fsp_str_dbg(fsp), strerror(errno))); ret = -1; goto out; } @@ -962,15 +972,28 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { - SMB_STRUCT_STAT statbuf; - if ( (vfs_lstat_smb_fname(conn,fname,&statbuf) != -1) && - (S_ISLNK(statbuf.st_ex_mode)) ) { + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + + status = create_synthetic_smb_fname(talloc_tos(), fname, NULL, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + if (free_resolved_name) { + SAFE_FREE(resolved_name); + } + return status; + } + + if ( (SMB_VFS_LSTAT(conn, smb_fname) != -1) && + (S_ISLNK(smb_fname->st.st_ex_mode)) ) { if (free_resolved_name) { SAFE_FREE(resolved_name); } DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name)); + TALLOC_FREE(smb_fname); return NT_STATUS_ACCESS_DENIED; } + TALLOC_FREE(smb_fname); } #endif @@ -980,3 +1003,58 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) } return NT_STATUS_OK; } + +/** + * XXX: This is temporary and there should be no callers of this once + * smb_filename is plumbed through all path based operations. + */ +int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf) +{ + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + int ret; + + status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + ret = SMB_VFS_STAT(conn, smb_fname); + if (ret != -1) { + *psbuf = smb_fname->st; + } + + TALLOC_FREE(smb_fname); + return ret; +} + +/** + * XXX: This is temporary and there should be no callers of this once + * smb_filename is plumbed through all path based operations. + */ +int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname, + SMB_STRUCT_STAT *psbuf) +{ + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + int ret; + + status = create_synthetic_smb_fname_split(talloc_tos(), fname, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + ret = SMB_VFS_LSTAT(conn, smb_fname); + if (ret != -1) { + *psbuf = smb_fname->st; + } + + TALLOC_FREE(smb_fname); + return ret; +} + diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index 33ced8fa54..cd550a4f48 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -317,11 +317,6 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c if (fsp == NULL) { return NT_STATUS_NO_MEMORY; } - fsp->fsp_name = SMB_STRDUP(argv[1]); - if (fsp->fsp_name == NULL) { - SAFE_FREE(fsp); - return NT_STATUS_NO_MEMORY; - } fsp->fh = SMB_MALLOC_P(struct fd_handle); if (fsp->fh == NULL) { SAFE_FREE(fsp->fsp_name); @@ -333,18 +328,18 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c status = create_synthetic_smb_fname_split(mem_ctx, argv[1], NULL, &smb_fname); if (!NT_STATUS_IS_OK(status)) { - SAFE_FREE(fsp->fsp_name); SAFE_FREE(fsp); return status; } + fsp->fsp_name = smb_fname; + fsp->fh->fd = SMB_VFS_OPEN(vfs->conn, smb_fname, fsp, flags, mode); - TALLOC_FREE(smb_fname); if (fsp->fh->fd == -1) { printf("open: error=%d (%s)\n", errno, strerror(errno)); SAFE_FREE(fsp->fh); - SAFE_FREE(fsp->fsp_name); SAFE_FREE(fsp); + TALLOC_FREE(smb_fname); return NT_STATUS_UNSUCCESSFUL; } @@ -415,7 +410,7 @@ static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, else printf("close: ok\n"); - SAFE_FREE(vfs->files[fd]->fsp_name); + TALLOC_FREE(vfs->files[fd]->fsp_name); SAFE_FREE(vfs->files[fd]->fh); SAFE_FREE(vfs->files[fd]); vfs->files[fd] = NULL; diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c index 30b84c073d..a90c2e2dfe 100644 --- a/source3/torture/locktest.c +++ b/source3/torture/locktest.c @@ -341,9 +341,9 @@ static bool test_one(struct cli_state *cli[NSERVERS][NCONNECTIONS], case OP_UNLOCK: /* unset a lock */ for (server=0;server<NSERVERS;server++) { - ret[server] = cli_unlock64(cli[server][conn], + ret[server] = NT_STATUS_IS_OK(cli_unlock64(cli[server][conn], fnum[server][conn][f], - start, len); + start, len)); status[server] = cli_nt_error(cli[server][conn]); } if (showall || diff --git a/source3/torture/locktest2.c b/source3/torture/locktest2.c index 93adcb51a6..5c8a2d8019 100644 --- a/source3/torture/locktest2.c +++ b/source3/torture/locktest2.c @@ -132,7 +132,7 @@ static bool try_unlock(struct cli_state *c, int fstype, switch (fstype) { case FSTYPE_SMB: - return cli_unlock(c, fd, start, len); + return NT_STATUS_IS_OK(cli_unlock(c, fd, start, len)); case FSTYPE_NFS: lock.l_type = F_UNLCK; diff --git a/source3/torture/pdbtest.c b/source3/torture/pdbtest.c index ab7edde85d..950177c3ca 100644 --- a/source3/torture/pdbtest.c +++ b/source3/torture/pdbtest.c @@ -288,7 +288,7 @@ int main(int argc, char **argv) pdb_set_homedir(out, "\\\\torture\\home", PDB_SET); pdb_set_logon_script(out, "torture_script.cmd", PDB_SET); - pdb_get_account_policy(AP_PASSWORD_HISTORY, &history); + pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &history); if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) { buf = (uint8 *)TALLOC(ctx, NT_HASH_LEN); } else { @@ -311,8 +311,8 @@ int main(int argc, char **argv) } pdb_set_pw_history(out, buf, history, PDB_SET); - pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire); - pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age); + pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &expire); + pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &min_age); pdb_set_pass_last_set_time(out, time(NULL), PDB_SET); if (expire == 0 || expire == (uint32)-1) { diff --git a/source3/torture/torture.c b/source3/torture/torture.c index aa7e83bcc8..f9192b12b7 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -492,7 +492,7 @@ static bool rw_torture(struct cli_state *c) correct = False; } - if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int))) { + if (!NT_STATUS_IS_OK(cli_unlock(c, fnum2, n*sizeof(int), sizeof(int)))) { printf("unlock failed (%s)\n", cli_errstr(c)); correct = False; } @@ -1429,12 +1429,12 @@ static bool run_locktest2(int dummy) printf("lock at 100 failed (%s)\n", cli_errstr(cli)); } cli_setpid(cli, 2); - if (cli_unlock(cli, fnum1, 100, 4)) { + if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 100, 4))) { printf("unlock at 100 succeeded! This is a locking bug\n"); correct = False; } - if (cli_unlock(cli, fnum1, 0, 4)) { + if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 4))) { printf("unlock1 succeeded! This is a locking bug\n"); correct = False; } else { @@ -1443,7 +1443,7 @@ static bool run_locktest2(int dummy) NT_STATUS_RANGE_NOT_LOCKED)) return False; } - if (cli_unlock(cli, fnum1, 0, 8)) { + if (NT_STATUS_IS_OK(cli_unlock(cli, fnum1, 0, 8))) { printf("unlock2 succeeded! This is a locking bug\n"); correct = False; } else { @@ -1565,14 +1565,14 @@ static bool run_locktest3(int dummy) for (offset=i=0;i<torture_numops;i++) { NEXT_OFFSET; - if (!cli_unlock(cli1, fnum1, offset-1, 1)) { + if (!NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, offset-1, 1))) { printf("unlock1 %d failed (%s)\n", i, cli_errstr(cli1)); return False; } - if (!cli_unlock(cli2, fnum2, offset-2, 1)) { + if (!NT_STATUS_IS_OK(cli_unlock(cli2, fnum2, offset-2, 1))) { printf("unlock2 %d failed (%s)\n", i, cli_errstr(cli1)); @@ -1703,7 +1703,7 @@ static bool run_locktest4(int dummy) ret = cli_lock(cli1, fnum1, 110, 4, 0, READ_LOCK) && cli_lock(cli1, fnum1, 112, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 110, 6); + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 110, 6)); EXPECTED(ret, False); printf("the same process %s coalesce read locks\n", ret?"can":"cannot"); @@ -1721,30 +1721,30 @@ static bool run_locktest4(int dummy) ret = cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) && cli_lock(cli1, fnum1, 140, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 140, 4) && - cli_unlock(cli1, fnum1, 140, 4); + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 140, 4)); EXPECTED(ret, True); printf("this server %s do recursive read locking\n", ret?"does":"doesn't"); ret = cli_lock(cli1, fnum1, 150, 4, 0, WRITE_LOCK) && cli_lock(cli1, fnum1, 150, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 150, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)) && (cli_read(cli2, fnum2, buf, 150, 4) == 4) && !(cli_write(cli2, fnum2, 0, buf, 150, 4) == 4) && - cli_unlock(cli1, fnum1, 150, 4); + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 150, 4)); EXPECTED(ret, True); printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't"); ret = cli_lock(cli1, fnum1, 160, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 160, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 160, 4)) && (cli_write(cli2, fnum2, 0, buf, 160, 4) == 4) && (cli_read(cli2, fnum2, buf, 160, 4) == 4); EXPECTED(ret, True); printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot"); ret = cli_lock(cli1, fnum1, 170, 4, 0, WRITE_LOCK) && - cli_unlock(cli1, fnum1, 170, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 170, 4)) && (cli_write(cli2, fnum2, 0, buf, 170, 4) == 4) && (cli_read(cli2, fnum2, buf, 170, 4) == 4); EXPECTED(ret, True); @@ -1752,7 +1752,7 @@ static bool run_locktest4(int dummy) ret = cli_lock(cli1, fnum1, 190, 4, 0, WRITE_LOCK) && cli_lock(cli1, fnum1, 190, 4, 0, READ_LOCK) && - cli_unlock(cli1, fnum1, 190, 4) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 190, 4)) && !(cli_write(cli2, fnum2, 0, buf, 190, 4) == 4) && (cli_read(cli2, fnum2, buf, 190, 4) == 4); EXPECTED(ret, True); @@ -1861,7 +1861,7 @@ static bool run_locktest5(int dummy) /* Unlock the first process lock, then check this was the WRITE lock that was removed. */ - ret = cli_unlock(cli1, fnum1, 0, 4) && + ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) && cli_lock(cli2, fnum2, 0, 4, 0, READ_LOCK); EXPECTED(ret, True); @@ -1872,15 +1872,15 @@ static bool run_locktest5(int dummy) /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */ - ret = cli_unlock(cli1, fnum1, 1, 1) && - cli_unlock(cli1, fnum1, 0, 4) && - cli_unlock(cli1, fnum1, 0, 4); + ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 1, 1)) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)) && + NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)); EXPECTED(ret, True); printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); /* Ensure the next unlock fails. */ - ret = cli_unlock(cli1, fnum1, 0, 4); + ret = NT_STATUS_IS_OK(cli_unlock(cli1, fnum1, 0, 4)); EXPECTED(ret, False); printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); @@ -4295,6 +4295,18 @@ static bool run_simple_posix_open_test(int dummy) goto out; } + /* Do a POSIX lock/unlock. */ + if (!NT_STATUS_IS_OK(cli_posix_lock(cli1, fnum1, 0, 100, true, READ_LOCK))) { + printf("POSIX lock failed %s\n", cli_errstr(cli1)); + goto out; + } + + /* Punch a hole in the locked area. */ + if (!NT_STATUS_IS_OK(cli_posix_unlock(cli1, fnum1, 10, 80))) { + printf("POSIX unlock failed %s\n", cli_errstr(cli1)); + goto out; + } + cli_close(cli1, fnum1); /* Open the symlink for read - this should fail. A POSIX @@ -5749,17 +5761,45 @@ static bool run_local_substitute(int dummy) return ok; } +static bool run_local_base64(int dummy) +{ + int i; + bool ret = true; + + for (i=1; i<2000; i++) { + DATA_BLOB blob1, blob2; + char *b64; + + blob1.data = talloc_array(talloc_tos(), uint8_t, i); + blob1.length = i; + generate_random_buffer(blob1.data, blob1.length); + + b64 = base64_encode_data_blob(talloc_tos(), blob1); + if (b64 == NULL) { + d_fprintf(stderr, "base64_encode_data_blob failed " + "for %d bytes\n", i); + ret = false; + } + blob2 = base64_decode_data_blob(b64); + TALLOC_FREE(b64); + + if (data_blob_cmp(&blob1, &blob2)) { + d_fprintf(stderr, "data_blob_cmp failed for %d " + "bytes\n", i); + ret = false; + } + TALLOC_FREE(blob1.data); + data_blob_free(&blob2); + } + return ret; +} + static bool run_local_gencache(int dummy) { char *val; time_t tm; DATA_BLOB blob; - if (!gencache_init()) { - d_printf("%s: gencache_init() failed\n", __location__); - return False; - } - if (!gencache_set("foo", "bar", time(NULL) + 1000)) { d_printf("%s: gencache_set() failed\n", __location__); return False; @@ -5796,15 +5836,13 @@ static bool run_local_gencache(int dummy) } blob = data_blob_string_const_null("bar"); - tm = time(NULL); + tm = time(NULL) + 60; if (!gencache_set_data_blob("foo", &blob, tm)) { d_printf("%s: gencache_set_data_blob() failed\n", __location__); return False; } - data_blob_free(&blob); - if (!gencache_get_data_blob("foo", &blob, NULL)) { d_printf("%s: gencache_get_data_blob() failed\n", __location__); return False; @@ -5835,17 +5873,6 @@ static bool run_local_gencache(int dummy) return False; } - if (!gencache_shutdown()) { - d_printf("%s: gencache_shutdown() failed\n", __location__); - return False; - } - - if (gencache_shutdown()) { - d_printf("%s: second gencache_shutdown() succeeded\n", - __location__); - return False; - } - return True; } @@ -6487,6 +6514,7 @@ static struct { { "STREAMERROR", run_streamerror }, { "LOCAL-SUBSTITUTE", run_local_substitute, 0}, { "LOCAL-GENCACHE", run_local_gencache, 0}, + { "LOCAL-BASE64", run_local_base64, 0}, { "LOCAL-RBTREE", run_local_rbtree, 0}, { "LOCAL-MEMCACHE", run_local_memcache, 0}, { "LOCAL-STREAM-NAME", run_local_stream_name, 0}, diff --git a/source3/utils/net.c b/source3/utils/net.c index 0e3946f5a5..f8bfab3e99 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -625,6 +625,7 @@ static struct functable net_func[] = { int main(int argc, const char **argv) { int opt,i; + char *p; int rc = 0; int argc_new = 0; const char ** argv_new; @@ -635,10 +636,12 @@ static struct functable net_func[] = { struct poptOption long_options[] = { {"help", 'h', POPT_ARG_NONE, 0, 'h'}, {"workgroup", 'w', POPT_ARG_STRING, &c->opt_target_workgroup}, + {"user", 'U', POPT_ARG_STRING, &c->opt_user_name, 'U'}, {"ipaddress", 'I', POPT_ARG_STRING, 0,'I'}, {"port", 'p', POPT_ARG_INT, &c->opt_port}, {"myname", 'n', POPT_ARG_STRING, &c->opt_requester_name}, {"server", 'S', POPT_ARG_STRING, &c->opt_host}, + {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" }, {"container", 'c', POPT_ARG_STRING, &c->opt_container}, {"comment", 'C', POPT_ARG_STRING, &c->opt_comment}, {"maxusers", 'M', POPT_ARG_INT, &c->opt_maxusers}, @@ -649,13 +652,15 @@ static struct functable net_func[] = { {"stdin", 'i', POPT_ARG_NONE, &c->opt_stdin}, {"timeout", 't', POPT_ARG_INT, &c->opt_timeout}, {"request-timeout",0,POPT_ARG_INT, &c->opt_request_timeout}, + {"machine-pass",'P', POPT_ARG_NONE, &c->opt_machine_pass}, + {"kerberos", 'k', POPT_ARG_NONE, &c->opt_kerberos}, {"myworkgroup", 'W', POPT_ARG_STRING, &c->opt_workgroup}, {"verbose", 'v', POPT_ARG_NONE, &c->opt_verbose}, {"test", 'T', POPT_ARG_NONE, &c->opt_testmode}, /* Options for 'net groupmap set' */ {"local", 'L', POPT_ARG_NONE, &c->opt_localgroup}, {"domain", 'D', POPT_ARG_NONE, &c->opt_domaingroup}, - {"ntname", 0, POPT_ARG_STRING, &c->opt_newntname}, + {"ntname", 'N', POPT_ARG_STRING, &c->opt_newntname}, {"rid", 'R', POPT_ARG_INT, &c->opt_rid}, /* Options for 'net rpc share migrate' */ {"acls", 0, POPT_ARG_NONE, &c->opt_acls}, @@ -670,7 +675,6 @@ static struct functable net_func[] = { {"clean-old-entries", 0, POPT_ARG_NONE, &c->opt_clean_old_entries}, POPT_COMMON_SAMBA - POPT_COMMON_CREDENTIALS { 0, 0, 0, 0} }; @@ -684,13 +688,6 @@ static struct functable net_func[] = { dbf = x_stderr; c->private_data = net_func; - c->auth_info = user_auth_info_init(frame); - if (c->auth_info == NULL) { - d_fprintf(stderr, "\nOut of memory!\n"); - exit(1); - } - popt_common_set_auth_info(c->auth_info); - pc = poptGetContext(NULL, argc, (const char **) argv, long_options, POPT_CONTEXT_KEEP_FIRST); @@ -698,7 +695,9 @@ static struct functable net_func[] = { switch (opt) { case 'h': c->display_usage = true; - set_cmdline_auth_info_password(c->auth_info, ""); + break; + case 'e': + c->smb_encrypt = true; break; case 'I': if (!interpret_string_addr(&c->opt_dest_ip, @@ -708,6 +707,15 @@ static struct functable net_func[] = { c->opt_have_ip = true; } break; + case 'U': + c->opt_user_specified = true; + c->opt_user_name = SMB_STRDUP(c->opt_user_name); + p = strchr(c->opt_user_name,'%'); + if (p) { + *p = 0; + c->opt_password = p+1; + } + break; default: d_fprintf(stderr, "\nInvalid option %s: %s\n", poptBadOption(pc, 0), poptStrerror(opt)); @@ -741,6 +749,10 @@ static struct functable net_func[] = { set_global_myname(c->opt_requester_name); } + if (!c->opt_user_name && getenv("LOGNAME")) { + c->opt_user_name = getenv("LOGNAME"); + } + if (!c->opt_workgroup) { c->opt_workgroup = smb_xstrdup(lp_workgroup()); } @@ -758,10 +770,23 @@ static struct functable net_func[] = { that it won't assert becouse we are not root */ sec_init(); + if (c->opt_machine_pass) { + /* it is very useful to be able to make ads queries as the + machine account for testing purposes and for domain leave */ + + net_use_krb_machine_account(c); + } + + if (!c->opt_password) { + c->opt_password = getenv("PASSWD"); + } + rc = net_run_function(c, argc_new-1, argv_new+1, "net", net_func); DEBUG(2,("return code = %d\n", rc)); + gencache_stabilize(); + libnetapi_free(c->netapi_ctx); poptFreeContext(pc); diff --git a/source3/utils/net.h b/source3/utils/net.h index f604d96361..d88f962d41 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -28,8 +28,11 @@ struct net_context { const char *opt_requester_name; const char *opt_host; - int opt_long_list_entries; + const char *opt_password; + const char *opt_user_name; + bool opt_user_specified; const char *opt_workgroup; + int opt_long_list_entries; int opt_reboot; int opt_force; int opt_stdin; @@ -42,6 +45,7 @@ struct net_context { int opt_timeout; int opt_request_timeout; const char *opt_target_workgroup; + int opt_machine_pass; int opt_localgroup; int opt_domaingroup; int do_talloc_report; @@ -53,14 +57,15 @@ struct net_context { const char *opt_exclude; const char *opt_destination; int opt_testmode; + bool opt_kerberos; int opt_force_full_repl; int opt_single_obj_repl; int opt_clean_old_entries; int opt_have_ip; struct sockaddr_storage opt_dest_ip; + bool smb_encrypt; struct libnetapi_ctx *netapi_ctx; - struct user_auth_info *auth_info; bool display_usage; void *private_data; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index d82715eb45..8f76c0eb09 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -231,23 +231,32 @@ retry_connect: ads = ads_init(realm, c->opt_target_workgroup, c->opt_host); + if (!c->opt_user_name) { + c->opt_user_name = "administrator"; + } + + if (c->opt_user_specified) { + need_password = true; + } + retry: - if (need_password) { - set_cmdline_auth_info_getpass(c->auth_info); + if (!c->opt_password && need_password && !c->opt_machine_pass) { + c->opt_password = net_prompt_pass(c, c->opt_user_name); + if (!c->opt_password) { + ads_destroy(&ads); + return ADS_ERROR(LDAP_NO_MEMORY); + } } - if (get_cmdline_auth_info_got_pass(c->auth_info) || - !get_cmdline_auth_info_use_kerberos(c->auth_info)) { + if (c->opt_password) { use_in_memory_ccache(); SAFE_FREE(ads->auth.password); - ads->auth.password = smb_xstrdup( - get_cmdline_auth_info_password(c->auth_info)); + ads->auth.password = smb_xstrdup(c->opt_password); } ads->auth.flags |= auth_flags; SAFE_FREE(ads->auth.user_name); - ads->auth.user_name = smb_xstrdup( - get_cmdline_auth_info_username(c->auth_info)); + ads->auth.user_name = smb_xstrdup(c->opt_user_name); /* * If the username is of the form "name@realm", @@ -521,7 +530,7 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv) return net_ads_user_usage(c, argc, argv); } - escaped_user = escape_ldap_string_alloc(argv[0]); + escaped_user = escape_ldap_string(talloc_tos(), argv[0]); if (!escaped_user) { d_fprintf(stderr, "ads_user_info: failed to escape user %s\n", argv[0]); @@ -529,12 +538,12 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv) } if (!ADS_ERR_OK(ads_startup(c, false, &ads))) { - SAFE_FREE(escaped_user); + TALLOC_FREE(escaped_user); return -1; } if (asprintf(&searchstring, "(sAMAccountName=%s)", escaped_user) == -1) { - SAFE_FREE(escaped_user); + TALLOC_FREE(escaped_user); return -1; } rc = ads_search(ads, &res, searchstring, attrs); @@ -543,7 +552,7 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv) if (!ADS_ERR_OK(rc)) { d_fprintf(stderr, "ads_search: %s\n", ads_errstr(rc)); ads_destroy(&ads); - SAFE_FREE(escaped_user); + TALLOC_FREE(escaped_user); return -1; } @@ -563,7 +572,7 @@ static int ads_user_info(struct net_context *c, int argc, const char **argv) ads_msgfree(ads, res); ads_destroy(&ads); - SAFE_FREE(escaped_user); + TALLOC_FREE(escaped_user); return 0; } @@ -866,7 +875,6 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv) TALLOC_CTX *ctx; struct libnet_UnjoinCtx *r = NULL; WERROR werr; - struct user_auth_info *ai = c->auth_info; if (c->display_usage) { d_printf("Usage:\n" @@ -885,7 +893,7 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv) return -1; } - if (!get_cmdline_auth_info_use_kerberos(ai)) { + if (!c->opt_kerberos) { use_in_memory_ccache(); } @@ -895,14 +903,12 @@ static int net_ads_leave(struct net_context *c, int argc, const char **argv) return -1; } - set_cmdline_auth_info_getpass(ai); - r->in.debug = true; - r->in.use_kerberos = get_cmdline_auth_info_use_kerberos(ai); + r->in.use_kerberos = c->opt_kerberos; r->in.dc_name = c->opt_host; r->in.domain_name = lp_realm(); - r->in.admin_account = get_cmdline_auth_info_username(ai); - r->in.admin_password = get_cmdline_auth_info_password(ai); + r->in.admin_account = c->opt_user_name; + r->in.admin_password = net_prompt_pass(c, c->opt_user_name); r->in.modify_config = lp_config_backend_is_registry(); /* Try to delete it, but if that fails, disable it. The @@ -960,8 +966,7 @@ static NTSTATUS net_ads_join_ok(struct net_context *c) return NT_STATUS_ACCESS_DENIED; } - set_cmdline_auth_info_use_machine_account(c->auth_info); - set_cmdline_auth_info_machine_account_creds(c->auth_info); + net_use_krb_machine_account(c); status = ads_startup(c, true, &ads); if (!ADS_ERR_OK(status)) { @@ -1192,7 +1197,6 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) const char *os_name = NULL; const char *os_version = NULL; bool modify_config = lp_config_backend_is_registry(); - struct user_auth_info *ai = c->auth_info;; if (c->display_usage) return net_ads_join_usage(c, argc, argv); @@ -1212,7 +1216,7 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) goto fail; } - if (!get_cmdline_auth_info_use_kerberos(ai)) { + if (!c->opt_kerberos) { use_in_memory_ccache(); } @@ -1262,8 +1266,6 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) /* Do the domain join here */ - set_cmdline_auth_info_getpass(ai); - r->in.domain_name = domain; r->in.create_upn = createupn; r->in.upn = machineupn; @@ -1271,10 +1273,10 @@ int net_ads_join(struct net_context *c, int argc, const char **argv) r->in.os_name = os_name; r->in.os_version = os_version; r->in.dc_name = c->opt_host; - r->in.admin_account = get_cmdline_auth_info_username(ai); - r->in.admin_password = get_cmdline_auth_info_password(ai); + r->in.admin_account = c->opt_user_name; + r->in.admin_password = net_prompt_pass(c, c->opt_user_name); r->in.debug = true; - r->in.use_kerberos = get_cmdline_auth_info_use_kerberos(ai); + r->in.use_kerberos = c->opt_kerberos; r->in.modify_config = modify_config; r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE | WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE | @@ -1585,7 +1587,6 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char * char *prt_dn, *srv_dn, **srv_cn; char *srv_cn_escaped = NULL, *printername_escaped = NULL; LDAPMessage *res = NULL; - struct user_auth_info *ai = c->auth_info; if (argc < 1 || c->display_usage) { d_printf("Usage:\n" @@ -1617,9 +1618,8 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char * nt_status = cli_full_connection(&cli, global_myname(), servername, &server_ss, 0, "IPC$", "IPC", - get_cmdline_auth_info_username(ai), - c->opt_workgroup, - get_cmdline_auth_info_password(ai), + c->opt_user_name, c->opt_workgroup, + c->opt_password ? c->opt_password : "", CLI_FULL_CONNECTION_USE_KERBEROS, Undefined, NULL); @@ -1807,8 +1807,8 @@ static int net_ads_printer(struct net_context *c, int argc, const char **argv) static int net_ads_password(struct net_context *c, int argc, const char **argv) { ADS_STRUCT *ads; - const char *auth_principal; - const char *auth_password; + const char *auth_principal = c->opt_user_name; + const char *auth_password = c->opt_password; char *realm = NULL; char *new_password = NULL; char *chr, *prompt; @@ -1823,9 +1823,10 @@ static int net_ads_password(struct net_context *c, int argc, const char **argv) return 0; } - auth_principal = get_cmdline_auth_info_username(c->auth_info); - set_cmdline_auth_info_getpass(c->auth_info); - auth_password = get_cmdline_auth_info_password(c->auth_info); + if (c->opt_user_name == NULL || c->opt_password == NULL) { + d_fprintf(stderr, "You must supply an administrator username/password\n"); + return -1; + } if (argc < 1) { d_fprintf(stderr, "ERROR: You must say which username to change password for\n"); @@ -1907,7 +1908,7 @@ int net_ads_changetrustpw(struct net_context *c, int argc, const char **argv) return -1; } - set_cmdline_auth_info_use_machine_account(c->auth_info); + net_use_krb_machine_account(c); use_in_memory_ccache(); @@ -2289,7 +2290,6 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar TALLOC_CTX *mem_ctx = NULL; NTSTATUS status; int ret = -1; - struct user_auth_info *ai = c->auth_info; if (c->display_usage) { d_printf("Usage:\n" @@ -2303,11 +2303,11 @@ static int net_ads_kerberos_pac(struct net_context *c, int argc, const char **ar goto out; } - set_cmdline_auth_info_getpass(ai); + c->opt_password = net_prompt_pass(c, c->opt_user_name); status = kerberos_return_pac(mem_ctx, - get_cmdline_auth_info_username(ai), - get_cmdline_auth_info_password(ai), + c->opt_user_name, + c->opt_password, 0, NULL, NULL, @@ -2340,7 +2340,6 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char ** TALLOC_CTX *mem_ctx = NULL; int ret = -1; NTSTATUS status; - struct user_auth_info *ai = c->auth_info; if (c->display_usage) { d_printf("Usage:\n" @@ -2354,10 +2353,10 @@ static int net_ads_kerberos_kinit(struct net_context *c, int argc, const char ** goto out; } - set_cmdline_auth_info_getpass(ai); + c->opt_password = net_prompt_pass(c, c->opt_user_name); - ret = kerberos_kinit_password_ext(get_cmdline_auth_info_username(ai), - get_cmdline_auth_info_password(ai), + ret = kerberos_kinit_password_ext(c->opt_user_name, + c->opt_password, 0, NULL, NULL, diff --git a/source3/utils/net_cache.c b/source3/utils/net_cache.c index 5e7db38515..36cd12fb82 100644 --- a/source3/utils/net_cache.c +++ b/source3/utils/net_cache.c @@ -171,12 +171,10 @@ static int net_cache_add(struct net_context *c, int argc, const char **argv) if (gencache_set(keystr, datastr, timeout)) { d_printf("New cache entry stored successfully.\n"); - gencache_shutdown(); return 0; } d_fprintf(stderr, "Entry couldn't be added. Perhaps there's already such a key.\n"); - gencache_shutdown(); return -1; } @@ -275,7 +273,6 @@ static int net_cache_list(struct net_context *c, int argc, const char **argv) return 0; } gencache_iterate(print_cache_entry, NULL, pattern); - gencache_shutdown(); return 0; } @@ -297,10 +294,24 @@ static int net_cache_flush(struct net_context *c, int argc, const char **argv) return 0; } gencache_iterate(delete_cache_entry, NULL, pattern); - gencache_shutdown(); return 0; } +static int net_cache_stabilize(struct net_context *c, int argc, + const char **argv) +{ + if (c->display_usage) { + d_printf("Usage:\n" + "net cache flush\n" + " Delete all cache entries.\n"); + return 0; + } + + if (!gencache_stabilize()) { + return -1; + } + return 0; +} /** * Entry point to 'net cache' subfunctionality * @@ -366,6 +377,14 @@ int net_cache(struct net_context *c, int argc, const char **argv) "net cache flush\n" " Delete all cache entries" }, + { + "stabilize", + net_cache_stabilize, + NET_TRANSPORT_LOCAL, + "Move transient cache content to stable storage", + "net cache stabilize\n" + " Move transient cache content to stable storage" + }, {NULL, NULL, 0, NULL, NULL} }; diff --git a/source3/utils/net_dom.c b/source3/utils/net_dom.c index a13f52c519..401079777f 100644 --- a/source3/utils/net_dom.c +++ b/source3/utils/net_dom.c @@ -368,11 +368,9 @@ int net_dom(struct net_context *c, int argc, const char **argv) return -1; } - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c index 5a170790c5..0502373aa2 100644 --- a/source3/utils/net_help.c +++ b/source3/utils/net_help.c @@ -65,6 +65,5 @@ int net_help(struct net_context *c, int argc, const char **argv) } c->display_usage = true; - set_cmdline_auth_info_password(c->auth_info, ""); return net_run_function(c, argc, argv, "net help", func); } diff --git a/source3/utils/net_proto.h b/source3/utils/net_proto.h index 8a09147aad..75ac032db9 100644 --- a/source3/utils/net_proto.h +++ b/source3/utils/net_proto.h @@ -459,6 +459,8 @@ NTSTATUS connect_to_ipc_krb5(struct net_context *c, NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, const struct ndr_syntax_id *interface); +int net_use_krb_machine_account(struct net_context *c); +int net_use_machine_account(struct net_context *c); bool net_find_server(struct net_context *c, const char *domain, unsigned flags, @@ -473,6 +475,7 @@ NTSTATUS net_make_ipc_connection_ex(struct net_context *c ,const char *domain, const char *server, struct sockaddr_storage *pss, unsigned flags, struct cli_state **pcli); +const char *net_prompt_pass(struct net_context *c, const char *user); int net_run_function(struct net_context *c, int argc, const char **argv, const char *whoami, struct functable *table); void net_display_usage_from_functable(struct functable *table); diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 0118b4818a..f6f90030fe 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -25,8 +25,7 @@ #include "../libcli/auth/libcli_auth.h" static int net_mode_share; -static bool sync_files(struct copy_clistate *cp_clistate, const char *mask, - const struct user_auth_info *auth_info); +static bool sync_files(struct copy_clistate *cp_clistate, const char *mask); /** * @file net_rpc.c @@ -123,7 +122,6 @@ int run_rpc_command(struct net_context *c, DOM_SID *domain_sid; const char *domain_name; int ret = -1; - struct user_auth_info *ai = c->auth_info; /* make use of cli_state handed over as an argument, if possible */ if (!cli_arg) { @@ -173,10 +171,8 @@ int run_rpc_command(struct net_context *c, nt_status = cli_rpc_pipe_open_ntlmssp( cli, interface, PIPE_AUTH_LEVEL_PRIVACY, - lp_workgroup(), - get_cmdline_auth_info_username(ai), - get_cmdline_auth_info_password(ai), - &pipe_hnd); + lp_workgroup(), c->opt_user_name, + c->opt_password, &pipe_hnd); } else { nt_status = cli_rpc_pipe_open_noauth( cli, interface, @@ -944,12 +940,9 @@ int net_rpc_user(struct net_context *c, int argc, const char **argv) if (status != 0) { return -1; } - set_cmdline_auth_info_getpass(c->auth_info); - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } @@ -2763,12 +2756,9 @@ int net_rpc_group(struct net_context *c, int argc, const char **argv) if (status != 0) { return -1; } - set_cmdline_auth_info_getpass(c->auth_info); - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } @@ -3255,7 +3245,7 @@ static void copy_fn(const char *mnt, file_info *f, old_dir = local_state->cwd; local_state->cwd = dir; - if (!sync_files(local_state, new_mask, c->auth_info)) + if (!sync_files(local_state, new_mask)) printf("could not handle files\n"); local_state->cwd = old_dir; @@ -3302,18 +3292,15 @@ static void copy_fn(const char *mnt, file_info *f, * * @return Boolean result **/ -static bool sync_files(struct copy_clistate *cp_clistate, const char *mask, - const struct user_auth_info *auth_info) +static bool sync_files(struct copy_clistate *cp_clistate, const char *mask) { struct cli_state *targetcli; char *targetpath = NULL; DEBUG(3,("calling cli_list with mask: %s\n", mask)); - - if ( !cli_resolve_path(talloc_tos(), "", auth_info, - cp_clistate->cli_share_src, mask, &targetcli, - &targetpath ) ) { + if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src, + mask, &targetcli, &targetpath ) ) { d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", mask, cli_errstr(cp_clistate->cli_share_src)); return false; @@ -3476,7 +3463,7 @@ static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c, goto done; } - if (!sync_files(&cp_clistate, mask, c->auth_info)) { + if (!sync_files(&cp_clistate, mask)) { d_fprintf(stderr, "could not handle files for share: %s\n", info502.name); nt_status = NT_STATUS_UNSUCCESSFUL; goto done; @@ -4577,12 +4564,9 @@ int net_rpc_share(struct net_context *c, int argc, const char **argv) if (status != 0) { return -1; } - set_cmdline_auth_info_getpass(c->auth_info); - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } @@ -4855,12 +4839,9 @@ int net_rpc_file(struct net_context *c, int argc, const char **argv) if (status != 0) { return -1; } - set_cmdline_auth_info_getpass(c->auth_info); - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } @@ -5550,7 +5531,7 @@ static int rpc_trustdom_establish(struct net_context *c, int argc, c->opt_workgroup = smb_xstrdup(domain_name); }; - set_cmdline_auth_info_username(c->auth_info, acct_name); + c->opt_user_name = acct_name; /* find the domain controller */ if (!net_find_pdc(&server_ss, pdc_name, domain_name)) { @@ -5647,9 +5628,7 @@ static int rpc_trustdom_establish(struct net_context *c, int argc, * Store the password in secrets db */ - if (!pdb_set_trusteddom_pw(domain_name, - get_cmdline_auth_info_password(c->auth_info), - domain_sid)) { + if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) { DEBUG(0, ("Storing password for trusted domain failed.\n")); cli_shutdown(cli); talloc_destroy(mem_ctx); @@ -7211,12 +7190,9 @@ int net_rpc(struct net_context *c, int argc, const char **argv) if (status != 0) { return -1; } - set_cmdline_auth_info_getpass(c->auth_info); - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index cae2491aed..ed0311317d 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -58,8 +58,7 @@ NTSTATUS net_rpc_join_ok(struct net_context *c, const char *domain, if (sec == SEC_ADS) { /* Connect to IPC$ using machine account's credentials. We don't use anonymous connection here, as it may be denied by server's local policy. */ - set_cmdline_auth_info_use_machine_account(c->auth_info); - set_cmdline_auth_info_machine_account_creds(c->auth_info); + net_use_machine_account(c); } else { /* some servers (e.g. WinNT) don't accept machine-authenticated diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index bd5047c1ff..309be171cc 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -379,8 +379,8 @@ NTSTATUS rpc_vampire_keytab_internals(struct net_context *c, ctx->cli = pipe_hnd; ctx->ops = &libnet_samsync_keytab_ops; ctx->domain_name = domain_name; - ctx->username = get_cmdline_auth_info_username(c->auth_info); - ctx->password = get_cmdline_auth_info_password(c->auth_info); + ctx->username = c->opt_user_name; + ctx->password = c->opt_password; ctx->force_full_replication = c->opt_force_full_repl ? true : false; ctx->clean_old_entries = c->opt_clean_old_entries ? true : false; @@ -493,17 +493,20 @@ int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv) if (!dc_info.is_ad) { printf("DC is not running Active Directory\n"); - return -1; - } - - if (dc_info.is_mixed_mode) { ret = run_rpc_command(c, cli, &ndr_table_netlogon.syntax_id, 0, rpc_vampire_keytab_internals, argc, argv); + return -1; } else { ret = run_rpc_command(c, cli, &ndr_table_drsuapi.syntax_id, NET_FLAGS_SEAL, rpc_vampire_keytab_ds_internals, argc, argv); + if (ret != 0 && dc_info.is_mixed_mode) { + printf("Fallback to NT4 vampire on Mixed-Mode AD Domain\n"); + ret = run_rpc_command(c, cli, &ndr_table_netlogon.syntax_id, + 0, + rpc_vampire_keytab_internals, argc, argv); + } } return ret; diff --git a/source3/utils/net_rpc_shell.c b/source3/utils/net_rpc_shell.c index dc13e91423..3aaed1ed18 100644 --- a/source3/utils/net_rpc_shell.c +++ b/source3/utils/net_rpc_shell.c @@ -220,12 +220,9 @@ int net_rpc_shell(struct net_context *c, int argc, const char **argv) if (libnetapi_init(&c->netapi_ctx) != 0) { return -1; } - set_cmdline_auth_info_getpass(c->auth_info); - libnetapi_set_username(c->netapi_ctx, - get_cmdline_auth_info_username(c->auth_info)); - libnetapi_set_password(c->netapi_ctx, - get_cmdline_auth_info_password(c->auth_info)); - if (get_cmdline_auth_info_use_kerberos(c->auth_info)) { + libnetapi_set_username(c->netapi_ctx, c->opt_user_name); + libnetapi_set_password(c->netapi_ctx, c->opt_password); + if (c->opt_kerberos) { libnetapi_set_use_kerberos(c->netapi_ctx); } diff --git a/source3/utils/net_sam.c b/source3/utils/net_sam.c index 62abef000d..41daa4180d 100644 --- a/source3/utils/net_sam.c +++ b/source3/utils/net_sam.c @@ -452,7 +452,7 @@ static int net_sam_policy_set(struct net_context *c, int argc, const char **argv const char *account_policy = NULL; uint32 value = 0; uint32 old_value = 0; - int field; + enum pdb_policy_type field; char *endptr; if (argc != 2 || c->display_usage) { @@ -462,7 +462,7 @@ static int net_sam_policy_set(struct net_context *c, int argc, const char **argv } account_policy = argv[0]; - field = account_policy_name_to_fieldnum(account_policy); + field = account_policy_name_to_typenum(account_policy); if (strequal(argv[1], "forever") || strequal(argv[1], "never") || strequal(argv[1], "off")) { @@ -519,7 +519,7 @@ static int net_sam_policy_show(struct net_context *c, int argc, const char **arg { const char *account_policy = NULL; uint32 old_value; - int field; + enum pdb_policy_type field; if (argc != 1 || c->display_usage) { d_fprintf(stderr, "usage: net sam policy show" @@ -528,7 +528,7 @@ static int net_sam_policy_show(struct net_context *c, int argc, const char **arg } account_policy = argv[0]; - field = account_policy_name_to_fieldnum(account_policy); + field = account_policy_name_to_typenum(account_policy); if (field == 0) { const char **names; diff --git a/source3/utils/net_usershare.c b/source3/utils/net_usershare.c index 992a03d813..6eacb1386c 100644 --- a/source3/utils/net_usershare.c +++ b/source3/utils/net_usershare.c @@ -163,7 +163,7 @@ static int net_usershare_delete(struct net_context *c, int argc, const char **ar d_fprintf(stderr, "net usershare delete: share name %s contains " "invalid characters (any of %s)\n", sharename, INVALID_SHARENAME_CHARS); - SAFE_FREE(sharename); + TALLOC_FREE(sharename); return -1; } @@ -172,7 +172,7 @@ static int net_usershare_delete(struct net_context *c, int argc, const char **ar lp_usershare_path(), sharename); if (!us_path) { - SAFE_FREE(sharename); + TALLOC_FREE(sharename); return -1; } @@ -180,10 +180,10 @@ static int net_usershare_delete(struct net_context *c, int argc, const char **ar d_fprintf(stderr, "net usershare delete: unable to remove usershare %s. " "Error was %s\n", us_path, strerror(errno)); - SAFE_FREE(sharename); + TALLOC_FREE(sharename); return -1; } - SAFE_FREE(sharename); + TALLOC_FREE(sharename); return 0; } @@ -672,7 +672,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: maximum number of allowed usershares (%d) reached\n", lp_usershare_max_shares() ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -681,7 +680,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) "invalid characters (any of %s)\n", sharename, INVALID_SHARENAME_CHARS); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -690,7 +688,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: share name %s is already a valid system user name\n", sharename ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -698,7 +695,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) full_path = get_basepath(ctx); if (!full_path) { TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } full_path_tmp = talloc_asprintf(ctx, @@ -706,7 +702,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) full_path); if (!full_path_tmp) { TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -715,7 +710,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) sharename); if (!full_path) { TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -724,7 +718,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr,"net usershare add: path %s is not an absolute path.\n", us_path); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -734,7 +727,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) "this is a directory. Error was %s\n", us_path, strerror(errno) ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -742,7 +734,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: path %s is not a directory.\n", us_path ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -756,7 +747,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) "\tto the [global] section of the smb.conf to allow this.\n", us_path ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -786,7 +776,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: malformed acl %s (missing ':').\n", pacl ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -802,7 +791,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) "(access control must be 'r', 'f', or 'd')\n", pacl ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -810,7 +798,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: malformed terminating character for acl %s\n", pacl ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -818,7 +805,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) if ((name = talloc_strndup(ctx, pacl, pcolon - pacl)) == NULL) { d_fprintf(stderr, "talloc_strndup failed\n"); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } if (!string_to_sid(&sid, name)) { @@ -833,7 +819,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "\n"); } TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } } @@ -854,7 +839,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) "but the \"usershare allow guests\" parameter is not enabled " "by this server.\n"); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -865,7 +849,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: cannot create tmp file %s\n", full_path_tmp ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -874,7 +857,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: cannot lstat tmp file %s\n", full_path_tmp ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -883,7 +865,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: cannot fstat tmp file %s\n", full_path_tmp ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -891,7 +872,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: tmp file %s is not a regular file ?\n", full_path_tmp ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -899,7 +879,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) d_fprintf(stderr, "net usershare add: failed to fchmod tmp file %s to 0644n", full_path_tmp ); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -915,7 +894,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) (unsigned int)to_write, full_path_tmp, strerror(errno)); unlink(full_path_tmp); TALLOC_FREE(ctx); - SAFE_FREE(sharename); return -1; } @@ -926,7 +904,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) sharename, strerror(errno)); TALLOC_FREE(ctx); close(tmpfd); - SAFE_FREE(sharename); return -1; } @@ -939,7 +916,6 @@ static int net_usershare_add(struct net_context *c, int argc, const char **argv) net_usershare_info(c, 1, my_argv); } - SAFE_FREE(sharename); TALLOC_FREE(ctx); return 0; } @@ -998,6 +974,7 @@ static int net_usershare_list(struct net_context *c, int argc, pi.ctx = ctx; pi.op = US_LIST_OP; + pi.c = c; ret = process_share_list(info_fn, &pi); talloc_destroy(ctx); diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c index 50f3c1db01..8bf9aac6f2 100644 --- a/source3/utils/net_util.c +++ b/source3/utils/net_util.c @@ -96,22 +96,22 @@ NTSTATUS connect_to_service(struct net_context *c, { NTSTATUS nt_status; int flags = 0; - struct user_auth_info *ai = c->auth_info; - set_cmdline_auth_info_getpass(ai); + c->opt_password = net_prompt_pass(c, c->opt_user_name); - if (get_cmdline_auth_info_use_kerberos(ai)) { - flags |= CLI_FULL_CONNECTION_USE_KERBEROS | - CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; + if (c->opt_kerberos) { + flags |= CLI_FULL_CONNECTION_USE_KERBEROS; + } + + if (c->opt_kerberos && c->opt_password) { + flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS; } nt_status = cli_full_connection(cli_ctx, NULL, server_name, server_ss, c->opt_port, service_name, service_type, - get_cmdline_auth_info_username(ai), - c->opt_workgroup, - get_cmdline_auth_info_password(ai), - flags, Undefined, NULL); + c->opt_user_name, c->opt_workgroup, + c->opt_password, flags, Undefined, NULL); if (!NT_STATUS_IS_OK(nt_status)) { d_fprintf(stderr, "Could not connect to server %s\n", server_name); @@ -131,10 +131,10 @@ NTSTATUS connect_to_service(struct net_context *c, return nt_status; } - if (get_cmdline_auth_info_smb_encrypt(ai)) { + if (c->smb_encrypt) { nt_status = cli_force_encryption(*cli_ctx, - get_cmdline_auth_info_username(ai), - get_cmdline_auth_info_password(ai), + c->opt_user_name, + c->opt_password, c->opt_workgroup); if (NT_STATUS_EQUAL(nt_status,NT_STATUS_NOT_SUPPORTED)) { @@ -234,12 +234,14 @@ NTSTATUS connect_to_ipc_krb5(struct net_context *c, { NTSTATUS nt_status; char *user_and_realm = NULL; - struct user_auth_info *ai = c->auth_info; /* FIXME: Should get existing kerberos ticket if possible. */ - set_cmdline_auth_info_getpass(ai); + c->opt_password = net_prompt_pass(c, c->opt_user_name); + if (!c->opt_password) { + return NT_STATUS_NO_MEMORY; + } - user_and_realm = get_user_and_realm(get_cmdline_auth_info_username(ai)); + user_and_realm = get_user_and_realm(c->opt_user_name); if (!user_and_realm) { return NT_STATUS_NO_MEMORY; } @@ -248,7 +250,7 @@ NTSTATUS connect_to_ipc_krb5(struct net_context *c, server_ss, c->opt_port, "IPC$", "IPC", user_and_realm, c->opt_workgroup, - get_cmdline_auth_info_password(ai), + c->opt_password, CLI_FULL_CONNECTION_USE_KERBEROS, Undefined, NULL); @@ -259,10 +261,10 @@ NTSTATUS connect_to_ipc_krb5(struct net_context *c, return nt_status; } - if (get_cmdline_auth_info_smb_encrypt(ai)) { + if (c->smb_encrypt) { nt_status = cli_cm_force_encryption(*cli_ctx, user_and_realm, - get_cmdline_auth_info_password(ai), + c->opt_password, c->opt_workgroup, "IPC$"); if (!NT_STATUS_IS_OK(nt_status)) { @@ -326,6 +328,50 @@ NTSTATUS connect_dst_pipe(struct net_context *c, struct cli_state **cli_dst, return nt_status; } +/**************************************************************************** + Use the local machine account (krb) and password for this session. +****************************************************************************/ + +int net_use_krb_machine_account(struct net_context *c) +{ + char *user_name = NULL; + + if (!secrets_init()) { + d_fprintf(stderr, "ERROR: Unable to open secrets database\n"); + exit(1); + } + + c->opt_password = secrets_fetch_machine_password( + c->opt_target_workgroup, NULL, NULL); + if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) { + return -1; + } + c->opt_user_name = user_name; + return 0; +} + +/**************************************************************************** + Use the machine account name and password for this session. +****************************************************************************/ + +int net_use_machine_account(struct net_context *c) +{ + char *user_name = NULL; + + if (!secrets_init()) { + d_fprintf(stderr, "ERROR: Unable to open secrets database\n"); + exit(1); + } + + c->opt_password = secrets_fetch_machine_password( + c->opt_target_workgroup, NULL, NULL); + if (asprintf(&user_name, "%s$", global_myname()) == -1) { + return -1; + } + c->opt_user_name = user_name; + return 0; +} + bool net_find_server(struct net_context *c, const char *domain, unsigned flags, @@ -489,6 +535,33 @@ done: /**************************************************************************** ****************************************************************************/ +const char *net_prompt_pass(struct net_context *c, const char *user) +{ + char *prompt = NULL; + const char *pass = NULL; + + if (c->opt_password) { + return c->opt_password; + } + + if (c->opt_machine_pass) { + return NULL; + } + + if (c->opt_kerberos && !c->opt_user_specified) { + return NULL; + } + + if (asprintf(&prompt, "Enter %s's password:", user) == -1) { + return NULL; + } + + pass = getpass(prompt); + SAFE_FREE(prompt); + + return pass; +} + int net_run_function(struct net_context *c, int argc, const char **argv, const char *whoami, struct functable *table) { diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index a464299438..dce2f05a83 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -1109,7 +1109,7 @@ int main (int argc, char **argv) /* account policy operations */ if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) { uint32 value; - int field = account_policy_name_to_fieldnum(account_policy); + enum pdb_policy_type field = account_policy_name_to_typenum(account_policy); if (field == 0) { const char **names; int count; diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index d617fe1f0b..34eaeb2d79 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -163,6 +163,8 @@ static void terminate(bool is_parent) trustdom_cache_shutdown(); + gencache_stabilize(); + #if 0 if (interactive) { TALLOC_CTX *mem_ctx = talloc_init("end_description"); diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 0f40419a0e..08afb46674 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -210,7 +210,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, gid_t primary_gid = (gid_t)-1; if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) || - ads_atype_map(atype) != SID_NAME_USER) { + ds_atype_map(atype) != SID_NAME_USER) { DEBUG(1,("Not a user account? atype=0x%x\n", atype)); continue; } @@ -608,7 +608,7 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain, goto done; } - if (!(escaped_dn = escape_ldap_string_alloc(user_dn))) { + if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) { status = NT_STATUS_NO_MEMORY; goto done; } @@ -620,12 +620,12 @@ static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain, GROUP_TYPE_SECURITY_ENABLED); if (!ldap_exp) { DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn)); - SAFE_FREE(escaped_dn); + TALLOC_FREE(escaped_dn); status = NT_STATUS_NO_MEMORY; goto done; } - SAFE_FREE(escaped_dn); + TALLOC_FREE(escaped_dn); rc = ads_search_retry(ads, &res, ldap_exp, group_attrs); diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 92f0d60817..ab07c9767d 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -179,10 +179,6 @@ int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, if (tevent_req_is_unix_error(req, err)) { return -1; } - if (state->response->result != WINBINDD_OK) { - *err = EIO; /* EIO doesn't fit, but what would be better? */ - return -1; - } *presponse = talloc_move(mem_ctx, &state->response); return 0; } diff --git a/source3/winbindd/winbindd_passdb.c b/source3/winbindd/winbindd_passdb.c index b18f0ff595..9a43c6d6a2 100644 --- a/source3/winbindd/winbindd_passdb.c +++ b/source3/winbindd/winbindd_passdb.c @@ -332,29 +332,29 @@ static NTSTATUS password_policy(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } - if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, + if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_LEN, &account_policy_temp)) { return NT_STATUS_ACCESS_DENIED; } p->min_password_length = account_policy_temp; - if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, + if (!pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &account_policy_temp)) { return NT_STATUS_ACCESS_DENIED; } p->password_history_length = account_policy_temp; - if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, + if (!pdb_get_account_policy(PDB_POLICY_USER_MUST_LOGON_TO_CHG_PASS, &p->password_properties)) { return NT_STATUS_ACCESS_DENIED; } - if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) { + if (!pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &account_policy_temp)) { return NT_STATUS_ACCESS_DENIED; } u_expire = account_policy_temp; - if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) { + if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &account_policy_temp)) { return NT_STATUS_ACCESS_DENIED; } u_min_age = account_policy_temp; diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index c091cd7f53..f8cf7db920 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -93,6 +93,11 @@ void winbindd_lookupname(struct winbindd_cli_state *state) *p = 0; name_domain = state->request->data.name.name; name_user = p+1; + } else if ((p = strchr(state->request->data.name.name, '@')) != NULL) { + /* upn */ + name_domain = p + 1; + *p = 0; + name_user = state->request->data.name.name; } else { name_domain = state->request->data.name.dom_name; name_user = state->request->data.name.name; diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index 283eee09af..44ae814ae9 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -996,7 +996,8 @@ bool parse_domain_user(const char *domuser, fstring domain, fstring user) if ( assume_domain(lp_workgroup())) { fstrcpy(domain, lp_workgroup()); } else if ((p = strchr(domuser, '@')) != NULL) { - fstrcpy(domain, ""); + fstrcpy(domain, p + 1); + user[PTR_DIFF(p, domuser)] = 0; } else { return False; } |