Merge branch 'master' of ssh://git.samba.org/data/git/samba into selftest
[kai/samba-autobuild/.git] / source3 / smbd / process.c
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
6    
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.
11    
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.
16    
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/>.
19 */
20
21 #include "includes.h"
22
23 extern int smb_echo_count;
24
25 /*
26  * Size of data we can send to client. Set
27  *  by the client for all protocols above CORE.
28  *  Set by us for CORE protocol.
29  */
30 int max_send = BUFFER_SIZE;
31 /*
32  * Size of the data we can receive. Set by us.
33  * Can be modified by the max xmit parameter.
34  */
35 int max_recv = BUFFER_SIZE;
36
37 SIG_ATOMIC_T reload_after_sighup = 0;
38 SIG_ATOMIC_T got_sig_term = 0;
39 extern bool global_machine_password_needs_changing;
40 extern int max_send;
41
42 /* Accessor function for smb_read_error for smbd functions. */
43
44 /****************************************************************************
45  Send an smb to a fd.
46 ****************************************************************************/
47
48 bool srv_send_smb(int fd, char *buffer, bool do_encrypt)
49 {
50         size_t len;
51         size_t nwritten=0;
52         ssize_t ret;
53         char *buf_out = buffer;
54
55         /* Sign the outgoing packet if required. */
56         srv_calculate_sign_mac(buf_out);
57
58         if (do_encrypt) {
59                 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
60                 if (!NT_STATUS_IS_OK(status)) {
61                         DEBUG(0, ("send_smb: SMB encryption failed "
62                                 "on outgoing packet! Error %s\n",
63                                 nt_errstr(status) ));
64                         return false;
65                 }
66         }
67
68         len = smb_len(buf_out) + 4;
69
70         while (nwritten < len) {
71                 ret = write_data(fd,buf_out+nwritten,len - nwritten);
72                 if (ret <= 0) {
73                         DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
74                                 (int)len,(int)ret, strerror(errno) ));
75                         srv_free_enc_buffer(buf_out);
76                         return false;
77                 }
78                 nwritten += ret;
79         }
80
81         srv_free_enc_buffer(buf_out);
82         return true;
83 }
84
85 /*******************************************************************
86  Setup the word count and byte count for a smb message.
87 ********************************************************************/
88
89 int srv_set_message(char *buf,
90                         int num_words,
91                         int num_bytes,
92                         bool zero)
93 {
94         if (zero && (num_words || num_bytes)) {
95                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
96         }
97         SCVAL(buf,smb_wct,num_words);
98         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
99         smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
100         return (smb_size + num_words*2 + num_bytes);
101 }
102
103 static bool valid_smb_header(const uint8_t *inbuf)
104 {
105         if (is_encrypted_packet(inbuf)) {
106                 return true;
107         }
108         return (strncmp(smb_base(inbuf),"\377SMB",4) == 0);
109 }
110
111 /* Socket functions for smbd packet processing. */
112
113 static bool valid_packet_size(size_t len)
114 {
115         /*
116          * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
117          * of header. Don't print the error if this fits.... JRA.
118          */
119
120         if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
121                 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
122                                         (unsigned long)len));
123                 return false;
124         }
125         return true;
126 }
127
128 static NTSTATUS read_packet_remainder(int fd, char *buffer,
129                                       unsigned int timeout, ssize_t len)
130 {
131         if (len <= 0) {
132                 return NT_STATUS_OK;
133         }
134
135         return read_socket_with_timeout(fd, buffer, len, len, timeout, NULL);
136 }
137
138 /****************************************************************************
139  Attempt a zerocopy writeX read. We know here that len > smb_size-4
140 ****************************************************************************/
141
142 /*
143  * Unfortunately, earlier versions of smbclient/libsmbclient
144  * don't send this "standard" writeX header. I've fixed this
145  * for 3.2 but we'll use the old method with earlier versions.
146  * Windows and CIFSFS at least use this standard size. Not
147  * sure about MacOSX.
148  */
149
150 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
151                                 (2*14) + /* word count (including bcc) */ \
152                                 1 /* pad byte */)
153
154 static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
155                                                     const char lenbuf[4],
156                                                     int fd, char **buffer,
157                                                     unsigned int timeout,
158                                                     size_t *p_unread,
159                                                     size_t *len_ret)
160 {
161         /* Size of a WRITEX call (+4 byte len). */
162         char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
163         ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
164         ssize_t toread;
165         NTSTATUS status;
166
167         memcpy(writeX_header, lenbuf, 4);
168
169         status = read_socket_with_timeout(
170                 fd, writeX_header + 4,
171                 STANDARD_WRITE_AND_X_HEADER_SIZE,
172                 STANDARD_WRITE_AND_X_HEADER_SIZE,
173                 timeout, NULL);
174
175         if (!NT_STATUS_IS_OK(status)) {
176                 return status;
177         }
178
179         /*
180          * Ok - now try and see if this is a possible
181          * valid writeX call.
182          */
183
184         if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
185                 /*
186                  * If the data offset is beyond what
187                  * we've read, drain the extra bytes.
188                  */
189                 uint16_t doff = SVAL(writeX_header,smb_vwv11);
190                 ssize_t newlen;
191
192                 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
193                         size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
194                         if (drain_socket(smbd_server_fd(), drain) != drain) {
195                                 smb_panic("receive_smb_raw_talloc_partial_read:"
196                                         " failed to drain pending bytes");
197                         }
198                 } else {
199                         doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
200                 }
201
202                 /* Spoof down the length and null out the bcc. */
203                 set_message_bcc(writeX_header, 0);
204                 newlen = smb_len(writeX_header);
205
206                 /* Copy the header we've written. */
207
208                 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
209                                 writeX_header,
210                                 sizeof(writeX_header));
211
212                 if (*buffer == NULL) {
213                         DEBUG(0, ("Could not allocate inbuf of length %d\n",
214                                   (int)sizeof(writeX_header)));
215                         return NT_STATUS_NO_MEMORY;
216                 }
217
218                 /* Work out the remaining bytes. */
219                 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
220                 *len_ret = newlen + 4;
221                 return NT_STATUS_OK;
222         }
223
224         if (!valid_packet_size(len)) {
225                 return NT_STATUS_INVALID_PARAMETER;
226         }
227
228         /*
229          * Not a valid writeX call. Just do the standard
230          * talloc and return.
231          */
232
233         *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
234
235         if (*buffer == NULL) {
236                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
237                           (int)len+4));
238                 return NT_STATUS_NO_MEMORY;
239         }
240
241         /* Copy in what we already read. */
242         memcpy(*buffer,
243                 writeX_header,
244                 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
245         toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
246
247         if(toread > 0) {
248                 status = read_packet_remainder(
249                         fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
250                         timeout, toread);
251
252                 if (!NT_STATUS_IS_OK(status)) {
253                         DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
254                                    nt_errstr(status)));
255                         return status;
256                 }
257         }
258
259         *len_ret = len + 4;
260         return NT_STATUS_OK;
261 }
262
263 static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
264                                        char **buffer, unsigned int timeout,
265                                        size_t *p_unread, size_t *plen)
266 {
267         char lenbuf[4];
268         size_t len;
269         int min_recv_size = lp_min_receive_file_size();
270         NTSTATUS status;
271
272         *p_unread = 0;
273
274         status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
275         if (!NT_STATUS_IS_OK(status)) {
276                 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
277                 return status;
278         }
279
280         if (CVAL(lenbuf,0) == 0 &&
281                         min_recv_size &&
282                         smb_len_large(lenbuf) > min_recv_size && /* Could be a UNIX large writeX. */
283                         !srv_is_signing_active()) {
284
285                 return receive_smb_raw_talloc_partial_read(
286                         mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
287         }
288
289         if (!valid_packet_size(len)) {
290                 return NT_STATUS_INVALID_PARAMETER;
291         }
292
293         /*
294          * The +4 here can't wrap, we've checked the length above already.
295          */
296
297         *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
298
299         if (*buffer == NULL) {
300                 DEBUG(0, ("Could not allocate inbuf of length %d\n",
301                           (int)len+4));
302                 return NT_STATUS_NO_MEMORY;
303         }
304
305         memcpy(*buffer, lenbuf, sizeof(lenbuf));
306
307         status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
308         if (!NT_STATUS_IS_OK(status)) {
309                 return status;
310         }
311
312         *plen = len + 4;
313         return NT_STATUS_OK;
314 }
315
316 static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
317                                    char **buffer, unsigned int timeout,
318                                    size_t *p_unread, bool *p_encrypted,
319                                    size_t *p_len)
320 {
321         size_t len = 0;
322         NTSTATUS status;
323
324         *p_encrypted = false;
325
326         status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
327                                         p_unread, &len);
328         if (!NT_STATUS_IS_OK(status)) {
329                 return status;
330         }
331
332         if (is_encrypted_packet((uint8_t *)*buffer)) {
333                 status = srv_decrypt_buffer(*buffer);
334                 if (!NT_STATUS_IS_OK(status)) {
335                         DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
336                                 "incoming packet! Error %s\n",
337                                 nt_errstr(status) ));
338                         return status;
339                 }
340                 *p_encrypted = true;
341         }
342
343         /* Check the incoming SMB signature. */
344         if (!srv_check_sign_mac(*buffer, true)) {
345                 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
346                           "incoming packet!\n"));
347                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
348         }
349
350         *p_len = len;
351         return NT_STATUS_OK;
352 }
353
354 /*
355  * Initialize a struct smb_request from an inbuf
356  */
357
358 void init_smb_request(struct smb_request *req,
359                         const uint8 *inbuf,
360                         size_t unread_bytes,
361                         bool encrypted)
362 {
363         size_t req_size = smb_len(inbuf) + 4;
364         /* Ensure we have at least smb_size bytes. */
365         if (req_size < smb_size) {
366                 DEBUG(0,("init_smb_request: invalid request size %u\n",
367                         (unsigned int)req_size ));
368                 exit_server_cleanly("Invalid SMB request");
369         }
370         req->flags2 = SVAL(inbuf, smb_flg2);
371         req->smbpid = SVAL(inbuf, smb_pid);
372         req->mid    = SVAL(inbuf, smb_mid);
373         req->vuid   = SVAL(inbuf, smb_uid);
374         req->tid    = SVAL(inbuf, smb_tid);
375         req->wct    = CVAL(inbuf, smb_wct);
376         req->unread_bytes = unread_bytes;
377         req->encrypted = encrypted;
378         req->conn = conn_find(req->tid);
379
380         /* Ensure we have at least wct words and 2 bytes of bcc. */
381         if (smb_size + req->wct*2 > req_size) {
382                 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
383                         (unsigned int)req->wct,
384                         (unsigned int)req_size));
385                 exit_server_cleanly("Invalid SMB request");
386         }
387         /* Ensure bcc is correct. */
388         if (((uint8 *)smb_buf(inbuf)) + smb_buflen(inbuf) > inbuf + req_size) {
389                 DEBUG(0,("init_smb_request: invalid bcc number %u "
390                         "(wct = %u, size %u)\n",
391                         (unsigned int)smb_buflen(inbuf),
392                         (unsigned int)req->wct,
393                         (unsigned int)req_size));
394                 exit_server_cleanly("Invalid SMB request");
395         }
396         req->inbuf  = inbuf;
397         req->outbuf = NULL;
398 }
399
400 /****************************************************************************
401  structure to hold a linked list of queued messages.
402  for processing.
403 ****************************************************************************/
404
405 static struct pending_message_list *deferred_open_queue;
406
407 /****************************************************************************
408  Function to push a message onto the tail of a linked list of smb messages ready
409  for processing.
410 ****************************************************************************/
411
412 static bool push_queued_message(struct smb_request *req,
413                                 struct timeval request_time,
414                                 struct timeval end_time,
415                                 char *private_data, size_t private_len)
416 {
417         int msg_len = smb_len(req->inbuf) + 4;
418         struct pending_message_list *msg;
419
420         msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
421
422         if(msg == NULL) {
423                 DEBUG(0,("push_message: malloc fail (1)\n"));
424                 return False;
425         }
426
427         msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
428         if(msg->buf.data == NULL) {
429                 DEBUG(0,("push_message: malloc fail (2)\n"));
430                 TALLOC_FREE(msg);
431                 return False;
432         }
433
434         msg->request_time = request_time;
435         msg->end_time = end_time;
436         msg->encrypted = req->encrypted;
437
438         if (private_data) {
439                 msg->private_data = data_blob_talloc(msg, private_data,
440                                                      private_len);
441                 if (msg->private_data.data == NULL) {
442                         DEBUG(0,("push_message: malloc fail (3)\n"));
443                         TALLOC_FREE(msg);
444                         return False;
445                 }
446         }
447
448         DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
449
450         DEBUG(10,("push_message: pushed message length %u on "
451                   "deferred_open_queue\n", (unsigned int)msg_len));
452
453         return True;
454 }
455
456 /****************************************************************************
457  Function to delete a sharing violation open message by mid.
458 ****************************************************************************/
459
460 void remove_deferred_open_smb_message(uint16 mid)
461 {
462         struct pending_message_list *pml;
463
464         for (pml = deferred_open_queue; pml; pml = pml->next) {
465                 if (mid == SVAL(pml->buf.data,smb_mid)) {
466                         DEBUG(10,("remove_sharing_violation_open_smb_message: "
467                                   "deleting mid %u len %u\n",
468                                   (unsigned int)mid,
469                                   (unsigned int)pml->buf.length ));
470                         DLIST_REMOVE(deferred_open_queue, pml);
471                         TALLOC_FREE(pml);
472                         return;
473                 }
474         }
475 }
476
477 /****************************************************************************
478  Move a sharing violation open retry message to the front of the list and
479  schedule it for immediate processing.
480 ****************************************************************************/
481
482 void schedule_deferred_open_smb_message(uint16 mid)
483 {
484         struct pending_message_list *pml;
485         int i = 0;
486
487         for (pml = deferred_open_queue; pml; pml = pml->next) {
488                 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
489                 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
490                         (unsigned int)msg_mid ));
491                 if (mid == msg_mid) {
492                         DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
493                                 mid ));
494                         pml->end_time.tv_sec = 0;
495                         pml->end_time.tv_usec = 0;
496                         DLIST_PROMOTE(deferred_open_queue, pml);
497                         return;
498                 }
499         }
500
501         DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
502                 mid ));
503 }
504
505 /****************************************************************************
506  Return true if this mid is on the deferred queue.
507 ****************************************************************************/
508
509 bool open_was_deferred(uint16 mid)
510 {
511         struct pending_message_list *pml;
512
513         for (pml = deferred_open_queue; pml; pml = pml->next) {
514                 if (SVAL(pml->buf.data,smb_mid) == mid) {
515                         return True;
516                 }
517         }
518         return False;
519 }
520
521 /****************************************************************************
522  Return the message queued by this mid.
523 ****************************************************************************/
524
525 struct pending_message_list *get_open_deferred_message(uint16 mid)
526 {
527         struct pending_message_list *pml;
528
529         for (pml = deferred_open_queue; pml; pml = pml->next) {
530                 if (SVAL(pml->buf.data,smb_mid) == mid) {
531                         return pml;
532                 }
533         }
534         return NULL;
535 }
536
537 /****************************************************************************
538  Function to push a deferred open smb message onto a linked list of local smb
539  messages ready for processing.
540 ****************************************************************************/
541
542 bool push_deferred_smb_message(struct smb_request *req,
543                                struct timeval request_time,
544                                struct timeval timeout,
545                                char *private_data, size_t priv_len)
546 {
547         struct timeval end_time;
548
549         if (req->unread_bytes) {
550                 DEBUG(0,("push_deferred_smb_message: logic error ! "
551                         "unread_bytes = %u\n",
552                         (unsigned int)req->unread_bytes ));
553                 smb_panic("push_deferred_smb_message: "
554                         "logic error unread_bytes != 0" );
555         }
556
557         end_time = timeval_sum(&request_time, &timeout);
558
559         DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
560                   "timeout time [%u.%06u]\n",
561                   (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
562                   (unsigned int)end_time.tv_sec,
563                   (unsigned int)end_time.tv_usec));
564
565         return push_queued_message(req, request_time, end_time,
566                                    private_data, priv_len);
567 }
568
569 struct idle_event {
570         struct timed_event *te;
571         struct timeval interval;
572         char *name;
573         bool (*handler)(const struct timeval *now, void *private_data);
574         void *private_data;
575 };
576
577 static void idle_event_handler(struct event_context *ctx,
578                                struct timed_event *te,
579                                const struct timeval *now,
580                                void *private_data)
581 {
582         struct idle_event *event =
583                 talloc_get_type_abort(private_data, struct idle_event);
584
585         TALLOC_FREE(event->te);
586
587         if (!event->handler(now, event->private_data)) {
588                 /* Don't repeat, delete ourselves */
589                 TALLOC_FREE(event);
590                 return;
591         }
592
593         event->te = event_add_timed(ctx, event,
594                                     timeval_sum(now, &event->interval),
595                                     event->name,
596                                     idle_event_handler, event);
597
598         /* We can't do much but fail here. */
599         SMB_ASSERT(event->te != NULL);
600 }
601
602 struct idle_event *event_add_idle(struct event_context *event_ctx,
603                                   TALLOC_CTX *mem_ctx,
604                                   struct timeval interval,
605                                   const char *name,
606                                   bool (*handler)(const struct timeval *now,
607                                                   void *private_data),
608                                   void *private_data)
609 {
610         struct idle_event *result;
611         struct timeval now = timeval_current();
612
613         result = TALLOC_P(mem_ctx, struct idle_event);
614         if (result == NULL) {
615                 DEBUG(0, ("talloc failed\n"));
616                 return NULL;
617         }
618
619         result->interval = interval;
620         result->handler = handler;
621         result->private_data = private_data;
622
623         if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
624                 DEBUG(0, ("talloc failed\n"));
625                 TALLOC_FREE(result);
626                 return NULL;
627         }
628
629         result->te = event_add_timed(event_ctx, result,
630                                      timeval_sum(&now, &interval),
631                                      result->name,
632                                      idle_event_handler, result);
633         if (result->te == NULL) {
634                 DEBUG(0, ("event_add_timed failed\n"));
635                 TALLOC_FREE(result);
636                 return NULL;
637         }
638
639         return result;
640 }
641
642 /****************************************************************************
643  Do all async processing in here. This includes kernel oplock messages, change
644  notify events etc.
645 ****************************************************************************/
646
647 static void async_processing(fd_set *pfds)
648 {
649         DEBUG(10,("async_processing: Doing async processing.\n"));
650
651         process_aio_queue();
652
653         process_kernel_oplocks(smbd_messaging_context(), pfds);
654
655         /* Do the aio check again after receive_local_message as it does a
656            select and may have eaten our signal. */
657         /* Is this till true? -- vl */
658         process_aio_queue();
659
660         if (got_sig_term) {
661                 exit_server_cleanly("termination signal");
662         }
663
664         /* check for sighup processing */
665         if (reload_after_sighup) {
666                 change_to_root_user();
667                 DEBUG(1,("Reloading services after SIGHUP\n"));
668                 reload_services(False);
669                 reload_after_sighup = 0;
670         }
671 }
672
673 /****************************************************************************
674  Add a fd to the set we will be select(2)ing on.
675 ****************************************************************************/
676
677 static int select_on_fd(int fd, int maxfd, fd_set *fds)
678 {
679         if (fd != -1) {
680                 FD_SET(fd, fds);
681                 maxfd = MAX(maxfd, fd);
682         }
683
684         return maxfd;
685 }
686
687 /****************************************************************************
688   Do a select on an two fd's - with timeout. 
689
690   If a local udp message has been pushed onto the
691   queue (this can only happen during oplock break
692   processing) call async_processing()
693
694   If a pending smb message has been pushed onto the
695   queue (this can only happen during oplock break
696   processing) return this next.
697
698   If the first smbfd is ready then read an smb from it.
699   if the second (loopback UDP) fd is ready then read a message
700   from it and setup the buffer header to identify the length
701   and from address.
702   Returns False on timeout or error.
703   Else returns True.
704
705 The timeout is in milliseconds
706 ****************************************************************************/
707
708 static NTSTATUS receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer,
709                                        size_t *buffer_len,
710                                        size_t *p_unread, bool *p_encrypted)
711 {
712         fd_set r_fds, w_fds;
713         int selrtn;
714         struct timeval to;
715         int maxfd = 0;
716         size_t len = 0;
717         NTSTATUS status;
718
719         *p_unread = 0;
720
721  again:
722
723         to.tv_sec = SMBD_SELECT_TIMEOUT;
724         to.tv_usec = 0;
725
726         /*
727          * Note that this call must be before processing any SMB
728          * messages as we need to synchronously process any messages
729          * we may have sent to ourselves from the previous SMB.
730          */
731         message_dispatch(smbd_messaging_context());
732
733         /*
734          * Check to see if we already have a message on the deferred open queue
735          * and it's time to schedule.
736          */
737         if(deferred_open_queue != NULL) {
738                 bool pop_message = False;
739                 struct pending_message_list *msg = deferred_open_queue;
740
741                 if (timeval_is_zero(&msg->end_time)) {
742                         pop_message = True;
743                 } else {
744                         struct timeval tv;
745                         SMB_BIG_INT tdif;
746
747                         GetTimeOfDay(&tv);
748                         tdif = usec_time_diff(&msg->end_time, &tv);
749                         if (tdif <= 0) {
750                                 /* Timed out. Schedule...*/
751                                 pop_message = True;
752                                 DEBUG(10,("receive_message_or_smb: queued message timed out.\n"));
753                         } else {
754                                 /* Make a more accurate select timeout. */
755                                 to.tv_sec = tdif / 1000000;
756                                 to.tv_usec = tdif % 1000000;
757                                 DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
758                                         (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
759                         }
760                 }
761
762                 if (pop_message) {
763
764                         *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data,
765                                                         msg->buf.length);
766                         if (*buffer == NULL) {
767                                 DEBUG(0, ("talloc failed\n"));
768                                 return NT_STATUS_NO_MEMORY;
769                         }
770                         *buffer_len = msg->buf.length;
771                         *p_encrypted = msg->encrypted;
772
773                         /* We leave this message on the queue so the open code can
774                            know this is a retry. */
775                         DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n"));
776                         return NT_STATUS_OK;
777                 }
778         }
779
780         /*
781          * Setup the select fd sets.
782          */
783
784         FD_ZERO(&r_fds);
785         FD_ZERO(&w_fds);
786
787         /*
788          * Ensure we process oplock break messages by preference.
789          * We have to do this before the select, after the select
790          * and if the select returns EINTR. This is due to the fact
791          * that the selects called from async_processing can eat an EINTR
792          * caused by a signal (we can't take the break message there).
793          * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
794          */
795
796         if (oplock_message_waiting(&r_fds)) {
797                 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
798                 async_processing(&r_fds);
799                 /*
800                  * After async processing we must go and do the select again, as
801                  * the state of the flag in fds for the server file descriptor is
802                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
803                  */
804                 goto again;
805         }
806
807         /*
808          * Are there any timed events waiting ? If so, ensure we don't
809          * select for longer than it would take to wait for them.
810          */
811
812         {
813                 struct timeval now;
814                 GetTimeOfDay(&now);
815
816                 event_add_to_select_args(smbd_event_context(), &now,
817                                          &r_fds, &w_fds, &to, &maxfd);
818         }
819
820         if (timeval_is_zero(&to)) {
821                 /* Process a timed event now... */
822                 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
823                         goto again;
824                 }
825         }
826         
827         {
828                 int sav;
829                 START_PROFILE(smbd_idle);
830
831                 maxfd = select_on_fd(smbd_server_fd(), maxfd, &r_fds);
832                 maxfd = select_on_fd(oplock_notify_fd(), maxfd, &r_fds);
833
834                 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
835                 sav = errno;
836
837                 END_PROFILE(smbd_idle);
838                 errno = sav;
839         }
840
841         if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
842                 goto again;
843         }
844
845         /* if we get EINTR then maybe we have received an oplock
846            signal - treat this as select returning 1. This is ugly, but
847            is the best we can do until the oplock code knows more about
848            signals */
849         if (selrtn == -1 && errno == EINTR) {
850                 async_processing(&r_fds);
851                 /*
852                  * After async processing we must go and do the select again, as
853                  * the state of the flag in fds for the server file descriptor is
854                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
855                  */
856                 goto again;
857         }
858
859         /* Check if error */
860         if (selrtn == -1) {
861                 /* something is wrong. Maybe the socket is dead? */
862                 return map_nt_error_from_unix(errno);
863         }
864
865         /* Did we timeout ? */
866         if (selrtn == 0) {
867                 goto again;
868         }
869
870         /*
871          * Ensure we process oplock break messages by preference.
872          * This is IMPORTANT ! Otherwise we can starve other processes
873          * sending us an oplock break message. JRA.
874          */
875
876         if (oplock_message_waiting(&r_fds)) {
877                 async_processing(&r_fds);
878                 /*
879                  * After async processing we must go and do the select again, as
880                  * the state of the flag in fds for the server file descriptor is
881                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
882                  */
883                 goto again;
884         }
885
886         /*
887          * We've just woken up from a protentially long select sleep.
888          * Ensure we process local messages as we need to synchronously
889          * process any messages from other smbd's to avoid file rename race
890          * conditions. This call is cheap if there are no messages waiting.
891          * JRA.
892          */
893         message_dispatch(smbd_messaging_context());
894
895         status = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0,
896                                     p_unread, p_encrypted, &len);
897
898         if (!NT_STATUS_IS_OK(status)) {
899                 return status;
900         }
901
902         *buffer_len = len;
903
904         return NT_STATUS_OK;
905 }
906
907 /*
908  * Only allow 5 outstanding trans requests. We're allocating memory, so
909  * prevent a DoS.
910  */
911
912 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
913 {
914         int count = 0;
915         for (; list != NULL; list = list->next) {
916
917                 if (list->mid == mid) {
918                         return NT_STATUS_INVALID_PARAMETER;
919                 }
920
921                 count += 1;
922         }
923         if (count > 5) {
924                 return NT_STATUS_INSUFFICIENT_RESOURCES;
925         }
926
927         return NT_STATUS_OK;
928 }
929
930 /****************************************************************************
931  We're terminating and have closed all our files/connections etc.
932  If there are any pending local messages we need to respond to them
933  before termination so that other smbds don't think we just died whilst
934  holding oplocks.
935 ****************************************************************************/
936
937 void respond_to_all_remaining_local_messages(void)
938 {
939         /*
940          * Assert we have no exclusive open oplocks.
941          */
942
943         if(get_number_of_exclusive_open_oplocks()) {
944                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
945                         get_number_of_exclusive_open_oplocks() ));
946                 return;
947         }
948
949         process_kernel_oplocks(smbd_messaging_context(), NULL);
950
951         return;
952 }
953
954
955 /*
956 These flags determine some of the permissions required to do an operation 
957
958 Note that I don't set NEED_WRITE on some write operations because they
959 are used by some brain-dead clients when printing, and I don't want to
960 force write permissions on print services.
961 */
962 #define AS_USER (1<<0)
963 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
964 #define TIME_INIT (1<<2)
965 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
966 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
967 #define DO_CHDIR (1<<6)
968
969 /* 
970    define a list of possible SMB messages and their corresponding
971    functions. Any message that has a NULL function is unimplemented -
972    please feel free to contribute implementations!
973 */
974 static const struct smb_message_struct {
975         const char *name;
976         void (*fn_new)(struct smb_request *req);
977         int flags;
978 } smb_messages[256] = {
979
980 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
981 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
982 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
983 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
984 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
985 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
986 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
987 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
988 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
989 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
990 /* 0x0a */ { "SMBread",reply_read,AS_USER},
991 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
992 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
993 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
994 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
995 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
996 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
997 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
998 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
999 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
1000 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
1001 /* 0x15 */ { NULL, NULL, 0 },
1002 /* 0x16 */ { NULL, NULL, 0 },
1003 /* 0x17 */ { NULL, NULL, 0 },
1004 /* 0x18 */ { NULL, NULL, 0 },
1005 /* 0x19 */ { NULL, NULL, 0 },
1006 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
1007 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
1008 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
1009 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
1010 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
1011 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
1012 /* 0x20 */ { "SMBwritec", NULL,0},
1013 /* 0x21 */ { NULL, NULL, 0 },
1014 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
1015 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
1016 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
1017 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
1018 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
1019 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
1020 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
1021 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
1022 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
1023 /* 0x2b */ { "SMBecho",reply_echo,0},
1024 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
1025 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
1026 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
1027 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
1028 /* 0x30 */ { NULL, NULL, 0 },
1029 /* 0x31 */ { NULL, NULL, 0 },
1030 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
1031 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
1032 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
1033 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
1034 /* 0x36 */ { NULL, NULL, 0 },
1035 /* 0x37 */ { NULL, NULL, 0 },
1036 /* 0x38 */ { NULL, NULL, 0 },
1037 /* 0x39 */ { NULL, NULL, 0 },
1038 /* 0x3a */ { NULL, NULL, 0 },
1039 /* 0x3b */ { NULL, NULL, 0 },
1040 /* 0x3c */ { NULL, NULL, 0 },
1041 /* 0x3d */ { NULL, NULL, 0 },
1042 /* 0x3e */ { NULL, NULL, 0 },
1043 /* 0x3f */ { NULL, NULL, 0 },
1044 /* 0x40 */ { NULL, NULL, 0 },
1045 /* 0x41 */ { NULL, NULL, 0 },
1046 /* 0x42 */ { NULL, NULL, 0 },
1047 /* 0x43 */ { NULL, NULL, 0 },
1048 /* 0x44 */ { NULL, NULL, 0 },
1049 /* 0x45 */ { NULL, NULL, 0 },
1050 /* 0x46 */ { NULL, NULL, 0 },
1051 /* 0x47 */ { NULL, NULL, 0 },
1052 /* 0x48 */ { NULL, NULL, 0 },
1053 /* 0x49 */ { NULL, NULL, 0 },
1054 /* 0x4a */ { NULL, NULL, 0 },
1055 /* 0x4b */ { NULL, NULL, 0 },
1056 /* 0x4c */ { NULL, NULL, 0 },
1057 /* 0x4d */ { NULL, NULL, 0 },
1058 /* 0x4e */ { NULL, NULL, 0 },
1059 /* 0x4f */ { NULL, NULL, 0 },
1060 /* 0x50 */ { NULL, NULL, 0 },
1061 /* 0x51 */ { NULL, NULL, 0 },
1062 /* 0x52 */ { NULL, NULL, 0 },
1063 /* 0x53 */ { NULL, NULL, 0 },
1064 /* 0x54 */ { NULL, NULL, 0 },
1065 /* 0x55 */ { NULL, NULL, 0 },
1066 /* 0x56 */ { NULL, NULL, 0 },
1067 /* 0x57 */ { NULL, NULL, 0 },
1068 /* 0x58 */ { NULL, NULL, 0 },
1069 /* 0x59 */ { NULL, NULL, 0 },
1070 /* 0x5a */ { NULL, NULL, 0 },
1071 /* 0x5b */ { NULL, NULL, 0 },
1072 /* 0x5c */ { NULL, NULL, 0 },
1073 /* 0x5d */ { NULL, NULL, 0 },
1074 /* 0x5e */ { NULL, NULL, 0 },
1075 /* 0x5f */ { NULL, NULL, 0 },
1076 /* 0x60 */ { NULL, NULL, 0 },
1077 /* 0x61 */ { NULL, NULL, 0 },
1078 /* 0x62 */ { NULL, NULL, 0 },
1079 /* 0x63 */ { NULL, NULL, 0 },
1080 /* 0x64 */ { NULL, NULL, 0 },
1081 /* 0x65 */ { NULL, NULL, 0 },
1082 /* 0x66 */ { NULL, NULL, 0 },
1083 /* 0x67 */ { NULL, NULL, 0 },
1084 /* 0x68 */ { NULL, NULL, 0 },
1085 /* 0x69 */ { NULL, NULL, 0 },
1086 /* 0x6a */ { NULL, NULL, 0 },
1087 /* 0x6b */ { NULL, NULL, 0 },
1088 /* 0x6c */ { NULL, NULL, 0 },
1089 /* 0x6d */ { NULL, NULL, 0 },
1090 /* 0x6e */ { NULL, NULL, 0 },
1091 /* 0x6f */ { NULL, NULL, 0 },
1092 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1093 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1094 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1095 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1096 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1097 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1098 /* 0x76 */ { NULL, NULL, 0 },
1099 /* 0x77 */ { NULL, NULL, 0 },
1100 /* 0x78 */ { NULL, NULL, 0 },
1101 /* 0x79 */ { NULL, NULL, 0 },
1102 /* 0x7a */ { NULL, NULL, 0 },
1103 /* 0x7b */ { NULL, NULL, 0 },
1104 /* 0x7c */ { NULL, NULL, 0 },
1105 /* 0x7d */ { NULL, NULL, 0 },
1106 /* 0x7e */ { NULL, NULL, 0 },
1107 /* 0x7f */ { NULL, NULL, 0 },
1108 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1109 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1110 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1111 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1112 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1113 /* 0x85 */ { NULL, NULL, 0 },
1114 /* 0x86 */ { NULL, NULL, 0 },
1115 /* 0x87 */ { NULL, NULL, 0 },
1116 /* 0x88 */ { NULL, NULL, 0 },
1117 /* 0x89 */ { NULL, NULL, 0 },
1118 /* 0x8a */ { NULL, NULL, 0 },
1119 /* 0x8b */ { NULL, NULL, 0 },
1120 /* 0x8c */ { NULL, NULL, 0 },
1121 /* 0x8d */ { NULL, NULL, 0 },
1122 /* 0x8e */ { NULL, NULL, 0 },
1123 /* 0x8f */ { NULL, NULL, 0 },
1124 /* 0x90 */ { NULL, NULL, 0 },
1125 /* 0x91 */ { NULL, NULL, 0 },
1126 /* 0x92 */ { NULL, NULL, 0 },
1127 /* 0x93 */ { NULL, NULL, 0 },
1128 /* 0x94 */ { NULL, NULL, 0 },
1129 /* 0x95 */ { NULL, NULL, 0 },
1130 /* 0x96 */ { NULL, NULL, 0 },
1131 /* 0x97 */ { NULL, NULL, 0 },
1132 /* 0x98 */ { NULL, NULL, 0 },
1133 /* 0x99 */ { NULL, NULL, 0 },
1134 /* 0x9a */ { NULL, NULL, 0 },
1135 /* 0x9b */ { NULL, NULL, 0 },
1136 /* 0x9c */ { NULL, NULL, 0 },
1137 /* 0x9d */ { NULL, NULL, 0 },
1138 /* 0x9e */ { NULL, NULL, 0 },
1139 /* 0x9f */ { NULL, NULL, 0 },
1140 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1141 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1142 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1143 /* 0xa3 */ { NULL, NULL, 0 },
1144 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1145 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1146 /* 0xa6 */ { NULL, NULL, 0 },
1147 /* 0xa7 */ { NULL, NULL, 0 },
1148 /* 0xa8 */ { NULL, NULL, 0 },
1149 /* 0xa9 */ { NULL, NULL, 0 },
1150 /* 0xaa */ { NULL, NULL, 0 },
1151 /* 0xab */ { NULL, NULL, 0 },
1152 /* 0xac */ { NULL, NULL, 0 },
1153 /* 0xad */ { NULL, NULL, 0 },
1154 /* 0xae */ { NULL, NULL, 0 },
1155 /* 0xaf */ { NULL, NULL, 0 },
1156 /* 0xb0 */ { NULL, NULL, 0 },
1157 /* 0xb1 */ { NULL, NULL, 0 },
1158 /* 0xb2 */ { NULL, NULL, 0 },
1159 /* 0xb3 */ { NULL, NULL, 0 },
1160 /* 0xb4 */ { NULL, NULL, 0 },
1161 /* 0xb5 */ { NULL, NULL, 0 },
1162 /* 0xb6 */ { NULL, NULL, 0 },
1163 /* 0xb7 */ { NULL, NULL, 0 },
1164 /* 0xb8 */ { NULL, NULL, 0 },
1165 /* 0xb9 */ { NULL, NULL, 0 },
1166 /* 0xba */ { NULL, NULL, 0 },
1167 /* 0xbb */ { NULL, NULL, 0 },
1168 /* 0xbc */ { NULL, NULL, 0 },
1169 /* 0xbd */ { NULL, NULL, 0 },
1170 /* 0xbe */ { NULL, NULL, 0 },
1171 /* 0xbf */ { NULL, NULL, 0 },
1172 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1173 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1174 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1175 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1176 /* 0xc4 */ { NULL, NULL, 0 },
1177 /* 0xc5 */ { NULL, NULL, 0 },
1178 /* 0xc6 */ { NULL, NULL, 0 },
1179 /* 0xc7 */ { NULL, NULL, 0 },
1180 /* 0xc8 */ { NULL, NULL, 0 },
1181 /* 0xc9 */ { NULL, NULL, 0 },
1182 /* 0xca */ { NULL, NULL, 0 },
1183 /* 0xcb */ { NULL, NULL, 0 },
1184 /* 0xcc */ { NULL, NULL, 0 },
1185 /* 0xcd */ { NULL, NULL, 0 },
1186 /* 0xce */ { NULL, NULL, 0 },
1187 /* 0xcf */ { NULL, NULL, 0 },
1188 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1189 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1190 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1191 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1192 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1193 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1194 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1195 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1196 /* 0xd8 */ { NULL, NULL, 0 },
1197 /* 0xd9 */ { NULL, NULL, 0 },
1198 /* 0xda */ { NULL, NULL, 0 },
1199 /* 0xdb */ { NULL, NULL, 0 },
1200 /* 0xdc */ { NULL, NULL, 0 },
1201 /* 0xdd */ { NULL, NULL, 0 },
1202 /* 0xde */ { NULL, NULL, 0 },
1203 /* 0xdf */ { NULL, NULL, 0 },
1204 /* 0xe0 */ { NULL, NULL, 0 },
1205 /* 0xe1 */ { NULL, NULL, 0 },
1206 /* 0xe2 */ { NULL, NULL, 0 },
1207 /* 0xe3 */ { NULL, NULL, 0 },
1208 /* 0xe4 */ { NULL, NULL, 0 },
1209 /* 0xe5 */ { NULL, NULL, 0 },
1210 /* 0xe6 */ { NULL, NULL, 0 },
1211 /* 0xe7 */ { NULL, NULL, 0 },
1212 /* 0xe8 */ { NULL, NULL, 0 },
1213 /* 0xe9 */ { NULL, NULL, 0 },
1214 /* 0xea */ { NULL, NULL, 0 },
1215 /* 0xeb */ { NULL, NULL, 0 },
1216 /* 0xec */ { NULL, NULL, 0 },
1217 /* 0xed */ { NULL, NULL, 0 },
1218 /* 0xee */ { NULL, NULL, 0 },
1219 /* 0xef */ { NULL, NULL, 0 },
1220 /* 0xf0 */ { NULL, NULL, 0 },
1221 /* 0xf1 */ { NULL, NULL, 0 },
1222 /* 0xf2 */ { NULL, NULL, 0 },
1223 /* 0xf3 */ { NULL, NULL, 0 },
1224 /* 0xf4 */ { NULL, NULL, 0 },
1225 /* 0xf5 */ { NULL, NULL, 0 },
1226 /* 0xf6 */ { NULL, NULL, 0 },
1227 /* 0xf7 */ { NULL, NULL, 0 },
1228 /* 0xf8 */ { NULL, NULL, 0 },
1229 /* 0xf9 */ { NULL, NULL, 0 },
1230 /* 0xfa */ { NULL, NULL, 0 },
1231 /* 0xfb */ { NULL, NULL, 0 },
1232 /* 0xfc */ { NULL, NULL, 0 },
1233 /* 0xfd */ { NULL, NULL, 0 },
1234 /* 0xfe */ { NULL, NULL, 0 },
1235 /* 0xff */ { NULL, NULL, 0 }
1236
1237 };
1238
1239 /*******************************************************************
1240  allocate and initialize a reply packet
1241 ********************************************************************/
1242
1243 bool create_outbuf(TALLOC_CTX *mem_ctx, const char *inbuf, char **outbuf,
1244                    uint8_t num_words, uint32_t num_bytes)
1245 {
1246         /*
1247          * Protect against integer wrap
1248          */
1249         if ((num_bytes > 0xffffff)
1250             || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1251                 char *msg;
1252                 if (asprintf(&msg, "num_bytes too large: %u",
1253                              (unsigned)num_bytes) == -1) {
1254                         msg = CONST_DISCARD(char *, "num_bytes too large");
1255                 }
1256                 smb_panic(msg);
1257         }
1258
1259         *outbuf = TALLOC_ARRAY(mem_ctx, char,
1260                                smb_size + num_words*2 + num_bytes);
1261         if (*outbuf == NULL) {
1262                 return false;
1263         }
1264
1265         construct_reply_common(inbuf, *outbuf);
1266         srv_set_message(*outbuf, num_words, num_bytes, false);
1267         /*
1268          * Zero out the word area, the caller has to take care of the bcc area
1269          * himself
1270          */
1271         if (num_words != 0) {
1272                 memset(*outbuf + smb_vwv0, 0, num_words*2);
1273         }
1274
1275         return true;
1276 }
1277
1278 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1279 {
1280         char *outbuf;
1281         if (!create_outbuf(req, (char *)req->inbuf, &outbuf, num_words,
1282                            num_bytes)) {
1283                 smb_panic("could not allocate output buffer\n");
1284         }
1285         req->outbuf = (uint8_t *)outbuf;
1286 }
1287
1288
1289 /*******************************************************************
1290  Dump a packet to a file.
1291 ********************************************************************/
1292
1293 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1294 {
1295         int fd, i;
1296         char *fname = NULL;
1297         if (DEBUGLEVEL < 50) {
1298                 return;
1299         }
1300
1301         if (len < 4) len = smb_len(data)+4;
1302         for (i=1;i<100;i++) {
1303                 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1304                              type ? "req" : "resp") == -1) {
1305                         return;
1306                 }
1307                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1308                 if (fd != -1 || errno != EEXIST) break;
1309         }
1310         if (fd != -1) {
1311                 ssize_t ret = write(fd, data, len);
1312                 if (ret != len)
1313                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1314                 close(fd);
1315                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1316         }
1317         SAFE_FREE(fname);
1318 }
1319
1320 /****************************************************************************
1321  Prepare everything for calling the actual request function, and potentially
1322  call the request function via the "new" interface.
1323
1324  Return False if the "legacy" function needs to be called, everything is
1325  prepared.
1326
1327  Return True if we're done.
1328
1329  I know this API sucks, but it is the one with the least code change I could
1330  find.
1331 ****************************************************************************/
1332
1333 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1334 {
1335         int flags;
1336         uint16 session_tag;
1337         connection_struct *conn = NULL;
1338
1339         static uint16 last_session_tag = UID_FIELD_INVALID;
1340
1341         errno = 0;
1342
1343         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1344          * so subtract 4 from it. */
1345         if (!valid_smb_header(req->inbuf)
1346             || (size < (smb_size - 4))) {
1347                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1348                          smb_len(req->inbuf)));
1349                 exit_server_cleanly("Non-SMB packet");
1350         }
1351
1352         if (smb_messages[type].fn_new == NULL) {
1353                 DEBUG(0,("Unknown message type %d!\n",type));
1354                 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1355                 reply_unknown_new(req, type);
1356                 return NULL;
1357         }
1358
1359         flags = smb_messages[type].flags;
1360
1361         /* In share mode security we must ignore the vuid. */
1362         session_tag = (lp_security() == SEC_SHARE)
1363                 ? UID_FIELD_INVALID : req->vuid;
1364         conn = req->conn;
1365
1366         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1367                  (int)sys_getpid(), (unsigned long)conn));
1368
1369         smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1370
1371         /* Ensure this value is replaced in the incoming packet. */
1372         SSVAL(req->inbuf,smb_uid,session_tag);
1373
1374         /*
1375          * Ensure the correct username is in current_user_info.  This is a
1376          * really ugly bugfix for problems with multiple session_setup_and_X's
1377          * being done and allowing %U and %G substitutions to work correctly.
1378          * There is a reason this code is done here, don't move it unless you
1379          * know what you're doing... :-).
1380          * JRA.
1381          */
1382
1383         if (session_tag != last_session_tag) {
1384                 user_struct *vuser = NULL;
1385
1386                 last_session_tag = session_tag;
1387                 if(session_tag != UID_FIELD_INVALID) {
1388                         vuser = get_valid_user_struct(session_tag);
1389                         if (vuser) {
1390                                 set_current_user_info(
1391                                         vuser->server_info->sanitized_username,
1392                                         vuser->server_info->unix_name,
1393                                         pdb_get_fullname(vuser->server_info
1394                                                          ->sam_account),
1395                                         pdb_get_domain(vuser->server_info
1396                                                        ->sam_account));
1397                         }
1398                 }
1399         }
1400
1401         /* Does this call need to be run as the connected user? */
1402         if (flags & AS_USER) {
1403
1404                 /* Does this call need a valid tree connection? */
1405                 if (!conn) {
1406                         /*
1407                          * Amazingly, the error code depends on the command
1408                          * (from Samba4).
1409                          */
1410                         if (type == SMBntcreateX) {
1411                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1412                         } else {
1413                                 reply_doserror(req, ERRSRV, ERRinvnid);
1414                         }
1415                         return NULL;
1416                 }
1417
1418                 if (!change_to_user(conn,session_tag)) {
1419                         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1420                         return conn;
1421                 }
1422
1423                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1424
1425                 /* Does it need write permission? */
1426                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1427                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1428                         return conn;
1429                 }
1430
1431                 /* IPC services are limited */
1432                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1433                         reply_doserror(req, ERRSRV,ERRaccess);
1434                         return conn;
1435                 }
1436         } else {
1437                 /* This call needs to be run as root */
1438                 change_to_root_user();
1439         }
1440
1441         /* load service specific parameters */
1442         if (conn) {
1443                 if (req->encrypted) {
1444                         conn->encrypted_tid = true;
1445                         /* encrypted required from now on. */
1446                         conn->encrypt_level = Required;
1447                 } else if (ENCRYPTION_REQUIRED(conn)) {
1448                         uint8 com = CVAL(req->inbuf,smb_com);
1449                         if (com != SMBtrans2 && com != SMBtranss2) {
1450                                 exit_server_cleanly("encryption required "
1451                                         "on connection");
1452                                 return conn;
1453                         }
1454                 }
1455
1456                 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1457                                          (flags & (AS_USER|DO_CHDIR)
1458                                           ?True:False))) {
1459                         reply_doserror(req, ERRSRV, ERRaccess);
1460                         return conn;
1461                 }
1462                 conn->num_smb_operations++;
1463         }
1464
1465         /* does this protocol need to be run as guest? */
1466         if ((flags & AS_GUEST)
1467             && (!change_to_guest() ||
1468                 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1469                               lp_hostsdeny(-1)))) {
1470                 reply_doserror(req, ERRSRV, ERRaccess);
1471                 return conn;
1472         }
1473
1474         smb_messages[type].fn_new(req);
1475         return req->conn;
1476 }
1477
1478 /****************************************************************************
1479  Construct a reply to the incoming packet.
1480 ****************************************************************************/
1481
1482 static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
1483 {
1484         uint8 type = CVAL(inbuf,smb_com);
1485         connection_struct *conn;
1486         struct smb_request *req;
1487
1488         chain_size = 0;
1489         file_chain_reset();
1490         reset_chain_p();
1491
1492         if (!(req = talloc(talloc_tos(), struct smb_request))) {
1493                 smb_panic("could not allocate smb_request");
1494         }
1495         init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1496
1497         conn = switch_message(type, req, size);
1498
1499         if (req->unread_bytes) {
1500                 /* writeX failed. drain socket. */
1501                 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1502                                 req->unread_bytes) {
1503                         smb_panic("failed to drain pending bytes");
1504                 }
1505                 req->unread_bytes = 0;
1506         }
1507
1508         if (req->outbuf == NULL) {
1509                 return;
1510         }
1511
1512         if (CVAL(req->outbuf,0) == 0) {
1513                 show_msg((char *)req->outbuf);
1514         }
1515
1516         if (!srv_send_smb(smbd_server_fd(),
1517                         (char *)req->outbuf,
1518                         IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
1519                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1520         }
1521
1522         TALLOC_FREE(req);
1523
1524         return;
1525 }
1526
1527 /****************************************************************************
1528  Process an smb from the client
1529 ****************************************************************************/
1530
1531 static void process_smb(char *inbuf, size_t nread, size_t unread_bytes, bool encrypted)
1532 {
1533         static int trans_num;
1534         int msg_type = CVAL(inbuf,0);
1535
1536         DO_PROFILE_INC(smb_count);
1537
1538         if (trans_num == 0) {
1539                 char addr[INET6_ADDRSTRLEN];
1540
1541                 /* on the first packet, check the global hosts allow/ hosts
1542                 deny parameters before doing any parsing of the packet
1543                 passed to us by the client.  This prevents attacks on our
1544                 parsing code from hosts not in the hosts allow list */
1545
1546                 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1547                                   lp_hostsdeny(-1))) {
1548                         /* send a negative session response "not listening on calling name" */
1549                         static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1550                         DEBUG( 1, ( "Connection denied from %s\n",
1551                                 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
1552                         (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
1553                         exit_server_cleanly("connection denied");
1554                 }
1555         }
1556
1557         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1558                     smb_len(inbuf) ) );
1559         DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1560                                 (int)nread,
1561                                 (unsigned int)unread_bytes ));
1562
1563         if (msg_type != 0) {
1564                 /*
1565                  * NetBIOS session request, keepalive, etc.
1566                  */
1567                 reply_special(inbuf);
1568                 return;
1569         }
1570
1571         show_msg(inbuf);
1572
1573         construct_reply(inbuf,nread,unread_bytes,encrypted);
1574
1575         trans_num++;
1576 }
1577
1578 /****************************************************************************
1579  Return a string containing the function name of a SMB command.
1580 ****************************************************************************/
1581
1582 const char *smb_fn_name(int type)
1583 {
1584         const char *unknown_name = "SMBunknown";
1585
1586         if (smb_messages[type].name == NULL)
1587                 return(unknown_name);
1588
1589         return(smb_messages[type].name);
1590 }
1591
1592 /****************************************************************************
1593  Helper functions for contruct_reply.
1594 ****************************************************************************/
1595
1596 static uint32 common_flags2 = FLAGS2_LONG_PATH_COMPONENTS|FLAGS2_32_BIT_ERROR_CODES;
1597
1598 void add_to_common_flags2(uint32 v)
1599 {
1600         common_flags2 |= v;
1601 }
1602
1603 void remove_from_common_flags2(uint32 v)
1604 {
1605         common_flags2 &= ~v;
1606 }
1607
1608 void construct_reply_common(const char *inbuf, char *outbuf)
1609 {
1610         srv_set_message(outbuf,0,0,false);
1611         
1612         SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
1613         SIVAL(outbuf,smb_rcls,0);
1614         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1615         SSVAL(outbuf,smb_flg2,
1616                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1617                 common_flags2);
1618         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1619
1620         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1621         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1622         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1623         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1624 }
1625
1626 /****************************************************************************
1627  Construct a chained reply and add it to the already made reply
1628 ****************************************************************************/
1629
1630 void chain_reply(struct smb_request *req)
1631 {
1632         static char *orig_inbuf;
1633
1634         /*
1635          * Dirty little const_discard: We mess with req->inbuf, which is
1636          * declared as const. If maybe at some point this routine gets
1637          * rewritten, this const_discard could go away.
1638          */
1639         char *inbuf = CONST_DISCARD(char *, req->inbuf);
1640         int size = smb_len(req->inbuf)+4;
1641
1642         int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0);
1643         unsigned smb_off2 = SVAL(inbuf,smb_vwv1);
1644         char *inbuf2;
1645         int outsize2;
1646         int new_size;
1647         char inbuf_saved[smb_wct];
1648         char *outbuf = (char *)req->outbuf;
1649         size_t outsize = smb_len(outbuf) + 4;
1650         size_t outsize_padded;
1651         size_t padding;
1652         size_t ofs, to_move;
1653
1654         struct smb_request *req2;
1655         size_t caller_outputlen;
1656         char *caller_output;
1657
1658         /* Maybe its not chained, or it's an error packet. */
1659         if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) {
1660                 SCVAL(outbuf,smb_vwv0,0xFF);
1661                 return;
1662         }
1663
1664         if (chain_size == 0) {
1665                 /* this is the first part of the chain */
1666                 orig_inbuf = inbuf;
1667         }
1668
1669         /*
1670          * We need to save the output the caller added to the chain so that we
1671          * can splice it into the final output buffer later.
1672          */
1673
1674         caller_outputlen = outsize - smb_wct;
1675
1676         caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen);
1677
1678         if (caller_output == NULL) {
1679                 /* TODO: NT_STATUS_NO_MEMORY */
1680                 smb_panic("could not dup outbuf");
1681         }
1682
1683         /*
1684          * The original Win95 redirector dies on a reply to
1685          * a lockingX and read chain unless the chain reply is
1686          * 4 byte aligned. JRA.
1687          */
1688
1689         outsize_padded = (outsize + 3) & ~3;
1690         padding = outsize_padded - outsize;
1691
1692         /*
1693          * remember how much the caller added to the chain, only counting
1694          * stuff after the parameter words
1695          */
1696         chain_size += (outsize_padded - smb_wct);
1697
1698         /*
1699          * work out pointers into the original packets. The
1700          * headers on these need to be filled in
1701          */
1702         inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct;
1703
1704         /* remember the original command type */
1705         smb_com1 = CVAL(orig_inbuf,smb_com);
1706
1707         /* save the data which will be overwritten by the new headers */
1708         memcpy(inbuf_saved,inbuf2,smb_wct);
1709
1710         /* give the new packet the same header as the last part of the SMB */
1711         memmove(inbuf2,inbuf,smb_wct);
1712
1713         /* create the in buffer */
1714         SCVAL(inbuf2,smb_com,smb_com2);
1715
1716         /* work out the new size for the in buffer. */
1717         new_size = size - (inbuf2 - inbuf);
1718         if (new_size < 0) {
1719                 DEBUG(0,("chain_reply: chain packet size incorrect "
1720                          "(orig size = %d, offset = %d)\n",
1721                          size, (int)(inbuf2 - inbuf) ));
1722                 exit_server_cleanly("Bad chained packet");
1723                 return;
1724         }
1725
1726         /* And set it in the header. */
1727         smb_setlen(inbuf2, new_size - 4);
1728
1729         DEBUG(3,("Chained message\n"));
1730         show_msg(inbuf2);
1731
1732         if (!(req2 = talloc(talloc_tos(), struct smb_request))) {
1733                 smb_panic("could not allocate smb_request");
1734         }
1735         init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted);
1736
1737         /* process the request */
1738         switch_message(smb_com2, req2, new_size);
1739
1740         /*
1741          * We don't accept deferred operations in chained requests.
1742          */
1743         SMB_ASSERT(req2->outbuf != NULL);
1744         outsize2 = smb_len(req2->outbuf)+4;
1745
1746         /*
1747          * Move away the new command output so that caller_output fits in,
1748          * copy in the caller_output saved above.
1749          */
1750
1751         SMB_ASSERT(outsize_padded >= smb_wct);
1752
1753         /*
1754          * "ofs" is the space we need for caller_output. Equal to
1755          * caller_outputlen plus the padding.
1756          */
1757
1758         ofs = outsize_padded - smb_wct;
1759
1760         /*
1761          * "to_move" is the amount of bytes the secondary routine gave us
1762          */
1763
1764         to_move = outsize2 - smb_wct;
1765
1766         if (to_move + ofs + smb_wct + chain_size > max_send) {
1767                 smb_panic("replies too large -- would have to cut");
1768         }
1769
1770         /*
1771          * In the "new" API "outbuf" is allocated via reply_outbuf, just for
1772          * the first request in the chain. So we have to re-allocate it. In
1773          * the "old" API the only outbuf ever used is the global OutBuffer
1774          * which is always large enough.
1775          */
1776
1777         outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char,
1778                                       to_move + ofs + smb_wct);
1779         if (outbuf == NULL) {
1780                 smb_panic("could not realloc outbuf");
1781         }
1782
1783         req->outbuf = (uint8 *)outbuf;
1784
1785         memmove(outbuf + smb_wct + ofs, req2->outbuf + smb_wct, to_move);
1786         memcpy(outbuf + smb_wct, caller_output, caller_outputlen);
1787
1788         /*
1789          * copy the new reply header over the old one but preserve the smb_com
1790          * field
1791          */
1792         memmove(outbuf, req2->outbuf, smb_wct);
1793         SCVAL(outbuf, smb_com, smb_com1);
1794
1795         /*
1796          * We've just copied in the whole "wct" area from the secondary
1797          * function. Fix up the chaining: com2 and the offset need to be
1798          * readjusted.
1799          */
1800
1801         SCVAL(outbuf, smb_vwv0, smb_com2);
1802         SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4);
1803
1804         if (padding != 0) {
1805
1806                 /*
1807                  * Due to padding we have some uninitialized bytes after the
1808                  * caller's output
1809                  */
1810
1811                 memset(outbuf + outsize, 0, padding);
1812         }
1813
1814         smb_setlen(outbuf, outsize2 + caller_outputlen + padding - 4);
1815
1816         /*
1817          * restore the saved data, being careful not to overwrite any data
1818          * from the reply header
1819          */
1820         memcpy(inbuf2,inbuf_saved,smb_wct);
1821
1822         SAFE_FREE(caller_output);
1823         TALLOC_FREE(req2);
1824
1825         /*
1826          * Reset the chain_size for our caller's offset calculations
1827          */
1828
1829         chain_size -= (outsize_padded - smb_wct);
1830
1831         return;
1832 }
1833
1834 /****************************************************************************
1835  Check if services need reloading.
1836 ****************************************************************************/
1837
1838 void check_reload(time_t t)
1839 {
1840         static pid_t mypid = 0;
1841         static time_t last_smb_conf_reload_time = 0;
1842         static time_t last_printer_reload_time = 0;
1843         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1844
1845         if(last_smb_conf_reload_time == 0) {
1846                 last_smb_conf_reload_time = t;
1847                 /* Our printing subsystem might not be ready at smbd start up.
1848                    Then no printer is available till the first printers check
1849                    is performed.  A lower initial interval circumvents this. */
1850                 if ( printcap_cache_time > 60 )
1851                         last_printer_reload_time = t - printcap_cache_time + 60;
1852                 else
1853                         last_printer_reload_time = t;
1854         }
1855
1856         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1857                 /* randomize over 60 second the printcap reload to avoid all
1858                  * process hitting cupsd at the same time */
1859                 int time_range = 60;
1860
1861                 last_printer_reload_time += random() % time_range;
1862                 mypid = getpid();
1863         }
1864
1865         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1866                 reload_services(True);
1867                 reload_after_sighup = False;
1868                 last_smb_conf_reload_time = t;
1869         }
1870
1871         /* 'printcap cache time = 0' disable the feature */
1872         
1873         if ( printcap_cache_time != 0 )
1874         { 
1875                 /* see if it's time to reload or if the clock has been set back */
1876                 
1877                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1878                         || (t-last_printer_reload_time  < 0) ) 
1879                 {
1880                         DEBUG( 3,( "Printcap cache time expired.\n"));
1881                         reload_printers();
1882                         last_printer_reload_time = t;
1883                 }
1884         }
1885 }
1886
1887 /****************************************************************************
1888  Process commands from the client
1889 ****************************************************************************/
1890
1891 void smbd_process(void)
1892 {
1893         unsigned int num_smbs = 0;
1894         size_t unread_bytes = 0;
1895
1896         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1897
1898         while (True) {
1899                 NTSTATUS status;
1900                 char *inbuf = NULL;
1901                 size_t inbuf_len = 0;
1902                 bool encrypted = false;
1903                 TALLOC_CTX *frame = talloc_stackframe_pool(8192);
1904
1905                 errno = 0;
1906
1907                 run_events(smbd_event_context(), 0, NULL, NULL);
1908
1909                 status = receive_message_or_smb(
1910                         talloc_tos(), &inbuf, &inbuf_len,
1911                         &unread_bytes, &encrypted);
1912
1913                 if (!NT_STATUS_IS_OK(status)) {
1914                         DEBUG(3, ("receive_message_or_smb failed: %s, "
1915                                   "exiting\n", nt_errstr(status)));
1916                         return;
1917                 }
1918
1919                 process_smb(inbuf, inbuf_len, unread_bytes, encrypted);
1920
1921                 TALLOC_FREE(inbuf);
1922
1923                 num_smbs++;
1924
1925                 /* The timeout_processing function isn't run nearly
1926                    often enough to implement 'max log size' without
1927                    overrunning the size of the file by many megabytes.
1928                    This is especially true if we are running at debug
1929                    level 10.  Checking every 50 SMBs is a nice
1930                    tradeoff of performance vs log file size overrun. */
1931
1932                 if ((num_smbs % 50) == 0 && need_to_check_log_size()) {
1933                         change_to_root_user();
1934                         check_log_size();
1935                 }
1936                 TALLOC_FREE(frame);
1937         }
1938 }