*/
#include "includes.h"
+#include "printing.h"
+#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "../libcli/smb/smb_common.h"
+#include "../librpc/gen_ndr/ndr_security.h"
+#include "../lib/util/tevent_ntstatus.h"
+#include "messages.h"
int map_smb2_oplock_levels_to_samba(uint8_t in_oplock_level)
{
{
const uint8_t *inbody;
int i = smb2req->current_idx;
- size_t expected_body_size = 0x39;
- size_t body_size;
uint8_t in_oplock_level;
uint32_t in_impersonation_level;
uint32_t in_desired_access;
bool ok;
struct tevent_req *tsubreq;
- if (smb2req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
+ status = smbd_smb2_request_verify_sizes(smb2req, 0x39);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(smb2req, status);
}
-
inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
- }
-
in_oplock_level = CVAL(inbody, 0x03);
in_impersonation_level = IVAL(inbody, 0x04);
in_desired_access = IVAL(inbody, 0x18);
* overlap
*/
- dyn_offset = SMB2_HDR_BODY + (body_size & 0xFFFFFFFE);
+ dyn_offset = SMB2_HDR_BODY + smb2req->in.vector[i+1].iov_len;
if (in_name_offset == 0 && in_name_length == 0) {
/* This is ok */
in_name_buffer.data,
in_name_buffer.length,
&in_name_string,
- &in_name_string_size, false);
+ &in_name_string_size);
if (!ok) {
return smbd_smb2_request_error(smb2req, NT_STATUS_ILLEGAL_CHARACTER);
}
+ if (in_name_buffer.length == 0) {
+ in_name_string_size = 0;
+ }
+
+ if (strlen(in_name_string) != in_name_string_size) {
+ return smbd_smb2_request_error(smb2req, NT_STATUS_OBJECT_NAME_INVALID);
+ }
+
ZERO_STRUCT(in_context_blobs);
status = smb2_create_blob_parse(smb2req, in_context_buffer, &in_context_blobs);
if (!NT_STATUS_IS_OK(status)) {
}
tsubreq = smbd_smb2_create_send(smb2req,
- smb2req->sconn->smb2.event_ctx,
+ smb2req->sconn->ev_ctx,
smb2req,
in_oplock_level,
in_impersonation_level,
}
tevent_req_set_callback(tsubreq, smbd_smb2_request_create_done, smb2req);
- return smbd_smb2_request_pending_queue(smb2req, tsubreq);
+ /*
+ * For now we keep the logic that we do not send STATUS_PENDING
+ * for sharing violations, so we just wait 2 seconds.
+ *
+ * TODO: we need more tests for this.
+ */
+ return smbd_smb2_request_pending_queue(smb2req, tsubreq, 2000000);
}
static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
{
struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
struct smbd_smb2_request);
- int i = smb2req->current_idx;
- uint8_t *outhdr;
DATA_BLOB outbody;
DATA_BLOB outdyn;
uint8_t out_oplock_level = 0;
out_context_buffer_offset = SMB2_HDR_BODY + 0x58;
}
- outhdr = (uint8_t *)smb2req->out.vector[i].iov_base;
-
outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x58);
if (outbody.data == NULL) {
error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
ZERO_STRUCT(out_context_blobs);
if(lp_fake_oplocks(SNUM(smb2req->tcon->compat_conn))) {
- requested_oplock_level = NO_OPLOCK;
+ requested_oplock_level = SMB2_OPLOCK_LEVEL_NONE;
} else {
requested_oplock_level = in_oplock_level;
}
- if (!smb2req->async) {
+ if (smb2req->subreq == NULL) {
/* New create call. */
req = tevent_req_create(mem_ctx, &state,
struct smbd_smb2_create_state);
return NULL;
}
state->smb2req = smb2req;
- smb2req->subreq = req; /* So we can find this when going async. */
smb1req = smbd_smb2_fake_smb_request(smb2req);
if (tevent_req_nomem(smb1req, req)) {
return tevent_req_post(req, ev);
}
state->smb1req = smb1req;
+ smb2req->subreq = req;
DEBUG(10,("smbd_smb2_create: name[%s]\n",
in_name));
} else {
return tevent_req_post(req, ev);
}
- status = print_fsp_open(smb1req,
- smb1req->conn,
- in_name,
- smb1req->vuid,
- result);
+ status = print_spool_open(result, in_name,
+ smb1req->vuid);
if (!NT_STATUS_IS_OK(status)) {
file_free(smb1req, result);
tevent_req_nterror(req, status);
if (exta) {
if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ tevent_req_nterror(req,NT_STATUS_OBJECT_NAME_NOT_FOUND);
return tevent_req_post(req, ev);
}
if (mxac) {
if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return tevent_req_post(req, ev);
}
enum ndr_err_code ndr_err;
if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return tevent_req_post(req, ev);
}
if (dhnq) {
if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return tevent_req_post(req, ev);
}
if (alsi) {
if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return tevent_req_post(req, ev);
}
struct tm *tm;
if (dhnc) {
- tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
return tevent_req_post(req, ev);
}
in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */
in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */
- /* convert '\\' into '/' */
- status = check_path_syntax(fname);
- if (!NT_STATUS_IS_OK(status)) {
- tevent_req_nterror(req, status);
- return tevent_req_post(req, ev);
+ /*
+ * For a DFS path the function parse_dfs_path()
+ * will do the path processing.
+ */
+
+ if (!(smb1req->flags2 & FLAGS2_DFS_PATHNAMES)) {
+ /* convert '\\' into '/' */
+ status = check_path_syntax(fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return tevent_req_post(req, ev);
+ }
}
status = filename_convert(req,
&result,
&info);
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(smb1req->mid)) {
+ if (open_was_deferred(smb1req->sconn, smb1req->mid)) {
return req;
}
tevent_req_nterror(req, status);
uint32_t max_access_granted;
DATA_BLOB blob = data_blob_const(p, sizeof(p));
- status = smbd_check_open_rights(smb1req->conn,
+ status = smbd_calculate_access_mask(smb1req->conn,
result->fsp_name,
SEC_FLAG_MAXIMUM_ALLOWED,
&max_access_granted);
/* Deal with other possible opens having a modified
write time. JRA. */
ZERO_STRUCT(write_time_ts);
- get_file_infos(result->file_id, NULL, &write_time_ts);
+ get_file_infos(result->file_id, 0, NULL, &write_time_ts);
if (!null_timespec(write_time_ts)) {
update_stat_ex_mtime(&result->fsp_name->st, write_time_ts);
}
get_change_timespec(smb1req->conn, result,
result->fsp_name));
state->out_allocation_size =
- result->fsp_name->st.st_ex_blksize *
- result->fsp_name->st.st_ex_blocks;
+ SMB_VFS_GET_ALLOC_SIZE(smb1req->conn, result,
+ &(result->fsp_name->st));
state->out_end_of_file = result->fsp_name->st.st_ex_size;
if (state->out_file_attributes == 0) {
state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
if (!smb2req) {
return false;
}
- if (!smb2req->async) {
+ if (smb2req->async_te == NULL) {
return false;
}
req = smb2req->subreq;
close.
*********************************************************/
-static struct smbd_smb2_request *find_open_smb2req(uint64_t mid)
+static struct smbd_smb2_request *find_open_smb2req(
+ struct smbd_server_connection *sconn, uint64_t mid)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
struct smbd_smb2_request *smb2req;
for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
return NULL;
}
-bool open_was_deferred_smb2(uint64_t mid)
+bool open_was_deferred_smb2(struct smbd_server_connection *sconn, uint64_t mid)
{
struct smbd_smb2_create_state *state = NULL;
- struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
+ struct smbd_smb2_request *smb2req;
+
+ smb2req = find_open_smb2req(sconn, mid);
if (!smb2req) {
DEBUG(10,("open_was_deferred_smb2: mid %llu smb2req == NULL\n",
TALLOC_FREE(state->im);
}
-void remove_deferred_open_message_smb2(uint64_t mid)
+void remove_deferred_open_message_smb2(
+ struct smbd_server_connection *sconn, uint64_t mid)
{
- struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
+ struct smbd_smb2_request *smb2req;
+
+ smb2req = find_open_smb2req(sconn, mid);
if (!smb2req) {
DEBUG(10,("remove_deferred_open_message_smb2: "
}
}
-void schedule_deferred_open_message_smb2(uint64_t mid)
+void schedule_deferred_open_message_smb2(
+ struct smbd_server_connection *sconn, uint64_t mid)
{
struct smbd_smb2_create_state *state = NULL;
- struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
+ struct smbd_smb2_request *smb2req;
+
+ smb2req = find_open_smb2req(sconn, mid);
if (!smb2req) {
DEBUG(10,("schedule_deferred_open_message_smb2: "
if (!state->im) {
smbd_server_connection_terminate(smb2req->sconn,
nt_errstr(NT_STATUS_NO_MEMORY));
+ return;
}
DEBUG(10,("schedule_deferred_open_message_smb2: "
(unsigned long long)mid ));
tevent_schedule_immediate(state->im,
- smb2req->sconn->smb2.event_ctx,
+ smb2req->sconn->ev_ctx,
smbd_smb2_create_request_dispatch_immediate,
smb2req);
}
smb2req = state->smb2req;
mid = get_mid_from_smb2req(smb2req);
- remove_deferred_open_entry(state->id, mid);
+ remove_deferred_open_entry(state->id, mid,
+ messaging_server_id(smb2req->sconn->msg_ctx));
remove_deferred_open_message_smb2_internal(smb2req, mid);
smb2req->cancelled = true;
return false;
}
-#if 1
- /* Boo - turns out this isn't what W2K8R2
- does. It actually sends the STATUS_PENDING
- message followed by the STATUS_SHARING_VIOLATION
- message. Surely this means that all open
- calls (even on directories) will potentially
- fail in a chain.... ? And I've seen directory
- opens as the start of a chain. JRA.
-
- Update: 19th May 2010. Talking with Microsoft
- engineers at the plugfest this is a bug in
- Windows. Re-enable this code.
- */
- /*
- * More subtlety. To match W2K8R2 don't
- * send a "gone async" message if it's simply
- * a STATUS_SHARING_VIOLATION (short) wait, not
- * an oplock break wait. We do this by prematurely
- * setting smb2req->async flag.
- */
- if (timeout.tv_sec < 2) {
- DEBUG(10,("push_deferred_open_message_smb2: "
- "short timer wait (usec = %u). "
- "Don't send async message.\n",
- (unsigned int)timeout.tv_usec ));
- smb2req->async = true;
- }
-#endif
-
/* Re-schedule us to retry on timer expiry. */
end_time = timeval_sum(&request_time, &timeout);
&end_time,
true) ));
- state->te = event_add_timed(smb2req->sconn->smb2.event_ctx,
+ state->te = tevent_add_timer(smb2req->sconn->ev_ctx,
state,
end_time,
smb2_deferred_open_timer,