spoolss: fix spoolss_EnumPrinterKey IDL.
[Samba.git] / source3 / smbd / process.c
blobfbaa9dee290491016be52e8f0d6d805da8e09355
1 /*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "smbd/globals.h"
24 extern bool global_machine_password_needs_changing;
26 static void construct_reply_common(struct smb_request *req, const char *inbuf,
27 char *outbuf);
29 /* Accessor function for smb_read_error for smbd functions. */
31 /****************************************************************************
32 Send an smb to a fd.
33 ****************************************************************************/
35 bool srv_send_smb(int fd, char *buffer,
36 bool do_signing, uint32_t seqnum,
37 bool do_encrypt,
38 struct smb_perfcount_data *pcd)
40 size_t len = 0;
41 size_t nwritten=0;
42 ssize_t ret;
43 char *buf_out = buffer;
45 if (do_signing) {
46 /* Sign the outgoing packet if required. */
47 srv_calculate_sign_mac(smbd_server_conn, buf_out, seqnum);
50 if (do_encrypt) {
51 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
52 if (!NT_STATUS_IS_OK(status)) {
53 DEBUG(0, ("send_smb: SMB encryption failed "
54 "on outgoing packet! Error %s\n",
55 nt_errstr(status) ));
56 goto out;
60 len = smb_len(buf_out) + 4;
62 ret = write_data(fd,buf_out+nwritten,len - nwritten);
63 if (ret <= 0) {
64 DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
65 (int)len,(int)ret, strerror(errno) ));
66 srv_free_enc_buffer(buf_out);
67 goto out;
70 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
71 srv_free_enc_buffer(buf_out);
72 out:
73 SMB_PERFCOUNT_END(pcd);
74 return true;
77 /*******************************************************************
78 Setup the word count and byte count for a smb message.
79 ********************************************************************/
81 int srv_set_message(char *buf,
82 int num_words,
83 int num_bytes,
84 bool zero)
86 if (zero && (num_words || num_bytes)) {
87 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
89 SCVAL(buf,smb_wct,num_words);
90 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
91 smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
92 return (smb_size + num_words*2 + num_bytes);
95 static bool valid_smb_header(const uint8_t *inbuf)
97 if (is_encrypted_packet(inbuf)) {
98 return true;
101 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
102 * but it just looks weird to call strncmp for this one.
104 return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
107 /* Socket functions for smbd packet processing. */
109 static bool valid_packet_size(size_t len)
112 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
113 * of header. Don't print the error if this fits.... JRA.
116 if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
117 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
118 (unsigned long)len));
119 return false;
121 return true;
124 static NTSTATUS read_packet_remainder(int fd, char *buffer,
125 unsigned int timeout, ssize_t len)
127 if (len <= 0) {
128 return NT_STATUS_OK;
131 return read_fd_with_timeout(fd, buffer, len, len, timeout, NULL);
134 /****************************************************************************
135 Attempt a zerocopy writeX read. We know here that len > smb_size-4
136 ****************************************************************************/
139 * Unfortunately, earlier versions of smbclient/libsmbclient
140 * don't send this "standard" writeX header. I've fixed this
141 * for 3.2 but we'll use the old method with earlier versions.
142 * Windows and CIFSFS at least use this standard size. Not
143 * sure about MacOSX.
146 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
147 (2*14) + /* word count (including bcc) */ \
148 1 /* pad byte */)
150 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
151 const char lenbuf[4],
152 int fd, char **buffer,
153 unsigned int timeout,
154 size_t *p_unread,
155 size_t *len_ret)
157 /* Size of a WRITEX call (+4 byte len). */
158 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
159 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
160 ssize_t toread;
161 NTSTATUS status;
163 memcpy(writeX_header, lenbuf, 4);
165 status = read_fd_with_timeout(
166 fd, writeX_header + 4,
167 STANDARD_WRITE_AND_X_HEADER_SIZE,
168 STANDARD_WRITE_AND_X_HEADER_SIZE,
169 timeout, NULL);
171 if (!NT_STATUS_IS_OK(status)) {
172 return status;
176 * Ok - now try and see if this is a possible
177 * valid writeX call.
180 if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
182 * If the data offset is beyond what
183 * we've read, drain the extra bytes.
185 uint16_t doff = SVAL(writeX_header,smb_vwv11);
186 ssize_t newlen;
188 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
189 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
190 if (drain_socket(smbd_server_fd(), drain) != drain) {
191 smb_panic("receive_smb_raw_talloc_partial_read:"
192 " failed to drain pending bytes");
194 } else {
195 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
198 /* Spoof down the length and null out the bcc. */
199 set_message_bcc(writeX_header, 0);
200 newlen = smb_len(writeX_header);
202 /* Copy the header we've written. */
204 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
205 writeX_header,
206 sizeof(writeX_header));
208 if (*buffer == NULL) {
209 DEBUG(0, ("Could not allocate inbuf of length %d\n",
210 (int)sizeof(writeX_header)));
211 return NT_STATUS_NO_MEMORY;
214 /* Work out the remaining bytes. */
215 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
216 *len_ret = newlen + 4;
217 return NT_STATUS_OK;
220 if (!valid_packet_size(len)) {
221 return NT_STATUS_INVALID_PARAMETER;
225 * Not a valid writeX call. Just do the standard
226 * talloc and return.
229 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
231 if (*buffer == NULL) {
232 DEBUG(0, ("Could not allocate inbuf of length %d\n",
233 (int)len+4));
234 return NT_STATUS_NO_MEMORY;
237 /* Copy in what we already read. */
238 memcpy(*buffer,
239 writeX_header,
240 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
241 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
243 if(toread > 0) {
244 status = read_packet_remainder(
245 fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
246 timeout, toread);
248 if (!NT_STATUS_IS_OK(status)) {
249 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
250 nt_errstr(status)));
251 return status;
255 *len_ret = len + 4;
256 return NT_STATUS_OK;
259 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
260 char **buffer, unsigned int timeout,
261 size_t *p_unread, size_t *plen)
263 char lenbuf[4];
264 size_t len;
265 int min_recv_size = lp_min_receive_file_size();
266 NTSTATUS status;
268 *p_unread = 0;
270 status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
271 if (!NT_STATUS_IS_OK(status)) {
272 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
273 return status;
276 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
277 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
278 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
279 !srv_is_signing_active(smbd_server_conn)) {
281 return receive_smb_raw_talloc_partial_read(
282 mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
285 if (!valid_packet_size(len)) {
286 return NT_STATUS_INVALID_PARAMETER;
290 * The +4 here can't wrap, we've checked the length above already.
293 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
295 if (*buffer == NULL) {
296 DEBUG(0, ("Could not allocate inbuf of length %d\n",
297 (int)len+4));
298 return NT_STATUS_NO_MEMORY;
301 memcpy(*buffer, lenbuf, sizeof(lenbuf));
303 status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
304 if (!NT_STATUS_IS_OK(status)) {
305 return status;
308 *plen = len + 4;
309 return NT_STATUS_OK;
312 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
313 char **buffer, unsigned int timeout,
314 size_t *p_unread, bool *p_encrypted,
315 size_t *p_len,
316 uint32_t *seqnum)
318 size_t len = 0;
319 NTSTATUS status;
321 *p_encrypted = false;
323 status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
324 p_unread, &len);
325 if (!NT_STATUS_IS_OK(status)) {
326 return status;
329 if (is_encrypted_packet((uint8_t *)*buffer)) {
330 status = srv_decrypt_buffer(*buffer);
331 if (!NT_STATUS_IS_OK(status)) {
332 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
333 "incoming packet! Error %s\n",
334 nt_errstr(status) ));
335 return status;
337 *p_encrypted = true;
340 /* Check the incoming SMB signature. */
341 if (!srv_check_sign_mac(smbd_server_conn, *buffer, seqnum)) {
342 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
343 "incoming packet!\n"));
344 return NT_STATUS_INVALID_NETWORK_RESPONSE;
347 *p_len = len;
348 return NT_STATUS_OK;
352 * Initialize a struct smb_request from an inbuf
355 void init_smb_request(struct smb_request *req,
356 const uint8 *inbuf,
357 size_t unread_bytes,
358 bool encrypted)
360 struct smbd_server_connection *sconn = smbd_server_conn;
361 size_t req_size = smb_len(inbuf) + 4;
362 /* Ensure we have at least smb_size bytes. */
363 if (req_size < smb_size) {
364 DEBUG(0,("init_smb_request: invalid request size %u\n",
365 (unsigned int)req_size ));
366 exit_server_cleanly("Invalid SMB request");
368 req->cmd = CVAL(inbuf, smb_com);
369 req->flags2 = SVAL(inbuf, smb_flg2);
370 req->smbpid = SVAL(inbuf, smb_pid);
371 req->mid = SVAL(inbuf, smb_mid);
372 req->seqnum = 0;
373 req->vuid = SVAL(inbuf, smb_uid);
374 req->tid = SVAL(inbuf, smb_tid);
375 req->wct = CVAL(inbuf, smb_wct);
376 req->vwv = (uint16_t *)(inbuf+smb_vwv);
377 req->buflen = smb_buflen(inbuf);
378 req->buf = (const uint8_t *)smb_buf(inbuf);
379 req->unread_bytes = unread_bytes;
380 req->encrypted = encrypted;
381 req->conn = conn_find(sconn,req->tid);
382 req->chain_fsp = NULL;
383 req->chain_outbuf = NULL;
384 req->done = false;
385 smb_init_perfcount_data(&req->pcd);
387 /* Ensure we have at least wct words and 2 bytes of bcc. */
388 if (smb_size + req->wct*2 > req_size) {
389 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
390 (unsigned int)req->wct,
391 (unsigned int)req_size));
392 exit_server_cleanly("Invalid SMB request");
394 /* Ensure bcc is correct. */
395 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
396 DEBUG(0,("init_smb_request: invalid bcc number %u "
397 "(wct = %u, size %u)\n",
398 (unsigned int)req->buflen,
399 (unsigned int)req->wct,
400 (unsigned int)req_size));
401 exit_server_cleanly("Invalid SMB request");
404 req->outbuf = NULL;
407 static void process_smb(struct smbd_server_connection *conn,
408 uint8_t *inbuf, size_t nread, size_t unread_bytes,
409 uint32_t seqnum, bool encrypted,
410 struct smb_perfcount_data *deferred_pcd);
412 static void smbd_deferred_open_timer(struct event_context *ev,
413 struct timed_event *te,
414 struct timeval _tval,
415 void *private_data)
417 struct pending_message_list *msg = talloc_get_type(private_data,
418 struct pending_message_list);
419 TALLOC_CTX *mem_ctx = talloc_tos();
420 uint16_t mid = SVAL(msg->buf.data,smb_mid);
421 uint8_t *inbuf;
423 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
424 msg->buf.length);
425 if (inbuf == NULL) {
426 exit_server("smbd_deferred_open_timer: talloc failed\n");
427 return;
430 /* We leave this message on the queue so the open code can
431 know this is a retry. */
432 DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
433 (unsigned int)mid ));
435 /* Mark the message as processed so this is not
436 * re-processed in error. */
437 msg->processed = true;
439 process_smb(smbd_server_conn, inbuf,
440 msg->buf.length, 0,
441 msg->seqnum, msg->encrypted, &msg->pcd);
443 /* If it's still there and was processed, remove it. */
444 msg = get_open_deferred_message(mid);
445 if (msg && msg->processed) {
446 remove_deferred_open_smb_message(mid);
450 /****************************************************************************
451 Function to push a message onto the tail of a linked list of smb messages ready
452 for processing.
453 ****************************************************************************/
455 static bool push_queued_message(struct smb_request *req,
456 struct timeval request_time,
457 struct timeval end_time,
458 char *private_data, size_t private_len)
460 int msg_len = smb_len(req->inbuf) + 4;
461 struct pending_message_list *msg;
463 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
465 if(msg == NULL) {
466 DEBUG(0,("push_message: malloc fail (1)\n"));
467 return False;
470 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
471 if(msg->buf.data == NULL) {
472 DEBUG(0,("push_message: malloc fail (2)\n"));
473 TALLOC_FREE(msg);
474 return False;
477 msg->request_time = request_time;
478 msg->seqnum = req->seqnum;
479 msg->encrypted = req->encrypted;
480 msg->processed = false;
481 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
483 if (private_data) {
484 msg->private_data = data_blob_talloc(msg, private_data,
485 private_len);
486 if (msg->private_data.data == NULL) {
487 DEBUG(0,("push_message: malloc fail (3)\n"));
488 TALLOC_FREE(msg);
489 return False;
493 msg->te = event_add_timed(smbd_event_context(),
494 msg,
495 end_time,
496 smbd_deferred_open_timer,
497 msg);
498 if (!msg->te) {
499 DEBUG(0,("push_message: event_add_timed failed\n"));
500 TALLOC_FREE(msg);
501 return false;
504 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
506 DEBUG(10,("push_message: pushed message length %u on "
507 "deferred_open_queue\n", (unsigned int)msg_len));
509 return True;
512 /****************************************************************************
513 Function to delete a sharing violation open message by mid.
514 ****************************************************************************/
516 void remove_deferred_open_smb_message(uint16 mid)
518 struct pending_message_list *pml;
520 for (pml = deferred_open_queue; pml; pml = pml->next) {
521 if (mid == SVAL(pml->buf.data,smb_mid)) {
522 DEBUG(10,("remove_deferred_open_smb_message: "
523 "deleting mid %u len %u\n",
524 (unsigned int)mid,
525 (unsigned int)pml->buf.length ));
526 DLIST_REMOVE(deferred_open_queue, pml);
527 TALLOC_FREE(pml);
528 return;
533 /****************************************************************************
534 Move a sharing violation open retry message to the front of the list and
535 schedule it for immediate processing.
536 ****************************************************************************/
538 void schedule_deferred_open_smb_message(uint16 mid)
540 struct pending_message_list *pml;
541 int i = 0;
543 for (pml = deferred_open_queue; pml; pml = pml->next) {
544 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
546 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
547 (unsigned int)msg_mid ));
549 if (mid == msg_mid) {
550 struct timed_event *te;
552 if (pml->processed) {
553 /* A processed message should not be
554 * rescheduled. */
555 DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR "
556 "message mid %u was already processed\n",
557 msg_mid ));
558 continue;
561 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
562 mid ));
564 te = event_add_timed(smbd_event_context(),
565 pml,
566 timeval_zero(),
567 smbd_deferred_open_timer,
568 pml);
569 if (!te) {
570 DEBUG(10,("schedule_deferred_open_smb_message: "
571 "event_add_timed() failed, skipping mid %u\n",
572 mid ));
575 TALLOC_FREE(pml->te);
576 pml->te = te;
577 DLIST_PROMOTE(deferred_open_queue, pml);
578 return;
582 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
583 mid ));
586 /****************************************************************************
587 Return true if this mid is on the deferred queue and was not yet processed.
588 ****************************************************************************/
590 bool open_was_deferred(uint16 mid)
592 struct pending_message_list *pml;
594 for (pml = deferred_open_queue; pml; pml = pml->next) {
595 if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) {
596 return True;
599 return False;
602 /****************************************************************************
603 Return the message queued by this mid.
604 ****************************************************************************/
606 struct pending_message_list *get_open_deferred_message(uint16 mid)
608 struct pending_message_list *pml;
610 for (pml = deferred_open_queue; pml; pml = pml->next) {
611 if (SVAL(pml->buf.data,smb_mid) == mid) {
612 return pml;
615 return NULL;
618 /****************************************************************************
619 Function to push a deferred open smb message onto a linked list of local smb
620 messages ready for processing.
621 ****************************************************************************/
623 bool push_deferred_smb_message(struct smb_request *req,
624 struct timeval request_time,
625 struct timeval timeout,
626 char *private_data, size_t priv_len)
628 struct timeval end_time;
630 if (req->unread_bytes) {
631 DEBUG(0,("push_deferred_smb_message: logic error ! "
632 "unread_bytes = %u\n",
633 (unsigned int)req->unread_bytes ));
634 smb_panic("push_deferred_smb_message: "
635 "logic error unread_bytes != 0" );
638 end_time = timeval_sum(&request_time, &timeout);
640 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
641 "timeout time [%u.%06u]\n",
642 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
643 (unsigned int)end_time.tv_sec,
644 (unsigned int)end_time.tv_usec));
646 return push_queued_message(req, request_time, end_time,
647 private_data, priv_len);
650 struct idle_event {
651 struct timed_event *te;
652 struct timeval interval;
653 char *name;
654 bool (*handler)(const struct timeval *now, void *private_data);
655 void *private_data;
658 static void smbd_idle_event_handler(struct event_context *ctx,
659 struct timed_event *te,
660 struct timeval now,
661 void *private_data)
663 struct idle_event *event =
664 talloc_get_type_abort(private_data, struct idle_event);
666 TALLOC_FREE(event->te);
668 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
669 event->name, event->te));
671 if (!event->handler(&now, event->private_data)) {
672 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
673 event->name, event->te));
674 /* Don't repeat, delete ourselves */
675 TALLOC_FREE(event);
676 return;
679 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
680 event->name, event->te));
682 event->te = event_add_timed(ctx, event,
683 timeval_sum(&now, &event->interval),
684 smbd_idle_event_handler, event);
686 /* We can't do much but fail here. */
687 SMB_ASSERT(event->te != NULL);
690 struct idle_event *event_add_idle(struct event_context *event_ctx,
691 TALLOC_CTX *mem_ctx,
692 struct timeval interval,
693 const char *name,
694 bool (*handler)(const struct timeval *now,
695 void *private_data),
696 void *private_data)
698 struct idle_event *result;
699 struct timeval now = timeval_current();
701 result = TALLOC_P(mem_ctx, struct idle_event);
702 if (result == NULL) {
703 DEBUG(0, ("talloc failed\n"));
704 return NULL;
707 result->interval = interval;
708 result->handler = handler;
709 result->private_data = private_data;
711 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
712 DEBUG(0, ("talloc failed\n"));
713 TALLOC_FREE(result);
714 return NULL;
717 result->te = event_add_timed(event_ctx, result,
718 timeval_sum(&now, &interval),
719 smbd_idle_event_handler, result);
720 if (result->te == NULL) {
721 DEBUG(0, ("event_add_timed failed\n"));
722 TALLOC_FREE(result);
723 return NULL;
726 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
727 return result;
730 static void smbd_sig_term_handler(struct tevent_context *ev,
731 struct tevent_signal *se,
732 int signum,
733 int count,
734 void *siginfo,
735 void *private_data)
737 exit_server_cleanly("termination signal");
740 void smbd_setup_sig_term_handler(void)
742 struct tevent_signal *se;
744 se = tevent_add_signal(smbd_event_context(),
745 smbd_event_context(),
746 SIGTERM, 0,
747 smbd_sig_term_handler,
748 NULL);
749 if (!se) {
750 exit_server("failed to setup SIGTERM handler");
754 static void smbd_sig_hup_handler(struct tevent_context *ev,
755 struct tevent_signal *se,
756 int signum,
757 int count,
758 void *siginfo,
759 void *private_data)
761 change_to_root_user();
762 DEBUG(1,("Reloading services after SIGHUP\n"));
763 reload_services(False);
766 void smbd_setup_sig_hup_handler(void)
768 struct tevent_signal *se;
770 se = tevent_add_signal(smbd_event_context(),
771 smbd_event_context(),
772 SIGHUP, 0,
773 smbd_sig_hup_handler,
774 NULL);
775 if (!se) {
776 exit_server("failed to setup SIGHUP handler");
780 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
782 fd_set r_fds, w_fds;
783 int selrtn;
784 struct timeval to;
785 int maxfd = 0;
787 to.tv_sec = SMBD_SELECT_TIMEOUT;
788 to.tv_usec = 0;
791 * Setup the select fd sets.
794 FD_ZERO(&r_fds);
795 FD_ZERO(&w_fds);
798 * Are there any timed events waiting ? If so, ensure we don't
799 * select for longer than it would take to wait for them.
803 struct timeval now;
804 GetTimeOfDay(&now);
806 event_add_to_select_args(smbd_event_context(), &now,
807 &r_fds, &w_fds, &to, &maxfd);
810 /* Process a signal and timed events now... */
811 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
812 return NT_STATUS_RETRY;
816 int sav;
817 START_PROFILE(smbd_idle);
819 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
820 sav = errno;
822 END_PROFILE(smbd_idle);
823 errno = sav;
826 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
827 return NT_STATUS_RETRY;
830 /* Check if error */
831 if (selrtn == -1) {
832 /* something is wrong. Maybe the socket is dead? */
833 return map_nt_error_from_unix(errno);
836 /* Did we timeout ? */
837 if (selrtn == 0) {
838 return NT_STATUS_RETRY;
841 /* should not be reached */
842 return NT_STATUS_INTERNAL_ERROR;
846 * Only allow 5 outstanding trans requests. We're allocating memory, so
847 * prevent a DoS.
850 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
852 int count = 0;
853 for (; list != NULL; list = list->next) {
855 if (list->mid == mid) {
856 return NT_STATUS_INVALID_PARAMETER;
859 count += 1;
861 if (count > 5) {
862 return NT_STATUS_INSUFFICIENT_RESOURCES;
865 return NT_STATUS_OK;
869 These flags determine some of the permissions required to do an operation
871 Note that I don't set NEED_WRITE on some write operations because they
872 are used by some brain-dead clients when printing, and I don't want to
873 force write permissions on print services.
875 #define AS_USER (1<<0)
876 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
877 #define TIME_INIT (1<<2)
878 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
879 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
880 #define DO_CHDIR (1<<6)
883 define a list of possible SMB messages and their corresponding
884 functions. Any message that has a NULL function is unimplemented -
885 please feel free to contribute implementations!
887 static const struct smb_message_struct {
888 const char *name;
889 void (*fn)(struct smb_request *req);
890 int flags;
891 } smb_messages[256] = {
893 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
894 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
895 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
896 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
897 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
898 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
899 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
900 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
901 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
902 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
903 /* 0x0a */ { "SMBread",reply_read,AS_USER},
904 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
905 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
906 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
907 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
908 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
909 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
910 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
911 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
912 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
913 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
914 /* 0x15 */ { NULL, NULL, 0 },
915 /* 0x16 */ { NULL, NULL, 0 },
916 /* 0x17 */ { NULL, NULL, 0 },
917 /* 0x18 */ { NULL, NULL, 0 },
918 /* 0x19 */ { NULL, NULL, 0 },
919 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
920 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
921 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
922 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
923 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
924 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
925 /* 0x20 */ { "SMBwritec", NULL,0},
926 /* 0x21 */ { NULL, NULL, 0 },
927 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
928 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
929 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
930 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
931 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
932 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
933 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
934 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
935 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
936 /* 0x2b */ { "SMBecho",reply_echo,0},
937 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
938 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
939 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
940 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
941 /* 0x30 */ { NULL, NULL, 0 },
942 /* 0x31 */ { NULL, NULL, 0 },
943 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
944 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
945 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
946 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
947 /* 0x36 */ { NULL, NULL, 0 },
948 /* 0x37 */ { NULL, NULL, 0 },
949 /* 0x38 */ { NULL, NULL, 0 },
950 /* 0x39 */ { NULL, NULL, 0 },
951 /* 0x3a */ { NULL, NULL, 0 },
952 /* 0x3b */ { NULL, NULL, 0 },
953 /* 0x3c */ { NULL, NULL, 0 },
954 /* 0x3d */ { NULL, NULL, 0 },
955 /* 0x3e */ { NULL, NULL, 0 },
956 /* 0x3f */ { NULL, NULL, 0 },
957 /* 0x40 */ { NULL, NULL, 0 },
958 /* 0x41 */ { NULL, NULL, 0 },
959 /* 0x42 */ { NULL, NULL, 0 },
960 /* 0x43 */ { NULL, NULL, 0 },
961 /* 0x44 */ { NULL, NULL, 0 },
962 /* 0x45 */ { NULL, NULL, 0 },
963 /* 0x46 */ { NULL, NULL, 0 },
964 /* 0x47 */ { NULL, NULL, 0 },
965 /* 0x48 */ { NULL, NULL, 0 },
966 /* 0x49 */ { NULL, NULL, 0 },
967 /* 0x4a */ { NULL, NULL, 0 },
968 /* 0x4b */ { NULL, NULL, 0 },
969 /* 0x4c */ { NULL, NULL, 0 },
970 /* 0x4d */ { NULL, NULL, 0 },
971 /* 0x4e */ { NULL, NULL, 0 },
972 /* 0x4f */ { NULL, NULL, 0 },
973 /* 0x50 */ { NULL, NULL, 0 },
974 /* 0x51 */ { NULL, NULL, 0 },
975 /* 0x52 */ { NULL, NULL, 0 },
976 /* 0x53 */ { NULL, NULL, 0 },
977 /* 0x54 */ { NULL, NULL, 0 },
978 /* 0x55 */ { NULL, NULL, 0 },
979 /* 0x56 */ { NULL, NULL, 0 },
980 /* 0x57 */ { NULL, NULL, 0 },
981 /* 0x58 */ { NULL, NULL, 0 },
982 /* 0x59 */ { NULL, NULL, 0 },
983 /* 0x5a */ { NULL, NULL, 0 },
984 /* 0x5b */ { NULL, NULL, 0 },
985 /* 0x5c */ { NULL, NULL, 0 },
986 /* 0x5d */ { NULL, NULL, 0 },
987 /* 0x5e */ { NULL, NULL, 0 },
988 /* 0x5f */ { NULL, NULL, 0 },
989 /* 0x60 */ { NULL, NULL, 0 },
990 /* 0x61 */ { NULL, NULL, 0 },
991 /* 0x62 */ { NULL, NULL, 0 },
992 /* 0x63 */ { NULL, NULL, 0 },
993 /* 0x64 */ { NULL, NULL, 0 },
994 /* 0x65 */ { NULL, NULL, 0 },
995 /* 0x66 */ { NULL, NULL, 0 },
996 /* 0x67 */ { NULL, NULL, 0 },
997 /* 0x68 */ { NULL, NULL, 0 },
998 /* 0x69 */ { NULL, NULL, 0 },
999 /* 0x6a */ { NULL, NULL, 0 },
1000 /* 0x6b */ { NULL, NULL, 0 },
1001 /* 0x6c */ { NULL, NULL, 0 },
1002 /* 0x6d */ { NULL, NULL, 0 },
1003 /* 0x6e */ { NULL, NULL, 0 },
1004 /* 0x6f */ { NULL, NULL, 0 },
1005 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1006 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1007 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1008 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1009 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1010 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1011 /* 0x76 */ { NULL, NULL, 0 },
1012 /* 0x77 */ { NULL, NULL, 0 },
1013 /* 0x78 */ { NULL, NULL, 0 },
1014 /* 0x79 */ { NULL, NULL, 0 },
1015 /* 0x7a */ { NULL, NULL, 0 },
1016 /* 0x7b */ { NULL, NULL, 0 },
1017 /* 0x7c */ { NULL, NULL, 0 },
1018 /* 0x7d */ { NULL, NULL, 0 },
1019 /* 0x7e */ { NULL, NULL, 0 },
1020 /* 0x7f */ { NULL, NULL, 0 },
1021 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1022 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1023 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1024 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1025 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1026 /* 0x85 */ { NULL, NULL, 0 },
1027 /* 0x86 */ { NULL, NULL, 0 },
1028 /* 0x87 */ { NULL, NULL, 0 },
1029 /* 0x88 */ { NULL, NULL, 0 },
1030 /* 0x89 */ { NULL, NULL, 0 },
1031 /* 0x8a */ { NULL, NULL, 0 },
1032 /* 0x8b */ { NULL, NULL, 0 },
1033 /* 0x8c */ { NULL, NULL, 0 },
1034 /* 0x8d */ { NULL, NULL, 0 },
1035 /* 0x8e */ { NULL, NULL, 0 },
1036 /* 0x8f */ { NULL, NULL, 0 },
1037 /* 0x90 */ { NULL, NULL, 0 },
1038 /* 0x91 */ { NULL, NULL, 0 },
1039 /* 0x92 */ { NULL, NULL, 0 },
1040 /* 0x93 */ { NULL, NULL, 0 },
1041 /* 0x94 */ { NULL, NULL, 0 },
1042 /* 0x95 */ { NULL, NULL, 0 },
1043 /* 0x96 */ { NULL, NULL, 0 },
1044 /* 0x97 */ { NULL, NULL, 0 },
1045 /* 0x98 */ { NULL, NULL, 0 },
1046 /* 0x99 */ { NULL, NULL, 0 },
1047 /* 0x9a */ { NULL, NULL, 0 },
1048 /* 0x9b */ { NULL, NULL, 0 },
1049 /* 0x9c */ { NULL, NULL, 0 },
1050 /* 0x9d */ { NULL, NULL, 0 },
1051 /* 0x9e */ { NULL, NULL, 0 },
1052 /* 0x9f */ { NULL, NULL, 0 },
1053 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1054 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1055 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1056 /* 0xa3 */ { NULL, NULL, 0 },
1057 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1058 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1059 /* 0xa6 */ { NULL, NULL, 0 },
1060 /* 0xa7 */ { NULL, NULL, 0 },
1061 /* 0xa8 */ { NULL, NULL, 0 },
1062 /* 0xa9 */ { NULL, NULL, 0 },
1063 /* 0xaa */ { NULL, NULL, 0 },
1064 /* 0xab */ { NULL, NULL, 0 },
1065 /* 0xac */ { NULL, NULL, 0 },
1066 /* 0xad */ { NULL, NULL, 0 },
1067 /* 0xae */ { NULL, NULL, 0 },
1068 /* 0xaf */ { NULL, NULL, 0 },
1069 /* 0xb0 */ { NULL, NULL, 0 },
1070 /* 0xb1 */ { NULL, NULL, 0 },
1071 /* 0xb2 */ { NULL, NULL, 0 },
1072 /* 0xb3 */ { NULL, NULL, 0 },
1073 /* 0xb4 */ { NULL, NULL, 0 },
1074 /* 0xb5 */ { NULL, NULL, 0 },
1075 /* 0xb6 */ { NULL, NULL, 0 },
1076 /* 0xb7 */ { NULL, NULL, 0 },
1077 /* 0xb8 */ { NULL, NULL, 0 },
1078 /* 0xb9 */ { NULL, NULL, 0 },
1079 /* 0xba */ { NULL, NULL, 0 },
1080 /* 0xbb */ { NULL, NULL, 0 },
1081 /* 0xbc */ { NULL, NULL, 0 },
1082 /* 0xbd */ { NULL, NULL, 0 },
1083 /* 0xbe */ { NULL, NULL, 0 },
1084 /* 0xbf */ { NULL, NULL, 0 },
1085 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1086 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1087 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1088 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1089 /* 0xc4 */ { NULL, NULL, 0 },
1090 /* 0xc5 */ { NULL, NULL, 0 },
1091 /* 0xc6 */ { NULL, NULL, 0 },
1092 /* 0xc7 */ { NULL, NULL, 0 },
1093 /* 0xc8 */ { NULL, NULL, 0 },
1094 /* 0xc9 */ { NULL, NULL, 0 },
1095 /* 0xca */ { NULL, NULL, 0 },
1096 /* 0xcb */ { NULL, NULL, 0 },
1097 /* 0xcc */ { NULL, NULL, 0 },
1098 /* 0xcd */ { NULL, NULL, 0 },
1099 /* 0xce */ { NULL, NULL, 0 },
1100 /* 0xcf */ { NULL, NULL, 0 },
1101 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1102 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1103 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1104 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1105 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1106 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1107 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1108 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1109 /* 0xd8 */ { NULL, NULL, 0 },
1110 /* 0xd9 */ { NULL, NULL, 0 },
1111 /* 0xda */ { NULL, NULL, 0 },
1112 /* 0xdb */ { NULL, NULL, 0 },
1113 /* 0xdc */ { NULL, NULL, 0 },
1114 /* 0xdd */ { NULL, NULL, 0 },
1115 /* 0xde */ { NULL, NULL, 0 },
1116 /* 0xdf */ { NULL, NULL, 0 },
1117 /* 0xe0 */ { NULL, NULL, 0 },
1118 /* 0xe1 */ { NULL, NULL, 0 },
1119 /* 0xe2 */ { NULL, NULL, 0 },
1120 /* 0xe3 */ { NULL, NULL, 0 },
1121 /* 0xe4 */ { NULL, NULL, 0 },
1122 /* 0xe5 */ { NULL, NULL, 0 },
1123 /* 0xe6 */ { NULL, NULL, 0 },
1124 /* 0xe7 */ { NULL, NULL, 0 },
1125 /* 0xe8 */ { NULL, NULL, 0 },
1126 /* 0xe9 */ { NULL, NULL, 0 },
1127 /* 0xea */ { NULL, NULL, 0 },
1128 /* 0xeb */ { NULL, NULL, 0 },
1129 /* 0xec */ { NULL, NULL, 0 },
1130 /* 0xed */ { NULL, NULL, 0 },
1131 /* 0xee */ { NULL, NULL, 0 },
1132 /* 0xef */ { NULL, NULL, 0 },
1133 /* 0xf0 */ { NULL, NULL, 0 },
1134 /* 0xf1 */ { NULL, NULL, 0 },
1135 /* 0xf2 */ { NULL, NULL, 0 },
1136 /* 0xf3 */ { NULL, NULL, 0 },
1137 /* 0xf4 */ { NULL, NULL, 0 },
1138 /* 0xf5 */ { NULL, NULL, 0 },
1139 /* 0xf6 */ { NULL, NULL, 0 },
1140 /* 0xf7 */ { NULL, NULL, 0 },
1141 /* 0xf8 */ { NULL, NULL, 0 },
1142 /* 0xf9 */ { NULL, NULL, 0 },
1143 /* 0xfa */ { NULL, NULL, 0 },
1144 /* 0xfb */ { NULL, NULL, 0 },
1145 /* 0xfc */ { NULL, NULL, 0 },
1146 /* 0xfd */ { NULL, NULL, 0 },
1147 /* 0xfe */ { NULL, NULL, 0 },
1148 /* 0xff */ { NULL, NULL, 0 }
1152 /*******************************************************************
1153 allocate and initialize a reply packet
1154 ********************************************************************/
1156 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1157 const char *inbuf, char **outbuf, uint8_t num_words,
1158 uint32_t num_bytes)
1161 * Protect against integer wrap
1163 if ((num_bytes > 0xffffff)
1164 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1165 char *msg;
1166 if (asprintf(&msg, "num_bytes too large: %u",
1167 (unsigned)num_bytes) == -1) {
1168 msg = CONST_DISCARD(char *, "num_bytes too large");
1170 smb_panic(msg);
1173 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1174 smb_size + num_words*2 + num_bytes);
1175 if (*outbuf == NULL) {
1176 return false;
1179 construct_reply_common(req, inbuf, *outbuf);
1180 srv_set_message(*outbuf, num_words, num_bytes, false);
1182 * Zero out the word area, the caller has to take care of the bcc area
1183 * himself
1185 if (num_words != 0) {
1186 memset(*outbuf + smb_vwv0, 0, num_words*2);
1189 return true;
1192 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1194 char *outbuf;
1195 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1196 num_bytes)) {
1197 smb_panic("could not allocate output buffer\n");
1199 req->outbuf = (uint8_t *)outbuf;
1203 /*******************************************************************
1204 Dump a packet to a file.
1205 ********************************************************************/
1207 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1209 int fd, i;
1210 char *fname = NULL;
1211 if (DEBUGLEVEL < 50) {
1212 return;
1215 if (len < 4) len = smb_len(data)+4;
1216 for (i=1;i<100;i++) {
1217 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1218 type ? "req" : "resp") == -1) {
1219 return;
1221 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1222 if (fd != -1 || errno != EEXIST) break;
1224 if (fd != -1) {
1225 ssize_t ret = write(fd, data, len);
1226 if (ret != len)
1227 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1228 close(fd);
1229 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1231 SAFE_FREE(fname);
1234 /****************************************************************************
1235 Prepare everything for calling the actual request function, and potentially
1236 call the request function via the "new" interface.
1238 Return False if the "legacy" function needs to be called, everything is
1239 prepared.
1241 Return True if we're done.
1243 I know this API sucks, but it is the one with the least code change I could
1244 find.
1245 ****************************************************************************/
1247 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1249 int flags;
1250 uint16 session_tag;
1251 connection_struct *conn = NULL;
1252 struct smbd_server_connection *sconn = smbd_server_conn;
1254 errno = 0;
1256 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1257 * so subtract 4 from it. */
1258 if (!valid_smb_header(req->inbuf)
1259 || (size < (smb_size - 4))) {
1260 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1261 smb_len(req->inbuf)));
1262 exit_server_cleanly("Non-SMB packet");
1265 if (smb_messages[type].fn == NULL) {
1266 DEBUG(0,("Unknown message type %d!\n",type));
1267 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1268 reply_unknown_new(req, type);
1269 return NULL;
1272 flags = smb_messages[type].flags;
1274 /* In share mode security we must ignore the vuid. */
1275 session_tag = (lp_security() == SEC_SHARE)
1276 ? UID_FIELD_INVALID : req->vuid;
1277 conn = req->conn;
1279 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1280 (int)sys_getpid(), (unsigned long)conn));
1282 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1284 /* Ensure this value is replaced in the incoming packet. */
1285 SSVAL(req->inbuf,smb_uid,session_tag);
1288 * Ensure the correct username is in current_user_info. This is a
1289 * really ugly bugfix for problems with multiple session_setup_and_X's
1290 * being done and allowing %U and %G substitutions to work correctly.
1291 * There is a reason this code is done here, don't move it unless you
1292 * know what you're doing... :-).
1293 * JRA.
1296 if (session_tag != sconn->smb1.sessions.last_session_tag) {
1297 user_struct *vuser = NULL;
1299 sconn->smb1.sessions.last_session_tag = session_tag;
1300 if(session_tag != UID_FIELD_INVALID) {
1301 vuser = get_valid_user_struct(sconn, session_tag);
1302 if (vuser) {
1303 set_current_user_info(
1304 vuser->server_info->sanitized_username,
1305 vuser->server_info->unix_name,
1306 pdb_get_domain(vuser->server_info
1307 ->sam_account));
1312 /* Does this call need to be run as the connected user? */
1313 if (flags & AS_USER) {
1315 /* Does this call need a valid tree connection? */
1316 if (!conn) {
1318 * Amazingly, the error code depends on the command
1319 * (from Samba4).
1321 if (type == SMBntcreateX) {
1322 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1323 } else {
1324 reply_doserror(req, ERRSRV, ERRinvnid);
1326 return NULL;
1329 if (!change_to_user(conn,session_tag)) {
1330 DEBUG(0, ("Error: Could not change to user. Removing "
1331 "deferred open, mid=%d.\n", req->mid));
1332 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1333 return conn;
1336 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1338 /* Does it need write permission? */
1339 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1340 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1341 return conn;
1344 /* IPC services are limited */
1345 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1346 reply_doserror(req, ERRSRV,ERRaccess);
1347 return conn;
1349 } else {
1350 /* This call needs to be run as root */
1351 change_to_root_user();
1354 /* load service specific parameters */
1355 if (conn) {
1356 if (req->encrypted) {
1357 conn->encrypted_tid = true;
1358 /* encrypted required from now on. */
1359 conn->encrypt_level = Required;
1360 } else if (ENCRYPTION_REQUIRED(conn)) {
1361 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1362 exit_server_cleanly("encryption required "
1363 "on connection");
1364 return conn;
1368 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1369 (flags & (AS_USER|DO_CHDIR)
1370 ?True:False))) {
1371 reply_doserror(req, ERRSRV, ERRaccess);
1372 return conn;
1374 conn->num_smb_operations++;
1377 /* does this protocol need to be run as guest? */
1378 if ((flags & AS_GUEST)
1379 && (!change_to_guest() ||
1380 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1381 lp_hostsdeny(-1)))) {
1382 reply_doserror(req, ERRSRV, ERRaccess);
1383 return conn;
1386 smb_messages[type].fn(req);
1387 return req->conn;
1390 /****************************************************************************
1391 Construct a reply to the incoming packet.
1392 ****************************************************************************/
1394 static void construct_reply(char *inbuf, int size, size_t unread_bytes,
1395 uint32_t seqnum, bool encrypted,
1396 struct smb_perfcount_data *deferred_pcd)
1398 connection_struct *conn;
1399 struct smb_request *req;
1401 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1402 smb_panic("could not allocate smb_request");
1405 init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1406 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1407 req->seqnum = seqnum;
1409 /* we popped this message off the queue - keep original perf data */
1410 if (deferred_pcd)
1411 req->pcd = *deferred_pcd;
1412 else {
1413 SMB_PERFCOUNT_START(&req->pcd);
1414 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1415 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1418 conn = switch_message(req->cmd, req, size);
1420 if (req->unread_bytes) {
1421 /* writeX failed. drain socket. */
1422 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1423 req->unread_bytes) {
1424 smb_panic("failed to drain pending bytes");
1426 req->unread_bytes = 0;
1429 if (req->done) {
1430 TALLOC_FREE(req);
1431 return;
1434 if (req->outbuf == NULL) {
1435 return;
1438 if (CVAL(req->outbuf,0) == 0) {
1439 show_msg((char *)req->outbuf);
1442 if (!srv_send_smb(smbd_server_fd(),
1443 (char *)req->outbuf,
1444 true, req->seqnum+1,
1445 IS_CONN_ENCRYPTED(conn)||req->encrypted,
1446 &req->pcd)) {
1447 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1450 TALLOC_FREE(req);
1452 return;
1455 /****************************************************************************
1456 Process an smb from the client
1457 ****************************************************************************/
1458 static void process_smb(struct smbd_server_connection *conn,
1459 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1460 uint32_t seqnum, bool encrypted,
1461 struct smb_perfcount_data *deferred_pcd)
1463 int msg_type = CVAL(inbuf,0);
1465 DO_PROFILE_INC(smb_count);
1467 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1468 smb_len(inbuf) ) );
1469 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1470 (int)nread,
1471 (unsigned int)unread_bytes ));
1473 if (msg_type != 0) {
1475 * NetBIOS session request, keepalive, etc.
1477 reply_special((char *)inbuf);
1478 goto done;
1481 if (smbd_server_conn->allow_smb2) {
1482 if (smbd_is_smb2_header(inbuf, nread)) {
1483 smbd_smb2_first_negprot(smbd_server_conn, inbuf, nread);
1484 return;
1486 smbd_server_conn->allow_smb2 = false;
1489 show_msg((char *)inbuf);
1491 construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
1492 trans_num++;
1494 done:
1495 conn->smb1.num_requests++;
1497 /* The timeout_processing function isn't run nearly
1498 often enough to implement 'max log size' without
1499 overrunning the size of the file by many megabytes.
1500 This is especially true if we are running at debug
1501 level 10. Checking every 50 SMBs is a nice
1502 tradeoff of performance vs log file size overrun. */
1504 if ((conn->smb1.num_requests % 50) == 0 &&
1505 need_to_check_log_size()) {
1506 change_to_root_user();
1507 check_log_size();
1511 /****************************************************************************
1512 Return a string containing the function name of a SMB command.
1513 ****************************************************************************/
1515 const char *smb_fn_name(int type)
1517 const char *unknown_name = "SMBunknown";
1519 if (smb_messages[type].name == NULL)
1520 return(unknown_name);
1522 return(smb_messages[type].name);
1525 /****************************************************************************
1526 Helper functions for contruct_reply.
1527 ****************************************************************************/
1529 void add_to_common_flags2(uint32 v)
1531 common_flags2 |= v;
1534 void remove_from_common_flags2(uint32 v)
1536 common_flags2 &= ~v;
1539 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1540 char *outbuf)
1542 srv_set_message(outbuf,0,0,false);
1544 SCVAL(outbuf, smb_com, req->cmd);
1545 SIVAL(outbuf,smb_rcls,0);
1546 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1547 SSVAL(outbuf,smb_flg2,
1548 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1549 common_flags2);
1550 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1552 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1553 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1554 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1555 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1558 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1560 construct_reply_common(req, (char *)req->inbuf, outbuf);
1564 * How many bytes have we already accumulated up to the current wct field
1565 * offset?
1568 size_t req_wct_ofs(struct smb_request *req)
1570 size_t buf_size;
1572 if (req->chain_outbuf == NULL) {
1573 return smb_wct - 4;
1575 buf_size = talloc_get_size(req->chain_outbuf);
1576 if ((buf_size % 4) != 0) {
1577 buf_size += (4 - (buf_size % 4));
1579 return buf_size - 4;
1583 * Hack around reply_nterror & friends not being aware of chained requests,
1584 * generating illegal (i.e. wct==0) chain replies.
1587 static void fixup_chain_error_packet(struct smb_request *req)
1589 uint8_t *outbuf = req->outbuf;
1590 req->outbuf = NULL;
1591 reply_outbuf(req, 2, 0);
1592 memcpy(req->outbuf, outbuf, smb_wct);
1593 TALLOC_FREE(outbuf);
1594 SCVAL(req->outbuf, smb_vwv0, 0xff);
1597 /****************************************************************************
1598 Construct a chained reply and add it to the already made reply
1599 ****************************************************************************/
1601 void chain_reply(struct smb_request *req)
1603 size_t smblen = smb_len(req->inbuf);
1604 size_t already_used, length_needed;
1605 uint8_t chain_cmd;
1606 uint32_t chain_offset; /* uint32_t to avoid overflow */
1608 uint8_t wct;
1609 uint16_t *vwv;
1610 uint16_t buflen;
1611 uint8_t *buf;
1613 if (IVAL(req->outbuf, smb_rcls) != 0) {
1614 fixup_chain_error_packet(req);
1618 * Any of the AndX requests and replies have at least a wct of
1619 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1620 * beginning of the SMB header to the next wct field.
1622 * None of the AndX requests put anything valuable in vwv[0] and [1],
1623 * so we can overwrite it here to form the chain.
1626 if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1627 goto error;
1631 * Here we assume that this is the end of the chain. For that we need
1632 * to set "next command" to 0xff and the offset to 0. If we later find
1633 * more commands in the chain, this will be overwritten again.
1636 SCVAL(req->outbuf, smb_vwv0, 0xff);
1637 SCVAL(req->outbuf, smb_vwv0+1, 0);
1638 SSVAL(req->outbuf, smb_vwv1, 0);
1640 if (req->chain_outbuf == NULL) {
1642 * In req->chain_outbuf we collect all the replies. Start the
1643 * chain by copying in the first reply.
1645 * We do the realloc because later on we depend on
1646 * talloc_get_size to determine the length of
1647 * chain_outbuf. The reply_xxx routines might have
1648 * over-allocated (reply_pipe_read_and_X used to be such an
1649 * example).
1651 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
1652 req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
1653 if (req->chain_outbuf == NULL) {
1654 goto error;
1656 req->outbuf = NULL;
1657 } else {
1659 * Update smb headers where subsequent chained commands
1660 * may have updated them.
1662 SCVAL(req->chain_outbuf, smb_tid, CVAL(req->outbuf, smb_tid));
1663 SCVAL(req->chain_outbuf, smb_uid, CVAL(req->outbuf, smb_uid));
1665 if (!smb_splice_chain(&req->chain_outbuf,
1666 CVAL(req->outbuf, smb_com),
1667 CVAL(req->outbuf, smb_wct),
1668 (uint16_t *)(req->outbuf + smb_vwv),
1669 0, smb_buflen(req->outbuf),
1670 (uint8_t *)smb_buf(req->outbuf))) {
1671 goto error;
1673 TALLOC_FREE(req->outbuf);
1677 * We use the old request's vwv field to grab the next chained command
1678 * and offset into the chained fields.
1681 chain_cmd = CVAL(req->vwv+0, 0);
1682 chain_offset = SVAL(req->vwv+1, 0);
1684 if (chain_cmd == 0xff) {
1686 * End of chain, no more requests from the client. So ship the
1687 * replies.
1689 smb_setlen((char *)(req->chain_outbuf),
1690 talloc_get_size(req->chain_outbuf) - 4);
1692 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1693 true, req->seqnum+1,
1694 IS_CONN_ENCRYPTED(req->conn)
1695 ||req->encrypted,
1696 &req->pcd)) {
1697 exit_server_cleanly("chain_reply: srv_send_smb "
1698 "failed.");
1700 TALLOC_FREE(req->chain_outbuf);
1701 req->done = true;
1702 return;
1705 /* add a new perfcounter for this element of chain */
1706 SMB_PERFCOUNT_ADD(&req->pcd);
1707 SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
1708 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
1711 * Check if the client tries to fool us. The request so far uses the
1712 * space to the end of the byte buffer in the request just
1713 * processed. The chain_offset can't point into that area. If that was
1714 * the case, we could end up with an endless processing of the chain,
1715 * we would always handle the same request.
1718 already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1719 if (chain_offset < already_used) {
1720 goto error;
1724 * Next check: Make sure the chain offset does not point beyond the
1725 * overall smb request length.
1728 length_needed = chain_offset+1; /* wct */
1729 if (length_needed > smblen) {
1730 goto error;
1734 * Now comes the pointer magic. Goal here is to set up req->vwv and
1735 * req->buf correctly again to be able to call the subsequent
1736 * switch_message(). The chain offset (the former vwv[1]) points at
1737 * the new wct field.
1740 wct = CVAL(smb_base(req->inbuf), chain_offset);
1743 * Next consistency check: Make the new vwv array fits in the overall
1744 * smb request.
1747 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1748 if (length_needed > smblen) {
1749 goto error;
1751 vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1754 * Now grab the new byte buffer....
1757 buflen = SVAL(vwv+wct, 0);
1760 * .. and check that it fits.
1763 length_needed += buflen;
1764 if (length_needed > smblen) {
1765 goto error;
1767 buf = (uint8_t *)(vwv+wct+1);
1769 req->cmd = chain_cmd;
1770 req->wct = wct;
1771 req->vwv = vwv;
1772 req->buflen = buflen;
1773 req->buf = buf;
1775 switch_message(chain_cmd, req, smblen);
1777 if (req->outbuf == NULL) {
1779 * This happens if the chained command has suspended itself or
1780 * if it has called srv_send_smb() itself.
1782 return;
1786 * We end up here if the chained command was not itself chained or
1787 * suspended, but for example a close() command. We now need to splice
1788 * the chained commands' outbuf into the already built up chain_outbuf
1789 * and ship the result.
1791 goto done;
1793 error:
1795 * We end up here if there's any error in the chain syntax. Report a
1796 * DOS error, just like Windows does.
1798 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1799 fixup_chain_error_packet(req);
1801 done:
1803 * This scary statement intends to set the
1804 * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
1805 * to the value req->outbuf carries
1807 SSVAL(req->chain_outbuf, smb_flg2,
1808 (SVAL(req->chain_outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1809 | (SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1812 * Transfer the error codes from the subrequest to the main one
1814 SSVAL(req->chain_outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1815 SSVAL(req->chain_outbuf, smb_err, SVAL(req->outbuf, smb_err));
1817 if (!smb_splice_chain(&req->chain_outbuf,
1818 CVAL(req->outbuf, smb_com),
1819 CVAL(req->outbuf, smb_wct),
1820 (uint16_t *)(req->outbuf + smb_vwv),
1821 0, smb_buflen(req->outbuf),
1822 (uint8_t *)smb_buf(req->outbuf))) {
1823 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1825 TALLOC_FREE(req->outbuf);
1827 smb_setlen((char *)(req->chain_outbuf),
1828 talloc_get_size(req->chain_outbuf) - 4);
1830 show_msg((char *)(req->chain_outbuf));
1832 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1833 true, req->seqnum+1,
1834 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
1835 &req->pcd)) {
1836 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1838 TALLOC_FREE(req->chain_outbuf);
1839 req->done = true;
1842 /****************************************************************************
1843 Check if services need reloading.
1844 ****************************************************************************/
1846 void check_reload(time_t t)
1848 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1850 if(last_smb_conf_reload_time == 0) {
1851 last_smb_conf_reload_time = t;
1852 /* Our printing subsystem might not be ready at smbd start up.
1853 Then no printer is available till the first printers check
1854 is performed. A lower initial interval circumvents this. */
1855 if ( printcap_cache_time > 60 )
1856 last_printer_reload_time = t - printcap_cache_time + 60;
1857 else
1858 last_printer_reload_time = t;
1861 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1862 /* randomize over 60 second the printcap reload to avoid all
1863 * process hitting cupsd at the same time */
1864 int time_range = 60;
1866 last_printer_reload_time += random() % time_range;
1867 mypid = getpid();
1870 if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
1871 reload_services(True);
1872 last_smb_conf_reload_time = t;
1875 /* 'printcap cache time = 0' disable the feature */
1877 if ( printcap_cache_time != 0 )
1879 /* see if it's time to reload or if the clock has been set back */
1881 if ( (t >= last_printer_reload_time+printcap_cache_time)
1882 || (t-last_printer_reload_time < 0) )
1884 DEBUG( 3,( "Printcap cache time expired.\n"));
1885 reload_printers();
1886 last_printer_reload_time = t;
1891 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1893 /* TODO: make write nonblocking */
1896 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1898 uint8_t *inbuf = NULL;
1899 size_t inbuf_len = 0;
1900 size_t unread_bytes = 0;
1901 bool encrypted = false;
1902 TALLOC_CTX *mem_ctx = talloc_tos();
1903 NTSTATUS status;
1904 uint32_t seqnum;
1906 /* TODO: make this completely nonblocking */
1908 status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1909 (char **)(void *)&inbuf,
1910 0, /* timeout */
1911 &unread_bytes,
1912 &encrypted,
1913 &inbuf_len, &seqnum);
1914 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1915 goto process;
1917 if (NT_STATUS_IS_ERR(status)) {
1918 exit_server_cleanly("failed to receive smb request");
1920 if (!NT_STATUS_IS_OK(status)) {
1921 return;
1924 process:
1925 process_smb(conn, inbuf, inbuf_len, unread_bytes,
1926 seqnum, encrypted, NULL);
1929 static void smbd_server_connection_handler(struct event_context *ev,
1930 struct fd_event *fde,
1931 uint16_t flags,
1932 void *private_data)
1934 struct smbd_server_connection *conn = talloc_get_type(private_data,
1935 struct smbd_server_connection);
1937 if (flags & EVENT_FD_WRITE) {
1938 smbd_server_connection_write_handler(conn);
1939 } else if (flags & EVENT_FD_READ) {
1940 smbd_server_connection_read_handler(conn);
1945 /****************************************************************************
1946 received when we should release a specific IP
1947 ****************************************************************************/
1948 static void release_ip(const char *ip, void *priv)
1950 char addr[INET6_ADDRSTRLEN];
1951 char *p = addr;
1953 client_socket_addr(get_client_fd(),addr,sizeof(addr));
1955 if (strncmp("::ffff:", addr, 7) == 0) {
1956 p = addr + 7;
1959 if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
1960 /* we can't afford to do a clean exit - that involves
1961 database writes, which would potentially mean we
1962 are still running after the failover has finished -
1963 we have to get rid of this process ID straight
1964 away */
1965 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
1966 ip));
1967 /* note we must exit with non-zero status so the unclean handler gets
1968 called in the parent, so that the brl database is tickled */
1969 _exit(1);
1973 static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
1974 uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
1976 release_ip((char *)data->data, NULL);
1979 #ifdef CLUSTER_SUPPORT
1980 static int client_get_tcp_info(struct sockaddr_storage *server,
1981 struct sockaddr_storage *client)
1983 socklen_t length;
1984 if (server_fd == -1) {
1985 return -1;
1987 length = sizeof(*server);
1988 if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) {
1989 return -1;
1991 length = sizeof(*client);
1992 if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) {
1993 return -1;
1995 return 0;
1997 #endif
2000 * Send keepalive packets to our client
2002 static bool keepalive_fn(const struct timeval *now, void *private_data)
2004 if (!send_keepalive(smbd_server_fd())) {
2005 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
2006 return False;
2008 return True;
2012 * Do the recurring check if we're idle
2014 static bool deadtime_fn(const struct timeval *now, void *private_data)
2016 struct smbd_server_connection *sconn = smbd_server_conn;
2017 if ((conn_num_open(sconn) == 0)
2018 || (conn_idle_all(sconn, now->tv_sec))) {
2019 DEBUG( 2, ( "Closing idle connection\n" ) );
2020 messaging_send(smbd_messaging_context(), procid_self(),
2021 MSG_SHUTDOWN, &data_blob_null);
2022 return False;
2025 return True;
2029 * Do the recurring log file and smb.conf reload checks.
2032 static bool housekeeping_fn(const struct timeval *now, void *private_data)
2034 change_to_root_user();
2036 /* update printer queue caches if necessary */
2037 update_monitored_printq_cache();
2039 /* check if we need to reload services */
2040 check_reload(time(NULL));
2042 /* Change machine password if neccessary. */
2043 attempt_machine_password_change();
2046 * Force a log file check.
2048 force_check_log_size();
2049 check_log_size();
2050 return true;
2053 /****************************************************************************
2054 Process commands from the client
2055 ****************************************************************************/
2057 void smbd_process(void)
2059 TALLOC_CTX *frame = talloc_stackframe();
2060 char remaddr[INET6_ADDRSTRLEN];
2062 if (lp_maxprotocol() == PROTOCOL_SMB2 &&
2063 lp_security() != SEC_SHARE) {
2064 smbd_server_conn->allow_smb2 = true;
2067 /* Ensure child is set to blocking mode */
2068 set_blocking(smbd_server_fd(),True);
2070 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
2071 set_socket_options(smbd_server_fd(), lp_socket_options());
2073 /* this is needed so that we get decent entries
2074 in smbstatus for port 445 connects */
2075 set_remote_machine_name(get_peer_addr(smbd_server_fd(),
2076 remaddr,
2077 sizeof(remaddr)),
2078 false);
2079 reload_services(true);
2082 * Before the first packet, check the global hosts allow/ hosts deny
2083 * parameters before doing any parsing of packets passed to us by the
2084 * client. This prevents attacks on our parsing code from hosts not in
2085 * the hosts allow list.
2088 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
2089 lp_hostsdeny(-1))) {
2090 char addr[INET6_ADDRSTRLEN];
2093 * send a negative session response "not listening on calling
2094 * name"
2096 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2097 DEBUG( 1, ("Connection denied from %s\n",
2098 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
2099 (void)srv_send_smb(smbd_server_fd(),(char *)buf, false,
2100 0, false, NULL);
2101 exit_server_cleanly("connection denied");
2104 static_init_rpc;
2106 init_modules();
2108 smb_perfcount_init();
2110 if (!init_account_policy()) {
2111 exit_server("Could not open account policy tdb.\n");
2114 if (*lp_rootdir()) {
2115 if (chroot(lp_rootdir()) != 0) {
2116 DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
2117 exit_server("Failed to chroot()");
2119 if (chdir("/") == -1) {
2120 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
2121 exit_server("Failed to chroot()");
2123 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
2126 if (!srv_init_signing(smbd_server_conn)) {
2127 exit_server("Failed to init smb_signing");
2130 /* Setup oplocks */
2131 if (!init_oplocks(smbd_messaging_context()))
2132 exit_server("Failed to init oplocks");
2134 /* Setup aio signal handler. */
2135 initialize_async_io_handler();
2137 /* register our message handlers */
2138 messaging_register(smbd_messaging_context(), NULL,
2139 MSG_SMB_FORCE_TDIS, msg_force_tdis);
2140 messaging_register(smbd_messaging_context(), NULL,
2141 MSG_SMB_RELEASE_IP, msg_release_ip);
2142 messaging_register(smbd_messaging_context(), NULL,
2143 MSG_SMB_CLOSE_FILE, msg_close_file);
2146 * Use the default MSG_DEBUG handler to avoid rebroadcasting
2147 * MSGs to all child processes
2149 messaging_deregister(smbd_messaging_context(),
2150 MSG_DEBUG, NULL);
2151 messaging_register(smbd_messaging_context(), NULL,
2152 MSG_DEBUG, debug_message);
2154 if ((lp_keepalive() != 0)
2155 && !(event_add_idle(smbd_event_context(), NULL,
2156 timeval_set(lp_keepalive(), 0),
2157 "keepalive", keepalive_fn,
2158 NULL))) {
2159 DEBUG(0, ("Could not add keepalive event\n"));
2160 exit(1);
2163 if (!(event_add_idle(smbd_event_context(), NULL,
2164 timeval_set(IDLE_CLOSED_TIMEOUT, 0),
2165 "deadtime", deadtime_fn, NULL))) {
2166 DEBUG(0, ("Could not add deadtime event\n"));
2167 exit(1);
2170 if (!(event_add_idle(smbd_event_context(), NULL,
2171 timeval_set(SMBD_SELECT_TIMEOUT, 0),
2172 "housekeeping", housekeeping_fn, NULL))) {
2173 DEBUG(0, ("Could not add housekeeping event\n"));
2174 exit(1);
2177 #ifdef CLUSTER_SUPPORT
2179 if (lp_clustering()) {
2181 * We need to tell ctdb about our client's TCP
2182 * connection, so that for failover ctdbd can send
2183 * tickle acks, triggering a reconnection by the
2184 * client.
2187 struct sockaddr_storage srv, clnt;
2189 if (client_get_tcp_info(&srv, &clnt) == 0) {
2191 NTSTATUS status;
2193 status = ctdbd_register_ips(
2194 messaging_ctdbd_connection(),
2195 &srv, &clnt, release_ip, NULL);
2197 if (!NT_STATUS_IS_OK(status)) {
2198 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
2199 nt_errstr(status)));
2201 } else
2203 DEBUG(0,("Unable to get tcp info for "
2204 "CTDB_CONTROL_TCP_CLIENT: %s\n",
2205 strerror(errno)));
2209 #endif
2211 smbd_server_conn->nbt.got_session = false;
2213 smbd_server_conn->smb1.negprot.max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
2215 smbd_server_conn->smb1.sessions.done_sesssetup = false;
2216 smbd_server_conn->smb1.sessions.max_send = BUFFER_SIZE;
2217 smbd_server_conn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
2218 /* users from session setup */
2219 smbd_server_conn->smb1.sessions.session_userlist = NULL;
2220 /* workgroup from session setup. */
2221 smbd_server_conn->smb1.sessions.session_workgroup = NULL;
2222 /* this holds info on user ids that are already validated for this VC */
2223 smbd_server_conn->smb1.sessions.validated_users = NULL;
2224 smbd_server_conn->smb1.sessions.next_vuid = VUID_OFFSET;
2225 smbd_server_conn->smb1.sessions.num_validated_vuids = 0;
2226 #ifdef HAVE_NETGROUP
2227 smbd_server_conn->smb1.sessions.my_yp_domain = NULL;
2228 #endif
2230 conn_init(smbd_server_conn);
2231 if (!init_dptrs(smbd_server_conn)) {
2232 exit_server("init_dptrs() failed");
2235 smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(),
2236 smbd_server_conn,
2237 smbd_server_fd(),
2238 EVENT_FD_READ,
2239 smbd_server_connection_handler,
2240 smbd_server_conn);
2241 if (!smbd_server_conn->smb1.fde) {
2242 exit_server("failed to create smbd_server_connection fde");
2245 TALLOC_FREE(frame);
2247 while (True) {
2248 NTSTATUS status;
2250 frame = talloc_stackframe_pool(8192);
2252 errno = 0;
2254 status = smbd_server_connection_loop_once(smbd_server_conn);
2255 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2256 !NT_STATUS_IS_OK(status)) {
2257 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2258 " exiting\n", nt_errstr(status)));
2259 break;
2262 TALLOC_FREE(frame);
2265 exit_server_cleanly(NULL);
2268 bool req_is_in_chain(struct smb_request *req)
2270 if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) {
2272 * We're right now handling a subsequent request, so we must
2273 * be in a chain
2275 return true;
2278 if (!is_andx_req(req->cmd)) {
2279 return false;
2282 if (req->wct < 2) {
2284 * Okay, an illegal request, but definitely not chained :-)
2286 return false;
2289 return (CVAL(req->vwv+0, 0) != 0xFF);