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