]> git.ipfire.org Git - thirdparty/samba.git/blame - source3/smbd/process.c
mount.cifs: don't leak passwords with verbose option
[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"
3dde0cbb 22#include "smbd/globals.h"
c3effa8b 23
30191d1a 24extern bool global_machine_password_needs_changing;
c3effa8b 25
ae0c6cff
VL
26static void construct_reply_common(struct smb_request *req, const char *inbuf,
27 char *outbuf);
5a33e906 28
36441da4
JA
29/* Accessor function for smb_read_error for smbd functions. */
30
9254bb4e
JA
31/****************************************************************************
32 Send an smb to a fd.
33****************************************************************************/
34
c16c90a1
SM
35bool srv_send_smb(int fd, char *buffer,
36 bool do_signing, uint32_t seqnum,
37 bool do_encrypt,
38 struct smb_perfcount_data *pcd)
9254bb4e 39{
54c51a66 40 size_t len = 0;
9254bb4e
JA
41 size_t nwritten=0;
42 ssize_t ret;
43 char *buf_out = buffer;
44
c16c90a1
SM
45 if (do_signing) {
46 /* Sign the outgoing packet if required. */
47 srv_calculate_sign_mac(smbd_server_conn, buf_out, seqnum);
48 }
9254bb4e
JA
49
50 if (do_encrypt) {
51 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
52 if (!NT_STATUS_IS_OK(status)) {
53 DEBUG(0, ("send_smb: SMB encryption failed "
54 "on outgoing packet! Error %s\n",
55 nt_errstr(status) ));
54c51a66 56 goto out;
9254bb4e
JA
57 }
58 }
59
60 len = smb_len(buf_out) + 4;
61
c344ad30
VL
62 ret = write_data(fd,buf_out+nwritten,len - nwritten);
63 if (ret <= 0) {
64 DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
65 (int)len,(int)ret, strerror(errno) ));
66 srv_free_enc_buffer(buf_out);
67 goto out;
9254bb4e
JA
68 }
69
54c51a66 70 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
9254bb4e 71 srv_free_enc_buffer(buf_out);
54c51a66 72out:
73 SMB_PERFCOUNT_END(pcd);
9254bb4e
JA
74 return true;
75}
76
afc93255
JA
77/*******************************************************************
78 Setup the word count and byte count for a smb message.
afc93255
JA
79********************************************************************/
80
9254bb4e 81int srv_set_message(char *buf,
afc93255
JA
82 int num_words,
83 int num_bytes,
84 bool zero)
85{
86 if (zero && (num_words || num_bytes)) {
87 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
88 }
89 SCVAL(buf,smb_wct,num_words);
90 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
9254bb4e 91 smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
afc93255
JA
92 return (smb_size + num_words*2 + num_bytes);
93}
94
9254bb4e 95static bool valid_smb_header(const uint8_t *inbuf)
afc93255 96{
9254bb4e
JA
97 if (is_encrypted_packet(inbuf)) {
98 return true;
afc93255 99 }
1510b7b8
VL
100 /*
101 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
102 * but it just looks weird to call strncmp for this one.
103 */
104 return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
afc93255
JA
105}
106
695c4a7a
JA
107/* Socket functions for smbd packet processing. */
108
58fbb512 109static bool valid_packet_size(size_t len)
695c4a7a
JA
110{
111 /*
112 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
113 * of header. Don't print the error if this fits.... JRA.
114 */
115
116 if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
117 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
118 (unsigned long)len));
d36434f3 119 return false;
695c4a7a
JA
120 }
121 return true;
122}
123
e604e137
VL
124static NTSTATUS read_packet_remainder(int fd, char *buffer,
125 unsigned int timeout, ssize_t len)
695c4a7a 126{
48b1ee61 127 if (len <= 0) {
e604e137 128 return NT_STATUS_OK;
48b1ee61 129 }
695c4a7a 130
43c766a1 131 return read_fd_with_timeout(fd, buffer, len, len, timeout, NULL);
695c4a7a
JA
132}
133
134/****************************************************************************
135 Attempt a zerocopy writeX read. We know here that len > smb_size-4
136****************************************************************************/
137
138/*
139 * Unfortunately, earlier versions of smbclient/libsmbclient
140 * don't send this "standard" writeX header. I've fixed this
141 * for 3.2 but we'll use the old method with earlier versions.
142 * Windows and CIFSFS at least use this standard size. Not
143 * sure about MacOSX.
144 */
145
146#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
147 (2*14) + /* word count (including bcc) */ \
148 1 /* pad byte */)
149
250b2b64
VL
150static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
151 const char lenbuf[4],
152 int fd, char **buffer,
153 unsigned int timeout,
154 size_t *p_unread,
155 size_t *len_ret)
695c4a7a
JA
156{
157 /* Size of a WRITEX call (+4 byte len). */
158 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
159 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
160 ssize_t toread;
250b2b64 161 NTSTATUS status;
695c4a7a 162
227718cd 163 memcpy(writeX_header, lenbuf, 4);
695c4a7a 164
43c766a1 165 status = read_fd_with_timeout(
250b2b64
VL
166 fd, writeX_header + 4,
167 STANDARD_WRITE_AND_X_HEADER_SIZE,
168 STANDARD_WRITE_AND_X_HEADER_SIZE,
169 timeout, NULL);
695c4a7a 170
250b2b64
VL
171 if (!NT_STATUS_IS_OK(status)) {
172 return status;
695c4a7a
JA
173 }
174
175 /*
176 * Ok - now try and see if this is a possible
177 * valid writeX call.
178 */
179
9254bb4e 180 if (is_valid_writeX_buffer((uint8_t *)writeX_header)) {
695c4a7a
JA
181 /*
182 * If the data offset is beyond what
183 * we've read, drain the extra bytes.
184 */
185 uint16_t doff = SVAL(writeX_header,smb_vwv11);
186 ssize_t newlen;
187
188 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
189 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
190 if (drain_socket(smbd_server_fd(), drain) != drain) {
191 smb_panic("receive_smb_raw_talloc_partial_read:"
192 " failed to drain pending bytes");
193 }
194 } else {
195 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
196 }
197
198 /* Spoof down the length and null out the bcc. */
199 set_message_bcc(writeX_header, 0);
200 newlen = smb_len(writeX_header);
201
202 /* Copy the header we've written. */
203
637f9d9b 204 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
695c4a7a
JA
205 writeX_header,
206 sizeof(writeX_header));
207
208 if (*buffer == NULL) {
209 DEBUG(0, ("Could not allocate inbuf of length %d\n",
210 (int)sizeof(writeX_header)));
250b2b64 211 return NT_STATUS_NO_MEMORY;
695c4a7a
JA
212 }
213
214 /* Work out the remaining bytes. */
215 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
250b2b64
VL
216 *len_ret = newlen + 4;
217 return NT_STATUS_OK;
695c4a7a
JA
218 }
219
220 if (!valid_packet_size(len)) {
250b2b64 221 return NT_STATUS_INVALID_PARAMETER;
695c4a7a
JA
222 }
223
224 /*
225 * Not a valid writeX call. Just do the standard
226 * talloc and return.
227 */
228
229 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
230
231 if (*buffer == NULL) {
232 DEBUG(0, ("Could not allocate inbuf of length %d\n",
233 (int)len+4));
250b2b64 234 return NT_STATUS_NO_MEMORY;
695c4a7a
JA
235 }
236
237 /* Copy in what we already read. */
238 memcpy(*buffer,
239 writeX_header,
240 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
241 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
242
243 if(toread > 0) {
e604e137
VL
244 status = read_packet_remainder(
245 fd, (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
246 timeout, toread);
247
248 if (!NT_STATUS_IS_OK(status)) {
8ca459e0
JA
249 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
250 nt_errstr(status)));
250b2b64 251 return status;
695c4a7a
JA
252 }
253 }
254
250b2b64
VL
255 *len_ret = len + 4;
256 return NT_STATUS_OK;
695c4a7a
JA
257}
258
9fe66ddd
VL
259static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
260 char **buffer, unsigned int timeout,
261 size_t *p_unread, size_t *plen)
695c4a7a
JA
262{
263 char lenbuf[4];
0afbfa42 264 size_t len;
695c4a7a 265 int min_recv_size = lp_min_receive_file_size();
0afbfa42 266 NTSTATUS status;
695c4a7a 267
695c4a7a
JA
268 *p_unread = 0;
269
0afbfa42
VL
270 status = read_smb_length_return_keepalive(fd, lenbuf, timeout, &len);
271 if (!NT_STATUS_IS_OK(status)) {
272 DEBUG(10, ("receive_smb_raw: %s\n", nt_errstr(status)));
9fe66ddd 273 return status;
695c4a7a
JA
274 }
275
dea223ba
TP
276 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
277 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
278 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
c16c90a1 279 !srv_is_signing_active(smbd_server_conn)) {
695c4a7a 280
8ca459e0
JA
281 return receive_smb_raw_talloc_partial_read(
282 mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
695c4a7a
JA
283 }
284
285 if (!valid_packet_size(len)) {
9fe66ddd 286 return NT_STATUS_INVALID_PARAMETER;
695c4a7a
JA
287 }
288
289 /*
290 * The +4 here can't wrap, we've checked the length above already.
291 */
292
293 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
294
295 if (*buffer == NULL) {
296 DEBUG(0, ("Could not allocate inbuf of length %d\n",
297 (int)len+4));
9fe66ddd 298 return NT_STATUS_NO_MEMORY;
695c4a7a
JA
299 }
300
301 memcpy(*buffer, lenbuf, sizeof(lenbuf));
302
e604e137
VL
303 status = read_packet_remainder(fd, (*buffer)+4, timeout, len);
304 if (!NT_STATUS_IS_OK(status)) {
9fe66ddd 305 return status;
695c4a7a
JA
306 }
307
9fe66ddd
VL
308 *plen = len + 4;
309 return NT_STATUS_OK;
695c4a7a
JA
310}
311
e514cd0a
VL
312static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
313 char **buffer, unsigned int timeout,
314 size_t *p_unread, bool *p_encrypted,
c16c90a1
SM
315 size_t *p_len,
316 uint32_t *seqnum)
695c4a7a 317{
47666c93 318 size_t len = 0;
9fe66ddd 319 NTSTATUS status;
695c4a7a 320
9254bb4e
JA
321 *p_encrypted = false;
322
9fe66ddd
VL
323 status = receive_smb_raw_talloc(mem_ctx, fd, buffer, timeout,
324 p_unread, &len);
325 if (!NT_STATUS_IS_OK(status)) {
e514cd0a 326 return status;
695c4a7a
JA
327 }
328
9254bb4e 329 if (is_encrypted_packet((uint8_t *)*buffer)) {
9fe66ddd 330 status = srv_decrypt_buffer(*buffer);
afc93255
JA
331 if (!NT_STATUS_IS_OK(status)) {
332 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
333 "incoming packet! Error %s\n",
334 nt_errstr(status) ));
e514cd0a 335 return status;
afc93255 336 }
9254bb4e 337 *p_encrypted = true;
afc93255
JA
338 }
339
695c4a7a 340 /* Check the incoming SMB signature. */
c16c90a1 341 if (!srv_check_sign_mac(smbd_server_conn, *buffer, seqnum)) {
695c4a7a
JA
342 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
343 "incoming packet!\n"));
e514cd0a 344 return NT_STATUS_INVALID_NETWORK_RESPONSE;
695c4a7a
JA
345 }
346
e514cd0a
VL
347 *p_len = len;
348 return NT_STATUS_OK;
695c4a7a
JA
349}
350
0bc56a2e
VL
351/*
352 * Initialize a struct smb_request from an inbuf
353 */
354
c3250149
JA
355void init_smb_request(struct smb_request *req,
356 const uint8 *inbuf,
9254bb4e
JA
357 size_t unread_bytes,
358 bool encrypted)
0bc56a2e 359{
c8620180 360 struct smbd_server_connection *sconn = smbd_server_conn;
ed70bc0d
JA
361 size_t req_size = smb_len(inbuf) + 4;
362 /* Ensure we have at least smb_size bytes. */
a1f593cd
JA
363 if (req_size < smb_size) {
364 DEBUG(0,("init_smb_request: invalid request size %u\n",
365 (unsigned int)req_size ));
366 exit_server_cleanly("Invalid SMB request");
367 }
7808a259 368 req->cmd = CVAL(inbuf, smb_com);
0bc56a2e
VL
369 req->flags2 = SVAL(inbuf, smb_flg2);
370 req->smbpid = SVAL(inbuf, smb_pid);
371 req->mid = SVAL(inbuf, smb_mid);
c16c90a1 372 req->seqnum = 0;
0bc56a2e 373 req->vuid = SVAL(inbuf, smb_uid);
cc6a4101
VL
374 req->tid = SVAL(inbuf, smb_tid);
375 req->wct = CVAL(inbuf, smb_wct);
2bab73a1 376 req->vwv = (uint16_t *)(inbuf+smb_vwv);
7f9d6f80 377 req->buflen = smb_buflen(inbuf);
7bdb571e 378 req->buf = (const uint8_t *)smb_buf(inbuf);
c3250149 379 req->unread_bytes = unread_bytes;
9254bb4e 380 req->encrypted = encrypted;
c8620180 381 req->conn = conn_find(sconn,req->tid);
d65afbe5 382 req->chain_fsp = NULL;
ba981128 383 req->chain_outbuf = NULL;
5135ebd6 384 req->done = false;
54c51a66 385 smb_init_perfcount_data(&req->pcd);
c3250149 386
a662a62e 387 /* Ensure we have at least wct words and 2 bytes of bcc. */
a1f593cd
JA
388 if (smb_size + req->wct*2 > req_size) {
389 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
390 (unsigned int)req->wct,
391 (unsigned int)req_size));
392 exit_server_cleanly("Invalid SMB request");
393 }
a662a62e 394 /* Ensure bcc is correct. */
7f9d6f80 395 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
a662a62e
JA
396 DEBUG(0,("init_smb_request: invalid bcc number %u "
397 "(wct = %u, size %u)\n",
7f9d6f80 398 (unsigned int)req->buflen,
a662a62e
JA
399 (unsigned int)req->wct,
400 (unsigned int)req_size));
401 exit_server_cleanly("Invalid SMB request");
402 }
54c51a66 403
cc6a4101 404 req->outbuf = NULL;
0bc56a2e
VL
405}
406
aeb798c3
SM
407static void process_smb(struct smbd_server_connection *conn,
408 uint8_t *inbuf, size_t nread, size_t unread_bytes,
c16c90a1
SM
409 uint32_t seqnum, bool encrypted,
410 struct smb_perfcount_data *deferred_pcd);
aeb798c3
SM
411
412static void smbd_deferred_open_timer(struct event_context *ev,
413 struct timed_event *te,
414 struct timeval _tval,
415 void *private_data)
416{
417 struct pending_message_list *msg = talloc_get_type(private_data,
418 struct pending_message_list);
419 TALLOC_CTX *mem_ctx = talloc_tos();
420 uint8_t *inbuf;
421
50aa8a4a
VL
422 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
423 msg->buf.length);
aeb798c3
SM
424 if (inbuf == NULL) {
425 exit_server("smbd_deferred_open_timer: talloc failed\n");
426 return;
427 }
428
429 /* We leave this message on the queue so the open code can
430 know this is a retry. */
431 DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
432 (unsigned int)SVAL(msg->buf.data,smb_mid)));
433
434 process_smb(smbd_server_conn, inbuf,
435 msg->buf.length, 0,
c16c90a1 436 msg->seqnum, msg->encrypted, &msg->pcd);
aeb798c3 437}
aab2fe02
JA
438
439/****************************************************************************
e5a95132
GJC
440 Function to push a message onto the tail of a linked list of smb messages ready
441 for processing.
aab2fe02
JA
442****************************************************************************/
443
30191d1a 444static bool push_queued_message(struct smb_request *req,
54abd2aa
GC
445 struct timeval request_time,
446 struct timeval end_time,
447 char *private_data, size_t private_len)
aab2fe02 448{
b578db69 449 int msg_len = smb_len(req->inbuf) + 4;
54abd2aa
GC
450 struct pending_message_list *msg;
451
452 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
aab2fe02 453
1eff0523
JA
454 if(msg == NULL) {
455 DEBUG(0,("push_message: malloc fail (1)\n"));
456 return False;
457 }
aab2fe02 458
b578db69 459 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
2fc57c9a 460 if(msg->buf.data == NULL) {
1eff0523 461 DEBUG(0,("push_message: malloc fail (2)\n"));
fb5362c0 462 TALLOC_FREE(msg);
1eff0523
JA
463 return False;
464 }
aab2fe02 465
54abd2aa 466 msg->request_time = request_time;
c16c90a1 467 msg->seqnum = req->seqnum;
9254bb4e 468 msg->encrypted = req->encrypted;
54c51a66 469 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
2fc57c9a 470
19ca97a7 471 if (private_data) {
54abd2aa
GC
472 msg->private_data = data_blob_talloc(msg, private_data,
473 private_len);
2fc57c9a
JA
474 if (msg->private_data.data == NULL) {
475 DEBUG(0,("push_message: malloc fail (3)\n"));
fb5362c0 476 TALLOC_FREE(msg);
b6fb0462 477 return False;
2fc57c9a
JA
478 }
479 }
aab2fe02 480
aeb798c3
SM
481 msg->te = event_add_timed(smbd_event_context(),
482 msg,
483 end_time,
484 smbd_deferred_open_timer,
485 msg);
486 if (!msg->te) {
487 DEBUG(0,("push_message: event_add_timed failed\n"));
488 TALLOC_FREE(msg);
489 return false;
490 }
491
258a465e 492 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
aab2fe02 493
54abd2aa
GC
494 DEBUG(10,("push_message: pushed message length %u on "
495 "deferred_open_queue\n", (unsigned int)msg_len));
2fc57c9a 496
1eff0523 497 return True;
aab2fe02
JA
498}
499
2fc57c9a
JA
500/****************************************************************************
501 Function to delete a sharing violation open message by mid.
502****************************************************************************/
503
54abd2aa 504void remove_deferred_open_smb_message(uint16 mid)
2fc57c9a
JA
505{
506 struct pending_message_list *pml;
507
54abd2aa 508 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a 509 if (mid == SVAL(pml->buf.data,smb_mid)) {
e5a95132 510 DEBUG(10,("remove_sharing_violation_open_smb_message: "
54abd2aa
GC
511 "deleting mid %u len %u\n",
512 (unsigned int)mid,
513 (unsigned int)pml->buf.length ));
514 DLIST_REMOVE(deferred_open_queue, pml);
fb5362c0 515 TALLOC_FREE(pml);
2fc57c9a
JA
516 return;
517 }
518 }
519}
520
521/****************************************************************************
522 Move a sharing violation open retry message to the front of the list and
523 schedule it for immediate processing.
524****************************************************************************/
525
54abd2aa 526void schedule_deferred_open_smb_message(uint16 mid)
2fc57c9a
JA
527{
528 struct pending_message_list *pml;
529 int i = 0;
530
54abd2aa 531 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a 532 uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
aeb798c3 533
e5a95132
GJC
534 DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
535 (unsigned int)msg_mid ));
aeb798c3 536
2fc57c9a 537 if (mid == msg_mid) {
aeb798c3
SM
538 struct timed_event *te;
539
e5a95132
GJC
540 DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
541 mid ));
aeb798c3
SM
542
543 te = event_add_timed(smbd_event_context(),
544 pml,
545 timeval_zero(),
546 smbd_deferred_open_timer,
547 pml);
548 if (!te) {
549 DEBUG(10,("schedule_deferred_open_smb_message: "
550 "event_add_timed() failed, skipping mid %u\n",
551 mid ));
552 }
553
554 TALLOC_FREE(pml->te);
555 pml->te = te;
54abd2aa 556 DLIST_PROMOTE(deferred_open_queue, pml);
2fc57c9a
JA
557 return;
558 }
559 }
560
e5a95132
GJC
561 DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
562 mid ));
2fc57c9a
JA
563}
564
565/****************************************************************************
566 Return true if this mid is on the deferred queue.
567****************************************************************************/
568
30191d1a 569bool open_was_deferred(uint16 mid)
2fc57c9a
JA
570{
571 struct pending_message_list *pml;
3e0f5862 572
54abd2aa 573 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a
JA
574 if (SVAL(pml->buf.data,smb_mid) == mid) {
575 return True;
576 }
577 }
578 return False;
579}
580
581/****************************************************************************
582 Return the message queued by this mid.
583****************************************************************************/
584
585struct pending_message_list *get_open_deferred_message(uint16 mid)
586{
587 struct pending_message_list *pml;
3e0f5862 588
54abd2aa 589 for (pml = deferred_open_queue; pml; pml = pml->next) {
2fc57c9a
JA
590 if (SVAL(pml->buf.data,smb_mid) == mid) {
591 return pml;
592 }
593 }
594 return NULL;
595}
596
597/****************************************************************************
54abd2aa
GC
598 Function to push a deferred open smb message onto a linked list of local smb
599 messages ready for processing.
600****************************************************************************/
601
30191d1a 602bool push_deferred_smb_message(struct smb_request *req,
54abd2aa
GC
603 struct timeval request_time,
604 struct timeval timeout,
605 char *private_data, size_t priv_len)
606{
607 struct timeval end_time;
608
c3250149
JA
609 if (req->unread_bytes) {
610 DEBUG(0,("push_deferred_smb_message: logic error ! "
611 "unread_bytes = %u\n",
612 (unsigned int)req->unread_bytes ));
613 smb_panic("push_deferred_smb_message: "
614 "logic error unread_bytes != 0" );
615 }
616
54abd2aa
GC
617 end_time = timeval_sum(&request_time, &timeout);
618
619 DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
620 "timeout time [%u.%06u]\n",
b578db69 621 (unsigned int) smb_len(req->inbuf)+4, (unsigned int)req->mid,
54abd2aa
GC
622 (unsigned int)end_time.tv_sec,
623 (unsigned int)end_time.tv_usec));
624
b578db69 625 return push_queued_message(req, request_time, end_time,
54abd2aa
GC
626 private_data, priv_len);
627}
628
54abd2aa
GC
629struct idle_event {
630 struct timed_event *te;
631 struct timeval interval;
7c2bc9c0 632 char *name;
30191d1a 633 bool (*handler)(const struct timeval *now, void *private_data);
54abd2aa
GC
634 void *private_data;
635};
636
c34d5f44
SM
637static void smbd_idle_event_handler(struct event_context *ctx,
638 struct timed_event *te,
639 struct timeval now,
640 void *private_data)
54abd2aa
GC
641{
642 struct idle_event *event =
643 talloc_get_type_abort(private_data, struct idle_event);
644
fb5362c0 645 TALLOC_FREE(event->te);
54abd2aa 646
c34d5f44
SM
647 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
648 event->name, event->te));
649
650 if (!event->handler(&now, event->private_data)) {
651 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
652 event->name, event->te));
54abd2aa 653 /* Don't repeat, delete ourselves */
fb5362c0 654 TALLOC_FREE(event);
54abd2aa
GC
655 return;
656 }
657
c34d5f44
SM
658 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
659 event->name, event->te));
660
7c2bc9c0 661 event->te = event_add_timed(ctx, event,
c34d5f44
SM
662 timeval_sum(&now, &event->interval),
663 smbd_idle_event_handler, event);
54abd2aa
GC
664
665 /* We can't do much but fail here. */
666 SMB_ASSERT(event->te != NULL);
667}
668
7c2bc9c0
VL
669struct idle_event *event_add_idle(struct event_context *event_ctx,
670 TALLOC_CTX *mem_ctx,
54abd2aa 671 struct timeval interval,
7c2bc9c0 672 const char *name,
30191d1a 673 bool (*handler)(const struct timeval *now,
54abd2aa
GC
674 void *private_data),
675 void *private_data)
676{
677 struct idle_event *result;
678 struct timeval now = timeval_current();
679
680 result = TALLOC_P(mem_ctx, struct idle_event);
681 if (result == NULL) {
682 DEBUG(0, ("talloc failed\n"));
683 return NULL;
684 }
685
686 result->interval = interval;
687 result->handler = handler;
688 result->private_data = private_data;
689
7c2bc9c0
VL
690 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
691 DEBUG(0, ("talloc failed\n"));
692 TALLOC_FREE(result);
693 return NULL;
694 }
695
696 result->te = event_add_timed(event_ctx, result,
bf219447 697 timeval_sum(&now, &interval),
c34d5f44 698 smbd_idle_event_handler, result);
54abd2aa 699 if (result->te == NULL) {
bf219447 700 DEBUG(0, ("event_add_timed failed\n"));
fb5362c0 701 TALLOC_FREE(result);
54abd2aa
GC
702 return NULL;
703 }
704
c34d5f44 705 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
54abd2aa
GC
706 return result;
707}
8fbdd112 708
ac61f650
SM
709static void smbd_sig_term_handler(struct tevent_context *ev,
710 struct tevent_signal *se,
711 int signum,
712 int count,
713 void *siginfo,
714 void *private_data)
715{
716 exit_server_cleanly("termination signal");
717}
718
719void smbd_setup_sig_term_handler(void)
720{
721 struct tevent_signal *se;
722
723 se = tevent_add_signal(smbd_event_context(),
724 smbd_event_context(),
725 SIGTERM, 0,
726 smbd_sig_term_handler,
727 NULL);
728 if (!se) {
729 exit_server("failed to setup SIGTERM handler");
730 }
731}
732
733static void smbd_sig_hup_handler(struct tevent_context *ev,
734 struct tevent_signal *se,
735 int signum,
736 int count,
737 void *siginfo,
738 void *private_data)
739{
740 change_to_root_user();
741 DEBUG(1,("Reloading services after SIGHUP\n"));
742 reload_services(False);
743}
744
745void smbd_setup_sig_hup_handler(void)
746{
747 struct tevent_signal *se;
748
749 se = tevent_add_signal(smbd_event_context(),
750 smbd_event_context(),
751 SIGHUP, 0,
752 smbd_sig_hup_handler,
753 NULL);
754 if (!se) {
755 exit_server("failed to setup SIGHUP handler");
756 }
757}
758
aeb798c3 759static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
aab2fe02 760{
bf219447 761 fd_set r_fds, w_fds;
8843a637 762 int selrtn;
cc203f3e 763 struct timeval to;
8fbdd112 764 int maxfd = 0;
aab2fe02 765
f6c883b4
JA
766 to.tv_sec = SMBD_SELECT_TIMEOUT;
767 to.tv_usec = 0;
2fc57c9a 768
8843a637 769 /*
bf219447 770 * Setup the select fd sets.
8843a637
AT
771 */
772
bf219447
VL
773 FD_ZERO(&r_fds);
774 FD_ZERO(&w_fds);
e90b6528 775
cc203f3e
JA
776 /*
777 * Are there any timed events waiting ? If so, ensure we don't
778 * select for longer than it would take to wait for them.
779 */
780
54abd2aa 781 {
bf219447
VL
782 struct timeval now;
783 GetTimeOfDay(&now);
784
785 event_add_to_select_args(smbd_event_context(), &now,
786 &r_fds, &w_fds, &to, &maxfd);
787 }
788
048f8dba
SM
789 /* Process a signal and timed events now... */
790 if (run_events(smbd_event_context(), 0, NULL, NULL)) {
791 return NT_STATUS_RETRY;
54abd2aa 792 }
048f8dba 793
fbdcf266
JA
794 {
795 int sav;
796 START_PROFILE(smbd_idle);
797
bf219447 798 selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&to);
fbdcf266
JA
799 sav = errno;
800
801 END_PROFILE(smbd_idle);
802 errno = sav;
803 }
8843a637 804
bf219447 805 if (run_events(smbd_event_context(), selrtn, &r_fds, &w_fds)) {
1ce9525b 806 return NT_STATUS_RETRY;
bf219447
VL
807 }
808
8843a637 809 /* Check if error */
b2d01bd2 810 if (selrtn == -1) {
8843a637 811 /* something is wrong. Maybe the socket is dead? */
eaf7621c 812 return map_nt_error_from_unix(errno);
6913f101
JA
813 }
814
8843a637
AT
815 /* Did we timeout ? */
816 if (selrtn == 0) {
1ce9525b 817 return NT_STATUS_RETRY;
8843a637 818 }
b2d01bd2 819
830b31a4
SM
820 /* should not be reached */
821 return NT_STATUS_INTERNAL_ERROR;
aab2fe02 822}
c3effa8b 823
22dbd677
JA
824/*
825 * Only allow 5 outstanding trans requests. We're allocating memory, so
826 * prevent a DoS.
827 */
aab2fe02 828
22dbd677 829NTSTATUS allow_new_trans(struct trans_state *list, int mid)
c3effa8b 830{
22dbd677
JA
831 int count = 0;
832 for (; list != NULL; list = list->next) {
c3effa8b 833
22dbd677
JA
834 if (list->mid == mid) {
835 return NT_STATUS_INVALID_PARAMETER;
836 }
837
838 count += 1;
839 }
840 if (count > 5) {
841 return NT_STATUS_INSUFFICIENT_RESOURCES;
842 }
c3effa8b 843
22dbd677 844 return NT_STATUS_OK;
c3effa8b
AT
845}
846
c3effa8b
AT
847/*
848These flags determine some of the permissions required to do an operation
849
850Note that I don't set NEED_WRITE on some write operations because they
851are used by some brain-dead clients when printing, and I don't want to
852force write permissions on print services.
853*/
854#define AS_USER (1<<0)
ce61fb21 855#define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
c3effa8b 856#define TIME_INIT (1<<2)
ce61fb21
JA
857#define CAN_IPC (1<<3) /* Must be paired with AS_USER */
858#define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
54abd2aa 859#define DO_CHDIR (1<<6)
c3effa8b
AT
860
861/*
862 define a list of possible SMB messages and their corresponding
863 functions. Any message that has a NULL function is unimplemented -
864 please feel free to contribute implementations!
865*/
1eff0523
JA
866static const struct smb_message_struct {
867 const char *name;
48d3a1d2 868 void (*fn)(struct smb_request *req);
1eff0523
JA
869 int flags;
870} smb_messages[256] = {
918c3ebe 871
b578db69
VL
872/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
873/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
874/* 0x02 */ { "SMBopen",reply_open,AS_USER },
875/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
876/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
877/* 0x05 */ { "SMBflush",reply_flush,AS_USER},
878/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
879/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
880/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
881/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
882/* 0x0a */ { "SMBread",reply_read,AS_USER},
883/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
884/* 0x0c */ { "SMBlock",reply_lock,AS_USER},
885/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
886/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
887/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
888/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
889/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
890/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
891/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
892/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
893/* 0x15 */ { NULL, NULL, 0 },
894/* 0x16 */ { NULL, NULL, 0 },
895/* 0x17 */ { NULL, NULL, 0 },
896/* 0x18 */ { NULL, NULL, 0 },
897/* 0x19 */ { NULL, NULL, 0 },
898/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
899/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
900/* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
901/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
902/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
903/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
904/* 0x20 */ { "SMBwritec", NULL,0},
905/* 0x21 */ { NULL, NULL, 0 },
906/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
907/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
908/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
909/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
910/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
911/* 0x27 */ { "SMBioctl",reply_ioctl,0},
912/* 0x28 */ { "SMBioctls", NULL,AS_USER},
913/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
914/* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
915/* 0x2b */ { "SMBecho",reply_echo,0},
916/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
917/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
918/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
919/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
920/* 0x30 */ { NULL, NULL, 0 },
921/* 0x31 */ { NULL, NULL, 0 },
922/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
7716ad68 923/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
b578db69
VL
924/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
925/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
926/* 0x36 */ { NULL, NULL, 0 },
927/* 0x37 */ { NULL, NULL, 0 },
928/* 0x38 */ { NULL, NULL, 0 },
929/* 0x39 */ { NULL, NULL, 0 },
930/* 0x3a */ { NULL, NULL, 0 },
931/* 0x3b */ { NULL, NULL, 0 },
932/* 0x3c */ { NULL, NULL, 0 },
933/* 0x3d */ { NULL, NULL, 0 },
934/* 0x3e */ { NULL, NULL, 0 },
935/* 0x3f */ { NULL, NULL, 0 },
936/* 0x40 */ { NULL, NULL, 0 },
937/* 0x41 */ { NULL, NULL, 0 },
938/* 0x42 */ { NULL, NULL, 0 },
939/* 0x43 */ { NULL, NULL, 0 },
940/* 0x44 */ { NULL, NULL, 0 },
941/* 0x45 */ { NULL, NULL, 0 },
942/* 0x46 */ { NULL, NULL, 0 },
943/* 0x47 */ { NULL, NULL, 0 },
944/* 0x48 */ { NULL, NULL, 0 },
945/* 0x49 */ { NULL, NULL, 0 },
946/* 0x4a */ { NULL, NULL, 0 },
947/* 0x4b */ { NULL, NULL, 0 },
948/* 0x4c */ { NULL, NULL, 0 },
949/* 0x4d */ { NULL, NULL, 0 },
950/* 0x4e */ { NULL, NULL, 0 },
951/* 0x4f */ { NULL, NULL, 0 },
952/* 0x50 */ { NULL, NULL, 0 },
953/* 0x51 */ { NULL, NULL, 0 },
954/* 0x52 */ { NULL, NULL, 0 },
955/* 0x53 */ { NULL, NULL, 0 },
956/* 0x54 */ { NULL, NULL, 0 },
957/* 0x55 */ { NULL, NULL, 0 },
958/* 0x56 */ { NULL, NULL, 0 },
959/* 0x57 */ { NULL, NULL, 0 },
960/* 0x58 */ { NULL, NULL, 0 },
961/* 0x59 */ { NULL, NULL, 0 },
962/* 0x5a */ { NULL, NULL, 0 },
963/* 0x5b */ { NULL, NULL, 0 },
964/* 0x5c */ { NULL, NULL, 0 },
965/* 0x5d */ { NULL, NULL, 0 },
966/* 0x5e */ { NULL, NULL, 0 },
967/* 0x5f */ { NULL, NULL, 0 },
968/* 0x60 */ { NULL, NULL, 0 },
969/* 0x61 */ { NULL, NULL, 0 },
970/* 0x62 */ { NULL, NULL, 0 },
971/* 0x63 */ { NULL, NULL, 0 },
972/* 0x64 */ { NULL, NULL, 0 },
973/* 0x65 */ { NULL, NULL, 0 },
974/* 0x66 */ { NULL, NULL, 0 },
975/* 0x67 */ { NULL, NULL, 0 },
976/* 0x68 */ { NULL, NULL, 0 },
977/* 0x69 */ { NULL, NULL, 0 },
978/* 0x6a */ { NULL, NULL, 0 },
979/* 0x6b */ { NULL, NULL, 0 },
980/* 0x6c */ { NULL, NULL, 0 },
981/* 0x6d */ { NULL, NULL, 0 },
982/* 0x6e */ { NULL, NULL, 0 },
983/* 0x6f */ { NULL, NULL, 0 },
984/* 0x70 */ { "SMBtcon",reply_tcon,0},
985/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
986/* 0x72 */ { "SMBnegprot",reply_negprot,0},
987/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
988/* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
989/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
990/* 0x76 */ { NULL, NULL, 0 },
991/* 0x77 */ { NULL, NULL, 0 },
992/* 0x78 */ { NULL, NULL, 0 },
993/* 0x79 */ { NULL, NULL, 0 },
994/* 0x7a */ { NULL, NULL, 0 },
995/* 0x7b */ { NULL, NULL, 0 },
996/* 0x7c */ { NULL, NULL, 0 },
997/* 0x7d */ { NULL, NULL, 0 },
998/* 0x7e */ { NULL, NULL, 0 },
999/* 0x7f */ { NULL, NULL, 0 },
1000/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1001/* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1002/* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1003/* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1004/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1005/* 0x85 */ { NULL, NULL, 0 },
1006/* 0x86 */ { NULL, NULL, 0 },
1007/* 0x87 */ { NULL, NULL, 0 },
1008/* 0x88 */ { NULL, NULL, 0 },
1009/* 0x89 */ { NULL, NULL, 0 },
1010/* 0x8a */ { NULL, NULL, 0 },
1011/* 0x8b */ { NULL, NULL, 0 },
1012/* 0x8c */ { NULL, NULL, 0 },
1013/* 0x8d */ { NULL, NULL, 0 },
1014/* 0x8e */ { NULL, NULL, 0 },
1015/* 0x8f */ { NULL, NULL, 0 },
1016/* 0x90 */ { NULL, NULL, 0 },
1017/* 0x91 */ { NULL, NULL, 0 },
1018/* 0x92 */ { NULL, NULL, 0 },
1019/* 0x93 */ { NULL, NULL, 0 },
1020/* 0x94 */ { NULL, NULL, 0 },
1021/* 0x95 */ { NULL, NULL, 0 },
1022/* 0x96 */ { NULL, NULL, 0 },
1023/* 0x97 */ { NULL, NULL, 0 },
1024/* 0x98 */ { NULL, NULL, 0 },
1025/* 0x99 */ { NULL, NULL, 0 },
1026/* 0x9a */ { NULL, NULL, 0 },
1027/* 0x9b */ { NULL, NULL, 0 },
1028/* 0x9c */ { NULL, NULL, 0 },
1029/* 0x9d */ { NULL, NULL, 0 },
1030/* 0x9e */ { NULL, NULL, 0 },
1031/* 0x9f */ { NULL, NULL, 0 },
1032/* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1033/* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1034/* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1035/* 0xa3 */ { NULL, NULL, 0 },
1036/* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1037/* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1038/* 0xa6 */ { NULL, NULL, 0 },
1039/* 0xa7 */ { NULL, NULL, 0 },
1040/* 0xa8 */ { NULL, NULL, 0 },
1041/* 0xa9 */ { NULL, NULL, 0 },
1042/* 0xaa */ { NULL, NULL, 0 },
1043/* 0xab */ { NULL, NULL, 0 },
1044/* 0xac */ { NULL, NULL, 0 },
1045/* 0xad */ { NULL, NULL, 0 },
1046/* 0xae */ { NULL, NULL, 0 },
1047/* 0xaf */ { NULL, NULL, 0 },
1048/* 0xb0 */ { NULL, NULL, 0 },
1049/* 0xb1 */ { NULL, NULL, 0 },
1050/* 0xb2 */ { NULL, NULL, 0 },
1051/* 0xb3 */ { NULL, NULL, 0 },
1052/* 0xb4 */ { NULL, NULL, 0 },
1053/* 0xb5 */ { NULL, NULL, 0 },
1054/* 0xb6 */ { NULL, NULL, 0 },
1055/* 0xb7 */ { NULL, NULL, 0 },
1056/* 0xb8 */ { NULL, NULL, 0 },
1057/* 0xb9 */ { NULL, NULL, 0 },
1058/* 0xba */ { NULL, NULL, 0 },
1059/* 0xbb */ { NULL, NULL, 0 },
1060/* 0xbc */ { NULL, NULL, 0 },
1061/* 0xbd */ { NULL, NULL, 0 },
1062/* 0xbe */ { NULL, NULL, 0 },
1063/* 0xbf */ { NULL, NULL, 0 },
1064/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1065/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1066/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1067/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1068/* 0xc4 */ { NULL, NULL, 0 },
1069/* 0xc5 */ { NULL, NULL, 0 },
1070/* 0xc6 */ { NULL, NULL, 0 },
1071/* 0xc7 */ { NULL, NULL, 0 },
1072/* 0xc8 */ { NULL, NULL, 0 },
1073/* 0xc9 */ { NULL, NULL, 0 },
1074/* 0xca */ { NULL, NULL, 0 },
1075/* 0xcb */ { NULL, NULL, 0 },
1076/* 0xcc */ { NULL, NULL, 0 },
1077/* 0xcd */ { NULL, NULL, 0 },
1078/* 0xce */ { NULL, NULL, 0 },
1079/* 0xcf */ { NULL, NULL, 0 },
1080/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1081/* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1082/* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1083/* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1084/* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1085/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1086/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1087/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1088/* 0xd8 */ { NULL, NULL, 0 },
1089/* 0xd9 */ { NULL, NULL, 0 },
1090/* 0xda */ { NULL, NULL, 0 },
1091/* 0xdb */ { NULL, NULL, 0 },
1092/* 0xdc */ { NULL, NULL, 0 },
1093/* 0xdd */ { NULL, NULL, 0 },
1094/* 0xde */ { NULL, NULL, 0 },
1095/* 0xdf */ { NULL, NULL, 0 },
1096/* 0xe0 */ { NULL, NULL, 0 },
1097/* 0xe1 */ { NULL, NULL, 0 },
1098/* 0xe2 */ { NULL, NULL, 0 },
1099/* 0xe3 */ { NULL, NULL, 0 },
1100/* 0xe4 */ { NULL, NULL, 0 },
1101/* 0xe5 */ { NULL, NULL, 0 },
1102/* 0xe6 */ { NULL, NULL, 0 },
1103/* 0xe7 */ { NULL, NULL, 0 },
1104/* 0xe8 */ { NULL, NULL, 0 },
1105/* 0xe9 */ { NULL, NULL, 0 },
1106/* 0xea */ { NULL, NULL, 0 },
1107/* 0xeb */ { NULL, NULL, 0 },
1108/* 0xec */ { NULL, NULL, 0 },
1109/* 0xed */ { NULL, NULL, 0 },
1110/* 0xee */ { NULL, NULL, 0 },
1111/* 0xef */ { NULL, NULL, 0 },
1112/* 0xf0 */ { NULL, NULL, 0 },
1113/* 0xf1 */ { NULL, NULL, 0 },
1114/* 0xf2 */ { NULL, NULL, 0 },
1115/* 0xf3 */ { NULL, NULL, 0 },
1116/* 0xf4 */ { NULL, NULL, 0 },
1117/* 0xf5 */ { NULL, NULL, 0 },
1118/* 0xf6 */ { NULL, NULL, 0 },
1119/* 0xf7 */ { NULL, NULL, 0 },
1120/* 0xf8 */ { NULL, NULL, 0 },
1121/* 0xf9 */ { NULL, NULL, 0 },
1122/* 0xfa */ { NULL, NULL, 0 },
1123/* 0xfb */ { NULL, NULL, 0 },
1124/* 0xfc */ { NULL, NULL, 0 },
1125/* 0xfd */ { NULL, NULL, 0 },
1126/* 0xfe */ { NULL, NULL, 0 },
1127/* 0xff */ { NULL, NULL, 0 }
918c3ebe
JA
1128
1129};
c3effa8b 1130
cc6a4101
VL
1131/*******************************************************************
1132 allocate and initialize a reply packet
1133********************************************************************/
1134
ae0c6cff
VL
1135static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1136 const char *inbuf, char **outbuf, uint8_t num_words,
1137 uint32_t num_bytes)
cc6a4101 1138{
2fb27fcb
VL
1139 /*
1140 * Protect against integer wrap
1141 */
1142 if ((num_bytes > 0xffffff)
1143 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1144 char *msg;
a4c0812a
VL
1145 if (asprintf(&msg, "num_bytes too large: %u",
1146 (unsigned)num_bytes) == -1) {
1147 msg = CONST_DISCARD(char *, "num_bytes too large");
1148 }
2fb27fcb
VL
1149 smb_panic(msg);
1150 }
1151
5cd8a427
VL
1152 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1153 smb_size + num_words*2 + num_bytes);
1154 if (*outbuf == NULL) {
1155 return false;
cc6a4101
VL
1156 }
1157
ae0c6cff 1158 construct_reply_common(req, inbuf, *outbuf);
5cd8a427 1159 srv_set_message(*outbuf, num_words, num_bytes, false);
cc6a4101
VL
1160 /*
1161 * Zero out the word area, the caller has to take care of the bcc area
1162 * himself
1163 */
1164 if (num_words != 0) {
5cd8a427 1165 memset(*outbuf + smb_vwv0, 0, num_words*2);
cc6a4101
VL
1166 }
1167
5cd8a427
VL
1168 return true;
1169}
1170
1171void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1172{
1173 char *outbuf;
ae0c6cff 1174 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
5cd8a427
VL
1175 num_bytes)) {
1176 smb_panic("could not allocate output buffer\n");
1177 }
1178 req->outbuf = (uint8_t *)outbuf;
cc6a4101
VL
1179}
1180
1181
712a30ed 1182/*******************************************************************
a834a73e
GC
1183 Dump a packet to a file.
1184********************************************************************/
1185
cc6a4101 1186static void smb_dump(const char *name, int type, const char *data, ssize_t len)
712a30ed
LL
1187{
1188 int fd, i;
d068bc64
JA
1189 char *fname = NULL;
1190 if (DEBUGLEVEL < 50) {
1191 return;
1192 }
712a30ed 1193
62707533 1194 if (len < 4) len = smb_len(data)+4;
712a30ed 1195 for (i=1;i<100;i++) {
a4c0812a
VL
1196 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1197 type ? "req" : "resp") == -1) {
d068bc64
JA
1198 return;
1199 }
712a30ed
LL
1200 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1201 if (fd != -1 || errno != EEXIST) break;
1202 }
1203 if (fd != -1) {
e400bfce
JA
1204 ssize_t ret = write(fd, data, len);
1205 if (ret != len)
1206 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
712a30ed 1207 close(fd);
9c8d23e5 1208 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
712a30ed 1209 }
d068bc64 1210 SAFE_FREE(fname);
712a30ed
LL
1211}
1212
c3effa8b 1213/****************************************************************************
cc6a4101
VL
1214 Prepare everything for calling the actual request function, and potentially
1215 call the request function via the "new" interface.
1216
1217 Return False if the "legacy" function needs to be called, everything is
1218 prepared.
1219
1220 Return True if we're done.
1221
1222 I know this API sucks, but it is the one with the least code change I could
1223 find.
c3effa8b 1224****************************************************************************/
a834a73e 1225
9254bb4e 1226static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
c3effa8b 1227{
941db29a 1228 int flags;
941db29a 1229 uint16 session_tag;
9254bb4e 1230 connection_struct *conn = NULL;
356f0336 1231 struct smbd_server_connection *sconn = smbd_server_conn;
24f8e973 1232
a834a73e 1233 errno = 0;
0557c6cb 1234
cc6a4101
VL
1235 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1236 * so subtract 4 from it. */
9254bb4e 1237 if (!valid_smb_header(req->inbuf)
cc6a4101
VL
1238 || (size < (smb_size - 4))) {
1239 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1240 smb_len(req->inbuf)));
eecdc6c9 1241 exit_server_cleanly("Non-SMB packet");
a834a73e 1242 }
c3effa8b 1243
48d3a1d2 1244 if (smb_messages[type].fn == NULL) {
a834a73e 1245 DEBUG(0,("Unknown message type %d!\n",type));
cc6a4101
VL
1246 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1247 reply_unknown_new(req, type);
9254bb4e 1248 return NULL;
941db29a 1249 }
a834a73e 1250
941db29a 1251 flags = smb_messages[type].flags;
a834a73e 1252
941db29a
VL
1253 /* In share mode security we must ignore the vuid. */
1254 session_tag = (lp_security() == SEC_SHARE)
cc6a4101 1255 ? UID_FIELD_INVALID : req->vuid;
9254bb4e 1256 conn = req->conn;
918c3ebe 1257
8579dd4d
VL
1258 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1259 (int)sys_getpid(), (unsigned long)conn));
941db29a 1260
cc6a4101 1261 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
918c3ebe 1262
941db29a 1263 /* Ensure this value is replaced in the incoming packet. */
cc6a4101 1264 SSVAL(req->inbuf,smb_uid,session_tag);
918c3ebe 1265
941db29a
VL
1266 /*
1267 * Ensure the correct username is in current_user_info. This is a
1268 * really ugly bugfix for problems with multiple session_setup_and_X's
1269 * being done and allowing %U and %G substitutions to work correctly.
1270 * There is a reason this code is done here, don't move it unless you
8579dd4d
VL
1271 * know what you're doing... :-).
1272 * JRA.
941db29a
VL
1273 */
1274
356f0336 1275 if (session_tag != sconn->smb1.sessions.last_session_tag) {
941db29a
VL
1276 user_struct *vuser = NULL;
1277
356f0336 1278 sconn->smb1.sessions.last_session_tag = session_tag;
941db29a 1279 if(session_tag != UID_FIELD_INVALID) {
75d03970 1280 vuser = get_valid_user_struct(sconn, session_tag);
941db29a 1281 if (vuser) {
bec1dfab
VL
1282 set_current_user_info(
1283 vuser->server_info->sanitized_username,
1284 vuser->server_info->unix_name,
bec1dfab
VL
1285 pdb_get_domain(vuser->server_info
1286 ->sam_account));
a59149b8
JA
1287 }
1288 }
941db29a 1289 }
d57e67f9 1290
941db29a
VL
1291 /* Does this call need to be run as the connected user? */
1292 if (flags & AS_USER) {
fcda2645 1293
941db29a
VL
1294 /* Does this call need a valid tree connection? */
1295 if (!conn) {
8579dd4d
VL
1296 /*
1297 * Amazingly, the error code depends on the command
1298 * (from Samba4).
1299 */
941db29a 1300 if (type == SMBntcreateX) {
cc6a4101 1301 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
941db29a 1302 } else {
cc6a4101 1303 reply_doserror(req, ERRSRV, ERRinvnid);
ce61fb21 1304 }
9254bb4e 1305 return NULL;
941db29a 1306 }
d57e67f9 1307
941db29a 1308 if (!change_to_user(conn,session_tag)) {
5e9aade5
ZK
1309 DEBUG(0, ("Error: Could not change to user. Removing "
1310 "deferred open, mid=%d.\n", req->mid));
cc6a4101 1311 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
09536880 1312 remove_deferred_open_smb_message(req->mid);
9254bb4e 1313 return conn;
941db29a 1314 }
c3effa8b 1315
941db29a 1316 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
918c3ebe 1317
941db29a
VL
1318 /* Does it need write permission? */
1319 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
cc6a4101 1320 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
9254bb4e 1321 return conn;
ce61fb21 1322 }
918c3ebe 1323
941db29a
VL
1324 /* IPC services are limited */
1325 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
cc6a4101 1326 reply_doserror(req, ERRSRV,ERRaccess);
9254bb4e 1327 return conn;
f60ad8de 1328 }
941db29a
VL
1329 } else {
1330 /* This call needs to be run as root */
1331 change_to_root_user();
1332 }
918c3ebe 1333
941db29a
VL
1334 /* load service specific parameters */
1335 if (conn) {
9254bb4e
JA
1336 if (req->encrypted) {
1337 conn->encrypted_tid = true;
1338 /* encrypted required from now on. */
1339 conn->encrypt_level = Required;
1340 } else if (ENCRYPTION_REQUIRED(conn)) {
7808a259 1341 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
9254bb4e
JA
1342 exit_server_cleanly("encryption required "
1343 "on connection");
1344 return conn;
1345 }
1346 }
1347
cc6a4101 1348 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
8579dd4d
VL
1349 (flags & (AS_USER|DO_CHDIR)
1350 ?True:False))) {
cc6a4101 1351 reply_doserror(req, ERRSRV, ERRaccess);
9254bb4e 1352 return conn;
afce2b24 1353 }
941db29a
VL
1354 conn->num_smb_operations++;
1355 }
918c3ebe 1356
941db29a
VL
1357 /* does this protocol need to be run as guest? */
1358 if ((flags & AS_GUEST)
8579dd4d 1359 && (!change_to_guest() ||
941db29a
VL
1360 !check_access(smbd_server_fd(), lp_hostsallow(-1),
1361 lp_hostsdeny(-1)))) {
cc6a4101 1362 reply_doserror(req, ERRSRV, ERRaccess);
9254bb4e 1363 return conn;
cc6a4101
VL
1364 }
1365
48d3a1d2 1366 smb_messages[type].fn(req);
9254bb4e 1367 return req->conn;
e9ea36e4
AT
1368}
1369
e9ea36e4 1370/****************************************************************************
a834a73e 1371 Construct a reply to the incoming packet.
e9ea36e4 1372****************************************************************************/
a834a73e 1373
54c51a66 1374static void construct_reply(char *inbuf, int size, size_t unread_bytes,
c16c90a1 1375 uint32_t seqnum, bool encrypted,
54c51a66 1376 struct smb_perfcount_data *deferred_pcd)
e9ea36e4 1377{
9254bb4e 1378 connection_struct *conn;
cc6a4101 1379 struct smb_request *req;
e9ea36e4 1380
929e1d99 1381 if (!(req = talloc(talloc_tos(), struct smb_request))) {
cc6a4101
VL
1382 smb_panic("could not allocate smb_request");
1383 }
54c51a66 1384
9254bb4e 1385 init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
b8125663 1386 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
c16c90a1 1387 req->seqnum = seqnum;
e9ea36e4 1388
54c51a66 1389 /* we popped this message off the queue - keep original perf data */
1390 if (deferred_pcd)
1391 req->pcd = *deferred_pcd;
1392 else {
1393 SMB_PERFCOUNT_START(&req->pcd);
1394 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1395 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1396 }
1397
7808a259 1398 conn = switch_message(req->cmd, req, size);
e9ea36e4 1399
c3250149
JA
1400 if (req->unread_bytes) {
1401 /* writeX failed. drain socket. */
1402 if (drain_socket(smbd_server_fd(), req->unread_bytes) !=
1403 req->unread_bytes) {
1404 smb_panic("failed to drain pending bytes");
1405 }
1406 req->unread_bytes = 0;
1407 }
1408
5135ebd6
VL
1409 if (req->done) {
1410 TALLOC_FREE(req);
1411 return;
1412 }
1413
b578db69
VL
1414 if (req->outbuf == NULL) {
1415 return;
cc6a4101 1416 }
e9ea36e4 1417
b578db69
VL
1418 if (CVAL(req->outbuf,0) == 0) {
1419 show_msg((char *)req->outbuf);
1420 }
e9ea36e4 1421
9254bb4e
JA
1422 if (!srv_send_smb(smbd_server_fd(),
1423 (char *)req->outbuf,
c16c90a1 1424 true, req->seqnum+1,
54c51a66 1425 IS_CONN_ENCRYPTED(conn)||req->encrypted,
1426 &req->pcd)) {
9254bb4e 1427 exit_server_cleanly("construct_reply: srv_send_smb failed.");
dc90cd89 1428 }
cc6a4101
VL
1429
1430 TALLOC_FREE(req);
1431
1432 return;
e9ea36e4
AT
1433}
1434
e9ea36e4 1435/****************************************************************************
49ecd176 1436 Process an smb from the client
e9ea36e4 1437****************************************************************************/
aeb798c3
SM
1438static void process_smb(struct smbd_server_connection *conn,
1439 uint8_t *inbuf, size_t nread, size_t unread_bytes,
c16c90a1
SM
1440 uint32_t seqnum, bool encrypted,
1441 struct smb_perfcount_data *deferred_pcd)
e9ea36e4 1442{
1eff0523 1443 int msg_type = CVAL(inbuf,0);
1eff0523
JA
1444
1445 DO_PROFILE_INC(smb_count);
1446
cc6a4101
VL
1447 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1448 smb_len(inbuf) ) );
c3250149
JA
1449 DEBUG( 3, ( "Transaction %d of length %d (%u toread)\n", trans_num,
1450 (int)nread,
1451 (unsigned int)unread_bytes ));
1eff0523 1452
cc6a4101
VL
1453 if (msg_type != 0) {
1454 /*
1455 * NetBIOS session request, keepalive, etc.
1456 */
aeb798c3
SM
1457 reply_special((char *)inbuf);
1458 goto done;
cc6a4101 1459 }
1eff0523 1460
688945a9
SM
1461 if (smbd_server_conn->allow_smb2) {
1462 if (smbd_is_smb2_header(inbuf, nread)) {
1463 smbd_smb2_first_negprot(smbd_server_conn, inbuf, nread);
1464 return;
1465 }
1466 smbd_server_conn->allow_smb2 = false;
1467 }
1468
aeb798c3 1469 show_msg((char *)inbuf);
cc6a4101 1470
c16c90a1 1471 construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
1eff0523 1472 trans_num++;
aeb798c3
SM
1473
1474done:
ebc860eb 1475 conn->smb1.num_requests++;
aeb798c3
SM
1476
1477 /* The timeout_processing function isn't run nearly
1478 often enough to implement 'max log size' without
1479 overrunning the size of the file by many megabytes.
1480 This is especially true if we are running at debug
1481 level 10. Checking every 50 SMBs is a nice
1482 tradeoff of performance vs log file size overrun. */
1483
ebc860eb 1484 if ((conn->smb1.num_requests % 50) == 0 &&
aeb798c3
SM
1485 need_to_check_log_size()) {
1486 change_to_root_user();
1487 check_log_size();
1488 }
e9ea36e4
AT
1489}
1490
e9ea36e4 1491/****************************************************************************
1eff0523 1492 Return a string containing the function name of a SMB command.
e9ea36e4 1493****************************************************************************/
1eff0523 1494
127e77e6 1495const char *smb_fn_name(int type)
e9ea36e4 1496{
634c5431 1497 const char *unknown_name = "SMBunknown";
e9ea36e4 1498
918c3ebe 1499 if (smb_messages[type].name == NULL)
e9ea36e4
AT
1500 return(unknown_name);
1501
918c3ebe 1502 return(smb_messages[type].name);
c3effa8b
AT
1503}
1504
dc76502c 1505/****************************************************************************
6bb8f54e 1506 Helper functions for contruct_reply.
dc76502c
JA
1507****************************************************************************/
1508
6219c997
JA
1509void add_to_common_flags2(uint32 v)
1510{
1511 common_flags2 |= v;
1512}
6bb8f54e 1513
27891bde 1514void remove_from_common_flags2(uint32 v)
6bb8f54e 1515{
27891bde 1516 common_flags2 &= ~v;
6bb8f54e
JA
1517}
1518
ae0c6cff
VL
1519static void construct_reply_common(struct smb_request *req, const char *inbuf,
1520 char *outbuf)
dc76502c 1521{
9254bb4e 1522 srv_set_message(outbuf,0,0,false);
e5a95132 1523
ae0c6cff 1524 SCVAL(outbuf, smb_com, req->cmd);
fc13f284 1525 SIVAL(outbuf,smb_rcls,0);
b7280423
AT
1526 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1527 SSVAL(outbuf,smb_flg2,
6bb8f54e
JA
1528 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1529 common_flags2);
fc13f284 1530 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
b7280423 1531
b7280423
AT
1532 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1533 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1534 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1535 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
dc76502c 1536}
c3effa8b 1537
e4897a53
VL
1538void construct_reply_common_req(struct smb_request *req, char *outbuf)
1539{
ae0c6cff 1540 construct_reply_common(req, (char *)req->inbuf, outbuf);
e4897a53
VL
1541}
1542
ddaa65ef
VL
1543/*
1544 * How many bytes have we already accumulated up to the current wct field
1545 * offset?
1546 */
1547
1548size_t req_wct_ofs(struct smb_request *req)
1549{
1550 size_t buf_size;
1551
1552 if (req->chain_outbuf == NULL) {
1553 return smb_wct - 4;
1554 }
1555 buf_size = talloc_get_size(req->chain_outbuf);
1556 if ((buf_size % 4) != 0) {
1557 buf_size += (4 - (buf_size % 4));
1558 }
1559 return buf_size - 4;
1560}
1561
ba981128
VL
1562/*
1563 * Hack around reply_nterror & friends not being aware of chained requests,
1564 * generating illegal (i.e. wct==0) chain replies.
1565 */
1566
1567static void fixup_chain_error_packet(struct smb_request *req)
1568{
1569 uint8_t *outbuf = req->outbuf;
1570 req->outbuf = NULL;
1571 reply_outbuf(req, 2, 0);
1572 memcpy(req->outbuf, outbuf, smb_wct);
1573 TALLOC_FREE(outbuf);
1574 SCVAL(req->outbuf, smb_vwv0, 0xff);
1575}
1576
0d7ca8e8
VL
1577/****************************************************************************
1578 Construct a chained reply and add it to the already made reply
1579****************************************************************************/
1580
ba981128
VL
1581void chain_reply(struct smb_request *req)
1582{
1583 size_t smblen = smb_len(req->inbuf);
1584 size_t already_used, length_needed;
1585 uint8_t chain_cmd;
1586 uint32_t chain_offset; /* uint32_t to avoid overflow */
1587
1588 uint8_t wct;
1589 uint16_t *vwv;
1590 uint16_t buflen;
1591 uint8_t *buf;
1592
1593 if (IVAL(req->outbuf, smb_rcls) != 0) {
1594 fixup_chain_error_packet(req);
1595 }
1596
1597 /*
1598 * Any of the AndX requests and replies have at least a wct of
1599 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1600 * beginning of the SMB header to the next wct field.
1601 *
1602 * None of the AndX requests put anything valuable in vwv[0] and [1],
1603 * so we can overwrite it here to form the chain.
1604 */
1605
1606 if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
1607 goto error;
1608 }
1609
1610 /*
1611 * Here we assume that this is the end of the chain. For that we need
1612 * to set "next command" to 0xff and the offset to 0. If we later find
1613 * more commands in the chain, this will be overwritten again.
1614 */
1615
1616 SCVAL(req->outbuf, smb_vwv0, 0xff);
1617 SCVAL(req->outbuf, smb_vwv0+1, 0);
1618 SSVAL(req->outbuf, smb_vwv1, 0);
1619
1620 if (req->chain_outbuf == NULL) {
1621 /*
1622 * In req->chain_outbuf we collect all the replies. Start the
1623 * chain by copying in the first reply.
c0fea1f0
VL
1624 *
1625 * We do the realloc because later on we depend on
1626 * talloc_get_size to determine the length of
1627 * chain_outbuf. The reply_xxx routines might have
1628 * over-allocated (reply_pipe_read_and_X used to be such an
1629 * example).
ba981128 1630 */
c0fea1f0
VL
1631 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
1632 req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
1633 if (req->chain_outbuf == NULL) {
1634 goto error;
1635 }
ba981128
VL
1636 req->outbuf = NULL;
1637 } else {
6c935f95
TP
1638 /*
1639 * Update smb headers where subsequent chained commands
1640 * may have updated them.
1641 */
1642 SCVAL(req->chain_outbuf, smb_tid, CVAL(req->outbuf, smb_tid));
1643 SCVAL(req->chain_outbuf, smb_uid, CVAL(req->outbuf, smb_uid));
1644
ba981128
VL
1645 if (!smb_splice_chain(&req->chain_outbuf,
1646 CVAL(req->outbuf, smb_com),
1647 CVAL(req->outbuf, smb_wct),
1648 (uint16_t *)(req->outbuf + smb_vwv),
1649 0, smb_buflen(req->outbuf),
1650 (uint8_t *)smb_buf(req->outbuf))) {
1651 goto error;
1652 }
1653 TALLOC_FREE(req->outbuf);
1654 }
1655
1656 /*
1657 * We use the old request's vwv field to grab the next chained command
1658 * and offset into the chained fields.
1659 */
1660
1661 chain_cmd = CVAL(req->vwv+0, 0);
1662 chain_offset = SVAL(req->vwv+1, 0);
1663
1664 if (chain_cmd == 0xff) {
1665 /*
1666 * End of chain, no more requests from the client. So ship the
1667 * replies.
1668 */
1669 smb_setlen((char *)(req->chain_outbuf),
1670 talloc_get_size(req->chain_outbuf) - 4);
54c51a66 1671
ba981128 1672 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
c16c90a1 1673 true, req->seqnum+1,
ba981128 1674 IS_CONN_ENCRYPTED(req->conn)
54c51a66 1675 ||req->encrypted,
1676 &req->pcd)) {
ba981128
VL
1677 exit_server_cleanly("chain_reply: srv_send_smb "
1678 "failed.");
1679 }
5135ebd6
VL
1680 TALLOC_FREE(req->chain_outbuf);
1681 req->done = true;
ba981128
VL
1682 return;
1683 }
1684
54c51a66 1685 /* add a new perfcounter for this element of chain */
1686 SMB_PERFCOUNT_ADD(&req->pcd);
1687 SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
1688 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
1689
ba981128
VL
1690 /*
1691 * Check if the client tries to fool us. The request so far uses the
1692 * space to the end of the byte buffer in the request just
1693 * processed. The chain_offset can't point into that area. If that was
1694 * the case, we could end up with an endless processing of the chain,
1695 * we would always handle the same request.
1696 */
1697
1698 already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
1699 if (chain_offset < already_used) {
1700 goto error;
1701 }
1702
1703 /*
1704 * Next check: Make sure the chain offset does not point beyond the
1705 * overall smb request length.
1706 */
1707
1708 length_needed = chain_offset+1; /* wct */
1709 if (length_needed > smblen) {
1710 goto error;
1711 }
1712
1713 /*
1714 * Now comes the pointer magic. Goal here is to set up req->vwv and
1715 * req->buf correctly again to be able to call the subsequent
1716 * switch_message(). The chain offset (the former vwv[1]) points at
1717 * the new wct field.
1718 */
1719
1720 wct = CVAL(smb_base(req->inbuf), chain_offset);
1721
1722 /*
1723 * Next consistency check: Make the new vwv array fits in the overall
1724 * smb request.
1725 */
1726
1727 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1728 if (length_needed > smblen) {
1729 goto error;
1730 }
1731 vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
1732
1733 /*
1734 * Now grab the new byte buffer....
1735 */
1736
1737 buflen = SVAL(vwv+wct, 0);
1738
1739 /*
1740 * .. and check that it fits.
1741 */
1742
1743 length_needed += buflen;
1744 if (length_needed > smblen) {
1745 goto error;
1746 }
1747 buf = (uint8_t *)(vwv+wct+1);
1748
1749 req->cmd = chain_cmd;
1750 req->wct = wct;
1751 req->vwv = vwv;
1752 req->buflen = buflen;
1753 req->buf = buf;
1754
1755 switch_message(chain_cmd, req, smblen);
1756
1757 if (req->outbuf == NULL) {
1758 /*
1759 * This happens if the chained command has suspended itself or
1760 * if it has called srv_send_smb() itself.
1761 */
1762 return;
1763 }
1764
1765 /*
1766 * We end up here if the chained command was not itself chained or
1767 * suspended, but for example a close() command. We now need to splice
1768 * the chained commands' outbuf into the already built up chain_outbuf
1769 * and ship the result.
1770 */
1771 goto done;
1772
1773 error:
1774 /*
1775 * We end up here if there's any error in the chain syntax. Report a
1776 * DOS error, just like Windows does.
1777 */
1778 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
1779 fixup_chain_error_packet(req);
1780
1781 done:
c116652a
VL
1782 /*
1783 * This scary statement intends to set the
1784 * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
1785 * to the value req->outbuf carries
1786 */
1787 SSVAL(req->chain_outbuf, smb_flg2,
1788 (SVAL(req->chain_outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1789 | (SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1790
1791 /*
1792 * Transfer the error codes from the subrequest to the main one
1793 */
1794 SSVAL(req->chain_outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1795 SSVAL(req->chain_outbuf, smb_err, SVAL(req->outbuf, smb_err));
1796
ba981128
VL
1797 if (!smb_splice_chain(&req->chain_outbuf,
1798 CVAL(req->outbuf, smb_com),
1799 CVAL(req->outbuf, smb_wct),
1800 (uint16_t *)(req->outbuf + smb_vwv),
1801 0, smb_buflen(req->outbuf),
1802 (uint8_t *)smb_buf(req->outbuf))) {
1803 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
1804 }
1805 TALLOC_FREE(req->outbuf);
1806
1807 smb_setlen((char *)(req->chain_outbuf),
1808 talloc_get_size(req->chain_outbuf) - 4);
1809
1810 show_msg((char *)(req->chain_outbuf));
1811
1812 if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
c16c90a1 1813 true, req->seqnum+1,
54c51a66 1814 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
1815 &req->pcd)) {
ba981128
VL
1816 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1817 }
5135ebd6
VL
1818 TALLOC_FREE(req->chain_outbuf);
1819 req->done = true;
ba981128
VL
1820}
1821
3db52feb
AT
1822/****************************************************************************
1823 Check if services need reloading.
1824****************************************************************************/
1825
54abd2aa 1826void check_reload(time_t t)
3db52feb 1827{
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
ac61f650 1850 if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
1eff0523 1851 reload_services(True);
1eff0523
JA
1852 last_smb_conf_reload_time = t;
1853 }
67d47486
GC
1854
1855 /* 'printcap cache time = 0' disable the feature */
1856
1857 if ( printcap_cache_time != 0 )
1858 {
1859 /* see if it's time to reload or if the clock has been set back */
1860
d097ea49
GC
1861 if ( (t >= last_printer_reload_time+printcap_cache_time)
1862 || (t-last_printer_reload_time < 0) )
67d47486
GC
1863 {
1864 DEBUG( 3,( "Printcap cache time expired.\n"));
d097ea49
GC
1865 reload_printers();
1866 last_printer_reload_time = t;
67d47486
GC
1867 }
1868 }
3db52feb 1869}
c3effa8b 1870
aeb798c3
SM
1871static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
1872{
1873 /* TODO: make write nonblocking */
1874}
1875
1876static void smbd_server_connection_read_handler(struct smbd_server_connection *conn)
1877{
1878 uint8_t *inbuf = NULL;
1879 size_t inbuf_len = 0;
1880 size_t unread_bytes = 0;
1881 bool encrypted = false;
1882 TALLOC_CTX *mem_ctx = talloc_tos();
1883 NTSTATUS status;
c16c90a1 1884 uint32_t seqnum;
aeb798c3
SM
1885
1886 /* TODO: make this completely nonblocking */
1887
1888 status = receive_smb_talloc(mem_ctx, smbd_server_fd(),
d9c40172 1889 (char **)(void *)&inbuf,
aeb798c3
SM
1890 0, /* timeout */
1891 &unread_bytes,
1892 &encrypted,
c16c90a1 1893 &inbuf_len, &seqnum);
aeb798c3
SM
1894 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
1895 goto process;
1896 }
1897 if (NT_STATUS_IS_ERR(status)) {
1898 exit_server_cleanly("failed to receive smb request");
1899 }
1900 if (!NT_STATUS_IS_OK(status)) {
1901 return;
1902 }
1903
1904process:
c16c90a1
SM
1905 process_smb(conn, inbuf, inbuf_len, unread_bytes,
1906 seqnum, encrypted, NULL);
aeb798c3
SM
1907}
1908
1909static void smbd_server_connection_handler(struct event_context *ev,
1910 struct fd_event *fde,
1911 uint16_t flags,
1912 void *private_data)
1913{
1914 struct smbd_server_connection *conn = talloc_get_type(private_data,
1915 struct smbd_server_connection);
1916
1917 if (flags & EVENT_FD_WRITE) {
1918 smbd_server_connection_write_handler(conn);
1919 } else if (flags & EVENT_FD_READ) {
1920 smbd_server_connection_read_handler(conn);
1921 }
1922}
1923
27f812f3
SM
1924
1925/****************************************************************************
1926received when we should release a specific IP
1927****************************************************************************/
1928static void release_ip(const char *ip, void *priv)
1929{
1930 char addr[INET6_ADDRSTRLEN];
7d6e4c7e 1931 char *p = addr;
27f812f3 1932
e86a534f
MA
1933 client_socket_addr(get_client_fd(),addr,sizeof(addr));
1934
1935 if (strncmp("::ffff:", addr, 7) == 0) {
1936 p = addr + 7;
1937 }
1938
7d6e4c7e 1939 if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
27f812f3
SM
1940 /* we can't afford to do a clean exit - that involves
1941 database writes, which would potentially mean we
1942 are still running after the failover has finished -
1943 we have to get rid of this process ID straight
1944 away */
1945 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
1946 ip));
1947 /* note we must exit with non-zero status so the unclean handler gets
1948 called in the parent, so that the brl database is tickled */
1949 _exit(1);
1950 }
1951}
1952
1953static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
1954 uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
1955{
1956 release_ip((char *)data->data, NULL);
1957}
1958
1959#ifdef CLUSTER_SUPPORT
1960static int client_get_tcp_info(struct sockaddr_storage *server,
1961 struct sockaddr_storage *client)
1962{
1963 socklen_t length;
1964 if (server_fd == -1) {
1965 return -1;
1966 }
1967 length = sizeof(*server);
1968 if (getsockname(server_fd, (struct sockaddr *)server, &length) != 0) {
1969 return -1;
1970 }
1971 length = sizeof(*client);
1972 if (getpeername(server_fd, (struct sockaddr *)client, &length) != 0) {
1973 return -1;
1974 }
1975 return 0;
1976}
1977#endif
1978
1979/*
1980 * Send keepalive packets to our client
1981 */
1982static bool keepalive_fn(const struct timeval *now, void *private_data)
1983{
1984 if (!send_keepalive(smbd_server_fd())) {
1985 DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
1986 return False;
1987 }
1988 return True;
1989}
1990
1991/*
1992 * Do the recurring check if we're idle
1993 */
1994static bool deadtime_fn(const struct timeval *now, void *private_data)
1995{
c8620180
SM
1996 struct smbd_server_connection *sconn = smbd_server_conn;
1997 if ((conn_num_open(sconn) == 0)
1998 || (conn_idle_all(sconn, now->tv_sec))) {
27f812f3
SM
1999 DEBUG( 2, ( "Closing idle connection\n" ) );
2000 messaging_send(smbd_messaging_context(), procid_self(),
2001 MSG_SHUTDOWN, &data_blob_null);
2002 return False;
2003 }
2004
2005 return True;
2006}
2007
2008/*
2009 * Do the recurring log file and smb.conf reload checks.
2010 */
2011
2012static bool housekeeping_fn(const struct timeval *now, void *private_data)
2013{
2014 change_to_root_user();
2015
2016 /* update printer queue caches if necessary */
2017 update_monitored_printq_cache();
2018
2019 /* check if we need to reload services */
2020 check_reload(time(NULL));
2021
2022 /* Change machine password if neccessary. */
2023 attempt_machine_password_change();
2024
2025 /*
2026 * Force a log file check.
2027 */
2028 force_check_log_size();
2029 check_log_size();
2030 return true;
2031}
2032
f2f55d70
JA
2033/****************************************************************************
2034 Process commands from the client
2035****************************************************************************/
2036
2037void smbd_process(void)
2038{
27f812f3
SM
2039 TALLOC_CTX *frame = talloc_stackframe();
2040 char remaddr[INET6_ADDRSTRLEN];
2041
8be8d911
SM
2042 if (lp_maxprotocol() == PROTOCOL_SMB2 &&
2043 lp_security() != SEC_SHARE) {
688945a9
SM
2044 smbd_server_conn->allow_smb2 = true;
2045 }
2046
27f812f3
SM
2047 /* Ensure child is set to blocking mode */
2048 set_blocking(smbd_server_fd(),True);
2049
2050 set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
2051 set_socket_options(smbd_server_fd(), lp_socket_options());
2052
2053 /* this is needed so that we get decent entries
2054 in smbstatus for port 445 connects */
2055 set_remote_machine_name(get_peer_addr(smbd_server_fd(),
2056 remaddr,
2057 sizeof(remaddr)),
2058 false);
2059 reload_services(true);
2060
ac647d03
VL
2061 /*
2062 * Before the first packet, check the global hosts allow/ hosts deny
2063 * parameters before doing any parsing of packets passed to us by the
2064 * client. This prevents attacks on our parsing code from hosts not in
2065 * the hosts allow list.
2066 */
2067
2068 if (!check_access(smbd_server_fd(), lp_hostsallow(-1),
2069 lp_hostsdeny(-1))) {
aeb798c3
SM
2070 char addr[INET6_ADDRSTRLEN];
2071
ac647d03
VL
2072 /*
2073 * send a negative session response "not listening on calling
2074 * name"
2075 */
2076 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
2077 DEBUG( 1, ("Connection denied from %s\n",
2078 client_addr(get_client_fd(),addr,sizeof(addr)) ) );
c16c90a1
SM
2079 (void)srv_send_smb(smbd_server_fd(),(char *)buf, false,
2080 0, false, NULL);
ac647d03
VL
2081 exit_server_cleanly("connection denied");
2082 }
2083
27f812f3 2084 static_init_rpc;
c3effa8b 2085
27f812f3
SM
2086 init_modules();
2087
54c51a66 2088 smb_perfcount_init();
2089
27f812f3
SM
2090 if (!init_account_policy()) {
2091 exit_server("Could not open account policy tdb.\n");
2092 }
2093
2094 if (*lp_rootdir()) {
2095 if (chroot(lp_rootdir()) != 0) {
f6821a15
JA
2096 DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
2097 exit_server("Failed to chroot()");
2098 }
2099 if (chdir("/") == -1) {
2100 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
27f812f3
SM
2101 exit_server("Failed to chroot()");
2102 }
2103 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
2104 }
2105
c16c90a1
SM
2106 if (!srv_init_signing(smbd_server_conn)) {
2107 exit_server("Failed to init smb_signing");
2108 }
2109
27f812f3
SM
2110 /* Setup oplocks */
2111 if (!init_oplocks(smbd_messaging_context()))
2112 exit_server("Failed to init oplocks");
2113
2114 /* Setup aio signal handler. */
2115 initialize_async_io_handler();
2116
2117 /* register our message handlers */
2118 messaging_register(smbd_messaging_context(), NULL,
2119 MSG_SMB_FORCE_TDIS, msg_force_tdis);
2120 messaging_register(smbd_messaging_context(), NULL,
2121 MSG_SMB_RELEASE_IP, msg_release_ip);
2122 messaging_register(smbd_messaging_context(), NULL,
2123 MSG_SMB_CLOSE_FILE, msg_close_file);
2124
5a4d6181
AS
2125 /*
2126 * Use the default MSG_DEBUG handler to avoid rebroadcasting
2127 * MSGs to all child processes
2128 */
2129 messaging_deregister(smbd_messaging_context(),
2130 MSG_DEBUG, NULL);
2131 messaging_register(smbd_messaging_context(), NULL,
2132 MSG_DEBUG, debug_message);
2133
27f812f3
SM
2134 if ((lp_keepalive() != 0)
2135 && !(event_add_idle(smbd_event_context(), NULL,
2136 timeval_set(lp_keepalive(), 0),
2137 "keepalive", keepalive_fn,
2138 NULL))) {
2139 DEBUG(0, ("Could not add keepalive event\n"));
2140 exit(1);
2141 }
2142
2143 if (!(event_add_idle(smbd_event_context(), NULL,
2144 timeval_set(IDLE_CLOSED_TIMEOUT, 0),
2145 "deadtime", deadtime_fn, NULL))) {
2146 DEBUG(0, ("Could not add deadtime event\n"));
2147 exit(1);
aeb798c3 2148 }
27f812f3
SM
2149
2150 if (!(event_add_idle(smbd_event_context(), NULL,
2151 timeval_set(SMBD_SELECT_TIMEOUT, 0),
2152 "housekeeping", housekeeping_fn, NULL))) {
2153 DEBUG(0, ("Could not add housekeeping event\n"));
2154 exit(1);
2155 }
2156
2157#ifdef CLUSTER_SUPPORT
2158
2159 if (lp_clustering()) {
2160 /*
2161 * We need to tell ctdb about our client's TCP
2162 * connection, so that for failover ctdbd can send
2163 * tickle acks, triggering a reconnection by the
2164 * client.
2165 */
2166
2167 struct sockaddr_storage srv, clnt;
2168
2169 if (client_get_tcp_info(&srv, &clnt) == 0) {
2170
2171 NTSTATUS status;
2172
2173 status = ctdbd_register_ips(
2174 messaging_ctdbd_connection(),
2175 &srv, &clnt, release_ip, NULL);
2176
2177 if (!NT_STATUS_IS_OK(status)) {
2178 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
2179 nt_errstr(status)));
2180 }
2181 } else
2182 {
2183 DEBUG(0,("Unable to get tcp info for "
2184 "CTDB_CONTROL_TCP_CLIENT: %s\n",
2185 strerror(errno)));
2186 }
2187 }
2188
2189#endif
2190
f554af18
SM
2191 smbd_server_conn->nbt.got_session = false;
2192
d9843b3d 2193 smbd_server_conn->smb1.negprot.max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
27f812f3 2194
356f0336
SM
2195 smbd_server_conn->smb1.sessions.done_sesssetup = false;
2196 smbd_server_conn->smb1.sessions.max_send = BUFFER_SIZE;
2197 smbd_server_conn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
75d03970
SM
2198 /* users from session setup */
2199 smbd_server_conn->smb1.sessions.session_userlist = NULL;
2200 /* workgroup from session setup. */
2201 smbd_server_conn->smb1.sessions.session_workgroup = NULL;
2202 /* this holds info on user ids that are already validated for this VC */
2203 smbd_server_conn->smb1.sessions.validated_users = NULL;
2204 smbd_server_conn->smb1.sessions.next_vuid = VUID_OFFSET;
2205 smbd_server_conn->smb1.sessions.num_validated_vuids = 0;
2206#ifdef HAVE_NETGROUP
2207 smbd_server_conn->smb1.sessions.my_yp_domain = NULL;
2208#endif
356f0336 2209
c8620180 2210 conn_init(smbd_server_conn);
59c3f5e3
SM
2211 if (!init_dptrs(smbd_server_conn)) {
2212 exit_server("init_dptrs() failed");
2213 }
c8620180 2214
ebc860eb
SM
2215 smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(),
2216 smbd_server_conn,
2217 smbd_server_fd(),
2218 EVENT_FD_READ,
2219 smbd_server_connection_handler,
2220 smbd_server_conn);
2221 if (!smbd_server_conn->smb1.fde) {
aeb798c3
SM
2222 exit_server("failed to create smbd_server_connection fde");
2223 }
2224
27f812f3
SM
2225 TALLOC_FREE(frame);
2226
b2d01bd2 2227 while (True) {
f6c883b4 2228 NTSTATUS status;
27f812f3
SM
2229
2230 frame = talloc_stackframe_pool(8192);
dc76502c 2231
c3250149
JA
2232 errno = 0;
2233
aeb798c3
SM
2234 status = smbd_server_connection_loop_once(smbd_server_conn);
2235 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
2236 !NT_STATUS_IS_OK(status)) {
2237 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
2238 " exiting\n", nt_errstr(status)));
27f812f3 2239 break;
b2d01bd2
AT
2240 }
2241
929e1d99 2242 TALLOC_FREE(frame);
b2d01bd2 2243 }
27f812f3
SM
2244
2245 exit_server_cleanly(NULL);
c3effa8b 2246}
d94e9c80
VL
2247
2248bool req_is_in_chain(struct smb_request *req)
2249{
2250 if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) {
2251 /*
2252 * We're right now handling a subsequent request, so we must
2253 * be in a chain
2254 */
2255 return true;
2256 }
2257
2258 if (!is_andx_req(req->cmd)) {
2259 return false;
2260 }
2261
2262 if (req->wct < 2) {
2263 /*
2264 * Okay, an illegal request, but definitely not chained :-)
2265 */
2266 return false;
2267 }
2268
2269 return (CVAL(req->vwv+0, 0) != 0xFF);
2270}