Plumb in get_nt_acl into SMB2.
authorJeremy Allison <jra@samba.org>
Tue, 27 Apr 2010 03:11:59 +0000 (20:11 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 27 Apr 2010 03:11:59 +0000 (20:11 -0700)
Jeremy.

source3/include/proto.h
source3/smbd/nttrans.c
source3/smbd/smb2_getinfo.c

index a27ef89d0158ab3f502e9821aad6dfd44d0e9f3f..ff4a04b4fa9a6c1294b77d29b05015f4df0aaef9 100644 (file)
@@ -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);
 
index 2783545540df7b1b669c8ef856ac81c41cb3d5de..3ce196d4673f6ac5d379e57bbe623141bc0c21bc 100644 (file)
@@ -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);
 
index 3a8c07757e91aa228b776e93a11c396ddcbc0a79..d59339fa590022077f78abf264ea4f5cfd160285 100644 (file)
@@ -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;