static void construct_reply_common(struct smb_request *req, const char *inbuf,
char *outbuf);
-static struct pending_message_list *get_deferred_open_message_smb(uint64_t mid);
+static struct pending_message_list *get_deferred_open_message_smb(
+ struct smbd_server_connection *sconn, uint64_t mid);
static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn)
{
msg->seqnum, msg->encrypted, &msg->pcd);
/* If it's still there and was processed, remove it. */
- msg = get_deferred_open_message_smb(mid);
+ msg = get_deferred_open_message_smb(smbd_server_conn, mid);
if (msg && msg->processed) {
- remove_deferred_open_message_smb(mid);
+ remove_deferred_open_message_smb(smbd_server_conn, mid);
}
}
return false;
}
- DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
+ DLIST_ADD_END(req->sconn->deferred_open_queue, msg,
+ struct pending_message_list *);
DEBUG(10,("push_message: pushed message length %u on "
"deferred_open_queue\n", (unsigned int)msg_len));
Function to delete a sharing violation open message by mid.
****************************************************************************/
-void remove_deferred_open_message_smb(uint64_t mid)
+void remove_deferred_open_message_smb(struct smbd_server_connection *sconn,
+ uint64_t mid)
{
struct pending_message_list *pml;
- if (smbd_server_conn->using_smb2) {
- remove_deferred_open_message_smb2(smbd_server_conn, mid);
+ if (sconn->using_smb2) {
+ remove_deferred_open_message_smb2(sconn, mid);
return;
}
- for (pml = deferred_open_queue; pml; pml = pml->next) {
+ for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
if (mid == (uint64_t)SVAL(pml->buf.data,smb_mid)) {
DEBUG(10,("remove_deferred_open_message_smb: "
"deleting mid %llu len %u\n",
(unsigned long long)mid,
(unsigned int)pml->buf.length ));
- DLIST_REMOVE(deferred_open_queue, pml);
+ DLIST_REMOVE(sconn->deferred_open_queue, pml);
TALLOC_FREE(pml);
return;
}
schedule it for immediate processing.
****************************************************************************/
-void schedule_deferred_open_message_smb(uint64_t mid)
+void schedule_deferred_open_message_smb(struct smbd_server_connection *sconn,
+ uint64_t mid)
{
struct pending_message_list *pml;
int i = 0;
- if (smbd_server_conn->using_smb2) {
- schedule_deferred_open_message_smb2(smbd_server_conn, mid);
+ if (sconn->using_smb2) {
+ schedule_deferred_open_message_smb2(sconn, mid);
return;
}
- for (pml = deferred_open_queue; pml; pml = pml->next) {
+ for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
uint64_t msg_mid = (uint64_t)SVAL(pml->buf.data,smb_mid);
DEBUG(10,("schedule_deferred_open_message_smb: [%d] "
TALLOC_FREE(pml->te);
pml->te = te;
- DLIST_PROMOTE(deferred_open_queue, pml);
+ DLIST_PROMOTE(sconn->deferred_open_queue, pml);
return;
}
}
Return true if this mid is on the deferred queue and was not yet processed.
****************************************************************************/
-bool open_was_deferred(uint64_t mid)
+bool open_was_deferred(struct smbd_server_connection *sconn, uint64_t mid)
{
struct pending_message_list *pml;
- if (smbd_server_conn->using_smb2) {
- return open_was_deferred_smb2(smbd_server_conn, mid);
+ if (sconn->using_smb2) {
+ return open_was_deferred_smb2(sconn, mid);
}
- for (pml = deferred_open_queue; pml; pml = pml->next) {
+ for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid && !pml->processed) {
return True;
}
Return the message queued by this mid.
****************************************************************************/
-static struct pending_message_list *get_deferred_open_message_smb(uint64_t mid)
+static struct pending_message_list *get_deferred_open_message_smb(
+ struct smbd_server_connection *sconn, uint64_t mid)
{
struct pending_message_list *pml;
- for (pml = deferred_open_queue; pml; pml = pml->next) {
+ for (pml = sconn->deferred_open_queue; pml; pml = pml->next) {
if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid) {
return pml;
}
pp_state);
}
- pml = get_deferred_open_message_smb(smbreq->mid);
+ pml = get_deferred_open_message_smb(smbreq->sconn, smbreq->mid);
if (!pml) {
return false;
}
DEBUG(1,("Reloading services after SIGHUP\n"));
reload_services(msg_ctx, smbd_server_conn->sock, False);
if (am_parent) {
- printing_subsystem_update(ev, msg_ctx);
+ printing_subsystem_update(ev, msg_ctx, true);
}
}
}
}
-static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
+static NTSTATUS smbd_server_connection_loop_once(struct tevent_context *ev_ctx,
+ struct smbd_server_connection *conn)
{
int timeout;
int num_pfds = 0;
* select for longer than it would take to wait for them.
*/
- event_add_to_poll_args(server_event_context(), conn,
- &conn->pfds, &num_pfds, &timeout);
+ event_add_to_poll_args(ev_ctx, conn, &conn->pfds, &num_pfds, &timeout);
/* Process a signal and timed events now... */
- if (run_events_poll(server_event_context(), 0, NULL, 0)) {
+ if (run_events_poll(ev_ctx, 0, NULL, 0)) {
return NT_STATUS_RETRY;
}
return map_nt_error_from_unix(errno);
}
- retry = run_events_poll(server_event_context(), ret, conn->pfds,
- num_pfds);
+ retry = run_events_poll(ev_ctx, ret, conn->pfds, num_pfds);
if (retry) {
return NT_STATUS_RETRY;
}
SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
/*
- * Check if the client tries to fool us. The request so far uses the
- * space to the end of the byte buffer in the request just
- * processed. The chain_offset can't point into that area. If that was
- * the case, we could end up with an endless processing of the chain,
- * we would always handle the same request.
+ * Check if the client tries to fool us. The chain offset
+ * needs to point beyond the current request in the chain, it
+ * needs to strictly grow. Otherwise we might be tricked into
+ * an endless loop always processing the same request over and
+ * over again. We used to assume that vwv and the byte buffer
+ * array in a chain are always attached, but OS/2 the
+ * Write&X/Read&X chain puts the Read&X vwv array right behind
+ * the Write&X vwv chain. The Write&X bcc array is put behind
+ * the Read&X vwv array. So now we check whether the chain
+ * offset points strictly behind the previous vwv
+ * array. req->buf points right after the vwv array of the
+ * previous request. See
+ * https://bugzilla.samba.org/show_bug.cgi?id=8360 for more
+ * information.
*/
- already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
- if (chain_offset < already_used) {
+ already_used = PTR_DIFF(req->buf, smb_base(req->inbuf));
+ if (chain_offset <= already_used) {
goto error;
}
return true;
}
-static int create_unlink_tmp(const char *dir)
-{
- char *fname;
- int fd;
-
- fname = talloc_asprintf(talloc_tos(), "%s/listenerlock_XXXXXX", dir);
- if (fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
- fd = mkstemp(fname);
- if (fd == -1) {
- TALLOC_FREE(fname);
- return -1;
- }
- if (unlink(fname) == -1) {
- int sys_errno = errno;
- close(fd);
- TALLOC_FREE(fname);
- errno = sys_errno;
- return -1;
- }
- TALLOC_FREE(fname);
- return fd;
-}
-
/*
* Read an smb packet in the echo handler child, giving the parent
* smbd one second to react once the socket becomes readable.
Process commands from the client
****************************************************************************/
-void smbd_process(struct smbd_server_connection *sconn)
+void smbd_process(struct tevent_context *ev_ctx,
+ struct smbd_server_connection *sconn)
{
TALLOC_CTX *frame = talloc_stackframe();
struct sockaddr_storage ss;
MSG_DEBUG, debug_message);
if ((lp_keepalive() != 0)
- && !(event_add_idle(server_event_context(), NULL,
+ && !(event_add_idle(ev_ctx, NULL,
timeval_set(lp_keepalive(), 0),
"keepalive", keepalive_fn,
NULL))) {
exit(1);
}
- if (!(event_add_idle(server_event_context(), NULL,
+ if (!(event_add_idle(ev_ctx, NULL,
timeval_set(IDLE_CLOSED_TIMEOUT, 0),
"deadtime", deadtime_fn, sconn))) {
DEBUG(0, ("Could not add deadtime event\n"));
exit(1);
}
- if (!(event_add_idle(server_event_context(), NULL,
+ if (!(event_add_idle(ev_ctx, NULL,
timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
"housekeeping", housekeeping_fn, sconn))) {
DEBUG(0, ("Could not add housekeeping event\n"));
exit_server("init_dptrs() failed");
}
- sconn->smb1.fde = event_add_fd(server_event_context(),
+ sconn->smb1.fde = event_add_fd(ev_ctx,
sconn,
sconn->sock,
EVENT_FD_READ,
errno = 0;
- status = smbd_server_connection_loop_once(sconn);
+ status = smbd_server_connection_loop_once(ev_ctx, sconn);
if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"