#include "../libcli/auth/libcli_auth.h"
#include "../librpc/gen_ndr/xattr.h"
#include "../librpc/gen_ndr/ndr_security.h"
+#include "../librpc/gen_ndr/open_files.h"
#include "libcli/security/security.h"
#include "trans2.h"
#include "auth.h"
#include "smbprofile.h"
#include "rpc_server/srv_pipe_hnd.h"
+#include "printing.h"
#define DIR_ENTRY_SAFETY_MARGIN 4096
files_struct *fsp,
const SMB_STRUCT_STAT *psbuf);
+/********************************************************************
+ The canonical "check access" based on object handle or path function.
+********************************************************************/
+
+NTSTATUS check_access(connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ uint32_t access_mask)
+{
+ if (fsp) {
+ if (!(fsp->access_mask & access_mask)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ } else {
+ NTSTATUS status = smbd_check_access_rights(conn,
+ smb_fname,
+ access_mask);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
/********************************************************************
Roundup a value to the nearest allocation roundup size boundary.
Only do this for Windows clients.
Return a linked list of the total EA's. Plus the total size
****************************************************************************/
-static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
- const char *fname, size_t *pea_total_len)
+static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
+ const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
{
/* Get a list of all xattrs. Max namesize is 64k. */
size_t i, num_names;
NTSTATUS status;
*pea_total_len = 0;
-
- if (!lp_ea_support(SNUM(conn))) {
- return NULL;
- }
+ *ea_list = NULL;
status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
&names, &num_names);
- if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
- return NULL;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (num_names == 0) {
+ *ea_list = NULL;
+ return NT_STATUS_OK;
}
for (i=0; i<num_names; i++) {
listp = talloc(mem_ctx, struct ea_list);
if (listp == NULL) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
- if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
- fname, names[i],
- &listp->ea))) {
- return NULL;
+ status = get_ea_value(mem_ctx, conn, fsp,
+ fname, names[i],
+ &listp->ea);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
push_ascii_fstring(dos_ea_name, listp->ea.name);
DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
(unsigned int)*pea_total_len));
- return ea_list_head;
+ *ea_list = ea_list_head;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
+ const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
+{
+ *pea_total_len = 0;
+ *ea_list = NULL;
+
+ if (!lp_ea_support(SNUM(conn))) {
+ return NT_STATUS_OK;
+ }
+
+ if (is_ntfs_stream_smb_fname(smb_fname)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
}
/****************************************************************************
return NT_STATUS_OK;
}
-static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
+static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
{
size_t total_ea_len = 0;
- TALLOC_CTX *mem_ctx = NULL;
+ TALLOC_CTX *mem_ctx;
+ struct ea_list *ea_list = NULL;
if (!lp_ea_support(SNUM(conn))) {
return 0;
}
- mem_ctx = talloc_tos();
- (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
+ mem_ctx = talloc_stackframe();
+
+ /* If this is a stream fsp, then we need to instead find the
+ * estimated ea len from the main file, not the stream
+ * (streams cannot have EAs), but the estimate isn't just 0 in
+ * this case! */
+ if (is_ntfs_stream_smb_fname(smb_fname)) {
+ fsp = NULL;
+ }
+ (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
+ TALLOC_FREE(mem_ctx);
return total_ea_len;
}
{
size_t total_ea_len;
TALLOC_CTX *mem_ctx = talloc_tos();
- struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
+ struct ea_list *ea_list;
+ NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
for (; ea_list; ea_list = ea_list->next) {
if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
const struct smb_filename *smb_fname, struct ea_list *ea_list)
{
+ NTSTATUS status;
char *fname = NULL;
if (!lp_ea_support(SNUM(conn))) {
return NT_STATUS_EAS_NOT_SUPPORTED;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Setting EAs on streams isn't supported. */
+ if (is_ntfs_stream_smb_fname(smb_fname)) {
+ return NT_STATUS_INVALID_PARAMETER;
}
- /* For now setting EAs on streams isn't supported. */
fname = smb_fname->base_name;
for (;ea_list; ea_list = ea_list->next) {
reply_outbuf(req, 10, total_sent_thistime + alignment_offset
+ data_alignment_offset);
- /*
- * We might have SMBtrans2s in req which was transferred to
- * the outbuf, fix that.
- */
- SCVAL(req->outbuf, smb_com, SMBtrans2);
-
/* Set total params and data to be sent */
SSVAL(req->outbuf,smb_tprcnt,paramsize);
SSVAL(req->outbuf,smb_tdrcnt,datasize);
uint32 open_size;
char *pname;
char *fname = NULL;
- SMB_OFF_T size=0;
+ off_t size=0;
int fattr=0,mtime=0;
SMB_INO_T inode = 0;
int smb_action = 0;
SSVAL(params,24,0); /* Padding. */
if (flags & 8) {
uint32 ea_size = estimate_ea_size(conn, fsp,
- fsp->fsp_name->base_name);
+ smb_fname);
SIVAL(params, 26, ea_size);
} else {
SIVAL(params, 26, 0);
switch (ptype) {
case PERM_NEW_FILE:
+ case PERM_EXISTING_FILE:
/* Apply mode mask */
ret &= lp_create_mask(SNUM(conn));
/* Add in force bits */
ret |= lp_force_create_mode(SNUM(conn));
break;
case PERM_NEW_DIR:
+ case PERM_EXISTING_DIR:
ret &= lp_dir_mask(SNUM(conn));
/* Add in force bits */
ret |= lp_force_dir_mode(SNUM(conn));
break;
- case PERM_EXISTING_FILE:
- /* Apply mode mask */
- ret &= lp_security_mask(SNUM(conn));
- /* Add in force bits */
- ret |= lp_force_security_mode(SNUM(conn));
- break;
- case PERM_EXISTING_DIR:
- /* Apply mode mask */
- ret &= lp_dir_security_mask(SNUM(conn));
- /* Add in force bits */
- ret |= lp_force_dir_security_mode(SNUM(conn));
- break;
}
*ret_perms = ret;
uint32_t len;
struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
- time_t c_date = (time_t)0;
char *nameptr;
char *last_entry_ptr;
bool was_8_3;
create_date = convert_timespec_to_time_t(create_date_ts);
mdate = convert_timespec_to_time_t(mdate_ts);
adate = convert_timespec_to_time_t(adate_ts);
- c_date = convert_timespec_to_time_t(cdate_ts);
/* align the record */
SMB_ASSERT(align >= 1);
SSVAL(p,20,mode);
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,22,ea_size); /* Extended attributes */
}
p += 27;
{
struct ea_list *file_list = NULL;
size_t ea_len = 0;
+ NTSTATUS status;
DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
if (!name_list) {
SSVAL(p,20,mode);
p += 22; /* p now points to the EA area. */
- file_list = get_ea_list_from_file(ctx, conn, NULL,
- smb_fname->base_name,
- &ea_len);
+ status = get_ea_list_from_file(ctx, conn, NULL,
+ smb_fname,
+ &ea_len, &file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ file_list = NULL;
+ }
name_list = ea_list_union(name_list, file_list, &ea_len);
/* We need to determine if this entry will fit in the space available. */
q = p; p += 4; /* q is placeholder for name length. */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p += 4;
}
q = p; p += 4; /* q is placeholder for name length. */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p +=4;
}
q = p; p += 4; /* q is placeholder for name length. */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p +=4;
}
q = p; p += 4; /* q is placeholder for name length */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p +=4;
}
TALLOC_CTX *ctx = talloc_tos();
struct dptr_struct *dirptr = NULL;
struct smbd_server_connection *sconn = req->sconn;
+ uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
+ bool backup_priv = false;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+ backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
+ security_token_has_privilege(get_current_nttok(conn),
+ SEC_PRIV_BACKUP));
+
info_level = SVAL(params,6);
DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
-close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
+close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
(unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
+ (int)backup_priv,
info_level, max_data_bytes));
if (!maxentries) {
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
goto out;
}
+ ucf_flags |= UCF_UNIX_NAME_LOOKUP;
break;
default:
reply_nterror(req, NT_STATUS_INVALID_LEVEL);
goto out;
}
- ntstatus = filename_convert(ctx, conn,
+ if (backup_priv) {
+ become_root();
+ ntstatus = filename_convert_with_privilege(ctx,
+ conn,
+ req,
+ directory,
+ ucf_flags,
+ &mask_contains_wcard,
+ &smb_dname);
+ } else {
+ ntstatus = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
- (UCF_SAVE_LCOMP |
- UCF_ALWAYS_ALLOW_WCARD_LCOMP),
+ ucf_flags,
&mask_contains_wcard,
&smb_dname);
+ }
+
if (!NT_STATUS_IS_OK(ntstatus)) {
if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
needed as lanman2 assumes these are being saved between calls */
ntstatus = dptr_create(conn,
+ req,
NULL, /* fsp */
directory,
False,
goto out;
}
+ if (backup_priv) {
+ /* Remember this in case we have
+ to do a findnext. */
+ dptr_set_priv(dirptr);
+ }
+
dptr_num = dptr_dnum(dirptr);
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
+ directory,lp_dontdescend(ctx, SNUM(conn))));
+ if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
name_to_8_3(mask, mangled_name, True, conn->params);
}
out:
+
+ if (backup_priv) {
+ unbecome_root();
+ }
+
TALLOC_FREE(smb_dname);
return;
}
TALLOC_CTX *ctx = talloc_tos();
struct dptr_struct *dirptr;
struct smbd_server_connection *sconn = req->sconn;
+ bool backup_priv = false;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
directory = dptr_path(sconn, dptr_num);
/* Get the wildcard mask from the dptr */
- if((p = dptr_wcard(sconn, dptr_num))== NULL) {
+ if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
reply_nterror(req, STATUS_NO_MORE_FILES);
return;
}
- mask = p;
-
/* Get the attr mask from the dptr */
dirtype = dptr_attr(sconn, dptr_num);
- DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
+ backup_priv = dptr_get_priv(dirptr);
+
+ DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
+ "backup_priv = %d\n",
dptr_num, mask, dirtype,
(long)dirptr,
- dptr_TellDir(dirptr)));
+ dptr_TellDir(dirptr),
+ (int)backup_priv));
/* Initialize per TRANS2_FIND_NEXT operation data */
dptr_init_search_op(dirptr);
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
+ directory,lp_dontdescend(ctx, SNUM(conn))));
+ if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
space_remaining = max_data_bytes;
out_of_space = False;
+ if (backup_priv) {
+ become_root();
+ }
+
/*
* Seek to the correct position. We no longer use the resume key but
* depend on the last file name instead.
dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
}
+ if (backup_priv) {
+ unbecome_root();
+ }
+
/* Set up the return parameter block */
SSVAL(params,0,numentries);
SSVAL(params,2,finished);
unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
{
- E_md4hash(lp_servicename(SNUM(conn)),objid);
+ E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
return objid;
}
uint16_t info_level,
uint16_t flags2,
unsigned int max_data_bytes,
+ struct smb_filename *fname,
char **ppdata,
int *ret_data_len)
{
char *pdata, *end_data;
int data_len = 0, len;
- const char *vname = volume_label(SNUM(conn));
+ const char *vname = volume_label(talloc_tos(), SNUM(conn));
int snum = SNUM(conn);
- char *fstype = lp_fstype(SNUM(conn));
+ char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
+ char *filename = NULL;
uint32 additional_flags = 0;
- struct smb_filename smb_fname_dot;
+ struct smb_filename smb_fname;
SMB_STRUCT_STAT st;
+ if (fname == NULL || fname->base_name == NULL) {
+ filename = ".";
+ } else {
+ filename = fname->base_name;
+ }
+
if (IS_IPC(conn)) {
if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
DEBUG(0,("smbd_do_qfsinfo: not an allowed "
DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
- ZERO_STRUCT(smb_fname_dot);
- smb_fname_dot.base_name = discard_const_p(char, ".");
+ ZERO_STRUCT(smb_fname);
+ smb_fname.base_name = discard_const_p(char, filename);
- if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
+ if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
return map_nt_error_from_unix(errno);
}
- st = smb_fname_dot.st;
+ st = smb_fname.st;
*ppdata = (char *)SMB_REALLOC(
*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
{
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) {
+ if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
* Add volume serial number - hash of a combination of
* the called hostname and the service name.
*/
- SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
+ SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
/*
* Win2k3 and previous mess this up by sending a name length
* one byte short. I believe only older clients (OS/2 Win9x) use
* Add volume serial number - hash of a combination of
* the called hostname and the service name.
*/
- SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
+ SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
(str_checksum(get_local_machine_name())<<16));
/* Max label len is 32 characters. */
data_len = 18+len;
DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
- (int)strlen(vname),vname, lp_servicename(snum)));
+ (int)strlen(vname),vname,
+ lp_servicename(talloc_tos(), snum)));
break;
case SMB_QUERY_FS_SIZE_INFO:
{
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) {
+ if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
block_size = lp_block_size(snum);
{
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) {
+ if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
block_size = lp_block_size(snum);
ZERO_STRUCT(quotas);
fsp.conn = conn;
- fsp.fnum = -1;
+ fsp.fnum = FNUM_FIELD_INVALID;
/* access check */
if (get_current_uid(conn) != 0) {
DEBUG(0,("set_user_quota: access_denied "
"service [%s] user [%s]\n",
- lp_servicename(SNUM(conn)),
+ lp_servicename(talloc_tos(), SNUM(conn)),
conn->session_info->unix_info->unix_name));
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))));
+ DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
return map_nt_error_from_unix(errno);
}
data_len = 48;
DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
- lp_servicename(SNUM(conn))));
+ lp_servicename(talloc_tos(), SNUM(conn))));
/* Unknown1 24 NULL bytes*/
SBIG_UINT(pdata,0,(uint64_t)0);
}
switch (conn->encrypt_level) {
- case 0:
+ case SMB_SIGNING_OFF:
encrypt_caps = 0;
break;
- case 1:
- case Auto:
+ case SMB_SIGNING_IF_REQUIRED:
+ case SMB_SIGNING_DEFAULT:
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
break;
- case Required:
+ case SMB_SIGNING_REQUIRED:
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
large_write = false;
return NT_STATUS_INVALID_LEVEL;
}
- rc = SMB_VFS_STATVFS(conn, ".", &svfs);
+ rc = SMB_VFS_STATVFS(conn, filename, &svfs);
if (!rc) {
data_len = 56;
return NT_STATUS_INVALID_LEVEL;
#endif /* EOPNOTSUPP */
} else {
- DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
+ DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
return NT_STATUS_DOS(ERRSRV, ERRerror);
}
break;
return NT_STATUS_BUFFER_TOO_SMALL;
}
- /* We ARE guest if global_sid_Builtin_Guests is
- * in our list of SIDs.
- */
- if (nt_token_check_sid(&global_sid_Builtin_Guests,
- conn->session_info->security_token)) {
+ if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
flags |= SMB_WHOAMI_GUEST;
}
- /* We are NOT guest if global_sid_Authenticated_Users
- * is in our list of SIDs.
- */
- if (nt_token_check_sid(&global_sid_Authenticated_Users,
- conn->session_info->security_token)) {
- flags &= ~SMB_WHOAMI_GUEST;
- }
-
/* NOTE: 8 bytes for UID/GID, irrespective of native
* platform size. This matches
* SMB_QUERY_FILE_UNIX_BASIC and friends.
* Thursby MAC extension... ONLY on NTFS filesystems
* once we do streams then we don't need this
*/
- if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
+ if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
data_len = 88;
SIVAL(pdata,84,0x100); /* Don't support mac... */
break;
DEBUG(0,("call_trans2qfsinfo: encryption required "
"and info level 0x%x sent.\n",
(unsigned int)info_level));
- exit_server_cleanly("encryption required "
- "on connection");
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
}
info_level,
req->flags2,
max_data_bytes,
+ NULL,
ppdata, &data_len);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
+ struct smbd_server_connection *sconn = req->sconn;
char *pdata = *ppdata;
char *params = *pparams;
uint16 info_level;
- DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
+ DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
+ lp_servicename(talloc_tos(), SNUM(conn))));
/* */
if (total_params < 4) {
DEBUG(0,("call_trans2setfsinfo: encryption required "
"and info level 0x%x sent.\n",
(unsigned int)info_level));
- exit_server_cleanly("encryption required "
- "on connection");
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
}
switch(info_level) {
case SMB_SET_CIFS_UNIX_INFO:
- {
- uint16 client_unix_major;
- uint16 client_unix_minor;
- uint32 client_unix_cap_low;
- uint32 client_unix_cap_high;
-
- if (!lp_unix_extensions()) {
- reply_nterror(req,
- NT_STATUS_INVALID_LEVEL);
- return;
- }
+ if (!lp_unix_extensions()) {
+ DEBUG(2,("call_trans2setfsinfo: "
+ "SMB_SET_CIFS_UNIX_INFO is invalid with "
+ "unix extensions off\n"));
+ reply_nterror(req,
+ NT_STATUS_INVALID_LEVEL);
+ return;
+ }
- /* There should be 12 bytes of capabilities set. */
- if (total_data < 8) {
- reply_nterror(
- req,
- NT_STATUS_INVALID_PARAMETER);
- return;
- }
- client_unix_major = SVAL(pdata,0);
- client_unix_minor = SVAL(pdata,2);
- client_unix_cap_low = IVAL(pdata,4);
- client_unix_cap_high = IVAL(pdata,8);
- /* Just print these values for now. */
- DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
-cap_low = 0x%x, cap_high = 0x%x\n",
- (unsigned int)client_unix_major,
- (unsigned int)client_unix_minor,
- (unsigned int)client_unix_cap_low,
- (unsigned int)client_unix_cap_high ));
-
- /* Here is where we must switch to posix pathname processing... */
- if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
- lp_set_posix_pathnames();
- mangle_change_to_posix();
- }
+ /* There should be 12 bytes of capabilities set. */
+ if (total_data < 12) {
+ reply_nterror(
+ req,
+ NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ sconn->smb1.unix_info.client_major = SVAL(pdata,0);
+ sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
+ sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
+ sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
+ /* Just print these values for now. */
+ DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
+ "major = %u, minor = %u cap_low = 0x%x, "
+ "cap_high = 0x%xn",
+ (unsigned int)sconn->
+ smb1.unix_info.client_major,
+ (unsigned int)sconn->
+ smb1.unix_info.client_minor,
+ (unsigned int)sconn->
+ smb1.unix_info.client_cap_low,
+ (unsigned int)sconn->
+ smb1.unix_info.client_cap_high));
+
+ /* Here is where we must switch to posix pathname processing... */
+ if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ lp_set_posix_pathnames();
+ mangle_change_to_posix();
+ }
- if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
- !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
- /* Client that knows how to do posix locks,
- * but not posix open/mkdir operations. Set a
- * default type for read/write checks. */
+ if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
+ !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
+ /* Client that knows how to do posix locks,
+ * but not posix open/mkdir operations. Set a
+ * default type for read/write checks. */
- lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
+ lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
- }
- break;
}
+ break;
case SMB_REQUEST_TRANSPORT_ENCRYPTION:
{
return;
}
- if (lp_smb_encrypt(SNUM(conn)) == false) {
+ if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
reply_nterror(
req,
NT_STATUS_NOT_SUPPORTED);
* encryption is now *on*. */
status = srv_encryption_start(conn);
if (!NT_STATUS_IS_OK(status)) {
- exit_server_cleanly(
- "Failure in setting "
- "up encrypted transport");
+ char *reason = talloc_asprintf(talloc_tos(),
+ "Failure in setting "
+ "up encrypted transport: %s",
+ nt_errstr(status));
+ exit_server_cleanly(reason);
}
}
return;
/* access check */
if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
- lp_servicename(SNUM(conn)),
+ lp_servicename(talloc_tos(), SNUM(conn)),
conn->session_info->unix_info->unix_name));
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
/* 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))));
+ DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
reply_nterror(req, map_nt_error_from_unix(errno));
return;
}
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
- while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
+ while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
/* get_next... */
if (entry_id == SMB_ACL_FIRST_ENTRY) {
entry_id = SMB_ACL_NEXT_ENTRY;
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
- while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
+ while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
unsigned char perms = 0;
entry_id = SMB_ACL_NEXT_ENTRY;
}
- if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
+ if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
return False;
}
- if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+ if (sys_acl_get_permset(entry, &permset) == -1) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
return False;
}
- perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
- perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
- perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
+ perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
+ perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
+ perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
SCVAL(pdata,1,perms);
break;
case SMB_ACL_USER:
{
- uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
if (!puid) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
return False;
}
own_grp = (unsigned int)*puid;
- SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
SCVAL(pdata,0,SMB_POSIX_ACL_USER);
SIVAL(pdata,2,own_grp);
SIVAL(pdata,6,0);
break;
case SMB_ACL_GROUP:
{
- gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
if (!pgid) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
return False;
}
own_grp = (unsigned int)*pgid;
- SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
SIVAL(pdata,2,own_grp);
SIVAL(pdata,6,0);
const SMB_STRUCT_STAT *psbuf)
{
uint64_t file_index = get_FileIndex(conn, psbuf);
+ dev_t devno;
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
pdata += 4;
- SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
+ if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
+ devno = psbuf->st_ex_rdev;
+ } else {
+ devno = psbuf->st_ex_dev;
+ }
+
+ SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
SIVAL(pdata,4,0);
pdata += 8;
- SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
+ SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
SIVAL(pdata,4,0);
pdata += 8;
unsigned int i;
unsigned int ofs = 0;
- for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
+ for (i = 0; i < num_streams; i++) {
unsigned int next_offset;
size_t namelen;
smb_ucs2_t *namebuf;
namelen -= 2;
+ /*
+ * We cannot overflow ...
+ */
+ if ((ofs + 24 + namelen) > max_data_bytes) {
+ DEBUG(10, ("refusing to overflow reply at stream %u\n",
+ i));
+ TALLOC_FREE(namebuf);
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
SIVAL(data, ofs+4, namelen);
SOFF_T(data, ofs+8, streams[i].size);
SOFF_T(data, ofs+16, streams[i].alloc_size);
else {
unsigned int align = ndr_align_size(next_offset, 8);
+ if ((next_offset + align) > max_data_bytes) {
+ DEBUG(10, ("refusing to overflow align "
+ "reply at stream %u\n",
+ i));
+ TALLOC_FREE(namebuf);
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
memset(data+next_offset, 0, align);
next_offset += align;
ofs = next_offset;
}
+ DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
+
*data_size = ofs;
return NT_STATUS_OK;
return NT_STATUS_INVALID_LEVEL;
}
- DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
- smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
+ DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
+ smb_fname_str_dbg(smb_fname),
+ fsp_fnum_dbg(fsp),
info_level, max_data_bytes));
mode = dos_mode(conn, smb_fname);
{
unsigned int ea_size =
estimate_ea_size(conn, fsp,
- smb_fname->base_name);
+ smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
data_size = 26;
srv_put_dos_date2(pdata,0,create_time);
{
size_t total_ea_len = 0;
struct ea_list *ea_file_list = NULL;
-
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
- ea_file_list =
+ status =
get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ smb_fname,
+ &total_ea_len, &ea_file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
if (!ea_list || (total_ea_len > data_size)) {
{
/* We have data_size bytes to put EA's into. */
size_t total_ea_len = 0;
-
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
- ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ status = get_ea_list_from_file(mem_ctx, conn, fsp,
+ smb_fname,
+ &total_ea_len, &ea_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
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. */
/*TODO: add filtering and index handling */
- ea_file_list =
- get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ status =
+ get_ea_list_from_file(mem_ctx, conn, fsp,
+ smb_fname,
+ &total_ea_len, &ea_file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (!ea_file_list) {
return NT_STATUS_NO_EAS_ON_FILE;
}
case SMB_QUERY_FILE_EA_INFO:
{
unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
+ estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
data_size = 4;
SIVAL(pdata,0,ea_size);
{
int len;
unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
+ estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
{
int len;
unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
+ estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
*/
case SMB_QUERY_FILE_STREAM_INFO:
case SMB_FILE_STREAM_INFORMATION: {
- unsigned int num_streams;
- struct stream_struct *streams;
+ unsigned int num_streams = 0;
+ struct stream_struct *streams = NULL;
DEBUG(10,("smbd_do_qfilepathinfo: "
"SMB_FILE_STREAM_INFORMATION\n"));
return NT_STATUS_INVALID_PARAMETER;
}
- status = SMB_VFS_STREAMINFO(
- conn, fsp, smb_fname->base_name, talloc_tos(),
- &num_streams, &streams);
+ status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
+ talloc_tos(), &num_streams, &streams);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("could not get stream info: %s\n",
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("marshall_stream_info failed: %s\n",
nt_errstr(status)));
+ TALLOC_FREE(streams);
return status;
}
uint16 num_def_acls = 0;
if (fsp && fsp->fh->fd != -1) {
- file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
+ file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
+ talloc_tos());
} else {
file_acl =
SMB_VFS_SYS_ACL_GET_FILE(conn,
smb_fname->base_name,
- SMB_ACL_TYPE_ACCESS);
+ SMB_ACL_TYPE_ACCESS,
+ talloc_tos());
}
if (file_acl == NULL && no_acl_syscall_error(errno)) {
SMB_VFS_SYS_ACL_GET_FILE(
conn,
fsp->fsp_name->base_name,
- SMB_ACL_TYPE_DEFAULT);
+ SMB_ACL_TYPE_DEFAULT,
+ talloc_tos());
} else {
def_acl =
SMB_VFS_SYS_ACL_GET_FILE(
conn,
smb_fname->base_name,
- SMB_ACL_TYPE_DEFAULT);
+ SMB_ACL_TYPE_DEFAULT,
+ talloc_tos());
}
def_acl = free_empty_sys_acl(conn, def_acl);
}
(unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
SMB_POSIX_ACL_HEADER_SIZE) ));
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
return NT_STATUS_BUFFER_TOO_SMALL;
}
SSVAL(pdata,4,num_def_acls);
if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
return NT_STATUS_INTERNAL_ERROR;
}
if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
return NT_STATUS_INTERNAL_ERROR;
}
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
break;
* Original code - this is an open file.
*/
if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
- DEBUG(3, ("fstat of fnum %d failed (%s)\n",
- fsp->fnum, strerror(errno)));
+ DEBUG(3, ("fstat of %s failed (%s)\n",
+ fsp_fnum_dbg(fsp), strerror(errno)));
reply_nterror(req,
map_nt_error_from_unix(errno));
return;
} else {
uint32_t name_hash;
char *fname = NULL;
+ uint32_t ucf_flags = 0;
/* qpathinfo */
if (total_params < 7) {
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;
+ if (INFO_LEVEL_IS_UNIX(info_level)) {
+ if (!lp_unix_extensions()) {
+ reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ return;
+ }
+ if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
+ info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
+ info_level == SMB_QUERY_FILE_UNIX_LINK) {
+ ucf_flags |= UCF_UNIX_NAME_LOOKUP;
+ }
}
srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ ucf_flags,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
}
}
- DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
+ DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
"total_data=%d\n", smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
+ fsp_fnum_dbg(fsp),
+ info_level,tran_call,total_data));
/* Pull out any data sent here before we realloc. */
switch (info_level) {
/****************************************************************************
Deal with setting the time from any of the setfilepathinfo functions.
+ NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
+ calling this function.
****************************************************************************/
NTSTATUS smb_set_file_time(connection_struct *conn,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* get some defaults (no modifications) if any info is zero or -1. */
if (null_timespec(ft->create_time)) {
action &= ~FILE_NOTIFY_CHANGE_CREATION;
/****************************************************************************
Deal with setting the dosmode from any of the setfilepathinfo functions.
+ NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
+ done before calling this function.
****************************************************************************/
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
files_struct *fsp,
const struct smb_filename *smb_fname,
const SMB_STRUCT_STAT *psbuf,
- SMB_OFF_T size,
+ off_t size,
bool fail_after_createfile)
{
NTSTATUS status = NT_STATUS_OK;
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
if (size == get_file_size_stat(psbuf)) {
if (fsp && fsp->fh->fd != -1) {
/* Handle based call. */
+ if (!(fsp->access_mask & FILE_WRITE_DATA)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (vfs_set_filelen(fsp, size) == -1) {
return map_nt_error_from_unix(errno);
}
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
status = set_ea(conn, fsp, smb_fname, ea_list);
return status;
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
/* The set is across all open files on this dev/inode pair. */
if (!set_delete_on_close(fsp, delete_on_close,
+ conn->session_info->security_token,
conn->session_info->unix_token)) {
return NT_STATUS_ACCESS_DENIED;
}
}
position_information = (uint64_t)IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
DEBUG(10,("smb_file_position_information: Set file position "
"information for file %s to %.0f\n", fsp_str_dbg(fsp),
}
DEBUG(10,("smb2_file_rename_information: "
- "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
status = rename_internals_fsp(conn, fsp, smb_fname_dst,
(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
}
DEBUG(10,("smb_file_link_information: "
- "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
status = hardlink_internals(ctx,
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
newname,
true,
+ !conn->sconn->using_smb2,
&newname,
&dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
if (fsp) {
DEBUG(10,("smb_file_rename_information: "
- "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
overwrite);
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Set the attributes */
files_struct *fsp,
const struct smb_filename *smb_fname)
{
+ NTSTATUS status;
struct smb_file_time ft;
ZERO_STRUCT(ft);
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* create time */
ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
/* access time */
DEBUG(10,("smb_set_info_standard: file %s\n",
smb_fname_str_dbg(smb_fname)));
+ status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
return smb_set_file_time(conn,
fsp,
smb_fname,
}
allocation_size = (uint64_t)IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
-
DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
(double)allocation_size));
allocation_size = smb_roundup(conn, allocation_size);
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
"allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
(double)allocation_size));
if (fsp && fsp->fh->fd != -1) {
/* Open file handle. */
+ if (!(fsp->access_mask & FILE_WRITE_DATA)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
/* Only change if needed. */
if (allocation_size != get_file_size_stat(&smb_fname->st)) {
if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
const struct smb_filename *smb_fname,
bool fail_after_createfile)
{
- SMB_OFF_T size;
+ off_t size;
if (total_data < 8) {
return NT_STATUS_INVALID_PARAMETER;
}
size = IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
- size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
+ size |= (((off_t)IVAL(pdata,4)) << 32);
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
(double)size));
- if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
return smb_set_file_size(conn, req,
fsp,
smb_fname,
struct smb_file_time ft;
uint32 raw_unixmode;
mode_t unixmode;
- SMB_OFF_T size = 0;
+ off_t size = 0;
uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
NTSTATUS status = NT_STATUS_OK;
if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
size=IVAL(pdata,0); /* first 8 Bytes are size */
-#ifdef LARGE_SMB_OFF_T
- size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
+ size |= (((off_t)IVAL(pdata,4)) << 32);
}
ft.atime = interpret_long_date(pdata+24); /* access_time */
/* File exists open. File not exist create. */
create_disp = FILE_OPEN_IF;
break;
+ case SMB_O_EXCL:
+ /* O_EXCL on its own without O_CREAT is undefined.
+ We deliberately ignore it as some versions of
+ Linux CIFSFS can send a bare O_EXCL on the
+ wire which other filesystems in the kernel
+ ignore. See bug 9519 for details. */
+
+ /* Fallthrough. */
+
case 0:
/* File exists open. File not exist fail. */
create_disp = FILE_OPEN;
break;
- case SMB_O_EXCL:
- /* O_EXCL on its own without O_CREAT is undefined. */
default:
DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
(unsigned int)wire_open_mode ));
* non-POSIX opens return SHARING_VIOLATION.
*/
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
- NULL);
+ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck == NULL) {
DEBUG(0, ("smb_posix_unlink: Could not get share mode "
"lock for file %s\n", fsp_str_dbg(fsp)));
* don't delete. If all opens are POSIX delete we can set the delete
* on close disposition.
*/
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
+ for (i=0; i<lck->data->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->data->share_modes[i];
if (is_valid_share_mode_entry(e)) {
if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
continue;
}
+ if (share_mode_stale_pid(lck->data, i)) {
+ continue;
+ }
/* Fail with sharing violation. */
- close_file(req, fsp, NORMAL_CLOSE);
TALLOC_FREE(lck);
+ close_file(req, fsp, NORMAL_CLOSE);
return NT_STATUS_SHARING_VIOLATION;
}
}
fsp,
smb_fname);
+ TALLOC_FREE(lck);
+
if (!NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
- TALLOC_FREE(lck);
return status;
}
- TALLOC_FREE(lck);
return close_file(req, fsp, NORMAL_CLOSE);
}
}
}
- DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
+ DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
"totdata=%d\n", smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level, total_data));
+ fsp_fnum_dbg(fsp),
+ info_level, total_data));
switch (info_level) {
*/
if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fstat "
- "of fnum %d failed (%s)\n", fsp->fnum,
+ "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
strerror(errno)));
reply_nterror(req, map_nt_error_from_unix(errno));
return;
}
} else {
char *fname = NULL;
+ uint32_t ucf_flags = 0;
/* set path info */
if (total_params < 7) {
return;
}
+ if (info_level == SMB_SET_FILE_UNIX_BASIC ||
+ info_level == SMB_SET_FILE_UNIX_INFO2 ||
+ info_level == SMB_FILE_RENAME_INFORMATION ||
+ info_level == SMB_POSIX_PATH_UNLINK) {
+ ucf_flags |= UCF_UNIX_NAME_LOOKUP;
+ }
+
status = filename_convert(req, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ ucf_flags,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
}
}
- DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
+ DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
"totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level,total_data));
+ fsp_fnum_dbg(fsp),
+ info_level,total_data));
/* Realloc the parameter size */
*pparams = (char *)SMB_REALLOC(*pparams,2);
CAN ACCEPT THIS IN UNICODE. JRA. */
/* Job number */
- if (fsp->print_file) {
- SSVAL(pdata, 0, fsp->print_file->rap_jobid);
- } else {
- SSVAL(pdata, 0, 0);
- }
+ SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
+
srvstr_push(pdata, req->flags2, pdata + 2,
lp_netbios_name(), 15,
STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
srvstr_push(pdata, req->flags2, pdata+18,
- lp_servicename(SNUM(conn)), 13,
+ lp_servicename(talloc_tos(), SNUM(conn)), 13,
STR_ASCII|STR_TERMINATE); /* Service name */
send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
max_data_bytes);
SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
}
- if (conn->encrypt_level == Required && !req->encrypted) {
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
if (state->call != TRANSACT2_QFSINFO &&
- state->call != TRANSACT2_SETFSINFO) {
+ state->call != TRANSACT2_SETFSINFO) {
DEBUG(0,("handle_trans2: encryption required "
"with call 0x%x\n",
(unsigned int)state->call));
show_msg((const char *)req->inbuf);
+ /* Windows clients expect all replies to
+ a transact secondary (SMBtranss2 0x33)
+ to have a command code of transact
+ (SMBtrans2 0x32). See bug #8989
+ and also [MS-CIFS] section 2.2.4.47.2
+ for details.
+ */
+ req->cmd = SMBtrans2;
+
if (req->wct < 8) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBtranss2);