*/
#include "includes.h"
+#include "system/filesys.h"
+#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "fake_file.h"
+#include "../libcli/security/security.h"
#include "../librpc/gen_ndr/ndr_security.h"
+#include "passdb/lookup_sid.h"
+#include "auth.h"
+#include "ntioctl.h"
extern const struct generic_mapping file_generic_mapping;
char *pp = params;
char *pd = pdata;
int params_sent_thistime, data_sent_thistime, total_sent_thistime;
- int alignment_offset = 3;
+ int alignment_offset = 1;
int data_alignment_offset = 0;
struct smbd_server_connection *sconn = req->sconn;
int max_send = sconn->smb1.sessions.max_send;
/* Deal with other possible opens having a modified
write time. JRA. */
ZERO_STRUCT(write_time_ts);
- get_file_infos(fsp->file_id, NULL, &write_time_ts);
+ get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
if (!null_timespec(write_time_ts)) {
update_stat_ex_mtime(&smb_fname->st, write_time_ts);
}
struct security_descriptor *psd = NULL;
NTSTATUS status;
+ if (sd_len == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
if (!CAN_WRITE(fsp->conn)) {
return NT_STATUS_ACCESS_DENIED;
}
- if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
+ if (!lp_nt_acl_support(SNUM(fsp->conn))) {
return NT_STATUS_OK;
}
security_info_sent &= ~SECINFO_GROUP;
}
- /* Convert all the generic bits. */
- security_acl_map_generic(psd->dacl, &file_generic_mapping);
- security_acl_map_generic(psd->sacl, &file_generic_mapping);
+ /* Ensure we have at least one thing set. */
+ if ((security_info_sent & (SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL)) == 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Ensure we have the rights to do this. */
+ if (security_info_sent & SECINFO_OWNER) {
+ if (!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ if (security_info_sent & SECINFO_GROUP) {
+ if (!(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+
+ if (security_info_sent & SECINFO_DACL) {
+ if (!(fsp->access_mask & SEC_STD_WRITE_DAC)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ /* Convert all the generic bits. */
+ if (psd->dacl) {
+ security_acl_map_generic(psd->dacl, &file_generic_mapping);
+ }
+ }
+
+ if (security_info_sent & SECINFO_SACL) {
+ if (!(fsp->access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ /* Convert all the generic bits. */
+ if (psd->sacl) {
+ security_acl_map_generic(psd->sacl, &file_generic_mapping);
+ }
+ }
if (DEBUGLEVEL >= 10) {
DEBUG(10,("set_sd for file %s\n", fsp_str_dbg(fsp)));
/* Deal with other possible opens having a modified
write time. JRA. */
ZERO_STRUCT(write_time_ts);
- get_file_infos(fsp->file_id, NULL, &write_time_ts);
+ get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
if (!null_timespec(write_time_ts)) {
update_stat_ex_mtime(&smb_fname->st, write_time_ts);
}
req, /* req */
0, /* root_dir_fid */
smb_fname_src, /* fname */
- FILE_READ_DATA, /* access_mask */
+ FILE_READ_DATA|FILE_READ_ATTRIBUTES|
+ FILE_READ_EA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
FILE_OPEN, /* create_disposition*/
req, /* req */
0, /* root_dir_fid */
smb_fname_dst, /* fname */
- FILE_WRITE_DATA, /* access_mask */
+ FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|
+ FILE_WRITE_EA, /* access_mask */
(FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE),
FILE_CREATE, /* create_disposition*/
uint32_t ucf_flags_dst = 0;
uint16 rename_type;
TALLOC_CTX *ctx = talloc_tos();
+ bool stream_rename = false;
START_PROFILE(SMBntrename);
goto out;
}
- /* 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;
+ if (!lp_posix_pathnames()) {
+ /* The newname must begin with a ':' if the
+ oldname contains a ':'. */
+ if (strchr_m(oldname, ':')) {
+ if (newname[0] != ':') {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ goto out;
+ }
+ stream_rename = true;
+ }
}
/*
goto out;
}
+ if (stream_rename) {
+ /* smb_fname_new must be the same as smb_fname_old. */
+ TALLOC_FREE(smb_fname_new->base_name);
+ smb_fname_new->base_name = talloc_strdup(smb_fname_new,
+ smb_fname_old->base_name);
+ if (!smb_fname_new->base_name) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ goto out;
+ }
+ }
+
DEBUG(3,("reply_ntrename: %s -> %s\n",
smb_fname_str_dbg(smb_fname_old),
smb_fname_str_dbg(smb_fname_new)));
* Get the permissions to return.
*/
+ if ((security_info_wanted & SECINFO_SACL) &&
+ !(fsp->access_mask & SEC_FLAG_SYSTEM_SECURITY)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if ((security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|SECINFO_GROUP)) &&
+ !(fsp->access_mask & SEC_STD_READ_CONTROL)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (!lp_nt_acl_support(SNUM(conn))) {
status = get_null_nt_acl(mem_ctx, &psd);
} else {
return status;
}
+ if (!(security_info_wanted & SECINFO_OWNER)) {
+ psd->owner_sid = NULL;
+ }
+ if (!(security_info_wanted & SECINFO_GROUP)) {
+ psd->group_sid = NULL;
+ }
+ if (!(security_info_wanted & SECINFO_DACL)) {
+ psd->dacl = NULL;
+ }
+ if (!(security_info_wanted & SECINFO_SACL)) {
+ psd->sacl = NULL;
+ }
+
/* If the SACL/DACL is NULL, but was requested, we mark that it is
* present in the reply to match Windows behavior */
if (psd->sacl == NULL &&
switch (function) {
case FSCTL_SET_SPARSE:
- /* pretend this succeeded - tho strictly we should
- mark the file sparse (if the local fs supports it)
- so we can know if we need to pre-allocate or not */
+ {
+ bool set_sparse = true;
+ NTSTATUS status;
+
+ if (data_count >= 1 && pdata[0] == 0) {
+ set_sparse = false;
+ }
+
+ DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X]set[%u]\n",
+ fidnum, set_sparse));
+
+ if (!check_fsp_open(conn, req, fsp)) {
+ return;
+ }
+
+ status = file_set_sparse(conn, fsp, set_sparse);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(9,("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
+ smb_fname_str_dbg(fsp->fsp_name), set_sparse, nt_errstr(status)));
+ reply_nterror(req, status);
+ return;
+ }
- DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
+ DEBUG(10,("FSCTL_SET_SPARSE: fname[%s] set[%u] - %s\n",
+ smb_fname_str_dbg(fsp->fsp_name), set_sparse, nt_errstr(status)));
send_nt_replies(conn, req, NT_STATUS_OK, NULL, 0, NULL, 0);
return;
-
+ }
case FSCTL_CREATE_OR_GET_OBJECT_ID:
{
unsigned char objid[16];
}
return;
}
+ case FSCTL_IS_VOLUME_DIRTY:
+ DEBUG(10,("FSCTL_IS_VOLUME_DIRTY: called on FID[0x%04X] "
+ "(but not implemented)\n", (int)fidnum));
+ /*
+ * http://msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
+ * says we have to respond with NT_STATUS_INVALID_PARAMETER
+ */
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
default:
+ /* Only print this once... */
if (!logged_ioctl_message) {
- logged_ioctl_message = true; /* Only print this once... */
- DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n",
+ logged_ioctl_message = true;
+ DEBUG(2,("call_nt_transact_ioctl(0x%x): "
+ "Currently not implemented.\n",
function));
}
}
ZERO_STRUCT(qt);
/* access check */
- if (conn->server_info->utok.uid != 0) {
+ if (conn->session_info->utok.uid != 0) {
DEBUG(1,("get_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(SNUM(conn)),
- conn->server_info->unix_name));
+ conn->session_info->unix_name));
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
break;
}
- sid_parse(pdata+8,sid_len,&sid);
+ if (!sid_parse(pdata+8,sid_len,&sid)) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
ZERO_STRUCT(qt);
ZERO_STRUCT(qt);
/* access check */
- if (conn->server_info->utok.uid != 0) {
+ if (conn->session_info->utok.uid != 0) {
DEBUG(1,("set_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(SNUM(conn)),
- conn->server_info->unix_name));
+ conn->session_info->unix_name));
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
if (data_count < 40) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
/* sid len */
sid_len = IVAL(pdata,4);
- if (data_count < 40+sid_len) {
+ if (data_count < 40+sid_len || (40+sid_len < sid_len)) {
DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len));
- reply_nterror(req, NT_STATUS_INVALID_LEVEL);
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
}
#endif /* LARGE_SMB_OFF_T */
- sid_parse(pdata+40,sid_len,&sid);
+ if (!sid_parse(pdata+40,sid_len,&sid)) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
DEBUGADD(8,("SID: %s\n", sid_string_dbg(&sid)));
/* 44 unknown bytes left... */