78e66e46203afcae8c5d39bd63e4cf838cfedef6
[obnox/samba-ctdb.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(void)
704 {
705         DEBUG(10,("async_processing: Doing async processing.\n"));
706
707         process_aio_queue();
708
709         process_kernel_oplocks(smbd_messaging_context());
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   Do a select on an two fd's - with timeout. 
731
732   If a local udp message has been pushed onto the
733   queue (this can only happen during oplock break
734   processing) call async_processing()
735
736   If a pending smb message has been pushed onto the
737   queue (this can only happen during oplock break
738   processing) return this next.
739
740   If the first smbfd is ready then read an smb from it.
741   if the second (loopback UDP) fd is ready then read a message
742   from it and setup the buffer header to identify the length
743   and from address.
744   Returns False on timeout or error.
745   Else returns True.
746
747 The timeout is in milliseconds
748 ****************************************************************************/
749
750 static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
751 {
752         fd_set r_fds, w_fds;
753         int selrtn;
754         struct timeval to;
755         int maxfd = 0;
756
757         to.tv_sec = SMBD_SELECT_TIMEOUT;
758         to.tv_usec = 0;
759
760         /*
761          * Note that this call must be before processing any SMB
762          * messages as we need to synchronously process any messages
763          * we may have sent to ourselves from the previous SMB.
764          */
765         message_dispatch(smbd_messaging_context());
766
767         /*
768          * Setup the select fd sets.
769          */
770
771         FD_ZERO(&r_fds);
772         FD_ZERO(&w_fds);
773
774         /*
775          * Ensure we process oplock break messages by preference.
776          * We have to do this before the select, after the select
777          * and if the select returns EINTR. This is due to the fact
778          * that the selects called from async_processing can eat an EINTR
779          * caused by a signal (we can't take the break message there).
780          * This is hideously complex - *MUST* be simplified for 3.0 ! JRA.
781          */
782
783         if (oplock_message_waiting()) {
784                 DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
785                 async_processing();
786                 /*
787                  * After async processing we must go and do the select again, as
788                  * the state of the flag in fds for the server file descriptor is
789                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
790                  */
791                 return NT_STATUS_RETRY;
792         }
793
794         /*
795          * Are there any timed events waiting ? If so, ensure we don't
796          * select for longer than it would take to wait for them.
797          */
798
799         {
800                 struct timeval now;
801                 GetTimeOfDay(&now);
802
803                 event_add_to_select_args(smbd_event_context(), &now,
804                                          &r_fds, &w_fds, &to, &maxfd);
805         }
806
807         /* Process a signal and timed events now... */
808         if (run_events(smbd_event_context(), 0, NULL, NULL)) {
809                 return NT_STATUS_RETRY;
810         }
811
812         {
813                 int sav;
814                 START_PROFILE(smbd_idle);
815
816                 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
817                 sav = errno;
818
819                 END_PROFILE(smbd_idle);
820                 errno = sav;
821         }
822
823         if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
824                 return NT_STATUS_RETRY;
825         }
826
827         /* if we get EINTR then maybe we have received an oplock
828            signal - treat this as select returning 1. This is ugly, but
829            is the best we can do until the oplock code knows more about
830            signals */
831         if (selrtn == -1 && errno == EINTR) {
832                 async_processing();
833                 /*
834                  * After async processing we must go and do the select again, as
835                  * the state of the flag in fds for the server file descriptor is
836                  * indeterminate - we may have done I/O on it in the oplock processing. JRA.
837                  */
838                 return NT_STATUS_RETRY;
839         }
840
841         /* Check if error */
842         if (selrtn == -1) {
843                 /* something is wrong. Maybe the socket is dead? */
844                 return map_nt_error_from_unix(errno);
845         }
846
847         /* Did we timeout ? */
848         if (selrtn == 0) {
849                 return NT_STATUS_RETRY;
850         }
851
852         /*
853          * We've just woken up from a protentially long select sleep.
854          * Ensure we process local messages as we need to synchronously
855          * process any messages from other smbd's to avoid file rename race
856          * conditions. This call is cheap if there are no messages waiting.
857          * JRA.
858          */
859         message_dispatch(smbd_messaging_context());
860
861         return NT_STATUS_OK;
862 }
863
864 /*
865  * Only allow 5 outstanding trans requests. We're allocating memory, so
866  * prevent a DoS.
867  */
868
869 NTSTATUS allow_new_trans(struct trans_state *list, int mid)
870 {
871         int count = 0;
872         for (; list != NULL; list = list->next) {
873
874                 if (list->mid == mid) {
875                         return NT_STATUS_INVALID_PARAMETER;
876                 }
877
878                 count += 1;
879         }
880         if (count > 5) {
881                 return NT_STATUS_INSUFFICIENT_RESOURCES;
882         }
883
884         return NT_STATUS_OK;
885 }
886
887 /****************************************************************************
888  We're terminating and have closed all our files/connections etc.
889  If there are any pending local messages we need to respond to them
890  before termination so that other smbds don't think we just died whilst
891  holding oplocks.
892 ****************************************************************************/
893
894 void respond_to_all_remaining_local_messages(void)
895 {
896         /*
897          * Assert we have no exclusive open oplocks.
898          */
899
900         if(get_number_of_exclusive_open_oplocks()) {
901                 DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n",
902                         get_number_of_exclusive_open_oplocks() ));
903                 return;
904         }
905
906         process_kernel_oplocks(smbd_messaging_context());
907
908         return;
909 }
910
911
912 /*
913 These flags determine some of the permissions required to do an operation 
914
915 Note that I don't set NEED_WRITE on some write operations because they
916 are used by some brain-dead clients when printing, and I don't want to
917 force write permissions on print services.
918 */
919 #define AS_USER (1<<0)
920 #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
921 #define TIME_INIT (1<<2)
922 #define CAN_IPC (1<<3) /* Must be paired with AS_USER */
923 #define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
924 #define DO_CHDIR (1<<6)
925
926 /* 
927    define a list of possible SMB messages and their corresponding
928    functions. Any message that has a NULL function is unimplemented -
929    please feel free to contribute implementations!
930 */
931 static const struct smb_message_struct {
932         const char *name;
933         void (*fn)(struct smb_request *req);
934         int flags;
935 } smb_messages[256] = {
936
937 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
938 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
939 /* 0x02 */ { "SMBopen",reply_open,AS_USER },
940 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
941 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
942 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
943 /* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
944 /* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
945 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
946 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
947 /* 0x0a */ { "SMBread",reply_read,AS_USER},
948 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
949 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
950 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
951 /* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
952 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
953 /* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
954 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
955 /* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
956 /* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
957 /* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
958 /* 0x15 */ { NULL, NULL, 0 },
959 /* 0x16 */ { NULL, NULL, 0 },
960 /* 0x17 */ { NULL, NULL, 0 },
961 /* 0x18 */ { NULL, NULL, 0 },
962 /* 0x19 */ { NULL, NULL, 0 },
963 /* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
964 /* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
965 /* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
966 /* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
967 /* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
968 /* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
969 /* 0x20 */ { "SMBwritec", NULL,0},
970 /* 0x21 */ { NULL, NULL, 0 },
971 /* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
972 /* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
973 /* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
974 /* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
975 /* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
976 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
977 /* 0x28 */ { "SMBioctls", NULL,AS_USER},
978 /* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
979 /* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
980 /* 0x2b */ { "SMBecho",reply_echo,0},
981 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
982 /* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
983 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
984 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
985 /* 0x30 */ { NULL, NULL, 0 },
986 /* 0x31 */ { NULL, NULL, 0 },
987 /* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
988 /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
989 /* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
990 /* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
991 /* 0x36 */ { NULL, NULL, 0 },
992 /* 0x37 */ { NULL, NULL, 0 },
993 /* 0x38 */ { NULL, NULL, 0 },
994 /* 0x39 */ { NULL, NULL, 0 },
995 /* 0x3a */ { NULL, NULL, 0 },
996 /* 0x3b */ { NULL, NULL, 0 },
997 /* 0x3c */ { NULL, NULL, 0 },
998 /* 0x3d */ { NULL, NULL, 0 },
999 /* 0x3e */ { NULL, NULL, 0 },
1000 /* 0x3f */ { NULL, NULL, 0 },
1001 /* 0x40 */ { NULL, NULL, 0 },
1002 /* 0x41 */ { NULL, NULL, 0 },
1003 /* 0x42 */ { NULL, NULL, 0 },
1004 /* 0x43 */ { NULL, NULL, 0 },
1005 /* 0x44 */ { NULL, NULL, 0 },
1006 /* 0x45 */ { NULL, NULL, 0 },
1007 /* 0x46 */ { NULL, NULL, 0 },
1008 /* 0x47 */ { NULL, NULL, 0 },
1009 /* 0x48 */ { NULL, NULL, 0 },
1010 /* 0x49 */ { NULL, NULL, 0 },
1011 /* 0x4a */ { NULL, NULL, 0 },
1012 /* 0x4b */ { NULL, NULL, 0 },
1013 /* 0x4c */ { NULL, NULL, 0 },
1014 /* 0x4d */ { NULL, NULL, 0 },
1015 /* 0x4e */ { NULL, NULL, 0 },
1016 /* 0x4f */ { NULL, NULL, 0 },
1017 /* 0x50 */ { NULL, NULL, 0 },
1018 /* 0x51 */ { NULL, NULL, 0 },
1019 /* 0x52 */ { NULL, NULL, 0 },
1020 /* 0x53 */ { NULL, NULL, 0 },
1021 /* 0x54 */ { NULL, NULL, 0 },
1022 /* 0x55 */ { NULL, NULL, 0 },
1023 /* 0x56 */ { NULL, NULL, 0 },
1024 /* 0x57 */ { NULL, NULL, 0 },
1025 /* 0x58 */ { NULL, NULL, 0 },
1026 /* 0x59 */ { NULL, NULL, 0 },
1027 /* 0x5a */ { NULL, NULL, 0 },
1028 /* 0x5b */ { NULL, NULL, 0 },
1029 /* 0x5c */ { NULL, NULL, 0 },
1030 /* 0x5d */ { NULL, NULL, 0 },
1031 /* 0x5e */ { NULL, NULL, 0 },
1032 /* 0x5f */ { NULL, NULL, 0 },
1033 /* 0x60 */ { NULL, NULL, 0 },
1034 /* 0x61 */ { NULL, NULL, 0 },
1035 /* 0x62 */ { NULL, NULL, 0 },
1036 /* 0x63 */ { NULL, NULL, 0 },
1037 /* 0x64 */ { NULL, NULL, 0 },
1038 /* 0x65 */ { NULL, NULL, 0 },
1039 /* 0x66 */ { NULL, NULL, 0 },
1040 /* 0x67 */ { NULL, NULL, 0 },
1041 /* 0x68 */ { NULL, NULL, 0 },
1042 /* 0x69 */ { NULL, NULL, 0 },
1043 /* 0x6a */ { NULL, NULL, 0 },
1044 /* 0x6b */ { NULL, NULL, 0 },
1045 /* 0x6c */ { NULL, NULL, 0 },
1046 /* 0x6d */ { NULL, NULL, 0 },
1047 /* 0x6e */ { NULL, NULL, 0 },
1048 /* 0x6f */ { NULL, NULL, 0 },
1049 /* 0x70 */ { "SMBtcon",reply_tcon,0},
1050 /* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1051 /* 0x72 */ { "SMBnegprot",reply_negprot,0},
1052 /* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1053 /* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1054 /* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1055 /* 0x76 */ { NULL, NULL, 0 },
1056 /* 0x77 */ { NULL, NULL, 0 },
1057 /* 0x78 */ { NULL, NULL, 0 },
1058 /* 0x79 */ { NULL, NULL, 0 },
1059 /* 0x7a */ { NULL, NULL, 0 },
1060 /* 0x7b */ { NULL, NULL, 0 },
1061 /* 0x7c */ { NULL, NULL, 0 },
1062 /* 0x7d */ { NULL, NULL, 0 },
1063 /* 0x7e */ { NULL, NULL, 0 },
1064 /* 0x7f */ { NULL, NULL, 0 },
1065 /* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1066 /* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1067 /* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1068 /* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1069 /* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1070 /* 0x85 */ { NULL, NULL, 0 },
1071 /* 0x86 */ { NULL, NULL, 0 },
1072 /* 0x87 */ { NULL, NULL, 0 },
1073 /* 0x88 */ { NULL, NULL, 0 },
1074 /* 0x89 */ { NULL, NULL, 0 },
1075 /* 0x8a */ { NULL, NULL, 0 },
1076 /* 0x8b */ { NULL, NULL, 0 },
1077 /* 0x8c */ { NULL, NULL, 0 },
1078 /* 0x8d */ { NULL, NULL, 0 },
1079 /* 0x8e */ { NULL, NULL, 0 },
1080 /* 0x8f */ { NULL, NULL, 0 },
1081 /* 0x90 */ { NULL, NULL, 0 },
1082 /* 0x91 */ { NULL, NULL, 0 },
1083 /* 0x92 */ { NULL, NULL, 0 },
1084 /* 0x93 */ { NULL, NULL, 0 },
1085 /* 0x94 */ { NULL, NULL, 0 },
1086 /* 0x95 */ { NULL, NULL, 0 },
1087 /* 0x96 */ { NULL, NULL, 0 },
1088 /* 0x97 */ { NULL, NULL, 0 },
1089 /* 0x98 */ { NULL, NULL, 0 },
1090 /* 0x99 */ { NULL, NULL, 0 },
1091 /* 0x9a */ { NULL, NULL, 0 },
1092 /* 0x9b */ { NULL, NULL, 0 },
1093 /* 0x9c */ { NULL, NULL, 0 },
1094 /* 0x9d */ { NULL, NULL, 0 },
1095 /* 0x9e */ { NULL, NULL, 0 },
1096 /* 0x9f */ { NULL, NULL, 0 },
1097 /* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1098 /* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1099 /* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1100 /* 0xa3 */ { NULL, NULL, 0 },
1101 /* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1102 /* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1103 /* 0xa6 */ { NULL, NULL, 0 },
1104 /* 0xa7 */ { NULL, NULL, 0 },
1105 /* 0xa8 */ { NULL, NULL, 0 },
1106 /* 0xa9 */ { NULL, NULL, 0 },
1107 /* 0xaa */ { NULL, NULL, 0 },
1108 /* 0xab */ { NULL, NULL, 0 },
1109 /* 0xac */ { NULL, NULL, 0 },
1110 /* 0xad */ { NULL, NULL, 0 },
1111 /* 0xae */ { NULL, NULL, 0 },
1112 /* 0xaf */ { NULL, NULL, 0 },
1113 /* 0xb0 */ { NULL, NULL, 0 },
1114 /* 0xb1 */ { NULL, NULL, 0 },
1115 /* 0xb2 */ { NULL, NULL, 0 },
1116 /* 0xb3 */ { NULL, NULL, 0 },
1117 /* 0xb4 */ { NULL, NULL, 0 },
1118 /* 0xb5 */ { NULL, NULL, 0 },
1119 /* 0xb6 */ { NULL, NULL, 0 },
1120 /* 0xb7 */ { NULL, NULL, 0 },
1121 /* 0xb8 */ { NULL, NULL, 0 },
1122 /* 0xb9 */ { NULL, NULL, 0 },
1123 /* 0xba */ { NULL, NULL, 0 },
1124 /* 0xbb */ { NULL, NULL, 0 },
1125 /* 0xbc */ { NULL, NULL, 0 },
1126 /* 0xbd */ { NULL, NULL, 0 },
1127 /* 0xbe */ { NULL, NULL, 0 },
1128 /* 0xbf */ { NULL, NULL, 0 },
1129 /* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1130 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1131 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1132 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1133 /* 0xc4 */ { NULL, NULL, 0 },
1134 /* 0xc5 */ { NULL, NULL, 0 },
1135 /* 0xc6 */ { NULL, NULL, 0 },
1136 /* 0xc7 */ { NULL, NULL, 0 },
1137 /* 0xc8 */ { NULL, NULL, 0 },
1138 /* 0xc9 */ { NULL, NULL, 0 },
1139 /* 0xca */ { NULL, NULL, 0 },
1140 /* 0xcb */ { NULL, NULL, 0 },
1141 /* 0xcc */ { NULL, NULL, 0 },
1142 /* 0xcd */ { NULL, NULL, 0 },
1143 /* 0xce */ { NULL, NULL, 0 },
1144 /* 0xcf */ { NULL, NULL, 0 },
1145 /* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1146 /* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1147 /* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1148 /* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1149 /* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1150 /* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1151 /* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1152 /* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1153 /* 0xd8 */ { NULL, NULL, 0 },
1154 /* 0xd9 */ { NULL, NULL, 0 },
1155 /* 0xda */ { NULL, NULL, 0 },
1156 /* 0xdb */ { NULL, NULL, 0 },
1157 /* 0xdc */ { NULL, NULL, 0 },
1158 /* 0xdd */ { NULL, NULL, 0 },
1159 /* 0xde */ { NULL, NULL, 0 },
1160 /* 0xdf */ { NULL, NULL, 0 },
1161 /* 0xe0 */ { NULL, NULL, 0 },
1162 /* 0xe1 */ { NULL, NULL, 0 },
1163 /* 0xe2 */ { NULL, NULL, 0 },
1164 /* 0xe3 */ { NULL, NULL, 0 },
1165 /* 0xe4 */ { NULL, NULL, 0 },
1166 /* 0xe5 */ { NULL, NULL, 0 },
1167 /* 0xe6 */ { NULL, NULL, 0 },
1168 /* 0xe7 */ { NULL, NULL, 0 },
1169 /* 0xe8 */ { NULL, NULL, 0 },
1170 /* 0xe9 */ { NULL, NULL, 0 },
1171 /* 0xea */ { NULL, NULL, 0 },
1172 /* 0xeb */ { NULL, NULL, 0 },
1173 /* 0xec */ { NULL, NULL, 0 },
1174 /* 0xed */ { NULL, NULL, 0 },
1175 /* 0xee */ { NULL, NULL, 0 },
1176 /* 0xef */ { NULL, NULL, 0 },
1177 /* 0xf0 */ { NULL, NULL, 0 },
1178 /* 0xf1 */ { NULL, NULL, 0 },
1179 /* 0xf2 */ { NULL, NULL, 0 },
1180 /* 0xf3 */ { NULL, NULL, 0 },
1181 /* 0xf4 */ { NULL, NULL, 0 },
1182 /* 0xf5 */ { NULL, NULL, 0 },
1183 /* 0xf6 */ { NULL, NULL, 0 },
1184 /* 0xf7 */ { NULL, NULL, 0 },
1185 /* 0xf8 */ { NULL, NULL, 0 },
1186 /* 0xf9 */ { NULL, NULL, 0 },
1187 /* 0xfa */ { NULL, NULL, 0 },
1188 /* 0xfb */ { NULL, NULL, 0 },
1189 /* 0xfc */ { NULL, NULL, 0 },
1190 /* 0xfd */ { NULL, NULL, 0 },
1191 /* 0xfe */ { NULL, NULL, 0 },
1192 /* 0xff */ { NULL, NULL, 0 }
1193
1194 };
1195
1196 /*******************************************************************
1197  allocate and initialize a reply packet
1198 ********************************************************************/
1199
1200 static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1201                           const char *inbuf, char **outbuf, uint8_t num_words,
1202                           uint32_t num_bytes)
1203 {
1204         /*
1205          * Protect against integer wrap
1206          */
1207         if ((num_bytes > 0xffffff)
1208             || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1209                 char *msg;
1210                 if (asprintf(&msg, "num_bytes too large: %u",
1211                              (unsigned)num_bytes) == -1) {
1212                         msg = CONST_DISCARD(char *, "num_bytes too large");
1213                 }
1214                 smb_panic(msg);
1215         }
1216
1217         *outbuf = TALLOC_ARRAY(mem_ctx, char,
1218                                smb_size + num_words*2 + num_bytes);
1219         if (*outbuf == NULL) {
1220                 return false;
1221         }
1222
1223         construct_reply_common(req, inbuf, *outbuf);
1224         srv_set_message(*outbuf, num_words, num_bytes, false);
1225         /*
1226          * Zero out the word area, the caller has to take care of the bcc area
1227          * himself
1228          */
1229         if (num_words != 0) {
1230                 memset(*outbuf + smb_vwv0, 0, num_words*2);
1231         }
1232
1233         return true;
1234 }
1235
1236 void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1237 {
1238         char *outbuf;
1239         if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1240                            num_bytes)) {
1241                 smb_panic("could not allocate output buffer\n");
1242         }
1243         req->outbuf = (uint8_t *)outbuf;
1244 }
1245
1246
1247 /*******************************************************************
1248  Dump a packet to a file.
1249 ********************************************************************/
1250
1251 static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1252 {
1253         int fd, i;
1254         char *fname = NULL;
1255         if (DEBUGLEVEL < 50) {
1256                 return;
1257         }
1258
1259         if (len < 4) len = smb_len(data)+4;
1260         for (i=1;i<100;i++) {
1261                 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1262                              type ? "req" : "resp") == -1) {
1263                         return;
1264                 }
1265                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1266                 if (fd != -1 || errno != EEXIST) break;
1267         }
1268         if (fd != -1) {
1269                 ssize_t ret = write(fd, data, len);
1270                 if (ret != len)
1271                         DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1272                 close(fd);
1273                 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1274         }
1275         SAFE_FREE(fname);
1276 }
1277
1278 /****************************************************************************
1279  Prepare everything for calling the actual request function, and potentially
1280  call the request function via the "new" interface.
1281
1282  Return False if the "legacy" function needs to be called, everything is
1283  prepared.
1284
1285  Return True if we're done.
1286
1287  I know this API sucks, but it is the one with the least code change I could
1288  find.
1289 ****************************************************************************/
1290
1291 static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1292 {
1293         int flags;
1294         uint16 session_tag;
1295         connection_struct *conn = NULL;
1296
1297         errno = 0;
1298
1299         /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1300          * so subtract 4 from it. */
1301         if (!valid_smb_header(req->inbuf)
1302             || (size < (smb_size - 4))) {
1303                 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1304                          smb_len(req->inbuf)));
1305                 exit_server_cleanly("Non-SMB packet");
1306         }
1307
1308         if (smb_messages[type].fn == NULL) {
1309                 DEBUG(0,("Unknown message type %d!\n",type));
1310                 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1311                 reply_unknown_new(req, type);
1312                 return NULL;
1313         }
1314
1315         flags = smb_messages[type].flags;
1316
1317         /* In share mode security we must ignore the vuid. */
1318         session_tag = (lp_security() == SEC_SHARE)
1319                 ? UID_FIELD_INVALID : req->vuid;
1320         conn = req->conn;
1321
1322         DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1323                  (int)sys_getpid(), (unsigned long)conn));
1324
1325         smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1326
1327         /* Ensure this value is replaced in the incoming packet. */
1328         SSVAL(req->inbuf,smb_uid,session_tag);
1329
1330         /*
1331          * Ensure the correct username is in current_user_info.  This is a
1332          * really ugly bugfix for problems with multiple session_setup_and_X's
1333          * being done and allowing %U and %G substitutions to work correctly.
1334          * There is a reason this code is done here, don't move it unless you
1335          * know what you're doing... :-).
1336          * JRA.
1337          */
1338
1339         if (session_tag != last_session_tag) {
1340                 user_struct *vuser = NULL;
1341
1342                 last_session_tag = session_tag;
1343                 if(session_tag != UID_FIELD_INVALID) {
1344                         vuser = get_valid_user_struct(session_tag);
1345                         if (vuser) {
1346                                 set_current_user_info(
1347                                         vuser->server_info->sanitized_username,
1348                                         vuser->server_info->unix_name,
1349                                         pdb_get_domain(vuser->server_info
1350                                                        ->sam_account));
1351                         }
1352                 }
1353         }
1354
1355         /* Does this call need to be run as the connected user? */
1356         if (flags & AS_USER) {
1357
1358                 /* Does this call need a valid tree connection? */
1359                 if (!conn) {
1360                         /*
1361                          * Amazingly, the error code depends on the command
1362                          * (from Samba4).
1363                          */
1364                         if (type == SMBntcreateX) {
1365                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1366                         } else {
1367                                 reply_doserror(req, ERRSRV, ERRinvnid);
1368                         }
1369                         return NULL;
1370                 }
1371
1372                 if (!change_to_user(conn,session_tag)) {
1373                         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
1374                         remove_deferred_open_smb_message(req->mid);
1375                         return conn;
1376                 }
1377
1378                 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1379
1380                 /* Does it need write permission? */
1381                 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1382                         reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1383                         return conn;
1384                 }
1385
1386                 /* IPC services are limited */
1387                 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1388                         reply_doserror(req, ERRSRV,ERRaccess);
1389                         return conn;
1390                 }
1391         } else {
1392                 /* This call needs to be run as root */
1393                 change_to_root_user();
1394         }
1395
1396         /* load service specific parameters */
1397         if (conn) {
1398                 if (req->encrypted) {
1399                         conn->encrypted_tid = true;
1400                         /* encrypted required from now on. */
1401                         conn->encrypt_level = Required;
1402                 } else if (ENCRYPTION_REQUIRED(conn)) {
1403                         if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1404                                 exit_server_cleanly("encryption required "
1405                                         "on connection");
1406                                 return conn;
1407                         }
1408                 }
1409
1410                 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1411                                          (flags & (AS_USER|DO_CHDIR)
1412                                           ?True:False))) {
1413                         reply_doserror(req, ERRSRV, ERRaccess);
1414                         return conn;
1415                 }
1416                 conn->num_smb_operations++;
1417         }
1418
1419         /* does this protocol need to be run as guest? */
1420         if ((flags & AS_GUEST)
1421             && (!change_to_guest() ||
1422                 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1423                               lp_hostsdeny(-1)))) {
1424                 reply_doserror(req, ERRSRV, ERRaccess);
1425                 return conn;
1426         }
1427
1428         smb_messages[type].fn(req);
1429         return req->conn;
1430 }
1431
1432 /****************************************************************************
1433  Construct a reply to the incoming packet.
1434 ****************************************************************************/
1435
1436 static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted)
1437 {
1438         connection_struct *conn;
1439         struct smb_request *req;
1440
1441         chain_size = 0;
1442
1443         if (!(req = talloc(talloc_tos(), struct smb_request))) {
1444                 smb_panic("could not allocate smb_request");
1445         }
1446         init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
1447         req->inbuf  = (uint8_t *)talloc_move(req, &inbuf);
1448
1449         conn = switch_message(req->cmd, req, size);
1450
1451         if (req->unread_bytes) {
1452                 /* writeX failed. drain socket. */
1453                 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1454                                 req->unread_bytes) {
1455                         smb_panic("failed to drain pending bytes");
1456                 }
1457                 req->unread_bytes = 0;
1458         }
1459
1460         if (req->outbuf == NULL) {
1461                 return;
1462         }
1463
1464         if (CVAL(req->outbuf,0) == 0) {
1465                 show_msg((char *)req->outbuf);
1466         }
1467
1468         if (!srv_send_smb(smbd_server_fd(),
1469                         (char *)req->outbuf,
1470                         IS_CONN_ENCRYPTED(conn)||req->encrypted)) {
1471                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1472         }
1473
1474         TALLOC_FREE(req);
1475
1476         return;
1477 }
1478
1479 /****************************************************************************
1480  Process an smb from the client
1481 ****************************************************************************/
1482
1483 static void process_smb(struct smbd_server_connection *conn,
1484                         uint8_t *inbuf, size_t nread, size_t unread_bytes,
1485                         bool encrypted)
1486 {
1487         int msg_type = CVAL(inbuf,0);
1488
1489         DO_PROFILE_INC(smb_count);
1490
1491         DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1492                     smb_len(inbuf) ) );
1493         DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1494                                 (int)nread,
1495                                 (unsigned int)unread_bytes ));
1496
1497         if (msg_type != 0) {
1498                 /*
1499                  * NetBIOS session request, keepalive, etc.
1500                  */
1501                 reply_special((char *)inbuf);
1502                 goto done;
1503         }
1504
1505         show_msg((char *)inbuf);
1506
1507         construct_reply((char *)inbuf,nread,unread_bytes,encrypted);
1508
1509         trans_num++;
1510
1511 done:
1512         conn->num_requests++;
1513
1514         /* The timeout_processing function isn't run nearly
1515            often enough to implement 'max log size' without
1516            overrunning the size of the file by many megabytes.
1517            This is especially true if we are running at debug
1518            level 10.  Checking every 50 SMBs is a nice
1519            tradeoff of performance vs log file size overrun. */
1520
1521         if ((conn->num_requests % 50) == 0 &&
1522             need_to_check_log_size()) {
1523                 change_to_root_user();
1524                 check_log_size();
1525         }
1526 }
1527
1528 /****************************************************************************
1529  Return a string containing the function name of a SMB command.
1530 ****************************************************************************/
1531
1532 const char *smb_fn_name(int type)
1533 {
1534         const char *unknown_name = "SMBunknown";
1535
1536         if (smb_messages[type].name == NULL)
1537                 return(unknown_name);
1538
1539         return(smb_messages[type].name);
1540 }
1541
1542 /****************************************************************************
1543  Helper functions for contruct_reply.
1544 ****************************************************************************/
1545
1546 void add_to_common_flags2(uint32 v)
1547 {
1548         common_flags2 |= v;
1549 }
1550
1551 void remove_from_common_flags2(uint32 v)
1552 {
1553         common_flags2 &= ~v;
1554 }
1555
1556 static void construct_reply_common(struct smb_request *req, const char *inbuf,
1557                                    char *outbuf)
1558 {
1559         srv_set_message(outbuf,0,0,false);
1560         
1561         SCVAL(outbuf, smb_com, req->cmd);
1562         SIVAL(outbuf,smb_rcls,0);
1563         SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES)); 
1564         SSVAL(outbuf,smb_flg2,
1565                 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1566                 common_flags2);
1567         memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1568
1569         SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1570         SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1571         SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1572         SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1573 }
1574
1575 void construct_reply_common_req(struct smb_request *req, char *outbuf)
1576 {
1577         construct_reply_common(req, (char *)req->inbuf, outbuf);
1578 }
1579
1580 /*
1581  * How many bytes have we already accumulated up to the current wct field
1582  * offset?
1583  */
1584
1585 size_t req_wct_ofs(struct smb_request *req)
1586 {
1587         size_t buf_size;
1588
1589         if (req->chain_outbuf == NULL) {
1590                 return smb_wct - 4;
1591         }
1592         buf_size = talloc_get_size(req->chain_outbuf);
1593         if ((buf_size % 4) != 0) {
1594                 buf_size += (4 - (buf_size % 4));
1595         }
1596         return buf_size - 4;
1597 }
1598
1599 /*
1600  * Hack around reply_nterror & friends not being aware of chained requests,
1601  * generating illegal (i.e. wct==0) chain replies.
1602  */
1603
1604 static void fixup_chain_error_packet(struct smb_request *req)
1605 {
1606         uint8_t *outbuf = req->outbuf;
1607         req->outbuf = NULL;
1608         reply_outbuf(req, 2, 0);
1609         memcpy(req->outbuf, outbuf, smb_wct);
1610         TALLOC_FREE(outbuf);
1611         SCVAL(req->outbuf, smb_vwv0, 0xff);
1612 }
1613
1614 /****************************************************************************
1615  Construct a chained reply and add it to the already made reply
1616 ****************************************************************************/
1617
1618 void chain_reply(struct smb_request *req)
1619 {
1620         size_t smblen = smb_len(req->inbuf);
1621         size_t already_used, length_needed;
1622         uint8_t chain_cmd;
1623         uint32_t chain_offset;  /* uint32_t to avoid overflow */
1624
1625         uint8_t wct;
1626         uint16_t *vwv;
1627         uint16_t buflen;
1628         uint8_t *buf;
1629
1630         if (IVAL(req->outbuf, smb_rcls) != 0) {
1631                 fixup_chain_error_packet(req);
1632         }
1633
1634         /*
1635          * Any of the AndX requests and replies have at least a wct of
1636          * 2. vwv[0] is the next command, vwv[1] is the offset from the
1637          * beginning of the SMB header to the next wct field.
1638          *
1639          * None of the AndX requests put anything valuable in vwv[0] and [1],
1640          * so we can overwrite it here to form the chain.
1641          */
1642
1643         if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1644                 goto error;
1645         }
1646
1647         /*
1648          * Here we assume that this is the end of the chain. For that we need
1649          * to set "next command" to 0xff and the offset to 0. If we later find
1650          * more commands in the chain, this will be overwritten again.
1651          */
1652
1653         SCVAL(req->outbuf, smb_vwv0, 0xff);
1654         SCVAL(req->outbuf, smb_vwv0+1, 0);
1655         SSVAL(req->outbuf, smb_vwv1, 0);
1656
1657         if (req->chain_outbuf == NULL) {
1658                 /*
1659                  * In req->chain_outbuf we collect all the replies. Start the
1660                  * chain by copying in the first reply.
1661                  */
1662                 req->chain_outbuf = req->outbuf;
1663                 req->outbuf = NULL;
1664         } else {
1665                 if (!smb_splice_chain(&req->chain_outbuf,
1666                                       CVAL(req->outbuf, smb_com),
1667                                       CVAL(req->outbuf, smb_wct),
1668                                       (uint16_t *)(req->outbuf + smb_vwv),
1669                                       0, smb_buflen(req->outbuf),
1670                                       (uint8_t *)smb_buf(req->outbuf))) {
1671                         goto error;
1672                 }
1673                 TALLOC_FREE(req->outbuf);
1674         }
1675
1676         /*
1677          * We use the old request's vwv field to grab the next chained command
1678          * and offset into the chained fields.
1679          */
1680
1681         chain_cmd = CVAL(req->vwv+0, 0);
1682         chain_offset = SVAL(req->vwv+1, 0);
1683
1684         if (chain_cmd == 0xff) {
1685                 /*
1686                  * End of chain, no more requests from the client. So ship the
1687                  * replies.
1688                  */
1689                 smb_setlen((char *)(req->chain_outbuf),
1690                            talloc_get_size(req->chain_outbuf) - 4);
1691                 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1692                                   IS_CONN_ENCRYPTED(req->conn)
1693                                   ||req->encrypted)) {
1694                         exit_server_cleanly("chain_reply: srv_send_smb "
1695                                             "failed.");
1696                 }
1697                 return;
1698         }
1699
1700         /*
1701          * Check if the client tries to fool us. The request so far uses the
1702          * space to the end of the byte buffer in the request just
1703          * processed. The chain_offset can't point into that area. If that was
1704          * the case, we could end up with an endless processing of the chain,
1705          * we would always handle the same request.
1706          */
1707
1708         already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1709         if (chain_offset < already_used) {
1710                 goto error;
1711         }
1712
1713         /*
1714          * Next check: Make sure the chain offset does not point beyond the
1715          * overall smb request length.
1716          */
1717
1718         length_needed = chain_offset+1; /* wct */
1719         if (length_needed > smblen) {
1720                 goto error;
1721         }
1722
1723         /*
1724          * Now comes the pointer magic. Goal here is to set up req->vwv and
1725          * req->buf correctly again to be able to call the subsequent
1726          * switch_message(). The chain offset (the former vwv[1]) points at
1727          * the new wct field.
1728          */
1729
1730         wct = CVAL(smb_base(req->inbuf), chain_offset);
1731
1732         /*
1733          * Next consistency check: Make the new vwv array fits in the overall
1734          * smb request.
1735          */
1736
1737         length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1738         if (length_needed > smblen) {
1739                 goto error;
1740         }
1741         vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1742
1743         /*
1744          * Now grab the new byte buffer....
1745          */
1746
1747         buflen = SVAL(vwv+wct, 0);
1748
1749         /*
1750          * .. and check that it fits.
1751          */
1752
1753         length_needed += buflen;
1754         if (length_needed > smblen) {
1755                 goto error;
1756         }
1757         buf = (uint8_t *)(vwv+wct+1);
1758
1759         req->cmd = chain_cmd;
1760         req->wct = wct;
1761         req->vwv = vwv;
1762         req->buflen = buflen;
1763         req->buf = buf;
1764
1765         switch_message(chain_cmd, req, smblen);
1766
1767         if (req->outbuf == NULL) {
1768                 /*
1769                  * This happens if the chained command has suspended itself or
1770                  * if it has called srv_send_smb() itself.
1771                  */
1772                 return;
1773         }
1774
1775         /*
1776          * We end up here if the chained command was not itself chained or
1777          * suspended, but for example a close() command. We now need to splice
1778          * the chained commands' outbuf into the already built up chain_outbuf
1779          * and ship the result.
1780          */
1781         goto done;
1782
1783  error:
1784         /*
1785          * We end up here if there's any error in the chain syntax. Report a
1786          * DOS error, just like Windows does.
1787          */
1788         reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1789         fixup_chain_error_packet(req);
1790
1791  done:
1792         if (!smb_splice_chain(&req->chain_outbuf,
1793                               CVAL(req->outbuf, smb_com),
1794                               CVAL(req->outbuf, smb_wct),
1795                               (uint16_t *)(req->outbuf + smb_vwv),
1796                               0, smb_buflen(req->outbuf),
1797                               (uint8_t *)smb_buf(req->outbuf))) {
1798                 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1799         }
1800         TALLOC_FREE(req->outbuf);
1801
1802         smb_setlen((char *)(req->chain_outbuf),
1803                    talloc_get_size(req->chain_outbuf) - 4);
1804
1805         show_msg((char *)(req->chain_outbuf));
1806
1807         if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
1808                           IS_CONN_ENCRYPTED(req->conn)||req->encrypted)) {
1809                 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1810         }
1811 }
1812
1813 /****************************************************************************
1814  Check if services need reloading.
1815 ****************************************************************************/
1816
1817 void check_reload(time_t t)
1818 {
1819         time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
1820
1821         if(last_smb_conf_reload_time == 0) {
1822                 last_smb_conf_reload_time = t;
1823                 /* Our printing subsystem might not be ready at smbd start up.
1824                    Then no printer is available till the first printers check
1825                    is performed.  A lower initial interval circumvents this. */
1826                 if ( printcap_cache_time > 60 )
1827                         last_printer_reload_time = t - printcap_cache_time + 60;
1828                 else
1829                         last_printer_reload_time = t;
1830         }
1831
1832         if (mypid != getpid()) { /* First time or fork happened meanwhile */
1833                 /* randomize over 60 second the printcap reload to avoid all
1834                  * process hitting cupsd at the same time */
1835                 int time_range = 60;
1836
1837                 last_printer_reload_time += random() % time_range;
1838                 mypid = getpid();
1839         }
1840
1841         if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) {
1842                 reload_services(True);
1843                 reload_after_sighup = False;
1844                 last_smb_conf_reload_time = t;
1845         }
1846
1847         /* 'printcap cache time = 0' disable the feature */
1848         
1849         if ( printcap_cache_time != 0 )
1850         { 
1851                 /* see if it's time to reload or if the clock has been set back */
1852                 
1853                 if ( (t >= last_printer_reload_time+printcap_cache_time) 
1854                         || (t-last_printer_reload_time  < 0) ) 
1855                 {
1856                         DEBUG( 3,( "Printcap cache time expired.\n"));
1857                         reload_printers();
1858                         last_printer_reload_time = t;
1859                 }
1860         }
1861 }
1862
1863 static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1864 {
1865         /* TODO: make write nonblocking */
1866 }
1867
1868 static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1869 {
1870         uint8_t *inbuf = NULL;
1871         size_t inbuf_len = 0;
1872         size_t unread_bytes = 0;
1873         bool encrypted = false;
1874         TALLOC_CTX *mem_ctx = talloc_tos();
1875         NTSTATUS status;
1876
1877         /* TODO: remove this hack */
1878         message_dispatch(smbd_messaging_context());
1879
1880         /* TODO: make this completely nonblocking */
1881
1882         status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
1883                                     (char **)(void *)&inbuf,
1884                                     0, /* timeout */
1885                                     &unread_bytes,
1886                                     &encrypted,
1887                                     &inbuf_len);
1888         if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1889                 goto process;
1890         }
1891         if (NT_STATUS_IS_ERR(status)) {
1892                 exit_server_cleanly("failed to receive smb request");
1893         }
1894         if (!NT_STATUS_IS_OK(status)) {
1895                 return;
1896         }
1897
1898 process:
1899         process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted);
1900 }
1901
1902 static void smbd_server_connection_handler(struct event_context *ev,
1903                                            struct fd_event *fde,
1904                                            uint16_t flags,
1905                                            void *private_data)
1906 {
1907         struct smbd_server_connection *conn = talloc_get_type(private_data,
1908                                               struct smbd_server_connection);
1909
1910         if (flags & EVENT_FD_WRITE) {
1911                 smbd_server_connection_write_handler(conn);
1912         } else if (flags & EVENT_FD_READ) {
1913                 smbd_server_connection_read_handler(conn);
1914         }
1915 }
1916
1917 /****************************************************************************
1918  Process commands from the client
1919 ****************************************************************************/
1920
1921 void smbd_process(void)
1922 {
1923         /*
1924          * Before the first packet, check the global hosts allow/ hosts deny
1925          * parameters before doing any parsing of packets passed to us by the
1926          * client. This prevents attacks on our parsing code from hosts not in
1927          * the hosts allow list.
1928          */
1929
1930         if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
1931                           lp_hostsdeny(-1))) {
1932                 char addr[INET6_ADDRSTRLEN];
1933
1934                 /*
1935                  * send a negative session response "not listening on calling
1936                  * name"
1937                  */
1938                 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
1939                 DEBUG( 1, ("Connection denied from %s\n",
1940                            client_addr(get_client_fd(),addr,sizeof(addr)) ) );
1941                 (void)srv_send_smb(smbd_server_fd(),(char *)buf,false);
1942                 exit_server_cleanly("connection denied");
1943         }
1944
1945         max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
1946
1947         smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
1948         if (!smbd_server_conn) {
1949                 exit_server("failed to create smbd_server_connection");
1950         }
1951         smbd_server_conn->fde = event_add_fd(smbd_event_context(),
1952                                              smbd_server_conn,
1953                                              smbd_server_fd(),
1954                                              EVENT_FD_READ,
1955                                              smbd_server_connection_handler,
1956                                              smbd_server_conn);
1957         if (!smbd_server_conn->fde) {
1958                 exit_server("failed to create smbd_server_connection fde");
1959         }
1960
1961         while (True) {
1962                 NTSTATUS status;
1963                 TALLOC_CTX *frame = talloc_stackframe_pool(8192);
1964
1965                 errno = 0;
1966
1967                 status = smbd_server_connection_loop_once(smbd_server_conn);
1968                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
1969                     !NT_STATUS_IS_OK(status)) {
1970                         DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
1971                                   " exiting\n", nt_errstr(status)));
1972                         return;
1973                 }
1974
1975                 TALLOC_FREE(frame);
1976         }
1977 }