diff --git a/source3/smbd/smb1_trans2.c b/source3/smbd/smb1_trans2.c index 619cec0b0eb..d63a239e2fd 100644 --- a/source3/smbd/smb1_trans2.c +++ b/source3/smbd/smb1_trans2.c @@ -271,3 +271,170 @@ void send_trans2_replies(connection_struct *conn, return; } + +/**************************************************************************** + Deal with SMB_SET_POSIX_LOCK. +****************************************************************************/ + +static void smb_set_posix_lock_done(struct tevent_req *subreq); + +NTSTATUS smb_set_posix_lock(connection_struct *conn, + struct smb_request *req, + const char *pdata, + int total_data, + files_struct *fsp) +{ + struct tevent_req *subreq = NULL; + struct smbd_lock_element *lck = NULL; + uint64_t count; + uint64_t offset; + uint64_t smblctx; + bool blocking_lock = False; + enum brl_type lock_type; + + NTSTATUS status = NT_STATUS_OK; + + if (fsp == NULL || + fsp->fsp_flags.is_pathref || + fsp_get_io_fd(fsp) == -1) + { + return NT_STATUS_INVALID_HANDLE; + } + + if (total_data != POSIX_LOCK_DATA_SIZE) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { + case POSIX_LOCK_TYPE_READ: + lock_type = READ_LOCK; + break; + case POSIX_LOCK_TYPE_WRITE: + /* Return the right POSIX-mappable error code for files opened read-only. */ + if (!fsp->fsp_flags.can_write) { + return NT_STATUS_INVALID_HANDLE; + } + lock_type = WRITE_LOCK; + break; + case POSIX_LOCK_TYPE_UNLOCK: + lock_type = UNLOCK_LOCK; + break; + default: + return NT_STATUS_INVALID_PARAMETER; + } + + switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) { + case POSIX_LOCK_FLAG_NOWAIT: + blocking_lock = false; + break; + case POSIX_LOCK_FLAG_WAIT: + blocking_lock = true; + break; + default: + return NT_STATUS_INVALID_PARAMETER; + } + + if (!lp_blocking_locks(SNUM(conn))) { + blocking_lock = False; + } + + smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET); + offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | + ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET)); + count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) | + ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET)); + + DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", " + "count = %"PRIu64", offset = %"PRIu64"\n", + fsp_str_dbg(fsp), + (unsigned int)lock_type, + smblctx, + count, + offset); + + if (lock_type == UNLOCK_LOCK) { + struct smbd_lock_element l = { + .req_guid = smbd_request_guid(req, 0), + .smblctx = smblctx, + .brltype = UNLOCK_LOCK, + .lock_flav = POSIX_LOCK, + .offset = offset, + .count = count, + }; + status = smbd_do_unlocking(req, fsp, 1, &l); + return status; + } + + lck = talloc(req, struct smbd_lock_element); + if (lck == NULL) { + return NT_STATUS_NO_MEMORY; + } + + *lck = (struct smbd_lock_element) { + .req_guid = smbd_request_guid(req, 0), + .smblctx = smblctx, + .brltype = lock_type, + .lock_flav = POSIX_LOCK, + .count = count, + .offset = offset, + }; + + subreq = smbd_smb1_do_locks_send( + fsp, + req->sconn->ev_ctx, + &req, + fsp, + blocking_lock ? UINT32_MAX : 0, + true, /* large_offset */ + 1, + lck); + if (subreq == NULL) { + TALLOC_FREE(lck); + return NT_STATUS_NO_MEMORY; + } + tevent_req_set_callback(subreq, smb_set_posix_lock_done, req); + return NT_STATUS_EVENT_PENDING; +} + +static void smb_set_posix_lock_done(struct tevent_req *subreq) +{ + struct smb_request *req = NULL; + NTSTATUS status; + bool ok; + + ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req); + SMB_ASSERT(ok); + + status = smbd_smb1_do_locks_recv(subreq); + TALLOC_FREE(subreq); + + if (NT_STATUS_IS_OK(status)) { + char params[2] = {0}; + /* Fake up max_data_bytes here - we know it fits. */ + send_trans2_replies( + req->conn, + req, + NT_STATUS_OK, + params, + 2, + NULL, + 0, + 0xffff); + } else { + reply_nterror(req, status); + ok = srv_send_smb( + req->xconn, + (char *)req->outbuf, + true, + req->seqnum+1, + IS_CONN_ENCRYPTED(req->conn), + NULL); + if (!ok) { + exit_server_cleanly("smb_set_posix_lock_done: " + "srv_send_smb failed."); + } + } + + TALLOC_FREE(req); + return; +} diff --git a/source3/smbd/smb1_trans2.h b/source3/smbd/smb1_trans2.h index 6eee7ca4aa5..b462dc55541 100644 --- a/source3/smbd/smb1_trans2.h +++ b/source3/smbd/smb1_trans2.h @@ -31,3 +31,8 @@ void send_trans2_replies(connection_struct *conn, const char *pdata, int datasize, int max_data_bytes); +NTSTATUS smb_set_posix_lock(connection_struct *conn, + struct smb_request *req, + const char *pdata, + int total_data, + files_struct *fsp); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 45544141adc..4d91eab8ee9 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -7367,173 +7367,6 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, } #endif -/**************************************************************************** - Deal with SMB_SET_POSIX_LOCK. -****************************************************************************/ - -static void smb_set_posix_lock_done(struct tevent_req *subreq); - -static NTSTATUS smb_set_posix_lock(connection_struct *conn, - struct smb_request *req, - const char *pdata, - int total_data, - files_struct *fsp) -{ - struct tevent_req *subreq = NULL; - struct smbd_lock_element *lck = NULL; - uint64_t count; - uint64_t offset; - uint64_t smblctx; - bool blocking_lock = False; - enum brl_type lock_type; - - NTSTATUS status = NT_STATUS_OK; - - if (fsp == NULL || - fsp->fsp_flags.is_pathref || - fsp_get_io_fd(fsp) == -1) - { - return NT_STATUS_INVALID_HANDLE; - } - - if (total_data != POSIX_LOCK_DATA_SIZE) { - return NT_STATUS_INVALID_PARAMETER; - } - - switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) { - case POSIX_LOCK_TYPE_READ: - lock_type = READ_LOCK; - break; - case POSIX_LOCK_TYPE_WRITE: - /* Return the right POSIX-mappable error code for files opened read-only. */ - if (!fsp->fsp_flags.can_write) { - return NT_STATUS_INVALID_HANDLE; - } - lock_type = WRITE_LOCK; - break; - case POSIX_LOCK_TYPE_UNLOCK: - lock_type = UNLOCK_LOCK; - break; - default: - return NT_STATUS_INVALID_PARAMETER; - } - - switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) { - case POSIX_LOCK_FLAG_NOWAIT: - blocking_lock = false; - break; - case POSIX_LOCK_FLAG_WAIT: - blocking_lock = true; - break; - default: - return NT_STATUS_INVALID_PARAMETER; - } - - if (!lp_blocking_locks(SNUM(conn))) { - blocking_lock = False; - } - - smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET); - offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) | - ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET)); - count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) | - ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET)); - - DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", " - "count = %"PRIu64", offset = %"PRIu64"\n", - fsp_str_dbg(fsp), - (unsigned int)lock_type, - smblctx, - count, - offset); - - if (lock_type == UNLOCK_LOCK) { - struct smbd_lock_element l = { - .req_guid = smbd_request_guid(req, 0), - .smblctx = smblctx, - .brltype = UNLOCK_LOCK, - .lock_flav = POSIX_LOCK, - .offset = offset, - .count = count, - }; - status = smbd_do_unlocking(req, fsp, 1, &l); - return status; - } - - lck = talloc(req, struct smbd_lock_element); - if (lck == NULL) { - return NT_STATUS_NO_MEMORY; - } - - *lck = (struct smbd_lock_element) { - .req_guid = smbd_request_guid(req, 0), - .smblctx = smblctx, - .brltype = lock_type, - .lock_flav = POSIX_LOCK, - .count = count, - .offset = offset, - }; - - subreq = smbd_smb1_do_locks_send( - fsp, - req->sconn->ev_ctx, - &req, - fsp, - blocking_lock ? UINT32_MAX : 0, - true, /* large_offset */ - 1, - lck); - if (subreq == NULL) { - TALLOC_FREE(lck); - return NT_STATUS_NO_MEMORY; - } - tevent_req_set_callback(subreq, smb_set_posix_lock_done, req); - return NT_STATUS_EVENT_PENDING; -} - -static void smb_set_posix_lock_done(struct tevent_req *subreq) -{ - struct smb_request *req = NULL; - NTSTATUS status; - bool ok; - - ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req); - SMB_ASSERT(ok); - - status = smbd_smb1_do_locks_recv(subreq); - TALLOC_FREE(subreq); - - if (NT_STATUS_IS_OK(status)) { - char params[2] = {0}; - /* Fake up max_data_bytes here - we know it fits. */ - send_trans2_replies( - req->conn, - req, - NT_STATUS_OK, - params, - 2, - NULL, - 0, - 0xffff); - } else { - reply_nterror(req, status); - ok = srv_send_smb( - req->xconn, - (char *)req->outbuf, - true, - req->seqnum+1, - IS_CONN_ENCRYPTED(req->conn), - NULL); - if (!ok) { - exit_server_cleanly("smb_set_posix_lock_done: " - "srv_send_smb failed."); - } - } - - TALLOC_FREE(req); - return; -} - /**************************************************************************** Deal with SMB_SET_FILE_BASIC_INFO. ****************************************************************************/