summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h7
-rw-r--r--source3/smbd/nttrans.c131
-rw-r--r--source3/smbd/smb2_getinfo.c82
3 files changed, 174 insertions, 46 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index a27ef89d01..ff4a04b4fa 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -6616,6 +6616,13 @@ void reply_ntcreate_and_X(struct smb_request *req);
struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size);
void reply_ntcancel(struct smb_request *req);
void reply_ntrename(struct smb_request *req);
+NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
+ TALLOC_CTX *mem_ctx,
+ files_struct *fsp,
+ uint32_t security_info_wanted,
+ uint32_t max_data_count,
+ uint8_t **ppmarshalled_sd,
+ size_t *psd_size);
void reply_nttrans(struct smb_request *req);
void reply_nttranss(struct smb_request *req);
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 2783545540..3ce196d467 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1770,6 +1770,75 @@ static NTSTATUS get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd)
/****************************************************************************
Reply to query a security descriptor.
+ Callable from SMB2 and SMB2.
+ If it returns NT_STATUS_BUFFER_TOO_SMALL, pdata_size is initialized with
+ the required size.
+****************************************************************************/
+
+NTSTATUS smbd_do_query_security_desc(connection_struct *conn,
+ TALLOC_CTX *mem_ctx,
+ files_struct *fsp,
+ uint32_t security_info_wanted,
+ uint32_t max_data_count,
+ uint8_t **ppmarshalled_sd,
+ size_t *psd_size)
+{
+ NTSTATUS status;
+ SEC_DESC *psd = NULL;
+
+ /*
+ * Get the permissions to return.
+ */
+
+ if (!lp_nt_acl_support(SNUM(conn))) {
+ status = get_null_nt_acl(mem_ctx, &psd);
+ } else {
+ status = SMB_VFS_FGET_NT_ACL(
+ fsp, security_info_wanted, &psd);
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* 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 &&
+ security_info_wanted & SACL_SECURITY_INFORMATION)
+ psd->type |= SEC_DESC_SACL_PRESENT;
+ if (psd->dacl == NULL &&
+ security_info_wanted & DACL_SECURITY_INFORMATION)
+ psd->type |= SEC_DESC_DACL_PRESENT;
+
+ *psd_size = ndr_size_security_descriptor(psd, NULL, 0);
+
+ DEBUG(3,("smbd_do_query_security_desc: sd_size = %lu.\n",
+ (unsigned long)*psd_size));
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("smbd_do_query_security_desc for file %s\n",
+ fsp_str_dbg(fsp)));
+ NDR_PRINT_DEBUG(security_descriptor, psd);
+ }
+
+ if (max_data_count < *psd_size) {
+ TALLOC_FREE(psd);
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ }
+
+ status = marshall_sec_desc(mem_ctx, psd,
+ ppmarshalled_sd, psd_size);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ TALLOC_FREE(psd);
+ return status;
+ }
+
+ TALLOC_FREE(psd);
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ SMB1 reply to query a security descriptor.
****************************************************************************/
static void call_nt_transact_query_security_desc(connection_struct *conn,
@@ -1784,12 +1853,11 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
{
char *params = *ppparams;
char *data = *ppdata;
- SEC_DESC *psd = NULL;
- size_t sd_size;
+ size_t sd_size = 0;
uint32 security_info_wanted;
files_struct *fsp = NULL;
NTSTATUS status;
- DATA_BLOB blob;
+ uint8_t *marshalled_sd = NULL;
if(parameter_count < 8) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -1818,46 +1886,38 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
* Get the permissions to return.
*/
- if (!lp_nt_acl_support(SNUM(conn))) {
- status = get_null_nt_acl(talloc_tos(), &psd);
- } else {
- status = SMB_VFS_FGET_NT_ACL(
- fsp, security_info_wanted, &psd);
- }
+ status = smbd_do_query_security_desc(conn,
+ talloc_tos(),
+ fsp,
+ security_info_wanted,
+ max_data_count,
+ &marshalled_sd,
+ &sd_size);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
+ SIVAL(params,0,(uint32_t)sd_size);
+ send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
+ params, 4, NULL, 0);
+ return;
+ }
+
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
}
- /* 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 &&
- security_info_wanted & SACL_SECURITY_INFORMATION)
- psd->type |= SEC_DESC_SACL_PRESENT;
- if (psd->dacl == NULL &&
- security_info_wanted & DACL_SECURITY_INFORMATION)
- psd->type |= SEC_DESC_DACL_PRESENT;
-
- sd_size = ndr_size_security_descriptor(psd, NULL, 0);
-
- 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_str_dbg(fsp)));
- NDR_PRINT_DEBUG(security_descriptor, psd);
- }
+ SMB_ASSERT(sd_size > 0);
- SIVAL(params,0,(uint32)sd_size);
+ SIVAL(params,0,(uint32_t)sd_size);
if (max_data_count < sd_size) {
send_nt_replies(conn, req, NT_STATUS_BUFFER_TOO_SMALL,
- params, 4, *ppdata, 0);
+ params, 4, NULL, 0);
return;
}
/*
- * Allocate the data we will point this at.
+ * Allocate the data we will return.
*/
data = nttrans_realloc(ppdata, sd_size);
@@ -1866,16 +1926,7 @@ static void call_nt_transact_query_security_desc(connection_struct *conn,
return;
}
- status = marshall_sec_desc(talloc_tos(), psd,
- &blob.data, &blob.length);
-
- if (!NT_STATUS_IS_OK(status)) {
- reply_nterror(req, status);
- return;
- }
-
- SMB_ASSERT(sd_size == blob.length);
- memcpy(data, blob.data, sd_size);
+ memcpy(data, marshalled_sd, sd_size);
send_nt_replies(conn, req, NT_STATUS_OK, params, 4, data, (int)sd_size);
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 3a8c07757e..d59339fa59 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -34,7 +34,8 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
uint64_t in_file_id_volatile);
static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer);
+ DATA_BLOB *out_output_buffer,
+ NTSTATUS *p_call_status);
static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq);
NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req)
@@ -128,11 +129,13 @@ static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq)
uint16_t out_output_buffer_offset;
DATA_BLOB out_output_buffer = data_blob_null;
NTSTATUS status;
+ NTSTATUS call_status;
NTSTATUS error; /* transport error */
status = smbd_smb2_getinfo_recv(subreq,
req,
- &out_output_buffer);
+ &out_output_buffer,
+ &call_status);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
error = smbd_smb2_request_error(req, status);
@@ -144,6 +147,20 @@ static void smbd_smb2_request_getinfo_done(struct tevent_req *subreq)
return;
}
+ if (!NT_STATUS_IS_OK(call_status)) {
+ /* Return a specific error with data. */
+ error = smbd_smb2_request_error_ex(req,
+ call_status,
+ &out_output_buffer,
+ __location__);
+ if (!NT_STATUS_IS_OK(error)) {
+ smbd_server_connection_terminate(req->sconn,
+ nt_errstr(error));
+ return;
+ }
+ return;
+ }
+
out_output_buffer_offset = SMB2_HDR_BODY + 0x08;
outhdr = (uint8_t *)req->out.vector[i].iov_base;
@@ -197,6 +214,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
struct smb_request *smbreq;
connection_struct *conn = smb2req->tcon->compat_conn;
files_struct *fsp;
+ NTSTATUS status;
req = tevent_req_create(mem_ctx, &state,
struct smbd_smb2_getinfo_state);
@@ -204,7 +222,7 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
return NULL;
}
state->smb2req = smb2req;
- state->status = NT_STATUS_INTERNAL_ERROR;
+ state->status = NT_STATUS_OK;
state->out_output_buffer = data_blob_null;
DEBUG(10,("smbd_smb2_getinfo_send: file_id[0x%016llX]\n",
@@ -246,7 +264,6 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
struct ea_list *ea_list = NULL;
int lock_data_count = 0;
char *lock_data = NULL;
- NTSTATUS status;
ZERO_STRUCT(write_time_ts);
@@ -360,7 +377,6 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
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;
@@ -392,7 +408,59 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
break;
}
+ case 0x03:/* SMB2_GETINFO_SEC */
+ {
+ uint8_t *p_marshalled_sd = NULL;
+ size_t sd_size = 0;
+
+ status = smbd_do_query_security_desc(conn,
+ state,
+ fsp,
+ /* Security info wanted. */
+ in_additional_information,
+ in_output_buffer_length,
+ &p_marshalled_sd,
+ &sd_size);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_BUFFER_TOO_SMALL)) {
+ /* Return needed size. */
+ state->out_output_buffer = data_blob_talloc(state,
+ NULL,
+ 4);
+ if (tevent_req_nomem(state->out_output_buffer.data, req)) {
+ return tevent_req_post(req, ev);
+ }
+ SIVAL(state->out_output_buffer.data,0,(uint32_t)sd_size);
+ state->status = NT_STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10,("smbd_smb2_getinfo_send: "
+ "smbd_do_query_security_desc of %s failed "
+ "(%s)\n", fsp_str_dbg(fsp),
+ nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
+
+ if (sd_size > 0) {
+ state->out_output_buffer = data_blob_talloc(state,
+ p_marshalled_sd,
+ sd_size);
+ if (tevent_req_nomem(state->out_output_buffer.data, req)) {
+ return tevent_req_post(req, ev);
+ }
+ }
+ break;
+ }
+
default:
+ DEBUG(10,("smbd_smb2_getinfo_send: "
+ "unknown in_info_type of %u "
+ " for file %s\n",
+ (unsigned int)in_info_type,
+ fsp_str_dbg(fsp) ));
+
tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
return tevent_req_post(req, ev);
}
@@ -403,7 +471,8 @@ static struct tevent_req *smbd_smb2_getinfo_send(TALLOC_CTX *mem_ctx,
static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
- DATA_BLOB *out_output_buffer)
+ DATA_BLOB *out_output_buffer,
+ NTSTATUS *pstatus)
{
NTSTATUS status;
struct smbd_smb2_getinfo_state *state = tevent_req_data(req,
@@ -416,6 +485,7 @@ static NTSTATUS smbd_smb2_getinfo_recv(struct tevent_req *req,
*out_output_buffer = state->out_output_buffer;
talloc_steal(mem_ctx, out_output_buffer->data);
+ *pstatus = state->status;
tevent_req_received(req);
return NT_STATUS_OK;