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