summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcli/smb/smb2_constants.h2
-rw-r--r--source3/smbd/smb2_close.c95
-rw-r--r--source4/libcli/raw/interfaces.h1
3 files changed, 77 insertions, 21 deletions
diff --git a/libcli/smb/smb2_constants.h b/libcli/smb/smb2_constants.h
index 6d29d6e9ea..7ab496df22 100644
--- a/libcli/smb/smb2_constants.h
+++ b/libcli/smb/smb2_constants.h
@@ -184,4 +184,6 @@
#define SMB2_GETINFO_SECURITY 0x03
#define SMB2_GETINFO_QUOTA 0x04
+#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (0x01)
+
#endif
diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c
index 56e3167e24..8ef9dfa820 100644
--- a/source3/smbd/smb2_close.c
+++ b/source3/smbd/smb2_close.c
@@ -24,7 +24,8 @@
static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
uint16_t in_flags,
- uint64_t in_file_id_volatile);
+ uint64_t in_file_id_volatile,
+ DATA_BLOB *outbody);
NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
{
@@ -52,6 +53,11 @@ NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
+ outbody = data_blob_talloc(req->out.vector, NULL, 0x3C);
+ if (outbody.data == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
+ }
+
in_flags = SVAL(inbody, 0x02);
in_file_id_persistent = BVAL(inbody, 0x08);
in_file_id_volatile = BVAL(inbody, 0x10);
@@ -64,40 +70,37 @@ NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
status = smbd_smb2_close(req,
in_flags,
- in_file_id_volatile);
+ in_file_id_volatile,
+ &outbody);
if (!NT_STATUS_IS_OK(status)) {
return smbd_smb2_request_error(req, status);
}
outhdr = (uint8_t *)req->out.vector[i].iov_base;
-
- outbody = data_blob_talloc(req->out.vector, NULL, 0x3C);
- if (outbody.data == NULL) {
- return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
- }
-
- SSVAL(outbody.data, 0x00, 0x3C); /* struct size */
- SSVAL(outbody.data, 0x02, 0); /* flags */
- SIVAL(outbody.data, 0x04, 0); /* reserved */
- SBVAL(outbody.data, 0x08, 0); /* creation time */
- SBVAL(outbody.data, 0x10, 0); /* last access time */
- SBVAL(outbody.data, 0x18, 0); /* last write time */
- SBVAL(outbody.data, 0x20, 0); /* change time */
- SBVAL(outbody.data, 0x28, 0); /* allocation size */
- SBVAL(outbody.data, 0x30, 0); /* end of size */
- SIVAL(outbody.data, 0x38, 0); /* file attributes */
-
return smbd_smb2_request_done(req, outbody, NULL);
}
static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
uint16_t in_flags,
- uint64_t in_file_id_volatile)
+ uint64_t in_file_id_volatile,
+ DATA_BLOB *outbody)
{
NTSTATUS status;
struct smb_request *smbreq;
connection_struct *conn = req->tcon->compat_conn;
files_struct *fsp;
+ struct smb_filename *smb_fname = NULL;
+ struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
+ uint64_t allocation_size = 0;
+ uint64_t file_size = 0;
+ uint32_t dos_attrs = 0;
+ uint16_t out_flags = 0;
+ bool posix_open = false;
+
+ ZERO_STRUCT(create_date_ts);
+ ZERO_STRUCT(adate_ts);
+ ZERO_STRUCT(mdate_ts);
+ ZERO_STRUCT(cdate_ts);
DEBUG(10,("smbd_smb2_close: file_id[0x%016llX]\n",
(unsigned long long)in_file_id_volatile));
@@ -118,6 +121,14 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
return NT_STATUS_FILE_CLOSED;
}
+ posix_open = fsp->posix_open;
+ status = copy_smb_filename(talloc_tos(),
+ fsp->fsp_name,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = close_file(smbreq, fsp, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("smbd_smb2_close: close_file[%s]: %s\n",
@@ -125,5 +136,49 @@ static NTSTATUS smbd_smb2_close(struct smbd_smb2_request *req,
return status;
}
+ if (in_flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) {
+ int ret;
+ if (posix_open) {
+ ret = SMB_VFS_LSTAT(conn, smb_fname);
+ } else {
+ ret = SMB_VFS_STAT(conn, smb_fname);
+ }
+ if (ret == 0) {
+ out_flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
+ dos_attrs = dos_mode(conn, smb_fname);
+ mdate_ts = smb_fname->st.st_ex_mtime;
+ adate_ts = smb_fname->st.st_ex_atime;
+ create_date_ts = get_create_timespec(conn, NULL, smb_fname);
+ cdate_ts = get_change_timespec(conn, NULL, smb_fname);
+
+ if (lp_dos_filetime_resolution(SNUM(conn))) {
+ dos_filetime_timespec(&create_date_ts);
+ dos_filetime_timespec(&mdate_ts);
+ dos_filetime_timespec(&adate_ts);
+ dos_filetime_timespec(&cdate_ts);
+ }
+ if (!(dos_attrs & FILE_ATTRIBUTE_DIRECTORY)) {
+ file_size = get_file_size_stat(&smb_fname->st);
+ }
+
+ allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
+ }
+ }
+
+ SSVAL(outbody->data, 0x00, 0x3C); /* struct size */
+ SSVAL(outbody->data, 0x02, out_flags); /* flags */
+ SIVAL(outbody->data, 0x04, 0); /* reserved */
+ put_long_date_timespec(conn->ts_res,
+ (char *)&outbody->data[0x8],create_date_ts); /* creation time */
+ put_long_date_timespec(conn->ts_res,
+ (char *)&outbody->data[0x10],adate_ts); /* last access time */
+ put_long_date_timespec(conn->ts_res,
+ (char *)&outbody->data[0x18],mdate_ts); /* last write time */
+ put_long_date_timespec(conn->ts_res,
+ (char *)&outbody->data[0x20],cdate_ts); /* change time */
+ SBVAL(outbody->data, 0x28, allocation_size);/* allocation size */
+ SBVAL(outbody->data, 0x30, file_size); /* end of file */
+ SIVAL(outbody->data, 0x38, dos_attrs); /* file attributes */
+
return NT_STATUS_OK;
}
diff --git a/source4/libcli/raw/interfaces.h b/source4/libcli/raw/interfaces.h
index f6d090539c..f3ce4e9c5f 100644
--- a/source4/libcli/raw/interfaces.h
+++ b/source4/libcli/raw/interfaces.h
@@ -2090,7 +2090,6 @@ union smb_close {
struct {
union smb_handle file;
time_t write_time;
-#define SMB2_CLOSE_FLAGS_FULL_INFORMATION (1<<0)
uint16_t flags; /* SMB2_CLOSE_FLAGS_* */
} in;
struct {