From: David Mulder Date: Fri, 11 Mar 2022 19:16:49 +0000 (-0700) Subject: smbd: Move smbd_do_query_getinfo_quota to smb2_nttrans.c X-Git-Tag: tevent-0.12.0~122 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a5292f0b1b58a72e5bb891a070218d4237efbfaa;p=thirdparty%2Fsamba.git smbd: Move smbd_do_query_getinfo_quota to smb2_nttrans.c Signed-off-by: David Mulder Reviewed-by: Jeremy Allison --- diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 67751cec7f4..fd3cb484880 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1988,273 +1988,6 @@ static void call_nt_transact_ioctl(connection_struct *conn, #ifdef HAVE_SYS_QUOTAS -static enum ndr_err_code fill_qtlist_from_sids(TALLOC_CTX *mem_ctx, - struct files_struct *fsp, - SMB_NTQUOTA_HANDLE *qt_handle, - struct dom_sid *sids, - uint32_t elems) -{ - uint32_t i; - TALLOC_CTX *list_ctx = NULL; - - list_ctx = talloc_init("quota_sid_list"); - - if (list_ctx == NULL) { - DBG_ERR("failed to allocate\n"); - return NDR_ERR_ALLOC; - } - - if (qt_handle->quota_list!=NULL) { - free_ntquota_list(&(qt_handle->quota_list)); - } - for (i = 0; i < elems; i++) { - SMB_NTQUOTA_STRUCT qt; - SMB_NTQUOTA_LIST *list_item; - bool ok; - - if (!NT_STATUS_IS_OK(vfs_get_ntquota(fsp, - SMB_USER_QUOTA_TYPE, - &sids[i], &qt))) { - /* non fatal error, return empty item in result */ - ZERO_STRUCT(qt); - continue; - } - - - list_item = talloc_zero(list_ctx, SMB_NTQUOTA_LIST); - if (list_item == NULL) { - DBG_ERR("failed to allocate\n"); - return NDR_ERR_ALLOC; - } - - ok = sid_to_uid(&sids[i], &list_item->uid); - if (!ok) { - struct dom_sid_buf buf; - DBG_WARNING("Could not convert SID %s to uid\n", - dom_sid_str_buf(&sids[i], &buf)); - /* No idea what to return here... */ - return NDR_ERR_INVALID_POINTER; - } - - list_item->quotas = talloc_zero(list_item, SMB_NTQUOTA_STRUCT); - if (list_item->quotas == NULL) { - DBG_ERR("failed to allocate\n"); - return NDR_ERR_ALLOC; - } - - *list_item->quotas = qt; - list_item->mem_ctx = list_ctx; - DLIST_ADD(qt_handle->quota_list, list_item); - } - qt_handle->tmp_list = qt_handle->quota_list; - return NDR_ERR_SUCCESS; -} - -static enum ndr_err_code extract_sids_from_buf(TALLOC_CTX *mem_ctx, - uint32_t sidlistlength, - DATA_BLOB *sid_buf, - struct dom_sid **sids, - uint32_t *num) -{ - DATA_BLOB blob; - uint32_t i = 0; - enum ndr_err_code err; - - struct sid_list_elem { - struct sid_list_elem *prev, *next; - struct dom_sid sid; - }; - - struct sid_list_elem *sid_list = NULL; - struct sid_list_elem *iter = NULL; - TALLOC_CTX *list_ctx = talloc_init("sid_list"); - if (!list_ctx) { - DBG_ERR("OOM\n"); - err = NDR_ERR_ALLOC; - goto done; - } - - *num = 0; - *sids = NULL; - - if (sidlistlength) { - uint32_t offset = 0; - struct ndr_pull *ndr_pull = NULL; - - if (sidlistlength > sid_buf->length) { - DBG_ERR("sid_list_length 0x%x exceeds " - "available bytes %zx\n", - sidlistlength, - sid_buf->length); - err = NDR_ERR_OFFSET; - goto done; - } - while (true) { - struct file_get_quota_info info; - struct sid_list_elem *item = NULL; - uint32_t new_offset = 0; - blob.data = sid_buf->data + offset; - blob.length = sidlistlength - offset; - ndr_pull = ndr_pull_init_blob(&blob, list_ctx); - if (!ndr_pull) { - DBG_ERR("OOM\n"); - err = NDR_ERR_ALLOC; - goto done; - } - err = ndr_pull_file_get_quota_info(ndr_pull, - NDR_SCALARS | NDR_BUFFERS, &info); - if (!NDR_ERR_CODE_IS_SUCCESS(err)) { - DBG_ERR("Failed to pull file_get_quota_info " - "from sidlist buffer\n"); - goto done; - } - item = talloc_zero(list_ctx, struct sid_list_elem); - if (!item) { - DBG_ERR("OOM\n"); - err = NDR_ERR_ALLOC; - goto done; - } - item->sid = info.sid; - DLIST_ADD(sid_list, item); - i++; - if (i == UINT32_MAX) { - DBG_ERR("Integer overflow\n"); - err = NDR_ERR_ARRAY_SIZE; - goto done; - } - new_offset = info.next_entry_offset; - - /* if new_offset == 0 no more sid(s) to read. */ - if (new_offset == 0) { - break; - } - - /* Integer wrap? */ - if ((offset + new_offset) < offset) { - DBG_ERR("Integer wrap while adding " - "new_offset 0x%x to current " - "buffer offset 0x%x\n", - new_offset, offset); - err = NDR_ERR_OFFSET; - goto done; - } - - offset += new_offset; - - /* check if new offset is outside buffer boundry. */ - if (offset >= sidlistlength) { - DBG_ERR("bufsize 0x%x exceeded by " - "new offset 0x%x)\n", - sidlistlength, - offset); - err = NDR_ERR_OFFSET; - goto done; - } - } - *sids = talloc_zero_array(mem_ctx, struct dom_sid, i); - if (*sids == NULL) { - DBG_ERR("OOM\n"); - err = NDR_ERR_ALLOC; - goto done; - } - - *num = i; - - for (iter = sid_list, i = 0; iter; iter = iter->next, i++) { - struct dom_sid_buf buf; - (*sids)[i] = iter->sid; - DBG_DEBUG("quota SID[%u] %s\n", - (unsigned int)i, - dom_sid_str_buf(&iter->sid, &buf)); - } - } - err = NDR_ERR_SUCCESS; -done: - TALLOC_FREE(list_ctx); - return err; -} - -NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx, - files_struct *fsp, - bool restart_scan, - bool return_single, - uint32_t sid_list_length, - DATA_BLOB *sid_buf, - uint32_t max_data_count, - uint8_t **p_data, - uint32_t *p_data_size) -{ - NTSTATUS status; - SMB_NTQUOTA_HANDLE *qt_handle = NULL; - SMB_NTQUOTA_LIST *qt_list = NULL; - DATA_BLOB blob = data_blob_null; - enum ndr_err_code err; - - qt_handle = - (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data; - - if (sid_list_length ) { - struct dom_sid *sids; - uint32_t elems = 0; - /* - * error check pulled offsets and lengths for wrap and - * exceeding available bytes. - */ - if (sid_list_length > sid_buf->length) { - DBG_ERR("sid_list_length 0x%x exceeds " - "available bytes %zx\n", - sid_list_length, - sid_buf->length); - return NT_STATUS_INVALID_PARAMETER; - } - - err = extract_sids_from_buf(mem_ctx, sid_list_length, - sid_buf, &sids, &elems); - if (!NDR_ERR_CODE_IS_SUCCESS(err) || elems == 0) { - return NT_STATUS_INVALID_PARAMETER; - } - err = fill_qtlist_from_sids(mem_ctx, - fsp, - qt_handle, - sids, - elems); - if (!NDR_ERR_CODE_IS_SUCCESS(err)) { - return NT_STATUS_INVALID_PARAMETER; - } - } else if (restart_scan) { - if (vfs_get_user_ntquota_list(fsp, - &(qt_handle->quota_list))!=0) { - return NT_STATUS_INTERNAL_ERROR; - } - } else { - if (qt_handle->quota_list!=NULL && - qt_handle->tmp_list==NULL) { - free_ntquota_list(&(qt_handle->quota_list)); - } - } - - if (restart_scan !=0 ) { - qt_list = qt_handle->quota_list; - } else { - qt_list = qt_handle->tmp_list; - } - status = fill_quota_buffer(mem_ctx, qt_list, - return_single != 0, - max_data_count, - &blob, - &qt_handle->tmp_list); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (blob.length > max_data_count) { - return NT_STATUS_BUFFER_TOO_SMALL; - } - - *p_data = blob.data; - *p_data_size = blob.length; - return NT_STATUS_OK; -} - /**************************************************************************** Reply to get user quota ****************************************************************************/ diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index 9fb7b707ed2..5cfaef92387 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -678,20 +678,6 @@ 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); -#ifdef HAVE_SYS_QUOTAS - -struct smb2_query_quota_info; - -NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx, - files_struct *fsp, - bool restart_scan, - bool return_single, - uint32_t sid_list_length, - DATA_BLOB *sidbuffer, - uint32_t max_data_count, - uint8_t **p_data, - uint32_t *p_data_size); -#endif void reply_nttrans(struct smb_request *req); void reply_nttranss(struct smb_request *req); @@ -714,6 +700,20 @@ NTSTATUS smbd_do_query_security_desc(connection_struct *conn, uint32_t max_data_count, uint8_t **ppmarshalled_sd, size_t *psd_size); +#ifdef HAVE_SYS_QUOTAS + +struct smb2_query_quota_info; + +NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx, + files_struct *fsp, + bool restart_scan, + bool return_single, + uint32_t sid_list_length, + DATA_BLOB *sidbuffer, + uint32_t max_data_count, + uint8_t **p_data, + uint32_t *p_data_size); +#endif /* The following definitions come from smbd/open.c */ diff --git a/source3/smbd/smb2_nttrans.c b/source3/smbd/smb2_nttrans.c index ce669d6961a..b8cb6424ca5 100644 --- a/source3/smbd/smb2_nttrans.c +++ b/source3/smbd/smb2_nttrans.c @@ -560,3 +560,272 @@ NTSTATUS smbd_do_query_security_desc(connection_struct *conn, TALLOC_FREE(psd); return status; } + +#ifdef HAVE_SYS_QUOTAS +static enum ndr_err_code fill_qtlist_from_sids(TALLOC_CTX *mem_ctx, + struct files_struct *fsp, + SMB_NTQUOTA_HANDLE *qt_handle, + struct dom_sid *sids, + uint32_t elems) +{ + uint32_t i; + TALLOC_CTX *list_ctx = NULL; + + list_ctx = talloc_init("quota_sid_list"); + + if (list_ctx == NULL) { + DBG_ERR("failed to allocate\n"); + return NDR_ERR_ALLOC; + } + + if (qt_handle->quota_list!=NULL) { + free_ntquota_list(&(qt_handle->quota_list)); + } + for (i = 0; i < elems; i++) { + SMB_NTQUOTA_STRUCT qt; + SMB_NTQUOTA_LIST *list_item; + bool ok; + + if (!NT_STATUS_IS_OK(vfs_get_ntquota(fsp, + SMB_USER_QUOTA_TYPE, + &sids[i], &qt))) { + /* non fatal error, return empty item in result */ + ZERO_STRUCT(qt); + continue; + } + + + list_item = talloc_zero(list_ctx, SMB_NTQUOTA_LIST); + if (list_item == NULL) { + DBG_ERR("failed to allocate\n"); + return NDR_ERR_ALLOC; + } + + ok = sid_to_uid(&sids[i], &list_item->uid); + if (!ok) { + struct dom_sid_buf buf; + DBG_WARNING("Could not convert SID %s to uid\n", + dom_sid_str_buf(&sids[i], &buf)); + /* No idea what to return here... */ + return NDR_ERR_INVALID_POINTER; + } + + list_item->quotas = talloc_zero(list_item, SMB_NTQUOTA_STRUCT); + if (list_item->quotas == NULL) { + DBG_ERR("failed to allocate\n"); + return NDR_ERR_ALLOC; + } + + *list_item->quotas = qt; + list_item->mem_ctx = list_ctx; + DLIST_ADD(qt_handle->quota_list, list_item); + } + qt_handle->tmp_list = qt_handle->quota_list; + return NDR_ERR_SUCCESS; +} + +static enum ndr_err_code extract_sids_from_buf(TALLOC_CTX *mem_ctx, + uint32_t sidlistlength, + DATA_BLOB *sid_buf, + struct dom_sid **sids, + uint32_t *num) +{ + DATA_BLOB blob; + uint32_t i = 0; + enum ndr_err_code err; + + struct sid_list_elem { + struct sid_list_elem *prev, *next; + struct dom_sid sid; + }; + + struct sid_list_elem *sid_list = NULL; + struct sid_list_elem *iter = NULL; + TALLOC_CTX *list_ctx = talloc_init("sid_list"); + if (!list_ctx) { + DBG_ERR("OOM\n"); + err = NDR_ERR_ALLOC; + goto done; + } + + *num = 0; + *sids = NULL; + + if (sidlistlength) { + uint32_t offset = 0; + struct ndr_pull *ndr_pull = NULL; + + if (sidlistlength > sid_buf->length) { + DBG_ERR("sid_list_length 0x%x exceeds " + "available bytes %zx\n", + sidlistlength, + sid_buf->length); + err = NDR_ERR_OFFSET; + goto done; + } + while (true) { + struct file_get_quota_info info; + struct sid_list_elem *item = NULL; + uint32_t new_offset = 0; + blob.data = sid_buf->data + offset; + blob.length = sidlistlength - offset; + ndr_pull = ndr_pull_init_blob(&blob, list_ctx); + if (!ndr_pull) { + DBG_ERR("OOM\n"); + err = NDR_ERR_ALLOC; + goto done; + } + err = ndr_pull_file_get_quota_info(ndr_pull, + NDR_SCALARS | NDR_BUFFERS, &info); + if (!NDR_ERR_CODE_IS_SUCCESS(err)) { + DBG_ERR("Failed to pull file_get_quota_info " + "from sidlist buffer\n"); + goto done; + } + item = talloc_zero(list_ctx, struct sid_list_elem); + if (!item) { + DBG_ERR("OOM\n"); + err = NDR_ERR_ALLOC; + goto done; + } + item->sid = info.sid; + DLIST_ADD(sid_list, item); + i++; + if (i == UINT32_MAX) { + DBG_ERR("Integer overflow\n"); + err = NDR_ERR_ARRAY_SIZE; + goto done; + } + new_offset = info.next_entry_offset; + + /* if new_offset == 0 no more sid(s) to read. */ + if (new_offset == 0) { + break; + } + + /* Integer wrap? */ + if ((offset + new_offset) < offset) { + DBG_ERR("Integer wrap while adding " + "new_offset 0x%x to current " + "buffer offset 0x%x\n", + new_offset, offset); + err = NDR_ERR_OFFSET; + goto done; + } + + offset += new_offset; + + /* check if new offset is outside buffer boundry. */ + if (offset >= sidlistlength) { + DBG_ERR("bufsize 0x%x exceeded by " + "new offset 0x%x)\n", + sidlistlength, + offset); + err = NDR_ERR_OFFSET; + goto done; + } + } + *sids = talloc_zero_array(mem_ctx, struct dom_sid, i); + if (*sids == NULL) { + DBG_ERR("OOM\n"); + err = NDR_ERR_ALLOC; + goto done; + } + + *num = i; + + for (iter = sid_list, i = 0; iter; iter = iter->next, i++) { + struct dom_sid_buf buf; + (*sids)[i] = iter->sid; + DBG_DEBUG("quota SID[%u] %s\n", + (unsigned int)i, + dom_sid_str_buf(&iter->sid, &buf)); + } + } + err = NDR_ERR_SUCCESS; +done: + TALLOC_FREE(list_ctx); + return err; +} + +NTSTATUS smbd_do_query_getinfo_quota(TALLOC_CTX *mem_ctx, + files_struct *fsp, + bool restart_scan, + bool return_single, + uint32_t sid_list_length, + DATA_BLOB *sid_buf, + uint32_t max_data_count, + uint8_t **p_data, + uint32_t *p_data_size) +{ + NTSTATUS status; + SMB_NTQUOTA_HANDLE *qt_handle = NULL; + SMB_NTQUOTA_LIST *qt_list = NULL; + DATA_BLOB blob = data_blob_null; + enum ndr_err_code err; + + qt_handle = + (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->private_data; + + if (sid_list_length ) { + struct dom_sid *sids; + uint32_t elems = 0; + /* + * error check pulled offsets and lengths for wrap and + * exceeding available bytes. + */ + if (sid_list_length > sid_buf->length) { + DBG_ERR("sid_list_length 0x%x exceeds " + "available bytes %zx\n", + sid_list_length, + sid_buf->length); + return NT_STATUS_INVALID_PARAMETER; + } + + err = extract_sids_from_buf(mem_ctx, sid_list_length, + sid_buf, &sids, &elems); + if (!NDR_ERR_CODE_IS_SUCCESS(err) || elems == 0) { + return NT_STATUS_INVALID_PARAMETER; + } + err = fill_qtlist_from_sids(mem_ctx, + fsp, + qt_handle, + sids, + elems); + if (!NDR_ERR_CODE_IS_SUCCESS(err)) { + return NT_STATUS_INVALID_PARAMETER; + } + } else if (restart_scan) { + if (vfs_get_user_ntquota_list(fsp, + &(qt_handle->quota_list))!=0) { + return NT_STATUS_INTERNAL_ERROR; + } + } else { + if (qt_handle->quota_list!=NULL && + qt_handle->tmp_list==NULL) { + free_ntquota_list(&(qt_handle->quota_list)); + } + } + + if (restart_scan !=0 ) { + qt_list = qt_handle->quota_list; + } else { + qt_list = qt_handle->tmp_list; + } + status = fill_quota_buffer(mem_ctx, qt_list, + return_single != 0, + max_data_count, + &blob, + &qt_handle->tmp_list); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (blob.length > max_data_count) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + *p_data = blob.data; + *p_data_size = blob.length; + return NT_STATUS_OK; +} +#endif /* HAVE_SYS_QUOTAS */