if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
DEBUG(0,("Invalid packet length! (%lu bytes).\n",
(unsigned long)len));
- if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {
- return false;
- }
+ return false;
}
return true;
}
ssize_t toread;
NTSTATUS status;
- memcpy(writeX_header, lenbuf, sizeof(lenbuf));
+ memcpy(writeX_header, lenbuf, 4);
status = read_socket_with_timeout(
fd, writeX_header + 4,
timeout, toread);
if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
+ nt_errstr(status)));
return status;
}
}
if (CVAL(lenbuf,0) == 0 &&
min_recv_size &&
- smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */
+ smb_len_large(lenbuf) > (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE) && /* Could be a UNIX large writeX. */
!srv_is_signing_active()) {
- status = receive_smb_raw_talloc_partial_read(
- mem_ctx, lenbuf, fd, buffer, timeout, p_unread, &len);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("receive_smb_raw: %s\n",
- nt_errstr(status)));
- return status;
- }
+ return receive_smb_raw_talloc_partial_read(
+ mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
}
if (!valid_packet_size(len)) {
msg->request_time = request_time;
msg->end_time = end_time;
msg->encrypted = req->encrypted;
+ msg->processed = false;
if (private_data) {
msg->private_data = data_blob_talloc(msg, private_data,
DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
(unsigned int)msg_mid ));
if (mid == msg_mid) {
+
+ if (pml->processed) {
+ /* A processed message should not be
+ * rescheduled. */
+ DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR "
+ "message mid %u was already processed\n",
+ (unsigned int)msg_mid ));
+ continue;
+ }
+
DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
mid ));
pml->end_time.tv_sec = 0;
}
/****************************************************************************
- Return true if this mid is on the deferred queue.
+ Return true if this mid is on the deferred queue and was not yet processed.
****************************************************************************/
bool open_was_deferred(uint16 mid)
struct pending_message_list *pml;
for (pml = deferred_open_queue; pml; pml = pml->next) {
- if (SVAL(pml->buf.data,smb_mid) == mid) {
+ if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) {
return True;
}
}
/* We leave this message on the queue so the open code can
know this is a retry. */
DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
+
+ /* Mark the message as processed so this is not
+ * re-processed in error. */
+ msg->processed = true;
return NT_STATUS_OK;
}
}
return map_nt_error_from_unix(errno);
}
- /*
- * We've just woken up from a protentially long select sleep.
- * Ensure we process local messages as we need to synchronously
- * process any messages from other smbd's to avoid file rename race
- * conditions. This call is cheap if there are no messages waiting.
- * JRA.
- */
- message_dispatch(smbd_messaging_context());
-
/* Did we timeout ? */
if (selrtn == 0) {
return NT_STATUS_IO_TIMEOUT;
goto again;
}
+ /*
+ * We've just woken up from a protentially long select sleep.
+ * Ensure we process local messages as we need to synchronously
+ * process any messages from other smbd's to avoid file rename race
+ * conditions. This call is cheap if there are no messages waiting.
+ * JRA.
+ */
+ message_dispatch(smbd_messaging_context());
+
status = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0,
p_unread, p_encrypted, &len);
/* 0x30 */ { NULL, NULL, 0 },
/* 0x31 */ { NULL, NULL, 0 },
/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
-/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
+/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC},
/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
/* 0x36 */ { NULL, NULL, 0 },
if ((num_bytes > 0xffffff)
|| ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
char *msg;
- asprintf(&msg, "num_bytes too large: %u",
- (unsigned)num_bytes);
+ if (asprintf(&msg, "num_bytes too large: %u",
+ (unsigned)num_bytes) == -1) {
+ msg = CONST_DISCARD(char *, "num_bytes too large");
+ }
smb_panic(msg);
}
if (len < 4) len = smb_len(data)+4;
for (i=1;i<100;i++) {
- asprintf(&fname, "/tmp/%s.%d.%s", name, i,
- type ? "req" : "resp");
- if (!fname) {
+ if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
+ type ? "req" : "resp") == -1) {
return;
}
fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
{
+ struct pending_message_list *pml = NULL;
uint8 type = CVAL(inbuf,smb_com);
connection_struct *conn;
struct smb_request *req;
conn = switch_message(type, req, size);
+ /* If this was a deferred message and it's still there and
+ * was processed, remove it. */
+ pml = get_open_deferred_message(req->mid);
+ if (pml && pml->processed) {
+ remove_deferred_open_smb_message(req->mid);
+ }
+
if (req->unread_bytes) {
/* writeX failed. drain socket. */
if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
char *outbuf = (char *)req->outbuf;
size_t outsize = smb_len(outbuf) + 4;
size_t outsize_padded;
+ size_t padding;
size_t ofs, to_move;
struct smb_request *req2;
*/
outsize_padded = (outsize + 3) & ~3;
+ padding = outsize_padded - outsize;
/*
* remember how much the caller added to the chain, only counting
* stuff after the parameter words
*/
- chain_size += outsize_padded - smb_wct;
+ chain_size += (outsize_padded - smb_wct);
/*
* work out pointers into the original packets. The
SCVAL(outbuf, smb_vwv0, smb_com2);
SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
- if (outsize_padded > outsize) {
+ if (padding != 0) {
/*
* Due to padding we have some uninitialized bytes after the
* caller's output
*/
- memset(outbuf + outsize, 0, outsize_padded - outsize);
+ memset(outbuf + outsize, 0, padding);
}
- smb_setlen(outbuf, outsize2 + chain_size - 4);
+ smb_setlen(outbuf, outsize2 + caller_outputlen + padding - 4);
/*
* restore the saved data, being careful not to overwrite any data
SAFE_FREE(caller_output);
TALLOC_FREE(req2);
+ /*
+ * Reset the chain_size for our caller's offset calculations
+ */
+
+ chain_size -= (outsize_padded - smb_wct);
+
return;
}