s3/docs: Fix typo.
[Samba/gebeck_regimport.git] / source3 / smbd / process.c
blob0a3777afe0bb74225e56a1fc16f86ca8a244c415
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_socket_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_socket_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 smb_init_perfcount_data(&req->pcd);
386 /* Ensure we have at least wct words and 2 bytes of bcc. */
387 if (smb_size + req->wct*2 > req_size) {
388 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
389 (unsigned int)req->wct,
390 (unsigned int)req_size));
391 exit_server_cleanly("Invalid SMB request");
393 /* Ensure bcc is correct. */
394 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
395 DEBUG(0,("init_smb_request: invalid bcc number %u "
396 "(wct = %u, size %u)\n",
397 (unsigned int)req->buflen,
398 (unsigned int)req->wct,
399 (unsigned int)req_size));
400 exit_server_cleanly("Invalid SMB request");
403 req->outbuf = NULL;
406 static void process_smb(struct smbd_server_connection *conn,
407 uint8_t *inbuf, size_t nread, size_t unread_bytes,
408 uint32_t seqnum, bool encrypted,
409 struct smb_perfcount_data *deferred_pcd);
411 static void smbd_deferred_open_timer(struct event_context *ev,
412 struct timed_event *te,
413 struct timeval _tval,
414 void *private_data)
416 struct pending_message_list *msg = talloc_get_type(private_data,
417 struct pending_message_list);
418 TALLOC_CTX *mem_ctx = talloc_tos();
419 uint8_t *inbuf;
421 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
422 msg->buf.length);
423 if (inbuf == NULL) {
424 exit_server("smbd_deferred_open_timer: talloc failed\n");
425 return;
428 /* We leave this message on the queue so the open code can
429 know this is a retry. */
430 DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
431 (unsigned int)SVAL(msg->buf.data,smb_mid)));
433 process_smb(smbd_server_conn, inbuf,
434 msg->buf.length, 0,
435 msg->seqnum, msg->encrypted, &msg->pcd);
438 /****************************************************************************
439 Function to push a message onto the tail of a linked list of smb messages ready
440 for processing.
441 ****************************************************************************/
443 static bool push_queued_message(struct smb_request *req,
444 struct timeval request_time,
445 struct timeval end_time,
446 char *private_data, size_t private_len)
448 int msg_len = smb_len(req->inbuf) + 4;
449 struct pending_message_list *msg;
451 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
453 if(msg == NULL) {
454 DEBUG(0,("push_message: malloc fail (1)\n"));
455 return False;
458 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
459 if(msg->buf.data == NULL) {
460 DEBUG(0,("push_message: malloc fail (2)\n"));
461 TALLOC_FREE(msg);
462 return False;
465 msg->request_time = request_time;
466 msg->seqnum = req->seqnum;
467 msg->encrypted = req->encrypted;
468 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
470 if (private_data) {
471 msg->private_data = data_blob_talloc(msg, private_data,
472 private_len);
473 if (msg->private_data.data == NULL) {
474 DEBUG(0,("push_message: malloc fail (3)\n"));
475 TALLOC_FREE(msg);
476 return False;
480 msg->te = event_add_timed(smbd_event_context(),
481 msg,
482 end_time,
483 smbd_deferred_open_timer,
484 msg);
485 if (!msg->te) {
486 DEBUG(0,("push_message: event_add_timed failed\n"));
487 TALLOC_FREE(msg);
488 return false;
491 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
493 DEBUG(10,("push_message: pushed message length %u on "
494 "deferred_open_queue\n", (unsigned int)msg_len));
496 return True;
499 /****************************************************************************
500 Function to delete a sharing violation open message by mid.
501 ****************************************************************************/
503 void remove_deferred_open_smb_message(uint16 mid)
505 struct pending_message_list *pml;
507 for (pml = deferred_open_queue; pml; pml = pml->next) {
508 if (mid == SVAL(pml->buf.data,smb_mid)) {
509 DEBUG(10,("remove_sharing_violation_open_smb_message: "
510 "deleting mid %u len %u\n",
511 (unsigned int)mid,
512 (unsigned int)pml->buf.length ));
513 DLIST_REMOVE(deferred_open_queue, pml);
514 TALLOC_FREE(pml);
515 return;
520 /****************************************************************************
521 Move a sharing violation open retry message to the front of the list and
522 schedule it for immediate processing.
523 ****************************************************************************/
525 void schedule_deferred_open_smb_message(uint16 mid)
527 struct pending_message_list *pml;
528 int i = 0;
530 for (pml = deferred_open_queue; pml; pml = pml->next) {
531 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
533 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
534 (unsigned int)msg_mid ));
536 if (mid == msg_mid) {
537 struct timed_event *te;
539 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
540 mid ));
542 te = event_add_timed(smbd_event_context(),
543 pml,
544 timeval_zero(),
545 smbd_deferred_open_timer,
546 pml);
547 if (!te) {
548 DEBUG(10,("schedule_deferred_open_smb_message: "
549 "event_add_timed() failed, skipping mid %u\n",
550 mid ));
553 TALLOC_FREE(pml->te);
554 pml->te = te;
555 DLIST_PROMOTE(deferred_open_queue, pml);
556 return;
560 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
561 mid ));
564 /****************************************************************************
565 Return true if this mid is on the deferred queue.
566 ****************************************************************************/
568 bool open_was_deferred(uint16 mid)
570 struct pending_message_list *pml;
572 for (pml = deferred_open_queue; pml; pml = pml->next) {
573 if (SVAL(pml->buf.data,smb_mid) == mid) {
574 return True;
577 return False;
580 /****************************************************************************
581 Return the message queued by this mid.
582 ****************************************************************************/
584 struct pending_message_list *get_open_deferred_message(uint16 mid)
586 struct pending_message_list *pml;
588 for (pml = deferred_open_queue; pml; pml = pml->next) {
589 if (SVAL(pml->buf.data,smb_mid) == mid) {
590 return pml;
593 return NULL;
596 /****************************************************************************
597 Function to push a deferred open smb message onto a linked list of local smb
598 messages ready for processing.
599 ****************************************************************************/
601 bool push_deferred_smb_message(struct smb_request *req,
602 struct timeval request_time,
603 struct timeval timeout,
604 char *private_data, size_t priv_len)
606 struct timeval end_time;
608 if (req->unread_bytes) {
609 DEBUG(0,("push_deferred_smb_message: logic error ! "
610 "unread_bytes = %u\n",
611 (unsigned int)req->unread_bytes ));
612 smb_panic("push_deferred_smb_message: "
613 "logic error unread_bytes != 0" );
616 end_time = timeval_sum(&request_time, &timeout);
618 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
619 "timeout time [%u.%06u]\n",
620 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
621 (unsigned int)end_time.tv_sec,
622 (unsigned int)end_time.tv_usec));
624 return push_queued_message(req, request_time, end_time,
625 private_data, priv_len);
628 struct idle_event {
629 struct timed_event *te;
630 struct timeval interval;
631 char *name;
632 bool (*handler)(const struct timeval *now, void *private_data);
633 void *private_data;
636 static void smbd_idle_event_handler(struct event_context *ctx,
637 struct timed_event *te,
638 struct timeval now,
639 void *private_data)
641 struct idle_event *event =
642 talloc_get_type_abort(private_data, struct idle_event);
644 TALLOC_FREE(event->te);
646 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
647 event->name, event->te));
649 if (!event->handler(&now, event->private_data)) {
650 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
651 event->name, event->te));
652 /* Don't repeat, delete ourselves */
653 TALLOC_FREE(event);
654 return;
657 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
658 event->name, event->te));
660 event->te = event_add_timed(ctx, event,
661 timeval_sum(&now, &event->interval),
662 smbd_idle_event_handler, event);
664 /* We can't do much but fail here. */
665 SMB_ASSERT(event->te != NULL);
668 struct idle_event *event_add_idle(struct event_context *event_ctx,
669 TALLOC_CTX *mem_ctx,
670 struct timeval interval,
671 const char *name,
672 bool (*handler)(const struct timeval *now,
673 void *private_data),
674 void *private_data)
676 struct idle_event *result;
677 struct timeval now = timeval_current();
679 result = TALLOC_P(mem_ctx, struct idle_event);
680 if (result == NULL) {
681 DEBUG(0, ("talloc failed\n"));
682 return NULL;
685 result->interval = interval;
686 result->handler = handler;
687 result->private_data = private_data;
689 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
690 DEBUG(0, ("talloc failed\n"));
691 TALLOC_FREE(result);
692 return NULL;
695 result->te = event_add_timed(event_ctx, result,
696 timeval_sum(&now, &interval),
697 smbd_idle_event_handler, result);
698 if (result->te == NULL) {
699 DEBUG(0, ("event_add_timed failed\n"));
700 TALLOC_FREE(result);
701 return NULL;
704 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
705 return result;
708 static void smbd_sig_term_handler(struct tevent_context *ev,
709 struct tevent_signal *se,
710 int signum,
711 int count,
712 void *siginfo,
713 void *private_data)
715 exit_server_cleanly("termination signal");
718 void smbd_setup_sig_term_handler(void)
720 struct tevent_signal *se;
722 se = tevent_add_signal(smbd_event_context(),
723 smbd_event_context(),
724 SIGTERM, 0,
725 smbd_sig_term_handler,
726 NULL);
727 if (!se) {
728 exit_server("failed to setup SIGTERM handler");
732 static void smbd_sig_hup_handler(struct tevent_context *ev,
733 struct tevent_signal *se,
734 int signum,
735 int count,
736 void *siginfo,
737 void *private_data)
739 change_to_root_user();
740 DEBUG(1,("Reloading services after SIGHUP\n"));
741 reload_services(False);
744 void smbd_setup_sig_hup_handler(void)
746 struct tevent_signal *se;
748 se = tevent_add_signal(smbd_event_context(),
749 smbd_event_context(),
750 SIGHUP, 0,
751 smbd_sig_hup_handler,
752 NULL);
753 if (!se) {
754 exit_server("failed to setup SIGHUP handler");
758 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
760 fd_set r_fds, w_fds;
761 int selrtn;
762 struct timeval to;
763 int maxfd = 0;
765 to.tv_sec = SMBD_SELECT_TIMEOUT;
766 to.tv_usec = 0;
769 * Setup the select fd sets.
772 FD_ZERO(&r_fds);
773 FD_ZERO(&w_fds);
776 * Are there any timed events waiting ? If so, ensure we don't
777 * select for longer than it would take to wait for them.
781 struct timeval now;
782 GetTimeOfDay(&now);
784 event_add_to_select_args(smbd_event_context(), &now,
785 &r_fds, &w_fds, &to, &maxfd);
788 /* Process a signal and timed events now... */
789 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
790 return NT_STATUS_RETRY;
794 int sav;
795 START_PROFILE(smbd_idle);
797 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
798 sav = errno;
800 END_PROFILE(smbd_idle);
801 errno = sav;
804 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
805 return NT_STATUS_RETRY;
808 /* Check if error */
809 if (selrtn == -1) {
810 /* something is wrong. Maybe the socket is dead? */
811 return map_nt_error_from_unix(errno);
814 /* Did we timeout ? */
815 if (selrtn == 0) {
816 return NT_STATUS_RETRY;
819 /* should not be reached */
820 return NT_STATUS_INTERNAL_ERROR;
824 * Only allow 5 outstanding trans requests. We're allocating memory, so
825 * prevent a DoS.
828 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
830 int count = 0;
831 for (; list != NULL; list = list->next) {
833 if (list->mid == mid) {
834 return NT_STATUS_INVALID_PARAMETER;
837 count += 1;
839 if (count > 5) {
840 return NT_STATUS_INSUFFICIENT_RESOURCES;
843 return NT_STATUS_OK;
847 These flags determine some of the permissions required to do an operation
849 Note that I don't set NEED_WRITE on some write operations because they
850 are used by some brain-dead clients when printing, and I don't want to
851 force write permissions on print services.
853 #define AS_USER (1<<0)
854 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
855 #define TIME_INIT (1<<2)
856 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
857 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
858 #define DO_CHDIR (1<<6)
861 define a list of possible SMB messages and their corresponding
862 functions. Any message that has a NULL function is unimplemented -
863 please feel free to contribute implementations!
865 static const struct smb_message_struct {
866 const char *name;
867 void (*fn)(struct smb_request *req);
868 int flags;
869 } smb_messages[256] = {
871 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
872 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
873 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
874 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
875 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
876 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
877 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
878 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
879 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
880 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
881 /* 0x0a */ { "SMBread",reply_read,AS_USER},
882 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
883 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
884 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
885 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
886 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
887 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
888 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
889 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
890 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
891 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
892 /* 0x15 */ { NULL, NULL, 0 },
893 /* 0x16 */ { NULL, NULL, 0 },
894 /* 0x17 */ { NULL, NULL, 0 },
895 /* 0x18 */ { NULL, NULL, 0 },
896 /* 0x19 */ { NULL, NULL, 0 },
897 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
898 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
899 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
900 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
901 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
902 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
903 /* 0x20 */ { "SMBwritec", NULL,0},
904 /* 0x21 */ { NULL, NULL, 0 },
905 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
906 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
907 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
908 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
909 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
910 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
911 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
912 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
913 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
914 /* 0x2b */ { "SMBecho",reply_echo,0},
915 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
916 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
917 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
918 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
919 /* 0x30 */ { NULL, NULL, 0 },
920 /* 0x31 */ { NULL, NULL, 0 },
921 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
922 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
923 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
924 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
925 /* 0x36 */ { NULL, NULL, 0 },
926 /* 0x37 */ { NULL, NULL, 0 },
927 /* 0x38 */ { NULL, NULL, 0 },
928 /* 0x39 */ { NULL, NULL, 0 },
929 /* 0x3a */ { NULL, NULL, 0 },
930 /* 0x3b */ { NULL, NULL, 0 },
931 /* 0x3c */ { NULL, NULL, 0 },
932 /* 0x3d */ { NULL, NULL, 0 },
933 /* 0x3e */ { NULL, NULL, 0 },
934 /* 0x3f */ { NULL, NULL, 0 },
935 /* 0x40 */ { NULL, NULL, 0 },
936 /* 0x41 */ { NULL, NULL, 0 },
937 /* 0x42 */ { NULL, NULL, 0 },
938 /* 0x43 */ { NULL, NULL, 0 },
939 /* 0x44 */ { NULL, NULL, 0 },
940 /* 0x45 */ { NULL, NULL, 0 },
941 /* 0x46 */ { NULL, NULL, 0 },
942 /* 0x47 */ { NULL, NULL, 0 },
943 /* 0x48 */ { NULL, NULL, 0 },
944 /* 0x49 */ { NULL, NULL, 0 },
945 /* 0x4a */ { NULL, NULL, 0 },
946 /* 0x4b */ { NULL, NULL, 0 },
947 /* 0x4c */ { NULL, NULL, 0 },
948 /* 0x4d */ { NULL, NULL, 0 },
949 /* 0x4e */ { NULL, NULL, 0 },
950 /* 0x4f */ { NULL, NULL, 0 },
951 /* 0x50 */ { NULL, NULL, 0 },
952 /* 0x51 */ { NULL, NULL, 0 },
953 /* 0x52 */ { NULL, NULL, 0 },
954 /* 0x53 */ { NULL, NULL, 0 },
955 /* 0x54 */ { NULL, NULL, 0 },
956 /* 0x55 */ { NULL, NULL, 0 },
957 /* 0x56 */ { NULL, NULL, 0 },
958 /* 0x57 */ { NULL, NULL, 0 },
959 /* 0x58 */ { NULL, NULL, 0 },
960 /* 0x59 */ { NULL, NULL, 0 },
961 /* 0x5a */ { NULL, NULL, 0 },
962 /* 0x5b */ { NULL, NULL, 0 },
963 /* 0x5c */ { NULL, NULL, 0 },
964 /* 0x5d */ { NULL, NULL, 0 },
965 /* 0x5e */ { NULL, NULL, 0 },
966 /* 0x5f */ { NULL, NULL, 0 },
967 /* 0x60 */ { NULL, NULL, 0 },
968 /* 0x61 */ { NULL, NULL, 0 },
969 /* 0x62 */ { NULL, NULL, 0 },
970 /* 0x63 */ { NULL, NULL, 0 },
971 /* 0x64 */ { NULL, NULL, 0 },
972 /* 0x65 */ { NULL, NULL, 0 },
973 /* 0x66 */ { NULL, NULL, 0 },
974 /* 0x67 */ { NULL, NULL, 0 },
975 /* 0x68 */ { NULL, NULL, 0 },
976 /* 0x69 */ { NULL, NULL, 0 },
977 /* 0x6a */ { NULL, NULL, 0 },
978 /* 0x6b */ { NULL, NULL, 0 },
979 /* 0x6c */ { NULL, NULL, 0 },
980 /* 0x6d */ { NULL, NULL, 0 },
981 /* 0x6e */ { NULL, NULL, 0 },
982 /* 0x6f */ { NULL, NULL, 0 },
983 /* 0x70 */ { "SMBtcon",reply_tcon,0},
984 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
985 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
986 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
987 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
988 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
989 /* 0x76 */ { NULL, NULL, 0 },
990 /* 0x77 */ { NULL, NULL, 0 },
991 /* 0x78 */ { NULL, NULL, 0 },
992 /* 0x79 */ { NULL, NULL, 0 },
993 /* 0x7a */ { NULL, NULL, 0 },
994 /* 0x7b */ { NULL, NULL, 0 },
995 /* 0x7c */ { NULL, NULL, 0 },
996 /* 0x7d */ { NULL, NULL, 0 },
997 /* 0x7e */ { NULL, NULL, 0 },
998 /* 0x7f */ { NULL, NULL, 0 },
999 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1000 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1001 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1002 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1003 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1004 /* 0x85 */ { NULL, NULL, 0 },
1005 /* 0x86 */ { NULL, NULL, 0 },
1006 /* 0x87 */ { NULL, NULL, 0 },
1007 /* 0x88 */ { NULL, NULL, 0 },
1008 /* 0x89 */ { NULL, NULL, 0 },
1009 /* 0x8a */ { NULL, NULL, 0 },
1010 /* 0x8b */ { NULL, NULL, 0 },
1011 /* 0x8c */ { NULL, NULL, 0 },
1012 /* 0x8d */ { NULL, NULL, 0 },
1013 /* 0x8e */ { NULL, NULL, 0 },
1014 /* 0x8f */ { NULL, NULL, 0 },
1015 /* 0x90 */ { NULL, NULL, 0 },
1016 /* 0x91 */ { NULL, NULL, 0 },
1017 /* 0x92 */ { NULL, NULL, 0 },
1018 /* 0x93 */ { NULL, NULL, 0 },
1019 /* 0x94 */ { NULL, NULL, 0 },
1020 /* 0x95 */ { NULL, NULL, 0 },
1021 /* 0x96 */ { NULL, NULL, 0 },
1022 /* 0x97 */ { NULL, NULL, 0 },
1023 /* 0x98 */ { NULL, NULL, 0 },
1024 /* 0x99 */ { NULL, NULL, 0 },
1025 /* 0x9a */ { NULL, NULL, 0 },
1026 /* 0x9b */ { NULL, NULL, 0 },
1027 /* 0x9c */ { NULL, NULL, 0 },
1028 /* 0x9d */ { NULL, NULL, 0 },
1029 /* 0x9e */ { NULL, NULL, 0 },
1030 /* 0x9f */ { NULL, NULL, 0 },
1031 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1032 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1033 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1034 /* 0xa3 */ { NULL, NULL, 0 },
1035 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1036 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1037 /* 0xa6 */ { NULL, NULL, 0 },
1038 /* 0xa7 */ { NULL, NULL, 0 },
1039 /* 0xa8 */ { NULL, NULL, 0 },
1040 /* 0xa9 */ { NULL, NULL, 0 },
1041 /* 0xaa */ { NULL, NULL, 0 },
1042 /* 0xab */ { NULL, NULL, 0 },
1043 /* 0xac */ { NULL, NULL, 0 },
1044 /* 0xad */ { NULL, NULL, 0 },
1045 /* 0xae */ { NULL, NULL, 0 },
1046 /* 0xaf */ { NULL, NULL, 0 },
1047 /* 0xb0 */ { NULL, NULL, 0 },
1048 /* 0xb1 */ { NULL, NULL, 0 },
1049 /* 0xb2 */ { NULL, NULL, 0 },
1050 /* 0xb3 */ { NULL, NULL, 0 },
1051 /* 0xb4 */ { NULL, NULL, 0 },
1052 /* 0xb5 */ { NULL, NULL, 0 },
1053 /* 0xb6 */ { NULL, NULL, 0 },
1054 /* 0xb7 */ { NULL, NULL, 0 },
1055 /* 0xb8 */ { NULL, NULL, 0 },
1056 /* 0xb9 */ { NULL, NULL, 0 },
1057 /* 0xba */ { NULL, NULL, 0 },
1058 /* 0xbb */ { NULL, NULL, 0 },
1059 /* 0xbc */ { NULL, NULL, 0 },
1060 /* 0xbd */ { NULL, NULL, 0 },
1061 /* 0xbe */ { NULL, NULL, 0 },
1062 /* 0xbf */ { NULL, NULL, 0 },
1063 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1064 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1065 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1066 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1067 /* 0xc4 */ { NULL, NULL, 0 },
1068 /* 0xc5 */ { NULL, NULL, 0 },
1069 /* 0xc6 */ { NULL, NULL, 0 },
1070 /* 0xc7 */ { NULL, NULL, 0 },
1071 /* 0xc8 */ { NULL, NULL, 0 },
1072 /* 0xc9 */ { NULL, NULL, 0 },
1073 /* 0xca */ { NULL, NULL, 0 },
1074 /* 0xcb */ { NULL, NULL, 0 },
1075 /* 0xcc */ { NULL, NULL, 0 },
1076 /* 0xcd */ { NULL, NULL, 0 },
1077 /* 0xce */ { NULL, NULL, 0 },
1078 /* 0xcf */ { NULL, NULL, 0 },
1079 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1080 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1081 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1082 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1083 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1084 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1085 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1086 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1087 /* 0xd8 */ { NULL, NULL, 0 },
1088 /* 0xd9 */ { NULL, NULL, 0 },
1089 /* 0xda */ { NULL, NULL, 0 },
1090 /* 0xdb */ { NULL, NULL, 0 },
1091 /* 0xdc */ { NULL, NULL, 0 },
1092 /* 0xdd */ { NULL, NULL, 0 },
1093 /* 0xde */ { NULL, NULL, 0 },
1094 /* 0xdf */ { NULL, NULL, 0 },
1095 /* 0xe0 */ { NULL, NULL, 0 },
1096 /* 0xe1 */ { NULL, NULL, 0 },
1097 /* 0xe2 */ { NULL, NULL, 0 },
1098 /* 0xe3 */ { NULL, NULL, 0 },
1099 /* 0xe4 */ { NULL, NULL, 0 },
1100 /* 0xe5 */ { NULL, NULL, 0 },
1101 /* 0xe6 */ { NULL, NULL, 0 },
1102 /* 0xe7 */ { NULL, NULL, 0 },
1103 /* 0xe8 */ { NULL, NULL, 0 },
1104 /* 0xe9 */ { NULL, NULL, 0 },
1105 /* 0xea */ { NULL, NULL, 0 },
1106 /* 0xeb */ { NULL, NULL, 0 },
1107 /* 0xec */ { NULL, NULL, 0 },
1108 /* 0xed */ { NULL, NULL, 0 },
1109 /* 0xee */ { NULL, NULL, 0 },
1110 /* 0xef */ { NULL, NULL, 0 },
1111 /* 0xf0 */ { NULL, NULL, 0 },
1112 /* 0xf1 */ { NULL, NULL, 0 },
1113 /* 0xf2 */ { NULL, NULL, 0 },
1114 /* 0xf3 */ { NULL, NULL, 0 },
1115 /* 0xf4 */ { NULL, NULL, 0 },
1116 /* 0xf5 */ { NULL, NULL, 0 },
1117 /* 0xf6 */ { NULL, NULL, 0 },
1118 /* 0xf7 */ { NULL, NULL, 0 },
1119 /* 0xf8 */ { NULL, NULL, 0 },
1120 /* 0xf9 */ { NULL, NULL, 0 },
1121 /* 0xfa */ { NULL, NULL, 0 },
1122 /* 0xfb */ { NULL, NULL, 0 },
1123 /* 0xfc */ { NULL, NULL, 0 },
1124 /* 0xfd */ { NULL, NULL, 0 },
1125 /* 0xfe */ { NULL, NULL, 0 },
1126 /* 0xff */ { NULL, NULL, 0 }
1130 /*******************************************************************
1131 allocate and initialize a reply packet
1132 ********************************************************************/
1134 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1135 const char *inbuf, char **outbuf, uint8_t num_words,
1136 uint32_t num_bytes)
1139 * Protect against integer wrap
1141 if ((num_bytes > 0xffffff)
1142 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1143 char *msg;
1144 if (asprintf(&msg, "num_bytes too large: %u",
1145 (unsigned)num_bytes) == -1) {
1146 msg = CONST_DISCARD(char *, "num_bytes too large");
1148 smb_panic(msg);
1151 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1152 smb_size + num_words*2 + num_bytes);
1153 if (*outbuf == NULL) {
1154 return false;
1157 construct_reply_common(req, inbuf, *outbuf);
1158 srv_set_message(*outbuf, num_words, num_bytes, false);
1160 * Zero out the word area, the caller has to take care of the bcc area
1161 * himself
1163 if (num_words != 0) {
1164 memset(*outbuf + smb_vwv0, 0, num_words*2);
1167 return true;
1170 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1172 char *outbuf;
1173 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1174 num_bytes)) {
1175 smb_panic("could not allocate output buffer\n");
1177 req->outbuf = (uint8_t *)outbuf;
1181 /*******************************************************************
1182 Dump a packet to a file.
1183 ********************************************************************/
1185 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1187 int fd, i;
1188 char *fname = NULL;
1189 if (DEBUGLEVEL < 50) {
1190 return;
1193 if (len < 4) len = smb_len(data)+4;
1194 for (i=1;i<100;i++) {
1195 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1196 type ? "req" : "resp") == -1) {
1197 return;
1199 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1200 if (fd != -1 || errno != EEXIST) break;
1202 if (fd != -1) {
1203 ssize_t ret = write(fd, data, len);
1204 if (ret != len)
1205 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1206 close(fd);
1207 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1209 SAFE_FREE(fname);
1212 /****************************************************************************
1213 Prepare everything for calling the actual request function, and potentially
1214 call the request function via the "new" interface.
1216 Return False if the "legacy" function needs to be called, everything is
1217 prepared.
1219 Return True if we're done.
1221 I know this API sucks, but it is the one with the least code change I could
1222 find.
1223 ****************************************************************************/
1225 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1227 int flags;
1228 uint16 session_tag;
1229 connection_struct *conn = NULL;
1230 struct smbd_server_connection *sconn = smbd_server_conn;
1232 errno = 0;
1234 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1235 * so subtract 4 from it. */
1236 if (!valid_smb_header(req->inbuf)
1237 || (size < (smb_size - 4))) {
1238 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1239 smb_len(req->inbuf)));
1240 exit_server_cleanly("Non-SMB packet");
1243 if (smb_messages[type].fn == NULL) {
1244 DEBUG(0,("Unknown message type %d!\n",type));
1245 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1246 reply_unknown_new(req, type);
1247 return NULL;
1250 flags = smb_messages[type].flags;
1252 /* In share mode security we must ignore the vuid. */
1253 session_tag = (lp_security() == SEC_SHARE)
1254 ? UID_FIELD_INVALID : req->vuid;
1255 conn = req->conn;
1257 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1258 (int)sys_getpid(), (unsigned long)conn));
1260 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1262 /* Ensure this value is replaced in the incoming packet. */
1263 SSVAL(req->inbuf,smb_uid,session_tag);
1266 * Ensure the correct username is in current_user_info. This is a
1267 * really ugly bugfix for problems with multiple session_setup_and_X's
1268 * being done and allowing %U and %G substitutions to work correctly.
1269 * There is a reason this code is done here, don't move it unless you
1270 * know what you're doing... :-).
1271 * JRA.
1274 if (session_tag != sconn->smb1.sessions.last_session_tag) {
1275 user_struct *vuser = NULL;
1277 sconn->smb1.sessions.last_session_tag = session_tag;
1278 if(session_tag != UID_FIELD_INVALID) {
1279 vuser = get_valid_user_struct(sconn, session_tag);
1280 if (vuser) {
1281 set_current_user_info(
1282 vuser->server_info->sanitized_username,
1283 vuser->server_info->unix_name,
1284 pdb_get_domain(vuser->server_info
1285 ->sam_account));
1290 /* Does this call need to be run as the connected user? */
1291 if (flags & AS_USER) {
1293 /* Does this call need a valid tree connection? */
1294 if (!conn) {
1296 * Amazingly, the error code depends on the command
1297 * (from Samba4).
1299 if (type == SMBntcreateX) {
1300 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1301 } else {
1302 reply_doserror(req, ERRSRV, ERRinvnid);
1304 return NULL;
1307 if (!change_to_user(conn,session_tag)) {
1308 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1309 remove_deferred_open_smb_message(req->mid);
1310 return conn;
1313 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1315 /* Does it need write permission? */
1316 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1317 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1318 return conn;
1321 /* IPC services are limited */
1322 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1323 reply_doserror(req, ERRSRV,ERRaccess);
1324 return conn;
1326 } else {
1327 /* This call needs to be run as root */
1328 change_to_root_user();
1331 /* load service specific parameters */
1332 if (conn) {
1333 if (req->encrypted) {
1334 conn->encrypted_tid = true;
1335 /* encrypted required from now on. */
1336 conn->encrypt_level = Required;
1337 } else if (ENCRYPTION_REQUIRED(conn)) {
1338 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1339 exit_server_cleanly("encryption required "
1340 "on connection");
1341 return conn;
1345 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1346 (flags & (AS_USER|DO_CHDIR)
1347 ?True:False))) {
1348 reply_doserror(req, ERRSRV, ERRaccess);
1349 return conn;
1351 conn->num_smb_operations++;
1354 /* does this protocol need to be run as guest? */
1355 if ((flags & AS_GUEST)
1356 && (!change_to_guest() ||
1357 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1358 lp_hostsdeny(-1)))) {
1359 reply_doserror(req, ERRSRV, ERRaccess);
1360 return conn;
1363 smb_messages[type].fn(req);
1364 return req->conn;
1367 /****************************************************************************
1368 Construct a reply to the incoming packet.
1369 ****************************************************************************/
1371 static void construct_reply(char *inbuf, int size, size_t unread_bytes,
1372 uint32_t seqnum, bool encrypted,
1373 struct smb_perfcount_data *deferred_pcd)
1375 connection_struct *conn;
1376 struct smb_request *req;
1378 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1379 smb_panic("could not allocate smb_request");
1382 init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1383 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1384 req->seqnum = seqnum;
1386 /* we popped this message off the queue - keep original perf data */
1387 if (deferred_pcd)
1388 req->pcd = *deferred_pcd;
1389 else {
1390 SMB_PERFCOUNT_START(&req->pcd);
1391 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1392 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1395 conn = switch_message(req->cmd, req, size);
1397 if (req->unread_bytes) {
1398 /* writeX failed. drain socket. */
1399 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1400 req->unread_bytes) {
1401 smb_panic("failed to drain pending bytes");
1403 req->unread_bytes = 0;
1406 if (req->outbuf == NULL) {
1407 return;
1410 if (CVAL(req->outbuf,0) == 0) {
1411 show_msg((char *)req->outbuf);
1414 if (!srv_send_smb(smbd_server_fd(),
1415 (char *)req->outbuf,
1416 true, req->seqnum+1,
1417 IS_CONN_ENCRYPTED(conn)||req->encrypted,
1418 &req->pcd)) {
1419 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1422 TALLOC_FREE(req);
1424 return;
1427 /****************************************************************************
1428 Process an smb from the client
1429 ****************************************************************************/
1430 static void process_smb(struct smbd_server_connection *conn,
1431 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1432 uint32_t seqnum, bool encrypted,
1433 struct smb_perfcount_data *deferred_pcd)
1435 int msg_type = CVAL(inbuf,0);
1437 DO_PROFILE_INC(smb_count);
1439 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1440 smb_len(inbuf) ) );
1441 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1442 (int)nread,
1443 (unsigned int)unread_bytes ));
1445 if (msg_type != 0) {
1447 * NetBIOS session request, keepalive, etc.
1449 reply_special((char *)inbuf);
1450 goto done;
1453 if (smbd_server_conn->allow_smb2) {
1454 if (smbd_is_smb2_header(inbuf, nread)) {
1455 smbd_smb2_first_negprot(smbd_server_conn, inbuf, nread);
1456 return;
1458 smbd_server_conn->allow_smb2 = false;
1461 show_msg((char *)inbuf);
1463 construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
1464 trans_num++;
1466 done:
1467 conn->smb1.num_requests++;
1469 /* The timeout_processing function isn't run nearly
1470 often enough to implement 'max log size' without
1471 overrunning the size of the file by many megabytes.
1472 This is especially true if we are running at debug
1473 level 10. Checking every 50 SMBs is a nice
1474 tradeoff of performance vs log file size overrun. */
1476 if ((conn->smb1.num_requests % 50) == 0 &&
1477 need_to_check_log_size()) {
1478 change_to_root_user();
1479 check_log_size();
1483 /****************************************************************************
1484 Return a string containing the function name of a SMB command.
1485 ****************************************************************************/
1487 const char *smb_fn_name(int type)
1489 const char *unknown_name = "SMBunknown";
1491 if (smb_messages[type].name == NULL)
1492 return(unknown_name);
1494 return(smb_messages[type].name);
1497 /****************************************************************************
1498 Helper functions for contruct_reply.
1499 ****************************************************************************/
1501 void add_to_common_flags2(uint32 v)
1503 common_flags2 |= v;
1506 void remove_from_common_flags2(uint32 v)
1508 common_flags2 &= ~v;
1511 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1512 char *outbuf)
1514 srv_set_message(outbuf,0,0,false);
1516 SCVAL(outbuf, smb_com, req->cmd);
1517 SIVAL(outbuf,smb_rcls,0);
1518 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1519 SSVAL(outbuf,smb_flg2,
1520 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1521 common_flags2);
1522 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1524 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1525 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1526 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1527 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1530 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1532 construct_reply_common(req, (char *)req->inbuf, outbuf);
1536 * How many bytes have we already accumulated up to the current wct field
1537 * offset?
1540 size_t req_wct_ofs(struct smb_request *req)
1542 size_t buf_size;
1544 if (req->chain_outbuf == NULL) {
1545 return smb_wct - 4;
1547 buf_size = talloc_get_size(req->chain_outbuf);
1548 if ((buf_size % 4) != 0) {
1549 buf_size += (4 - (buf_size % 4));
1551 return buf_size - 4;
1555 * Hack around reply_nterror & friends not being aware of chained requests,
1556 * generating illegal (i.e. wct==0) chain replies.
1559 static void fixup_chain_error_packet(struct smb_request *req)
1561 uint8_t *outbuf = req->outbuf;
1562 req->outbuf = NULL;
1563 reply_outbuf(req, 2, 0);
1564 memcpy(req->outbuf, outbuf, smb_wct);
1565 TALLOC_FREE(outbuf);
1566 SCVAL(req->outbuf, smb_vwv0, 0xff);
1569 /****************************************************************************
1570 Construct a chained reply and add it to the already made reply
1571 ****************************************************************************/
1573 void chain_reply(struct smb_request *req)
1575 size_t smblen = smb_len(req->inbuf);
1576 size_t already_used, length_needed;
1577 uint8_t chain_cmd;
1578 uint32_t chain_offset; /* uint32_t to avoid overflow */
1580 uint8_t wct;
1581 uint16_t *vwv;
1582 uint16_t buflen;
1583 uint8_t *buf;
1585 if (IVAL(req->outbuf, smb_rcls) != 0) {
1586 fixup_chain_error_packet(req);
1590 * Any of the AndX requests and replies have at least a wct of
1591 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1592 * beginning of the SMB header to the next wct field.
1594 * None of the AndX requests put anything valuable in vwv[0] and [1],
1595 * so we can overwrite it here to form the chain.
1598 if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1599 goto error;
1603 * Here we assume that this is the end of the chain. For that we need
1604 * to set "next command" to 0xff and the offset to 0. If we later find
1605 * more commands in the chain, this will be overwritten again.
1608 SCVAL(req->outbuf, smb_vwv0, 0xff);
1609 SCVAL(req->outbuf, smb_vwv0+1, 0);
1610 SSVAL(req->outbuf, smb_vwv1, 0);
1612 if (req->chain_outbuf == NULL) {
1614 * In req->chain_outbuf we collect all the replies. Start the
1615 * chain by copying in the first reply.
1617 * We do the realloc because later on we depend on
1618 * talloc_get_size to determine the length of
1619 * chain_outbuf. The reply_xxx routines might have
1620 * over-allocated (reply_pipe_read_and_X used to be such an
1621 * example).
1623 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
1624 req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
1625 if (req->chain_outbuf == NULL) {
1626 goto error;
1628 req->outbuf = NULL;
1629 } else {
1631 * Update smb headers where subsequent chained commands
1632 * may have updated them.
1634 SCVAL(req->chain_outbuf, smb_tid, CVAL(req->outbuf, smb_tid));
1635 SCVAL(req->chain_outbuf, smb_uid, CVAL(req->outbuf, smb_uid));
1637 if (!smb_splice_chain(&req->chain_outbuf,
1638 CVAL(req->outbuf, smb_com),
1639 CVAL(req->outbuf, smb_wct),
1640 (uint16_t *)(req->outbuf + smb_vwv),
1641 0, smb_buflen(req->outbuf),
1642 (uint8_t *)smb_buf(req->outbuf))) {
1643 goto error;
1645 TALLOC_FREE(req->outbuf);
1649 * We use the old request's vwv field to grab the next chained command
1650 * and offset into the chained fields.
1653 chain_cmd = CVAL(req->vwv+0, 0);
1654 chain_offset = SVAL(req->vwv+1, 0);
1656 if (chain_cmd == 0xff) {
1658 * End of chain, no more requests from the client. So ship the
1659 * replies.
1661 smb_setlen((char *)(req->chain_outbuf),
1662 talloc_get_size(req->chain_outbuf) - 4);
1664 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1665 true, req->seqnum+1,
1666 IS_CONN_ENCRYPTED(req->conn)
1667 ||req->encrypted,
1668 &req->pcd)) {
1669 exit_server_cleanly("chain_reply: srv_send_smb "
1670 "failed.");
1672 TALLOC_FREE(req);
1674 return;
1677 /* add a new perfcounter for this element of chain */
1678 SMB_PERFCOUNT_ADD(&req->pcd);
1679 SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
1680 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
1683 * Check if the client tries to fool us. The request so far uses the
1684 * space to the end of the byte buffer in the request just
1685 * processed. The chain_offset can't point into that area. If that was
1686 * the case, we could end up with an endless processing of the chain,
1687 * we would always handle the same request.
1690 already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1691 if (chain_offset < already_used) {
1692 goto error;
1696 * Next check: Make sure the chain offset does not point beyond the
1697 * overall smb request length.
1700 length_needed = chain_offset+1; /* wct */
1701 if (length_needed > smblen) {
1702 goto error;
1706 * Now comes the pointer magic. Goal here is to set up req->vwv and
1707 * req->buf correctly again to be able to call the subsequent
1708 * switch_message(). The chain offset (the former vwv[1]) points at
1709 * the new wct field.
1712 wct = CVAL(smb_base(req->inbuf), chain_offset);
1715 * Next consistency check: Make the new vwv array fits in the overall
1716 * smb request.
1719 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1720 if (length_needed > smblen) {
1721 goto error;
1723 vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1726 * Now grab the new byte buffer....
1729 buflen = SVAL(vwv+wct, 0);
1732 * .. and check that it fits.
1735 length_needed += buflen;
1736 if (length_needed > smblen) {
1737 goto error;
1739 buf = (uint8_t *)(vwv+wct+1);
1741 req->cmd = chain_cmd;
1742 req->wct = wct;
1743 req->vwv = vwv;
1744 req->buflen = buflen;
1745 req->buf = buf;
1747 switch_message(chain_cmd, req, smblen);
1749 if (req->outbuf == NULL) {
1751 * This happens if the chained command has suspended itself or
1752 * if it has called srv_send_smb() itself.
1754 return;
1758 * We end up here if the chained command was not itself chained or
1759 * suspended, but for example a close() command. We now need to splice
1760 * the chained commands' outbuf into the already built up chain_outbuf
1761 * and ship the result.
1763 goto done;
1765 error:
1767 * We end up here if there's any error in the chain syntax. Report a
1768 * DOS error, just like Windows does.
1770 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1771 fixup_chain_error_packet(req);
1773 done:
1774 if (!smb_splice_chain(&req->chain_outbuf,
1775 CVAL(req->outbuf, smb_com),
1776 CVAL(req->outbuf, smb_wct),
1777 (uint16_t *)(req->outbuf + smb_vwv),
1778 0, smb_buflen(req->outbuf),
1779 (uint8_t *)smb_buf(req->outbuf))) {
1780 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1782 TALLOC_FREE(req->outbuf);
1784 smb_setlen((char *)(req->chain_outbuf),
1785 talloc_get_size(req->chain_outbuf) - 4);
1787 show_msg((char *)(req->chain_outbuf));
1789 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1790 true, req->seqnum+1,
1791 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
1792 &req->pcd)) {
1793 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1795 TALLOC_FREE(req);
1798 /****************************************************************************
1799 Check if services need reloading.
1800 ****************************************************************************/
1802 void check_reload(time_t t)
1804 time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1806 if(last_smb_conf_reload_time == 0) {
1807 last_smb_conf_reload_time = t;
1808 /* Our printing subsystem might not be ready at smbd start up.
1809 Then no printer is available till the first printers check
1810 is performed. A lower initial interval circumvents this. */
1811 if ( printcap_cache_time > 60 )
1812 last_printer_reload_time = t - printcap_cache_time + 60;
1813 else
1814 last_printer_reload_time = t;
1817 if (mypid != getpid()) { /* First time or fork happened meanwhile */
1818 /* randomize over 60 second the printcap reload to avoid all
1819 * process hitting cupsd at the same time */
1820 int time_range = 60;
1822 last_printer_reload_time += random() % time_range;
1823 mypid = getpid();
1826 if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
1827 reload_services(True);
1828 last_smb_conf_reload_time = t;
1831 /* 'printcap cache time = 0' disable the feature */
1833 if ( printcap_cache_time != 0 )
1835 /* see if it's time to reload or if the clock has been set back */
1837 if ( (t >= last_printer_reload_time+printcap_cache_time)
1838 || (t-last_printer_reload_time < 0) )
1840 DEBUG( 3,( "Printcap cache time expired.\n"));
1841 reload_printers();
1842 last_printer_reload_time = t;
1847 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1849 /* TODO: make write nonblocking */
1852 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1854 uint8_t *inbuf = NULL;
1855 size_t inbuf_len = 0;
1856 size_t unread_bytes = 0;
1857 bool encrypted = false;
1858 TALLOC_CTX *mem_ctx = talloc_tos();
1859 NTSTATUS status;
1860 uint32_t seqnum;
1862 /* TODO: make this completely nonblocking */
1864 status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1865 (char **)(void *)&inbuf,
1866 0, /* timeout */
1867 &unread_bytes,
1868 &encrypted,
1869 &inbuf_len, &seqnum);
1870 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1871 goto process;
1873 if (NT_STATUS_IS_ERR(status)) {
1874 exit_server_cleanly("failed to receive smb request");
1876 if (!NT_STATUS_IS_OK(status)) {
1877 return;
1880 process:
1881 process_smb(conn, inbuf, inbuf_len, unread_bytes,
1882 seqnum, encrypted, NULL);
1885 static void smbd_server_connection_handler(struct event_context *ev,
1886 struct fd_event *fde,
1887 uint16_t flags,
1888 void *private_data)
1890 struct smbd_server_connection *conn = talloc_get_type(private_data,
1891 struct smbd_server_connection);
1893 if (flags & EVENT_FD_WRITE) {
1894 smbd_server_connection_write_handler(conn);
1895 } else if (flags & EVENT_FD_READ) {
1896 smbd_server_connection_read_handler(conn);
1901 /****************************************************************************
1902 received when we should release a specific IP
1903 ****************************************************************************/
1904 static void release_ip(const char *ip, void *priv)
1906 char addr[INET6_ADDRSTRLEN];
1907 char *p = addr;
1909 client_socket_addr(get_client_fd(),addr,sizeof(addr));
1911 if (strncmp("::ffff:", addr, 7) == 0) {
1912 p = addr + 7;
1915 if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
1916 /* we can't afford to do a clean exit - that involves
1917 database writes, which would potentially mean we
1918 are still running after the failover has finished -
1919 we have to get rid of this process ID straight
1920 away */
1921 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
1922 ip));
1923 /* note we must exit with non-zero status so the unclean handler gets
1924 called in the parent, so that the brl database is tickled */
1925 _exit(1);
1929 static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
1930 uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
1932 release_ip((char *)data->data, NULL);
1935 #ifdef CLUSTER_SUPPORT
1936 static int client_get_tcp_info(struct sockaddr_storage *server,
1937 struct sockaddr_storage *client)
1939 socklen_t length;
1940 if (server_fd == -1) {
1941 return -1;
1943 length = sizeof(*server);
1944 if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) {
1945 return -1;
1947 length = sizeof(*client);
1948 if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) {
1949 return -1;
1951 return 0;
1953 #endif
1956 * Send keepalive packets to our client
1958 static bool keepalive_fn(const struct timeval *now, void *private_data)
1960 if (!send_keepalive(smbd_server_fd())) {
1961 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1962 return False;
1964 return True;
1968 * Do the recurring check if we're idle
1970 static bool deadtime_fn(const struct timeval *now, void *private_data)
1972 struct smbd_server_connection *sconn = smbd_server_conn;
1973 if ((conn_num_open(sconn) == 0)
1974 || (conn_idle_all(sconn, now->tv_sec))) {
1975 DEBUG( 2, ( "Closing idle connection\n" ) );
1976 messaging_send(smbd_messaging_context(), procid_self(),
1977 MSG_SHUTDOWN, &data_blob_null);
1978 return False;
1981 return True;
1985 * Do the recurring log file and smb.conf reload checks.
1988 static bool housekeeping_fn(const struct timeval *now, void *private_data)
1990 change_to_root_user();
1992 /* update printer queue caches if necessary */
1993 update_monitored_printq_cache();
1995 /* check if we need to reload services */
1996 check_reload(time(NULL));
1998 /* Change machine password if neccessary. */
1999 attempt_machine_password_change();
2002 * Force a log file check.
2004 force_check_log_size();
2005 check_log_size();
2006 return true;
2009 /****************************************************************************
2010 Process commands from the client
2011 ****************************************************************************/
2013 void smbd_process(void)
2015 TALLOC_CTX *frame = talloc_stackframe();
2016 char remaddr[INET6_ADDRSTRLEN];
2018 smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
2019 if (!smbd_server_conn) {
2020 exit_server("failed to create smbd_server_connection");
2023 if (lp_maxprotocol() == PROTOCOL_SMB2 &&
2024 lp_security() != SEC_SHARE) {
2025 smbd_server_conn->allow_smb2 = true;
2028 /* Ensure child is set to blocking mode */
2029 set_blocking(smbd_server_fd(),True);
2031 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
2032 set_socket_options(smbd_server_fd(), lp_socket_options());
2034 /* this is needed so that we get decent entries
2035 in smbstatus for port 445 connects */
2036 set_remote_machine_name(get_peer_addr(smbd_server_fd(),
2037 remaddr,
2038 sizeof(remaddr)),
2039 false);
2040 reload_services(true);
2043 * Before the first packet, check the global hosts allow/ hosts deny
2044 * parameters before doing any parsing of packets passed to us by the
2045 * client. This prevents attacks on our parsing code from hosts not in
2046 * the hosts allow list.
2049 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
2050 lp_hostsdeny(-1))) {
2051 char addr[INET6_ADDRSTRLEN];
2054 * send a negative session response "not listening on calling
2055 * name"
2057 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2058 DEBUG( 1, ("Connection denied from %s\n",
2059 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
2060 (void)srv_send_smb(smbd_server_fd(),(char *)buf, false,
2061 0, false, NULL);
2062 exit_server_cleanly("connection denied");
2065 static_init_rpc;
2067 init_modules();
2069 smb_perfcount_init();
2071 if (!init_account_policy()) {
2072 exit_server("Could not open account policy tdb.\n");
2075 if (*lp_rootdir()) {
2076 if (chroot(lp_rootdir()) != 0) {
2077 DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
2078 exit_server("Failed to chroot()");
2080 if (chdir("/") == -1) {
2081 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
2082 exit_server("Failed to chroot()");
2084 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
2087 if (!srv_init_signing(smbd_server_conn)) {
2088 exit_server("Failed to init smb_signing");
2091 /* Setup oplocks */
2092 if (!init_oplocks(smbd_messaging_context()))
2093 exit_server("Failed to init oplocks");
2095 /* Setup aio signal handler. */
2096 initialize_async_io_handler();
2098 /* register our message handlers */
2099 messaging_register(smbd_messaging_context(), NULL,
2100 MSG_SMB_FORCE_TDIS, msg_force_tdis);
2101 messaging_register(smbd_messaging_context(), NULL,
2102 MSG_SMB_RELEASE_IP, msg_release_ip);
2103 messaging_register(smbd_messaging_context(), NULL,
2104 MSG_SMB_CLOSE_FILE, msg_close_file);
2106 if ((lp_keepalive() != 0)
2107 && !(event_add_idle(smbd_event_context(), NULL,
2108 timeval_set(lp_keepalive(), 0),
2109 "keepalive", keepalive_fn,
2110 NULL))) {
2111 DEBUG(0, ("Could not add keepalive event\n"));
2112 exit(1);
2115 if (!(event_add_idle(smbd_event_context(), NULL,
2116 timeval_set(IDLE_CLOSED_TIMEOUT, 0),
2117 "deadtime", deadtime_fn, NULL))) {
2118 DEBUG(0, ("Could not add deadtime event\n"));
2119 exit(1);
2122 if (!(event_add_idle(smbd_event_context(), NULL,
2123 timeval_set(SMBD_SELECT_TIMEOUT, 0),
2124 "housekeeping", housekeeping_fn, NULL))) {
2125 DEBUG(0, ("Could not add housekeeping event\n"));
2126 exit(1);
2129 #ifdef CLUSTER_SUPPORT
2131 if (lp_clustering()) {
2133 * We need to tell ctdb about our client's TCP
2134 * connection, so that for failover ctdbd can send
2135 * tickle acks, triggering a reconnection by the
2136 * client.
2139 struct sockaddr_storage srv, clnt;
2141 if (client_get_tcp_info(&srv, &clnt) == 0) {
2143 NTSTATUS status;
2145 status = ctdbd_register_ips(
2146 messaging_ctdbd_connection(),
2147 &srv, &clnt, release_ip, NULL);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
2151 nt_errstr(status)));
2153 } else
2155 DEBUG(0,("Unable to get tcp info for "
2156 "CTDB_CONTROL_TCP_CLIENT: %s\n",
2157 strerror(errno)));
2161 #endif
2163 smbd_server_conn->nbt.got_session = false;
2165 smbd_server_conn->smb1.negprot.max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
2167 smbd_server_conn->smb1.sessions.done_sesssetup = false;
2168 smbd_server_conn->smb1.sessions.max_send = BUFFER_SIZE;
2169 smbd_server_conn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
2170 /* users from session setup */
2171 smbd_server_conn->smb1.sessions.session_userlist = NULL;
2172 /* workgroup from session setup. */
2173 smbd_server_conn->smb1.sessions.session_workgroup = NULL;
2174 /* this holds info on user ids that are already validated for this VC */
2175 smbd_server_conn->smb1.sessions.validated_users = NULL;
2176 smbd_server_conn->smb1.sessions.next_vuid = VUID_OFFSET;
2177 smbd_server_conn->smb1.sessions.num_validated_vuids = 0;
2178 #ifdef HAVE_NETGROUP
2179 smbd_server_conn->smb1.sessions.my_yp_domain = NULL;
2180 #endif
2182 conn_init(smbd_server_conn);
2184 smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(),
2185 smbd_server_conn,
2186 smbd_server_fd(),
2187 EVENT_FD_READ,
2188 smbd_server_connection_handler,
2189 smbd_server_conn);
2190 if (!smbd_server_conn->smb1.fde) {
2191 exit_server("failed to create smbd_server_connection fde");
2194 TALLOC_FREE(frame);
2196 while (True) {
2197 NTSTATUS status;
2199 frame = talloc_stackframe_pool(8192);
2201 errno = 0;
2203 status = smbd_server_connection_loop_once(smbd_server_conn);
2204 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2205 !NT_STATUS_IS_OK(status)) {
2206 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2207 " exiting\n", nt_errstr(status)));
2208 break;
2211 TALLOC_FREE(frame);
2214 exit_server_cleanly(NULL);
2217 bool req_is_in_chain(struct smb_request *req)
2219 if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) {
2221 * We're right now handling a subsequent request, so we must
2222 * be in a chain
2224 return true;
2227 if (!is_andx_req(req->cmd)) {
2228 return false;
2231 if (req->wct < 2) {
2233 * Okay, an illegal request, but definitely not chained :-)
2235 return false;
2238 return (CVAL(req->vwv+0, 0) != 0xFF);