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