source: trunk/server/source3/smbd/process.c@ 745

Last change on this file since 745 was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 86.8 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005-2007
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22#include "../lib/tsocket/tsocket.h"
23#include "system/filesys.h"
24#include "smbd/smbd.h"
25#include "smbd/globals.h"
26#include "librpc/gen_ndr/netlogon.h"
27#include "../lib/async_req/async_sock.h"
28#include "ctdbd_conn.h"
29#include "../lib/util/select.h"
30#include "printing/pcap.h"
31#include "system/select.h"
32#include "passdb.h"
33#include "auth.h"
34#include "messages.h"
35#include "smbprofile.h"
36#include "rpc_server/spoolss/srv_spoolss_nt.h"
37#include "libsmb/libsmb.h"
38#ifdef __OS2__
39#define pipe(A) os2_pipe(A)
40#endif
41
42extern bool global_machine_password_needs_changing;
43
44static void construct_reply_common(struct smb_request *req, const char *inbuf,
45 char *outbuf);
46static struct pending_message_list *get_deferred_open_message_smb(uint64_t mid);
47
48static bool smbd_lock_socket_internal(struct smbd_server_connection *sconn)
49{
50 bool ok;
51
52 if (sconn->smb1.echo_handler.socket_lock_fd == -1) {
53 return true;
54 }
55
56 sconn->smb1.echo_handler.ref_count++;
57
58 if (sconn->smb1.echo_handler.ref_count > 1) {
59 return true;
60 }
61
62 DEBUG(10,("pid[%d] wait for socket lock\n", (int)sys_getpid()));
63
64 do {
65 ok = fcntl_lock(
66 sconn->smb1.echo_handler.socket_lock_fd,
67 SMB_F_SETLKW, 0, 0, F_WRLCK);
68 } while (!ok && (errno == EINTR));
69
70 if (!ok) {
71 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
72 return false;
73 }
74
75 DEBUG(10,("pid[%d] got for socket lock\n", (int)sys_getpid()));
76
77 return true;
78}
79
80void smbd_lock_socket(struct smbd_server_connection *sconn)
81{
82 if (!smbd_lock_socket_internal(sconn)) {
83 exit_server_cleanly("failed to lock socket");
84 }
85}
86
87static bool smbd_unlock_socket_internal(struct smbd_server_connection *sconn)
88{
89 bool ok;
90
91 if (sconn->smb1.echo_handler.socket_lock_fd == -1) {
92 return true;
93 }
94
95 sconn->smb1.echo_handler.ref_count--;
96
97 if (sconn->smb1.echo_handler.ref_count > 0) {
98 return true;
99 }
100
101 do {
102 ok = fcntl_lock(
103 sconn->smb1.echo_handler.socket_lock_fd,
104 SMB_F_SETLKW, 0, 0, F_UNLCK);
105 } while (!ok && (errno == EINTR));
106
107 if (!ok) {
108 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
109 return false;
110 }
111
112 DEBUG(10,("pid[%d] unlocked socket\n", (int)sys_getpid()));
113
114 return true;
115}
116
117void smbd_unlock_socket(struct smbd_server_connection *sconn)
118{
119 if (!smbd_unlock_socket_internal(sconn)) {
120 exit_server_cleanly("failed to unlock socket");
121 }
122}
123
124/* Accessor function for smb_read_error for smbd functions. */
125
126/****************************************************************************
127 Send an smb to a fd.
128****************************************************************************/
129
130bool srv_send_smb(struct smbd_server_connection *sconn, char *buffer,
131 bool do_signing, uint32_t seqnum,
132 bool do_encrypt,
133 struct smb_perfcount_data *pcd)
134{
135 size_t len = 0;
136 size_t nwritten=0;
137 ssize_t ret;
138 char *buf_out = buffer;
139
140 smbd_lock_socket(sconn);
141
142 if (do_signing) {
143 /* Sign the outgoing packet if required. */
144 srv_calculate_sign_mac(sconn, buf_out, seqnum);
145 }
146
147 if (do_encrypt) {
148 NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
149 if (!NT_STATUS_IS_OK(status)) {
150 DEBUG(0, ("send_smb: SMB encryption failed "
151 "on outgoing packet! Error %s\n",
152 nt_errstr(status) ));
153 goto out;
154 }
155 }
156
157 len = smb_len(buf_out) + 4;
158
159 ret = write_data(sconn->sock, buf_out+nwritten, len - nwritten);
160 if (ret <= 0) {
161
162 char addr[INET6_ADDRSTRLEN];
163 /*
164 * Try and give an error message saying what
165 * client failed.
166 */
167 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
168 (int)sys_getpid(), (int)len,
169 get_peer_addr(sconn->sock, addr, sizeof(addr)),
170 (int)ret, strerror(errno) ));
171
172 srv_free_enc_buffer(buf_out);
173 goto out;
174 }
175
176 SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
177 srv_free_enc_buffer(buf_out);
178out:
179 SMB_PERFCOUNT_END(pcd);
180
181 smbd_unlock_socket(sconn);
182 return true;
183}
184
185/*******************************************************************
186 Setup the word count and byte count for a smb message.
187********************************************************************/
188
189int srv_set_message(char *buf,
190 int num_words,
191 int num_bytes,
192 bool zero)
193{
194 if (zero && (num_words || num_bytes)) {
195 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
196 }
197 SCVAL(buf,smb_wct,num_words);
198 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
199 smb_setlen(buf,(smb_size + num_words*2 + num_bytes - 4));
200 return (smb_size + num_words*2 + num_bytes);
201}
202
203static bool valid_smb_header(const uint8_t *inbuf)
204{
205 if (is_encrypted_packet(inbuf)) {
206 return true;
207 }
208 /*
209 * This used to be (strncmp(smb_base(inbuf),"\377SMB",4) == 0)
210 * but it just looks weird to call strncmp for this one.
211 */
212 return (IVAL(smb_base(inbuf), 0) == 0x424D53FF);
213}
214
215/* Socket functions for smbd packet processing. */
216
217static bool valid_packet_size(size_t len)
218{
219 /*
220 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
221 * of header. Don't print the error if this fits.... JRA.
222 */
223
224 if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
225 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
226 (unsigned long)len));
227 return false;
228 }
229 return true;
230}
231
232static NTSTATUS read_packet_remainder(int fd, char *buffer,
233 unsigned int timeout, ssize_t len)
234{
235 NTSTATUS status;
236
237 if (len <= 0) {
238 return NT_STATUS_OK;
239 }
240
241 status = read_fd_with_timeout(fd, buffer, len, len, timeout, NULL);
242 if (!NT_STATUS_IS_OK(status)) {
243 char addr[INET6_ADDRSTRLEN];
244 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
245 "error = %s.\n",
246 get_peer_addr(fd, addr, sizeof(addr)),
247 nt_errstr(status)));
248 }
249 return status;
250}
251
252/****************************************************************************
253 Attempt a zerocopy writeX read. We know here that len > smb_size-4
254****************************************************************************/
255
256/*
257 * Unfortunately, earlier versions of smbclient/libsmbclient
258 * don't send this "standard" writeX header. I've fixed this
259 * for 3.2 but we'll use the old method with earlier versions.
260 * Windows and CIFSFS at least use this standard size. Not
261 * sure about MacOSX.
262 */
263
264#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
265 (2*14) + /* word count (including bcc) */ \
266 1 /* pad byte */)
267
268static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
269 const char lenbuf[4],
270 struct smbd_server_connection *sconn,
271 int sock,
272 char **buffer,
273 unsigned int timeout,
274 size_t *p_unread,
275 size_t *len_ret)
276{
277 /* Size of a WRITEX call (+4 byte len). */
278 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
279 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
280 ssize_t toread;
281 NTSTATUS status;
282
283 memcpy(writeX_header, lenbuf, 4);
284
285 status = read_fd_with_timeout(
286 sock, writeX_header + 4,
287 STANDARD_WRITE_AND_X_HEADER_SIZE,
288 STANDARD_WRITE_AND_X_HEADER_SIZE,
289 timeout, NULL);
290
291 if (!NT_STATUS_IS_OK(status)) {
292 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
293 "error = %s.\n", sconn->client_id.addr,
294 nt_errstr(status)));
295 return status;
296 }
297
298 /*
299 * Ok - now try and see if this is a possible
300 * valid writeX call.
301 */
302
303 if (is_valid_writeX_buffer(sconn, (uint8_t *)writeX_header)) {
304 /*
305 * If the data offset is beyond what
306 * we've read, drain the extra bytes.
307 */
308 uint16_t doff = SVAL(writeX_header,smb_vwv11);
309 ssize_t newlen;
310
311 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
312 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
313 if (drain_socket(sock, drain) != drain) {
314 smb_panic("receive_smb_raw_talloc_partial_read:"
315 " failed to drain pending bytes");
316 }
317 } else {
318 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
319 }
320
321 /* Spoof down the length and null out the bcc. */
322 set_message_bcc(writeX_header, 0);
323 newlen = smb_len(writeX_header);
324
325 /* Copy the header we've written. */
326
327 *buffer = (char *)TALLOC_MEMDUP(mem_ctx,
328 writeX_header,
329 sizeof(writeX_header));
330
331 if (*buffer == NULL) {
332 DEBUG(0, ("Could not allocate inbuf of length %d\n",
333 (int)sizeof(writeX_header)));
334 return NT_STATUS_NO_MEMORY;
335 }
336
337 /* Work out the remaining bytes. */
338 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
339 *len_ret = newlen + 4;
340 return NT_STATUS_OK;
341 }
342
343 if (!valid_packet_size(len)) {
344 return NT_STATUS_INVALID_PARAMETER;
345 }
346
347 /*
348 * Not a valid writeX call. Just do the standard
349 * talloc and return.
350 */
351
352 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
353
354 if (*buffer == NULL) {
355 DEBUG(0, ("Could not allocate inbuf of length %d\n",
356 (int)len+4));
357 return NT_STATUS_NO_MEMORY;
358 }
359
360 /* Copy in what we already read. */
361 memcpy(*buffer,
362 writeX_header,
363 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
364 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
365
366 if(toread > 0) {
367 status = read_packet_remainder(
368 sock,
369 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
370 timeout, toread);
371
372 if (!NT_STATUS_IS_OK(status)) {
373 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
374 nt_errstr(status)));
375 return status;
376 }
377 }
378
379 *len_ret = len + 4;
380 return NT_STATUS_OK;
381}
382
383static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
384 struct smbd_server_connection *sconn,
385 int sock,
386 char **buffer, unsigned int timeout,
387 size_t *p_unread, size_t *plen)
388{
389 char lenbuf[4];
390 size_t len;
391 int min_recv_size = lp_min_receive_file_size();
392 NTSTATUS status;
393
394 *p_unread = 0;
395
396 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
397 &len);
398 if (!NT_STATUS_IS_OK(status)) {
399 return status;
400 }
401
402 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
403 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
404 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
405 !srv_is_signing_active(sconn) &&
406 sconn->smb1.echo_handler.trusted_fde == NULL) {
407
408 return receive_smb_raw_talloc_partial_read(
409 mem_ctx, lenbuf, sconn, sock, buffer, timeout,
410 p_unread, plen);
411 }
412
413 if (!valid_packet_size(len)) {
414 return NT_STATUS_INVALID_PARAMETER;
415 }
416
417 /*
418 * The +4 here can't wrap, we've checked the length above already.
419 */
420
421 *buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
422
423 if (*buffer == NULL) {
424 DEBUG(0, ("Could not allocate inbuf of length %d\n",
425 (int)len+4));
426 return NT_STATUS_NO_MEMORY;
427 }
428
429 memcpy(*buffer, lenbuf, sizeof(lenbuf));
430
431 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
432 if (!NT_STATUS_IS_OK(status)) {
433 return status;
434 }
435
436 *plen = len + 4;
437 return NT_STATUS_OK;
438}
439
440static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx,
441 struct smbd_server_connection *sconn,
442 int sock,
443 char **buffer, unsigned int timeout,
444 size_t *p_unread, bool *p_encrypted,
445 size_t *p_len,
446 uint32_t *seqnum,
447 bool trusted_channel)
448{
449 size_t len = 0;
450 NTSTATUS status;
451
452 *p_encrypted = false;
453
454 status = receive_smb_raw_talloc(mem_ctx, sconn, sock, buffer, timeout,
455 p_unread, &len);
456 if (!NT_STATUS_IS_OK(status)) {
457 DEBUG(1, ("read_smb_length_return_keepalive failed for "
458 "client %s read error = %s.\n",
459 sconn->client_id.addr, nt_errstr(status)));
460 return status;
461 }
462
463 if (is_encrypted_packet((uint8_t *)*buffer)) {
464 status = srv_decrypt_buffer(*buffer);
465 if (!NT_STATUS_IS_OK(status)) {
466 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
467 "incoming packet! Error %s\n",
468 nt_errstr(status) ));
469 return status;
470 }
471 *p_encrypted = true;
472 }
473
474 /* Check the incoming SMB signature. */
475 if (!srv_check_sign_mac(sconn, *buffer, seqnum, trusted_channel)) {
476 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
477 "incoming packet!\n"));
478 return NT_STATUS_INVALID_NETWORK_RESPONSE;
479 }
480
481 *p_len = len;
482 return NT_STATUS_OK;
483}
484
485/*
486 * Initialize a struct smb_request from an inbuf
487 */
488
489static bool init_smb_request(struct smb_request *req,
490 struct smbd_server_connection *sconn,
491 const uint8 *inbuf,
492 size_t unread_bytes, bool encrypted,
493 uint32_t seqnum)
494{
495 size_t req_size = smb_len(inbuf) + 4;
496 /* Ensure we have at least smb_size bytes. */
497 if (req_size < smb_size) {
498 DEBUG(0,("init_smb_request: invalid request size %u\n",
499 (unsigned int)req_size ));
500 return false;
501 }
502 req->cmd = CVAL(inbuf, smb_com);
503 req->flags2 = SVAL(inbuf, smb_flg2);
504 req->smbpid = SVAL(inbuf, smb_pid);
505 req->mid = (uint64_t)SVAL(inbuf, smb_mid);
506 req->seqnum = seqnum;
507 req->vuid = SVAL(inbuf, smb_uid);
508 req->tid = SVAL(inbuf, smb_tid);
509 req->wct = CVAL(inbuf, smb_wct);
510 req->vwv = (uint16_t *)(inbuf+smb_vwv);
511 req->buflen = smb_buflen(inbuf);
512 req->buf = (const uint8_t *)smb_buf(inbuf);
513 req->unread_bytes = unread_bytes;
514 req->encrypted = encrypted;
515 req->sconn = sconn;
516 req->conn = conn_find(sconn,req->tid);
517 req->chain_fsp = NULL;
518 req->chain_outbuf = NULL;
519 req->done = false;
520 req->smb2req = NULL;
521 smb_init_perfcount_data(&req->pcd);
522
523 /* Ensure we have at least wct words and 2 bytes of bcc. */
524 if (smb_size + req->wct*2 > req_size) {
525 DEBUG(0,("init_smb_request: invalid wct number %u (size %u)\n",
526 (unsigned int)req->wct,
527 (unsigned int)req_size));
528 return false;
529 }
530 /* Ensure bcc is correct. */
531 if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) {
532 DEBUG(0,("init_smb_request: invalid bcc number %u "
533 "(wct = %u, size %u)\n",
534 (unsigned int)req->buflen,
535 (unsigned int)req->wct,
536 (unsigned int)req_size));
537 return false;
538 }
539
540 req->outbuf = NULL;
541 return true;
542}
543
544static void process_smb(struct smbd_server_connection *conn,
545 uint8_t *inbuf, size_t nread, size_t unread_bytes,
546 uint32_t seqnum, bool encrypted,
547 struct smb_perfcount_data *deferred_pcd);
548
549static void smbd_deferred_open_timer(struct event_context *ev,
550 struct timed_event *te,
551 struct timeval _tval,
552 void *private_data)
553{
554 struct pending_message_list *msg = talloc_get_type(private_data,
555 struct pending_message_list);
556 TALLOC_CTX *mem_ctx = talloc_tos();
557 uint64_t mid = (uint64_t)SVAL(msg->buf.data,smb_mid);
558 uint8_t *inbuf;
559
560 inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
561 msg->buf.length);
562 if (inbuf == NULL) {
563 exit_server("smbd_deferred_open_timer: talloc failed\n");
564 return;
565 }
566
567 /* We leave this message on the queue so the open code can
568 know this is a retry. */
569 DEBUG(5,("smbd_deferred_open_timer: trigger mid %llu.\n",
570 (unsigned long long)mid ));
571
572 /* Mark the message as processed so this is not
573 * re-processed in error. */
574 msg->processed = true;
575
576 process_smb(smbd_server_conn, inbuf,
577 msg->buf.length, 0,
578 msg->seqnum, msg->encrypted, &msg->pcd);
579
580 /* If it's still there and was processed, remove it. */
581 msg = get_deferred_open_message_smb(mid);
582 if (msg && msg->processed) {
583 remove_deferred_open_message_smb(mid);
584 }
585}
586
587/****************************************************************************
588 Function to push a message onto the tail of a linked list of smb messages ready
589 for processing.
590****************************************************************************/
591
592static bool push_queued_message(struct smb_request *req,
593 struct timeval request_time,
594 struct timeval end_time,
595 char *private_data, size_t private_len)
596{
597 int msg_len = smb_len(req->inbuf) + 4;
598 struct pending_message_list *msg;
599
600 msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
601
602 if(msg == NULL) {
603 DEBUG(0,("push_message: malloc fail (1)\n"));
604 return False;
605 }
606
607 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
608 if(msg->buf.data == NULL) {
609 DEBUG(0,("push_message: malloc fail (2)\n"));
610 TALLOC_FREE(msg);
611 return False;
612 }
613
614 msg->request_time = request_time;
615 msg->seqnum = req->seqnum;
616 msg->encrypted = req->encrypted;
617 msg->processed = false;
618 SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
619
620 if (private_data) {
621 msg->private_data = data_blob_talloc(msg, private_data,
622 private_len);
623 if (msg->private_data.data == NULL) {
624 DEBUG(0,("push_message: malloc fail (3)\n"));
625 TALLOC_FREE(msg);
626 return False;
627 }
628 }
629
630 msg->te = event_add_timed(smbd_event_context(),
631 msg,
632 end_time,
633 smbd_deferred_open_timer,
634 msg);
635 if (!msg->te) {
636 DEBUG(0,("push_message: event_add_timed failed\n"));
637 TALLOC_FREE(msg);
638 return false;
639 }
640
641 DLIST_ADD_END(deferred_open_queue, msg, struct pending_message_list *);
642
643 DEBUG(10,("push_message: pushed message length %u on "
644 "deferred_open_queue\n", (unsigned int)msg_len));
645
646 return True;
647}
648
649/****************************************************************************
650 Function to delete a sharing violation open message by mid.
651****************************************************************************/
652
653void remove_deferred_open_message_smb(uint64_t mid)
654{
655 struct pending_message_list *pml;
656
657 if (smbd_server_conn->using_smb2) {
658 remove_deferred_open_message_smb2(smbd_server_conn, mid);
659 return;
660 }
661
662 for (pml = deferred_open_queue; pml; pml = pml->next) {
663 if (mid == (uint64_t)SVAL(pml->buf.data,smb_mid)) {
664 DEBUG(10,("remove_deferred_open_message_smb: "
665 "deleting mid %llu len %u\n",
666 (unsigned long long)mid,
667 (unsigned int)pml->buf.length ));
668 DLIST_REMOVE(deferred_open_queue, pml);
669 TALLOC_FREE(pml);
670 return;
671 }
672 }
673}
674
675/****************************************************************************
676 Move a sharing violation open retry message to the front of the list and
677 schedule it for immediate processing.
678****************************************************************************/
679
680void schedule_deferred_open_message_smb(uint64_t mid)
681{
682 struct pending_message_list *pml;
683 int i = 0;
684
685 if (smbd_server_conn->using_smb2) {
686 schedule_deferred_open_message_smb2(smbd_server_conn, mid);
687 return;
688 }
689
690 for (pml = deferred_open_queue; pml; pml = pml->next) {
691 uint64_t msg_mid = (uint64_t)SVAL(pml->buf.data,smb_mid);
692
693 DEBUG(10,("schedule_deferred_open_message_smb: [%d] "
694 "msg_mid = %llu\n",
695 i++,
696 (unsigned long long)msg_mid ));
697
698 if (mid == msg_mid) {
699 struct timed_event *te;
700
701 if (pml->processed) {
702 /* A processed message should not be
703 * rescheduled. */
704 DEBUG(0,("schedule_deferred_open_message_smb: LOGIC ERROR "
705 "message mid %llu was already processed\n",
706 (unsigned long long)msg_mid ));
707 continue;
708 }
709
710 DEBUG(10,("schedule_deferred_open_message_smb: "
711 "scheduling mid %llu\n",
712 (unsigned long long)mid ));
713
714 te = event_add_timed(smbd_event_context(),
715 pml,
716 timeval_zero(),
717 smbd_deferred_open_timer,
718 pml);
719 if (!te) {
720 DEBUG(10,("schedule_deferred_open_message_smb: "
721 "event_add_timed() failed, "
722 "skipping mid %llu\n",
723 (unsigned long long)msg_mid ));
724 }
725
726 TALLOC_FREE(pml->te);
727 pml->te = te;
728 DLIST_PROMOTE(deferred_open_queue, pml);
729 return;
730 }
731 }
732
733 DEBUG(10,("schedule_deferred_open_message_smb: failed to "
734 "find message mid %llu\n",
735 (unsigned long long)mid ));
736}
737
738/****************************************************************************
739 Return true if this mid is on the deferred queue and was not yet processed.
740****************************************************************************/
741
742bool open_was_deferred(uint64_t mid)
743{
744 struct pending_message_list *pml;
745
746 if (smbd_server_conn->using_smb2) {
747 return open_was_deferred_smb2(smbd_server_conn, mid);
748 }
749
750 for (pml = deferred_open_queue; pml; pml = pml->next) {
751 if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid && !pml->processed) {
752 return True;
753 }
754 }
755 return False;
756}
757
758/****************************************************************************
759 Return the message queued by this mid.
760****************************************************************************/
761
762static struct pending_message_list *get_deferred_open_message_smb(uint64_t mid)
763{
764 struct pending_message_list *pml;
765
766 for (pml = deferred_open_queue; pml; pml = pml->next) {
767 if (((uint64_t)SVAL(pml->buf.data,smb_mid)) == mid) {
768 return pml;
769 }
770 }
771 return NULL;
772}
773
774/****************************************************************************
775 Get the state data queued by this mid.
776****************************************************************************/
777
778bool get_deferred_open_message_state(struct smb_request *smbreq,
779 struct timeval *p_request_time,
780 void **pp_state)
781{
782 struct pending_message_list *pml;
783
784 if (smbd_server_conn->using_smb2) {
785 return get_deferred_open_message_state_smb2(smbreq->smb2req,
786 p_request_time,
787 pp_state);
788 }
789
790 pml = get_deferred_open_message_smb(smbreq->mid);
791 if (!pml) {
792 return false;
793 }
794 if (p_request_time) {
795 *p_request_time = pml->request_time;
796 }
797 if (pp_state) {
798 *pp_state = (void *)pml->private_data.data;
799 }
800 return true;
801}
802
803/****************************************************************************
804 Function to push a deferred open smb message onto a linked list of local smb
805 messages ready for processing.
806****************************************************************************/
807
808bool push_deferred_open_message_smb(struct smb_request *req,
809 struct timeval request_time,
810 struct timeval timeout,
811 struct file_id id,
812 char *private_data, size_t priv_len)
813{
814 struct timeval end_time;
815
816 if (req->smb2req) {
817 return push_deferred_open_message_smb2(req->smb2req,
818 request_time,
819 timeout,
820 id,
821 private_data,
822 priv_len);
823 }
824
825 if (req->unread_bytes) {
826 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
827 "unread_bytes = %u\n",
828 (unsigned int)req->unread_bytes ));
829 smb_panic("push_deferred_open_message_smb: "
830 "logic error unread_bytes != 0" );
831 }
832
833 end_time = timeval_sum(&request_time, &timeout);
834
835 DEBUG(10,("push_deferred_open_message_smb: pushing message "
836 "len %u mid %llu timeout time [%u.%06u]\n",
837 (unsigned int) smb_len(req->inbuf)+4,
838 (unsigned long long)req->mid,
839 (unsigned int)end_time.tv_sec,
840 (unsigned int)end_time.tv_usec));
841
842 return push_queued_message(req, request_time, end_time,
843 private_data, priv_len);
844}
845
846struct idle_event {
847 struct timed_event *te;
848 struct timeval interval;
849 char *name;
850 bool (*handler)(const struct timeval *now, void *private_data);
851 void *private_data;
852};
853
854static void smbd_idle_event_handler(struct event_context *ctx,
855 struct timed_event *te,
856 struct timeval now,
857 void *private_data)
858{
859 struct idle_event *event =
860 talloc_get_type_abort(private_data, struct idle_event);
861
862 TALLOC_FREE(event->te);
863
864 DEBUG(10,("smbd_idle_event_handler: %s %p called\n",
865 event->name, event->te));
866
867 if (!event->handler(&now, event->private_data)) {
868 DEBUG(10,("smbd_idle_event_handler: %s %p stopped\n",
869 event->name, event->te));
870 /* Don't repeat, delete ourselves */
871 TALLOC_FREE(event);
872 return;
873 }
874
875 DEBUG(10,("smbd_idle_event_handler: %s %p rescheduled\n",
876 event->name, event->te));
877
878 event->te = event_add_timed(ctx, event,
879 timeval_sum(&now, &event->interval),
880 smbd_idle_event_handler, event);
881
882 /* We can't do much but fail here. */
883 SMB_ASSERT(event->te != NULL);
884}
885
886struct idle_event *event_add_idle(struct event_context *event_ctx,
887 TALLOC_CTX *mem_ctx,
888 struct timeval interval,
889 const char *name,
890 bool (*handler)(const struct timeval *now,
891 void *private_data),
892 void *private_data)
893{
894 struct idle_event *result;
895 struct timeval now = timeval_current();
896
897 result = TALLOC_P(mem_ctx, struct idle_event);
898 if (result == NULL) {
899 DEBUG(0, ("talloc failed\n"));
900 return NULL;
901 }
902
903 result->interval = interval;
904 result->handler = handler;
905 result->private_data = private_data;
906
907 if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
908 DEBUG(0, ("talloc failed\n"));
909 TALLOC_FREE(result);
910 return NULL;
911 }
912
913 result->te = event_add_timed(event_ctx, result,
914 timeval_sum(&now, &interval),
915 smbd_idle_event_handler, result);
916 if (result->te == NULL) {
917 DEBUG(0, ("event_add_timed failed\n"));
918 TALLOC_FREE(result);
919 return NULL;
920 }
921
922 DEBUG(10,("event_add_idle: %s %p\n", result->name, result->te));
923 return result;
924}
925
926static void smbd_sig_term_handler(struct tevent_context *ev,
927 struct tevent_signal *se,
928 int signum,
929 int count,
930 void *siginfo,
931 void *private_data)
932{
933 exit_server_cleanly("termination signal");
934}
935
936void smbd_setup_sig_term_handler(void)
937{
938 struct tevent_signal *se;
939
940 se = tevent_add_signal(smbd_event_context(),
941 smbd_event_context(),
942 SIGTERM, 0,
943 smbd_sig_term_handler,
944 NULL);
945 if (!se) {
946 exit_server("failed to setup SIGTERM handler");
947 }
948}
949
950static void smbd_sig_hup_handler(struct tevent_context *ev,
951 struct tevent_signal *se,
952 int signum,
953 int count,
954 void *siginfo,
955 void *private_data)
956{
957 struct messaging_context *msg_ctx = talloc_get_type_abort(
958 private_data, struct messaging_context);
959 change_to_root_user();
960 DEBUG(1,("Reloading services after SIGHUP\n"));
961 reload_services(msg_ctx, smbd_server_conn->sock, False);
962 if (am_parent) {
963 pcap_cache_reload(ev, msg_ctx, &reload_pcap_change_notify);
964 }
965}
966
967void smbd_setup_sig_hup_handler(struct tevent_context *ev,
968 struct messaging_context *msg_ctx)
969{
970 struct tevent_signal *se;
971
972 se = tevent_add_signal(ev, ev, SIGHUP, 0, smbd_sig_hup_handler,
973 msg_ctx);
974 if (!se) {
975 exit_server("failed to setup SIGHUP handler");
976 }
977}
978
979static NTSTATUS smbd_server_connection_loop_once(struct smbd_server_connection *conn)
980{
981 int timeout;
982 int num_pfds = 0;
983 int ret;
984 bool retry;
985
986 timeout = SMBD_SELECT_TIMEOUT * 1000;
987
988 /*
989 * Are there any timed events waiting ? If so, ensure we don't
990 * select for longer than it would take to wait for them.
991 */
992
993 event_add_to_poll_args(smbd_event_context(), conn,
994 &conn->pfds, &num_pfds, &timeout);
995
996 /* Process a signal and timed events now... */
997 if (run_events_poll(smbd_event_context(), 0, NULL, 0)) {
998 return NT_STATUS_RETRY;
999 }
1000
1001 {
1002 int sav;
1003 START_PROFILE(smbd_idle);
1004
1005 ret = sys_poll(conn->pfds, num_pfds, timeout);
1006 sav = errno;
1007
1008 END_PROFILE(smbd_idle);
1009 errno = sav;
1010 }
1011
1012 if (ret == -1) {
1013 if (errno == EINTR) {
1014 return NT_STATUS_RETRY;
1015 }
1016 return map_nt_error_from_unix(errno);
1017 }
1018
1019 retry = run_events_poll(smbd_event_context(), ret, conn->pfds,
1020 num_pfds);
1021 if (retry) {
1022 return NT_STATUS_RETRY;
1023 }
1024
1025 /* Did we timeout ? */
1026 if (ret == 0) {
1027 return NT_STATUS_RETRY;
1028 }
1029
1030 /* should not be reached */
1031 return NT_STATUS_INTERNAL_ERROR;
1032}
1033
1034/*
1035 * Only allow 5 outstanding trans requests. We're allocating memory, so
1036 * prevent a DoS.
1037 */
1038
1039NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
1040{
1041 int count = 0;
1042 for (; list != NULL; list = list->next) {
1043
1044 if (list->mid == mid) {
1045 return NT_STATUS_INVALID_PARAMETER;
1046 }
1047
1048 count += 1;
1049 }
1050 if (count > 5) {
1051 return NT_STATUS_INSUFFICIENT_RESOURCES;
1052 }
1053
1054 return NT_STATUS_OK;
1055}
1056
1057/*
1058These flags determine some of the permissions required to do an operation
1059
1060Note that I don't set NEED_WRITE on some write operations because they
1061are used by some brain-dead clients when printing, and I don't want to
1062force write permissions on print services.
1063*/
1064#define AS_USER (1<<0)
1065#define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
1066#define TIME_INIT (1<<2)
1067#define CAN_IPC (1<<3) /* Must be paired with AS_USER */
1068#define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
1069#define DO_CHDIR (1<<6)
1070
1071/*
1072 define a list of possible SMB messages and their corresponding
1073 functions. Any message that has a NULL function is unimplemented -
1074 please feel free to contribute implementations!
1075*/
1076static const struct smb_message_struct {
1077 const char *name;
1078 void (*fn)(struct smb_request *req);
1079 int flags;
1080} smb_messages[256] = {
1081
1082/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
1083/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
1084/* 0x02 */ { "SMBopen",reply_open,AS_USER },
1085/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
1086/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
1087/* 0x05 */ { "SMBflush",reply_flush,AS_USER},
1088/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
1089/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
1090/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
1091/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
1092/* 0x0a */ { "SMBread",reply_read,AS_USER},
1093/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
1094/* 0x0c */ { "SMBlock",reply_lock,AS_USER},
1095/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
1096/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
1097/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
1098/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
1099/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
1100/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
1101/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
1102/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
1103/* 0x15 */ { NULL, NULL, 0 },
1104/* 0x16 */ { NULL, NULL, 0 },
1105/* 0x17 */ { NULL, NULL, 0 },
1106/* 0x18 */ { NULL, NULL, 0 },
1107/* 0x19 */ { NULL, NULL, 0 },
1108/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
1109/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
1110/* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
1111/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
1112/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
1113/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
1114/* 0x20 */ { "SMBwritec", NULL,0},
1115/* 0x21 */ { NULL, NULL, 0 },
1116/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
1117/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
1118/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
1119/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
1120/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
1121/* 0x27 */ { "SMBioctl",reply_ioctl,0},
1122/* 0x28 */ { "SMBioctls", NULL,AS_USER},
1123/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
1124/* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
1125/* 0x2b */ { "SMBecho",reply_echo,0},
1126/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
1127/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
1128/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
1129/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
1130/* 0x30 */ { NULL, NULL, 0 },
1131/* 0x31 */ { NULL, NULL, 0 },
1132/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
1133/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
1134/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
1135/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
1136/* 0x36 */ { NULL, NULL, 0 },
1137/* 0x37 */ { NULL, NULL, 0 },
1138/* 0x38 */ { NULL, NULL, 0 },
1139/* 0x39 */ { NULL, NULL, 0 },
1140/* 0x3a */ { NULL, NULL, 0 },
1141/* 0x3b */ { NULL, NULL, 0 },
1142/* 0x3c */ { NULL, NULL, 0 },
1143/* 0x3d */ { NULL, NULL, 0 },
1144/* 0x3e */ { NULL, NULL, 0 },
1145/* 0x3f */ { NULL, NULL, 0 },
1146/* 0x40 */ { NULL, NULL, 0 },
1147/* 0x41 */ { NULL, NULL, 0 },
1148/* 0x42 */ { NULL, NULL, 0 },
1149/* 0x43 */ { NULL, NULL, 0 },
1150/* 0x44 */ { NULL, NULL, 0 },
1151/* 0x45 */ { NULL, NULL, 0 },
1152/* 0x46 */ { NULL, NULL, 0 },
1153/* 0x47 */ { NULL, NULL, 0 },
1154/* 0x48 */ { NULL, NULL, 0 },
1155/* 0x49 */ { NULL, NULL, 0 },
1156/* 0x4a */ { NULL, NULL, 0 },
1157/* 0x4b */ { NULL, NULL, 0 },
1158/* 0x4c */ { NULL, NULL, 0 },
1159/* 0x4d */ { NULL, NULL, 0 },
1160/* 0x4e */ { NULL, NULL, 0 },
1161/* 0x4f */ { NULL, NULL, 0 },
1162/* 0x50 */ { NULL, NULL, 0 },
1163/* 0x51 */ { NULL, NULL, 0 },
1164/* 0x52 */ { NULL, NULL, 0 },
1165/* 0x53 */ { NULL, NULL, 0 },
1166/* 0x54 */ { NULL, NULL, 0 },
1167/* 0x55 */ { NULL, NULL, 0 },
1168/* 0x56 */ { NULL, NULL, 0 },
1169/* 0x57 */ { NULL, NULL, 0 },
1170/* 0x58 */ { NULL, NULL, 0 },
1171/* 0x59 */ { NULL, NULL, 0 },
1172/* 0x5a */ { NULL, NULL, 0 },
1173/* 0x5b */ { NULL, NULL, 0 },
1174/* 0x5c */ { NULL, NULL, 0 },
1175/* 0x5d */ { NULL, NULL, 0 },
1176/* 0x5e */ { NULL, NULL, 0 },
1177/* 0x5f */ { NULL, NULL, 0 },
1178/* 0x60 */ { NULL, NULL, 0 },
1179/* 0x61 */ { NULL, NULL, 0 },
1180/* 0x62 */ { NULL, NULL, 0 },
1181/* 0x63 */ { NULL, NULL, 0 },
1182/* 0x64 */ { NULL, NULL, 0 },
1183/* 0x65 */ { NULL, NULL, 0 },
1184/* 0x66 */ { NULL, NULL, 0 },
1185/* 0x67 */ { NULL, NULL, 0 },
1186/* 0x68 */ { NULL, NULL, 0 },
1187/* 0x69 */ { NULL, NULL, 0 },
1188/* 0x6a */ { NULL, NULL, 0 },
1189/* 0x6b */ { NULL, NULL, 0 },
1190/* 0x6c */ { NULL, NULL, 0 },
1191/* 0x6d */ { NULL, NULL, 0 },
1192/* 0x6e */ { NULL, NULL, 0 },
1193/* 0x6f */ { NULL, NULL, 0 },
1194/* 0x70 */ { "SMBtcon",reply_tcon,0},
1195/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
1196/* 0x72 */ { "SMBnegprot",reply_negprot,0},
1197/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
1198/* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
1199/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
1200/* 0x76 */ { NULL, NULL, 0 },
1201/* 0x77 */ { NULL, NULL, 0 },
1202/* 0x78 */ { NULL, NULL, 0 },
1203/* 0x79 */ { NULL, NULL, 0 },
1204/* 0x7a */ { NULL, NULL, 0 },
1205/* 0x7b */ { NULL, NULL, 0 },
1206/* 0x7c */ { NULL, NULL, 0 },
1207/* 0x7d */ { NULL, NULL, 0 },
1208/* 0x7e */ { NULL, NULL, 0 },
1209/* 0x7f */ { NULL, NULL, 0 },
1210/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
1211/* 0x81 */ { "SMBsearch",reply_search,AS_USER},
1212/* 0x82 */ { "SMBffirst",reply_search,AS_USER},
1213/* 0x83 */ { "SMBfunique",reply_search,AS_USER},
1214/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
1215/* 0x85 */ { NULL, NULL, 0 },
1216/* 0x86 */ { NULL, NULL, 0 },
1217/* 0x87 */ { NULL, NULL, 0 },
1218/* 0x88 */ { NULL, NULL, 0 },
1219/* 0x89 */ { NULL, NULL, 0 },
1220/* 0x8a */ { NULL, NULL, 0 },
1221/* 0x8b */ { NULL, NULL, 0 },
1222/* 0x8c */ { NULL, NULL, 0 },
1223/* 0x8d */ { NULL, NULL, 0 },
1224/* 0x8e */ { NULL, NULL, 0 },
1225/* 0x8f */ { NULL, NULL, 0 },
1226/* 0x90 */ { NULL, NULL, 0 },
1227/* 0x91 */ { NULL, NULL, 0 },
1228/* 0x92 */ { NULL, NULL, 0 },
1229/* 0x93 */ { NULL, NULL, 0 },
1230/* 0x94 */ { NULL, NULL, 0 },
1231/* 0x95 */ { NULL, NULL, 0 },
1232/* 0x96 */ { NULL, NULL, 0 },
1233/* 0x97 */ { NULL, NULL, 0 },
1234/* 0x98 */ { NULL, NULL, 0 },
1235/* 0x99 */ { NULL, NULL, 0 },
1236/* 0x9a */ { NULL, NULL, 0 },
1237/* 0x9b */ { NULL, NULL, 0 },
1238/* 0x9c */ { NULL, NULL, 0 },
1239/* 0x9d */ { NULL, NULL, 0 },
1240/* 0x9e */ { NULL, NULL, 0 },
1241/* 0x9f */ { NULL, NULL, 0 },
1242/* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
1243/* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
1244/* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
1245/* 0xa3 */ { NULL, NULL, 0 },
1246/* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
1247/* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
1248/* 0xa6 */ { NULL, NULL, 0 },
1249/* 0xa7 */ { NULL, NULL, 0 },
1250/* 0xa8 */ { NULL, NULL, 0 },
1251/* 0xa9 */ { NULL, NULL, 0 },
1252/* 0xaa */ { NULL, NULL, 0 },
1253/* 0xab */ { NULL, NULL, 0 },
1254/* 0xac */ { NULL, NULL, 0 },
1255/* 0xad */ { NULL, NULL, 0 },
1256/* 0xae */ { NULL, NULL, 0 },
1257/* 0xaf */ { NULL, NULL, 0 },
1258/* 0xb0 */ { NULL, NULL, 0 },
1259/* 0xb1 */ { NULL, NULL, 0 },
1260/* 0xb2 */ { NULL, NULL, 0 },
1261/* 0xb3 */ { NULL, NULL, 0 },
1262/* 0xb4 */ { NULL, NULL, 0 },
1263/* 0xb5 */ { NULL, NULL, 0 },
1264/* 0xb6 */ { NULL, NULL, 0 },
1265/* 0xb7 */ { NULL, NULL, 0 },
1266/* 0xb8 */ { NULL, NULL, 0 },
1267/* 0xb9 */ { NULL, NULL, 0 },
1268/* 0xba */ { NULL, NULL, 0 },
1269/* 0xbb */ { NULL, NULL, 0 },
1270/* 0xbc */ { NULL, NULL, 0 },
1271/* 0xbd */ { NULL, NULL, 0 },
1272/* 0xbe */ { NULL, NULL, 0 },
1273/* 0xbf */ { NULL, NULL, 0 },
1274/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
1275/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
1276/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
1277/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
1278/* 0xc4 */ { NULL, NULL, 0 },
1279/* 0xc5 */ { NULL, NULL, 0 },
1280/* 0xc6 */ { NULL, NULL, 0 },
1281/* 0xc7 */ { NULL, NULL, 0 },
1282/* 0xc8 */ { NULL, NULL, 0 },
1283/* 0xc9 */ { NULL, NULL, 0 },
1284/* 0xca */ { NULL, NULL, 0 },
1285/* 0xcb */ { NULL, NULL, 0 },
1286/* 0xcc */ { NULL, NULL, 0 },
1287/* 0xcd */ { NULL, NULL, 0 },
1288/* 0xce */ { NULL, NULL, 0 },
1289/* 0xcf */ { NULL, NULL, 0 },
1290/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
1291/* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
1292/* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
1293/* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
1294/* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
1295/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
1296/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
1297/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
1298/* 0xd8 */ { NULL, NULL, 0 },
1299/* 0xd9 */ { NULL, NULL, 0 },
1300/* 0xda */ { NULL, NULL, 0 },
1301/* 0xdb */ { NULL, NULL, 0 },
1302/* 0xdc */ { NULL, NULL, 0 },
1303/* 0xdd */ { NULL, NULL, 0 },
1304/* 0xde */ { NULL, NULL, 0 },
1305/* 0xdf */ { NULL, NULL, 0 },
1306/* 0xe0 */ { NULL, NULL, 0 },
1307/* 0xe1 */ { NULL, NULL, 0 },
1308/* 0xe2 */ { NULL, NULL, 0 },
1309/* 0xe3 */ { NULL, NULL, 0 },
1310/* 0xe4 */ { NULL, NULL, 0 },
1311/* 0xe5 */ { NULL, NULL, 0 },
1312/* 0xe6 */ { NULL, NULL, 0 },
1313/* 0xe7 */ { NULL, NULL, 0 },
1314/* 0xe8 */ { NULL, NULL, 0 },
1315/* 0xe9 */ { NULL, NULL, 0 },
1316/* 0xea */ { NULL, NULL, 0 },
1317/* 0xeb */ { NULL, NULL, 0 },
1318/* 0xec */ { NULL, NULL, 0 },
1319/* 0xed */ { NULL, NULL, 0 },
1320/* 0xee */ { NULL, NULL, 0 },
1321/* 0xef */ { NULL, NULL, 0 },
1322/* 0xf0 */ { NULL, NULL, 0 },
1323/* 0xf1 */ { NULL, NULL, 0 },
1324/* 0xf2 */ { NULL, NULL, 0 },
1325/* 0xf3 */ { NULL, NULL, 0 },
1326/* 0xf4 */ { NULL, NULL, 0 },
1327/* 0xf5 */ { NULL, NULL, 0 },
1328/* 0xf6 */ { NULL, NULL, 0 },
1329/* 0xf7 */ { NULL, NULL, 0 },
1330/* 0xf8 */ { NULL, NULL, 0 },
1331/* 0xf9 */ { NULL, NULL, 0 },
1332/* 0xfa */ { NULL, NULL, 0 },
1333/* 0xfb */ { NULL, NULL, 0 },
1334/* 0xfc */ { NULL, NULL, 0 },
1335/* 0xfd */ { NULL, NULL, 0 },
1336/* 0xfe */ { NULL, NULL, 0 },
1337/* 0xff */ { NULL, NULL, 0 }
1338
1339};
1340
1341/*******************************************************************
1342 allocate and initialize a reply packet
1343********************************************************************/
1344
1345static bool create_outbuf(TALLOC_CTX *mem_ctx, struct smb_request *req,
1346 const char *inbuf, char **outbuf, uint8_t num_words,
1347 uint32_t num_bytes)
1348{
1349 /*
1350 * Protect against integer wrap
1351 */
1352 if ((num_bytes > 0xffffff)
1353 || ((num_bytes + smb_size + num_words*2) > 0xffffff)) {
1354 char *msg;
1355 if (asprintf(&msg, "num_bytes too large: %u",
1356 (unsigned)num_bytes) == -1) {
1357 msg = CONST_DISCARD(char *, "num_bytes too large");
1358 }
1359 smb_panic(msg);
1360 }
1361
1362 *outbuf = TALLOC_ARRAY(mem_ctx, char,
1363 smb_size + num_words*2 + num_bytes);
1364 if (*outbuf == NULL) {
1365 return false;
1366 }
1367
1368 construct_reply_common(req, inbuf, *outbuf);
1369 srv_set_message(*outbuf, num_words, num_bytes, false);
1370 /*
1371 * Zero out the word area, the caller has to take care of the bcc area
1372 * himself
1373 */
1374 if (num_words != 0) {
1375 memset(*outbuf + smb_vwv0, 0, num_words*2);
1376 }
1377
1378 return true;
1379}
1380
1381void reply_outbuf(struct smb_request *req, uint8 num_words, uint32 num_bytes)
1382{
1383 char *outbuf;
1384 if (!create_outbuf(req, req, (char *)req->inbuf, &outbuf, num_words,
1385 num_bytes)) {
1386 smb_panic("could not allocate output buffer\n");
1387 }
1388 req->outbuf = (uint8_t *)outbuf;
1389}
1390
1391
1392/*******************************************************************
1393 Dump a packet to a file.
1394********************************************************************/
1395
1396static void smb_dump(const char *name, int type, const char *data, ssize_t len)
1397{
1398 int fd, i;
1399 char *fname = NULL;
1400 if (DEBUGLEVEL < 50) {
1401 return;
1402 }
1403
1404 if (len < 4) len = smb_len(data)+4;
1405 for (i=1;i<100;i++) {
1406 if (asprintf(&fname, "/tmp/%s.%d.%s", name, i,
1407 type ? "req" : "resp") == -1) {
1408 return;
1409 }
1410 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
1411 if (fd != -1 || errno != EEXIST) break;
1412 }
1413 if (fd != -1) {
1414 ssize_t ret = write(fd, data, len);
1415 if (ret != len)
1416 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
1417 close(fd);
1418 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
1419 }
1420 SAFE_FREE(fname);
1421}
1422
1423/****************************************************************************
1424 Prepare everything for calling the actual request function, and potentially
1425 call the request function via the "new" interface.
1426
1427 Return False if the "legacy" function needs to be called, everything is
1428 prepared.
1429
1430 Return True if we're done.
1431
1432 I know this API sucks, but it is the one with the least code change I could
1433 find.
1434****************************************************************************/
1435
1436static connection_struct *switch_message(uint8 type, struct smb_request *req, int size)
1437{
1438 int flags;
1439 uint16 session_tag;
1440 connection_struct *conn = NULL;
1441 struct smbd_server_connection *sconn = req->sconn;
1442
1443 errno = 0;
1444
1445 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1446 * so subtract 4 from it. */
1447 if (!valid_smb_header(req->inbuf)
1448 || (size < (smb_size - 4))) {
1449 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1450 smb_len(req->inbuf)));
1451 exit_server_cleanly("Non-SMB packet");
1452 }
1453
1454 if (smb_messages[type].fn == NULL) {
1455 DEBUG(0,("Unknown message type %d!\n",type));
1456 smb_dump("Unknown", 1, (char *)req->inbuf, size);
1457 reply_unknown_new(req, type);
1458 return NULL;
1459 }
1460
1461 flags = smb_messages[type].flags;
1462
1463 /* In share mode security we must ignore the vuid. */
1464 session_tag = (lp_security() == SEC_SHARE)
1465 ? UID_FIELD_INVALID : req->vuid;
1466 conn = req->conn;
1467
1468 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1469 (int)sys_getpid(), (unsigned long)conn));
1470
1471 smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size);
1472
1473 /* Ensure this value is replaced in the incoming packet. */
1474 SSVAL(req->inbuf,smb_uid,session_tag);
1475
1476 /*
1477 * Ensure the correct username is in current_user_info. This is a
1478 * really ugly bugfix for problems with multiple session_setup_and_X's
1479 * being done and allowing %U and %G substitutions to work correctly.
1480 * There is a reason this code is done here, don't move it unless you
1481 * know what you're doing... :-).
1482 * JRA.
1483 */
1484
1485 if (session_tag != sconn->smb1.sessions.last_session_tag) {
1486 user_struct *vuser = NULL;
1487
1488 sconn->smb1.sessions.last_session_tag = session_tag;
1489 if(session_tag != UID_FIELD_INVALID) {
1490 vuser = get_valid_user_struct(sconn, session_tag);
1491 if (vuser) {
1492 set_current_user_info(
1493 vuser->session_info->sanitized_username,
1494 vuser->session_info->unix_name,
1495 vuser->session_info->info3->base.domain.string);
1496 }
1497 }
1498 }
1499
1500 /* Does this call need to be run as the connected user? */
1501 if (flags & AS_USER) {
1502
1503 /* Does this call need a valid tree connection? */
1504 if (!conn) {
1505 /*
1506 * Amazingly, the error code depends on the command
1507 * (from Samba4).
1508 */
1509 if (type == SMBntcreateX) {
1510 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1511 } else {
1512 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1513 }
1514 return NULL;
1515 }
1516
1517 if (!change_to_user(conn,session_tag)) {
1518 DEBUG(0, ("Error: Could not change to user. Removing "
1519 "deferred open, mid=%llu.\n",
1520 (unsigned long long)req->mid));
1521 reply_force_doserror(req, ERRSRV, ERRbaduid);
1522 return conn;
1523 }
1524
1525 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1526
1527 /* Does it need write permission? */
1528 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1529 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1530 return conn;
1531 }
1532
1533 /* IPC services are limited */
1534 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1535 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1536 return conn;
1537 }
1538 } else {
1539 /* This call needs to be run as root */
1540 change_to_root_user();
1541 }
1542
1543 /* load service specific parameters */
1544 if (conn) {
1545 if (req->encrypted) {
1546 conn->encrypted_tid = true;
1547 /* encrypted required from now on. */
1548 conn->encrypt_level = Required;
1549 } else if (ENCRYPTION_REQUIRED(conn)) {
1550 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1551 exit_server_cleanly("encryption required "
1552 "on connection");
1553 return conn;
1554 }
1555 }
1556
1557 if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
1558 (flags & (AS_USER|DO_CHDIR)
1559 ?True:False))) {
1560 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1561 return conn;
1562 }
1563 conn->num_smb_operations++;
1564 }
1565
1566 /* does this protocol need to be run as guest? */
1567 if ((flags & AS_GUEST)
1568 && (!change_to_guest() ||
1569 !allow_access(lp_hostsdeny(-1), lp_hostsallow(-1),
1570 sconn->client_id.name,
1571 sconn->client_id.addr))) {
1572 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1573 return conn;
1574 }
1575
1576 smb_messages[type].fn(req);
1577 return req->conn;
1578}
1579
1580/****************************************************************************
1581 Construct a reply to the incoming packet.
1582****************************************************************************/
1583
1584static void construct_reply(struct smbd_server_connection *sconn,
1585 char *inbuf, int size, size_t unread_bytes,
1586 uint32_t seqnum, bool encrypted,
1587 struct smb_perfcount_data *deferred_pcd)
1588{
1589 connection_struct *conn;
1590 struct smb_request *req;
1591
1592 if (!(req = talloc(talloc_tos(), struct smb_request))) {
1593 smb_panic("could not allocate smb_request");
1594 }
1595
1596 if (!init_smb_request(req, sconn, (uint8 *)inbuf, unread_bytes,
1597 encrypted, seqnum)) {
1598 exit_server_cleanly("Invalid SMB request");
1599 }
1600
1601 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1602
1603 /* we popped this message off the queue - keep original perf data */
1604 if (deferred_pcd)
1605 req->pcd = *deferred_pcd;
1606 else {
1607 SMB_PERFCOUNT_START(&req->pcd);
1608 SMB_PERFCOUNT_SET_OP(&req->pcd, req->cmd);
1609 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, size);
1610 }
1611
1612 conn = switch_message(req->cmd, req, size);
1613
1614 if (req->unread_bytes) {
1615 /* writeX failed. drain socket. */
1616 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
1617 req->unread_bytes) {
1618 smb_panic("failed to drain pending bytes");
1619 }
1620 req->unread_bytes = 0;
1621 }
1622
1623 if (req->done) {
1624 TALLOC_FREE(req);
1625 return;
1626 }
1627
1628 if (req->outbuf == NULL) {
1629 return;
1630 }
1631
1632 if (CVAL(req->outbuf,0) == 0) {
1633 show_msg((char *)req->outbuf);
1634 }
1635
1636 if (!srv_send_smb(req->sconn,
1637 (char *)req->outbuf,
1638 true, req->seqnum+1,
1639 IS_CONN_ENCRYPTED(conn)||req->encrypted,
1640 &req->pcd)) {
1641 exit_server_cleanly("construct_reply: srv_send_smb failed.");
1642 }
1643
1644 TALLOC_FREE(req);
1645
1646 return;
1647}
1648
1649/****************************************************************************
1650 Process an smb from the client
1651****************************************************************************/
1652static void process_smb(struct smbd_server_connection *sconn,
1653 uint8_t *inbuf, size_t nread, size_t unread_bytes,
1654 uint32_t seqnum, bool encrypted,
1655 struct smb_perfcount_data *deferred_pcd)
1656{
1657 int msg_type = CVAL(inbuf,0);
1658
1659 DO_PROFILE_INC(smb_count);
1660
1661 DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type,
1662 smb_len(inbuf) ) );
1663 DEBUG(3, ("Transaction %d of length %d (%u toread)\n",
1664 sconn->trans_num, (int)nread, (unsigned int)unread_bytes));
1665
1666 if (msg_type != 0) {
1667 /*
1668 * NetBIOS session request, keepalive, etc.
1669 */
1670 reply_special(sconn, (char *)inbuf, nread);
1671 goto done;
1672 }
1673
1674 if (sconn->using_smb2) {
1675 /* At this point we're not really using smb2,
1676 * we make the decision here.. */
1677 if (smbd_is_smb2_header(inbuf, nread)) {
1678 smbd_smb2_first_negprot(sconn, inbuf, nread);
1679 return;
1680 } else if (nread >= smb_size && valid_smb_header(inbuf)
1681 && CVAL(inbuf, smb_com) != 0x72) {
1682 /* This is a non-negprot SMB1 packet.
1683 Disable SMB2 from now on. */
1684 sconn->using_smb2 = false;
1685 }
1686 }
1687
1688 show_msg((char *)inbuf);
1689
1690 construct_reply(sconn, (char *)inbuf, nread, unread_bytes, seqnum,
1691 encrypted, deferred_pcd);
1692 sconn->trans_num++;
1693
1694done:
1695 sconn->num_requests++;
1696
1697 /* The timeout_processing function isn't run nearly
1698 often enough to implement 'max log size' without
1699 overrunning the size of the file by many megabytes.
1700 This is especially true if we are running at debug
1701 level 10. Checking every 50 SMBs is a nice
1702 tradeoff of performance vs log file size overrun. */
1703
1704 if ((sconn->num_requests % 50) == 0 &&
1705 need_to_check_log_size()) {
1706 change_to_root_user();
1707 check_log_size();
1708 }
1709}
1710
1711/****************************************************************************
1712 Return a string containing the function name of a SMB command.
1713****************************************************************************/
1714
1715const char *smb_fn_name(int type)
1716{
1717 const char *unknown_name = "SMBunknown";
1718
1719 if (smb_messages[type].name == NULL)
1720 return(unknown_name);
1721
1722 return(smb_messages[type].name);
1723}
1724
1725/****************************************************************************
1726 Helper functions for contruct_reply.
1727****************************************************************************/
1728
1729void add_to_common_flags2(uint32 v)
1730{
1731 common_flags2 |= v;
1732}
1733
1734void remove_from_common_flags2(uint32 v)
1735{
1736 common_flags2 &= ~v;
1737}
1738
1739static void construct_reply_common(struct smb_request *req, const char *inbuf,
1740 char *outbuf)
1741{
1742 srv_set_message(outbuf,0,0,false);
1743
1744 SCVAL(outbuf, smb_com, req->cmd);
1745 SIVAL(outbuf,smb_rcls,0);
1746 SCVAL(outbuf,smb_flg, FLAG_REPLY | (CVAL(inbuf,smb_flg) & FLAG_CASELESS_PATHNAMES));
1747 SSVAL(outbuf,smb_flg2,
1748 (SVAL(inbuf,smb_flg2) & FLAGS2_UNICODE_STRINGS) |
1749 common_flags2);
1750 memset(outbuf+smb_pidhigh,'\0',(smb_tid-smb_pidhigh));
1751
1752 SSVAL(outbuf,smb_tid,SVAL(inbuf,smb_tid));
1753 SSVAL(outbuf,smb_pid,SVAL(inbuf,smb_pid));
1754 SSVAL(outbuf,smb_uid,SVAL(inbuf,smb_uid));
1755 SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid));
1756}
1757
1758void construct_reply_common_req(struct smb_request *req, char *outbuf)
1759{
1760 construct_reply_common(req, (char *)req->inbuf, outbuf);
1761}
1762
1763/*
1764 * How many bytes have we already accumulated up to the current wct field
1765 * offset?
1766 */
1767
1768size_t req_wct_ofs(struct smb_request *req)
1769{
1770 size_t buf_size;
1771
1772 if (req->chain_outbuf == NULL) {
1773 return smb_wct - 4;
1774 }
1775 buf_size = talloc_get_size(req->chain_outbuf);
1776 if ((buf_size % 4) != 0) {
1777 buf_size += (4 - (buf_size % 4));
1778 }
1779 return buf_size - 4;
1780}
1781
1782/*
1783 * Hack around reply_nterror & friends not being aware of chained requests,
1784 * generating illegal (i.e. wct==0) chain replies.
1785 */
1786
1787static void fixup_chain_error_packet(struct smb_request *req)
1788{
1789 uint8_t *outbuf = req->outbuf;
1790 req->outbuf = NULL;
1791 reply_outbuf(req, 2, 0);
1792 memcpy(req->outbuf, outbuf, smb_wct);
1793 TALLOC_FREE(outbuf);
1794 SCVAL(req->outbuf, smb_vwv0, 0xff);
1795}
1796
1797/**
1798 * @brief Find the smb_cmd offset of the last command pushed
1799 * @param[in] buf The buffer we're building up
1800 * @retval Where can we put our next andx cmd?
1801 *
1802 * While chaining requests, the "next" request we're looking at needs to put
1803 * its SMB_Command before the data the previous request already built up added
1804 * to the chain. Find the offset to the place where we have to put our cmd.
1805 */
1806
1807static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1808{
1809 uint8_t cmd;
1810 size_t ofs;
1811
1812 cmd = CVAL(buf, smb_com);
1813
1814 SMB_ASSERT(is_andx_req(cmd));
1815
1816 ofs = smb_vwv0;
1817
1818 while (CVAL(buf, ofs) != 0xff) {
1819
1820 if (!is_andx_req(CVAL(buf, ofs))) {
1821 return false;
1822 }
1823
1824 /*
1825 * ofs is from start of smb header, so add the 4 length
1826 * bytes. The next cmd is right after the wct field.
1827 */
1828 ofs = SVAL(buf, ofs+2) + 4 + 1;
1829
1830 SMB_ASSERT(ofs+4 < talloc_get_size(buf));
1831 }
1832
1833 *pofs = ofs;
1834 return true;
1835}
1836
1837/**
1838 * @brief Do the smb chaining at a buffer level
1839 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
1840 * @param[in] smb_command The command that we want to issue
1841 * @param[in] wct How many words?
1842 * @param[in] vwv The words, already in network order
1843 * @param[in] bytes_alignment How shall we align "bytes"?
1844 * @param[in] num_bytes How many bytes?
1845 * @param[in] bytes The data the request ships
1846 *
1847 * smb_splice_chain() adds the vwv and bytes to the request already present in
1848 * *poutbuf.
1849 */
1850
1851static bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command,
1852 uint8_t wct, const uint16_t *vwv,
1853 size_t bytes_alignment,
1854 uint32_t num_bytes, const uint8_t *bytes)
1855{
1856 uint8_t *outbuf;
1857 size_t old_size, new_size;
1858 size_t ofs;
1859 size_t chain_padding = 0;
1860 size_t bytes_padding = 0;
1861 bool first_request;
1862
1863 old_size = talloc_get_size(*poutbuf);
1864
1865 /*
1866 * old_size == smb_wct means we're pushing the first request in for
1867 * libsmb/
1868 */
1869
1870 first_request = (old_size == smb_wct);
1871
1872 if (!first_request && ((old_size % 4) != 0)) {
1873 /*
1874 * Align the wct field of subsequent requests to a 4-byte
1875 * boundary
1876 */
1877 chain_padding = 4 - (old_size % 4);
1878 }
1879
1880 /*
1881 * After the old request comes the new wct field (1 byte), the vwv's
1882 * and the num_bytes field. After at we might need to align the bytes
1883 * given to us to "bytes_alignment", increasing the num_bytes value.
1884 */
1885
1886 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1887
1888 if ((bytes_alignment != 0) && ((new_size % bytes_alignment) != 0)) {
1889 bytes_padding = bytes_alignment - (new_size % bytes_alignment);
1890 }
1891
1892 new_size += bytes_padding + num_bytes;
1893
1894 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1895 DEBUG(1, ("splice_chain: %u bytes won't fit\n",
1896 (unsigned)new_size));
1897 return false;
1898 }
1899
1900 outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, uint8_t, new_size);
1901 if (outbuf == NULL) {
1902 DEBUG(0, ("talloc failed\n"));
1903 return false;
1904 }
1905 *poutbuf = outbuf;
1906
1907 if (first_request) {
1908 SCVAL(outbuf, smb_com, smb_command);
1909 } else {
1910 size_t andx_cmd_ofs;
1911
1912 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1913 DEBUG(1, ("invalid command chain\n"));
1914 *poutbuf = TALLOC_REALLOC_ARRAY(
1915 NULL, *poutbuf, uint8_t, old_size);
1916 return false;
1917 }
1918
1919 if (chain_padding != 0) {
1920 memset(outbuf + old_size, 0, chain_padding);
1921 old_size += chain_padding;
1922 }
1923
1924 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1925 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1926 }
1927
1928 ofs = old_size;
1929
1930 /*
1931 * Push the chained request:
1932 *
1933 * wct field
1934 */
1935
1936 SCVAL(outbuf, ofs, wct);
1937 ofs += 1;
1938
1939 /*
1940 * vwv array
1941 */
1942
1943 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
1944 ofs += sizeof(uint16_t) * wct;
1945
1946 /*
1947 * bcc (byte count)
1948 */
1949
1950 SSVAL(outbuf, ofs, num_bytes + bytes_padding);
1951 ofs += sizeof(uint16_t);
1952
1953 /*
1954 * padding
1955 */
1956
1957 if (bytes_padding != 0) {
1958 memset(outbuf + ofs, 0, bytes_padding);
1959 ofs += bytes_padding;
1960 }
1961
1962 /*
1963 * The bytes field
1964 */
1965
1966 memcpy(outbuf + ofs, bytes, num_bytes);
1967
1968 return true;
1969}
1970
1971/****************************************************************************
1972 Construct a chained reply and add it to the already made reply
1973****************************************************************************/
1974
1975void chain_reply(struct smb_request *req)
1976{
1977 size_t smblen = smb_len(req->inbuf);
1978 size_t already_used, length_needed;
1979 uint8_t chain_cmd;
1980 uint32_t chain_offset; /* uint32_t to avoid overflow */
1981
1982 uint8_t wct;
1983 uint16_t *vwv;
1984 uint16_t buflen;
1985 uint8_t *buf;
1986
1987 if (IVAL(req->outbuf, smb_rcls) != 0) {
1988 fixup_chain_error_packet(req);
1989 }
1990
1991 /*
1992 * Any of the AndX requests and replies have at least a wct of
1993 * 2. vwv[0] is the next command, vwv[1] is the offset from the
1994 * beginning of the SMB header to the next wct field.
1995 *
1996 * None of the AndX requests put anything valuable in vwv[0] and [1],
1997 * so we can overwrite it here to form the chain.
1998 */
1999
2000 if ((req->wct < 2) || (CVAL(req->outbuf, smb_wct) < 2)) {
2001 if (req->chain_outbuf == NULL) {
2002 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
2003 req, req->outbuf, uint8_t,
2004 smb_len(req->outbuf) + 4);
2005 if (req->chain_outbuf == NULL) {
2006 smb_panic("talloc failed");
2007 }
2008 }
2009 req->outbuf = NULL;
2010 goto error;
2011 }
2012
2013 /*
2014 * Here we assume that this is the end of the chain. For that we need
2015 * to set "next command" to 0xff and the offset to 0. If we later find
2016 * more commands in the chain, this will be overwritten again.
2017 */
2018
2019 SCVAL(req->outbuf, smb_vwv0, 0xff);
2020 SCVAL(req->outbuf, smb_vwv0+1, 0);
2021 SSVAL(req->outbuf, smb_vwv1, 0);
2022
2023 if (req->chain_outbuf == NULL) {
2024 /*
2025 * In req->chain_outbuf we collect all the replies. Start the
2026 * chain by copying in the first reply.
2027 *
2028 * We do the realloc because later on we depend on
2029 * talloc_get_size to determine the length of
2030 * chain_outbuf. The reply_xxx routines might have
2031 * over-allocated (reply_pipe_read_and_X used to be such an
2032 * example).
2033 */
2034 req->chain_outbuf = TALLOC_REALLOC_ARRAY(
2035 req, req->outbuf, uint8_t, smb_len(req->outbuf) + 4);
2036 if (req->chain_outbuf == NULL) {
2037 smb_panic("talloc failed");
2038 }
2039 req->outbuf = NULL;
2040 } else {
2041 /*
2042 * Update smb headers where subsequent chained commands
2043 * may have updated them.
2044 */
2045 SSVAL(req->chain_outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
2046 SSVAL(req->chain_outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
2047
2048 if (!smb_splice_chain(&req->chain_outbuf,
2049 CVAL(req->outbuf, smb_com),
2050 CVAL(req->outbuf, smb_wct),
2051 (uint16_t *)(req->outbuf + smb_vwv),
2052 0, smb_buflen(req->outbuf),
2053 (uint8_t *)smb_buf(req->outbuf))) {
2054 goto error;
2055 }
2056 TALLOC_FREE(req->outbuf);
2057 }
2058
2059 /*
2060 * We use the old request's vwv field to grab the next chained command
2061 * and offset into the chained fields.
2062 */
2063
2064 chain_cmd = CVAL(req->vwv+0, 0);
2065 chain_offset = SVAL(req->vwv+1, 0);
2066
2067 if (chain_cmd == 0xff) {
2068 /*
2069 * End of chain, no more requests from the client. So ship the
2070 * replies.
2071 */
2072 smb_setlen((char *)(req->chain_outbuf),
2073 talloc_get_size(req->chain_outbuf) - 4);
2074
2075 if (!srv_send_smb(req->sconn, (char *)req->chain_outbuf,
2076 true, req->seqnum+1,
2077 IS_CONN_ENCRYPTED(req->conn)
2078 ||req->encrypted,
2079 &req->pcd)) {
2080 exit_server_cleanly("chain_reply: srv_send_smb "
2081 "failed.");
2082 }
2083 TALLOC_FREE(req->chain_outbuf);
2084 req->done = true;
2085 return;
2086 }
2087
2088 /* add a new perfcounter for this element of chain */
2089 SMB_PERFCOUNT_ADD(&req->pcd);
2090 SMB_PERFCOUNT_SET_OP(&req->pcd, chain_cmd);
2091 SMB_PERFCOUNT_SET_MSGLEN_IN(&req->pcd, smblen);
2092
2093 /*
2094 * Check if the client tries to fool us. The request so far uses the
2095 * space to the end of the byte buffer in the request just
2096 * processed. The chain_offset can't point into that area. If that was
2097 * the case, we could end up with an endless processing of the chain,
2098 * we would always handle the same request.
2099 */
2100
2101 already_used = PTR_DIFF(req->buf+req->buflen, smb_base(req->inbuf));
2102 if (chain_offset < already_used) {
2103 goto error;
2104 }
2105
2106 /*
2107 * Next check: Make sure the chain offset does not point beyond the
2108 * overall smb request length.
2109 */
2110
2111 length_needed = chain_offset+1; /* wct */
2112 if (length_needed > smblen) {
2113 goto error;
2114 }
2115
2116 /*
2117 * Now comes the pointer magic. Goal here is to set up req->vwv and
2118 * req->buf correctly again to be able to call the subsequent
2119 * switch_message(). The chain offset (the former vwv[1]) points at
2120 * the new wct field.
2121 */
2122
2123 wct = CVAL(smb_base(req->inbuf), chain_offset);
2124
2125 /*
2126 * Next consistency check: Make the new vwv array fits in the overall
2127 * smb request.
2128 */
2129
2130 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
2131 if (length_needed > smblen) {
2132 goto error;
2133 }
2134 vwv = (uint16_t *)(smb_base(req->inbuf) + chain_offset + 1);
2135
2136 /*
2137 * Now grab the new byte buffer....
2138 */
2139
2140 buflen = SVAL(vwv+wct, 0);
2141
2142 /*
2143 * .. and check that it fits.
2144 */
2145
2146 length_needed += buflen;
2147 if (length_needed > smblen) {
2148 goto error;
2149 }
2150 buf = (uint8_t *)(vwv+wct+1);
2151
2152 req->cmd = chain_cmd;
2153 req->wct = wct;
2154 req->vwv = vwv;
2155 req->buflen = buflen;
2156 req->buf = buf;
2157
2158 switch_message(chain_cmd, req, smblen);
2159
2160 if (req->outbuf == NULL) {
2161 /*
2162 * This happens if the chained command has suspended itself or
2163 * if it has called srv_send_smb() itself.
2164 */
2165 return;
2166 }
2167
2168 /*
2169 * We end up here if the chained command was not itself chained or
2170 * suspended, but for example a close() command. We now need to splice
2171 * the chained commands' outbuf into the already built up chain_outbuf
2172 * and ship the result.
2173 */
2174 goto done;
2175
2176 error:
2177 /*
2178 * We end up here if there's any error in the chain syntax. Report a
2179 * DOS error, just like Windows does.
2180 */
2181 reply_force_doserror(req, ERRSRV, ERRerror);
2182 fixup_chain_error_packet(req);
2183
2184 done:
2185 /*
2186 * This scary statement intends to set the
2187 * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
2188 * to the value req->outbuf carries
2189 */
2190 SSVAL(req->chain_outbuf, smb_flg2,
2191 (SVAL(req->chain_outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
2192 | (SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
2193
2194 /*
2195 * Transfer the error codes from the subrequest to the main one
2196 */
2197 SSVAL(req->chain_outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
2198 SSVAL(req->chain_outbuf, smb_err, SVAL(req->outbuf, smb_err));
2199
2200 if (!smb_splice_chain(&req->chain_outbuf,
2201 CVAL(req->outbuf, smb_com),
2202 CVAL(req->outbuf, smb_wct),
2203 (uint16_t *)(req->outbuf + smb_vwv),
2204 0, smb_buflen(req->outbuf),
2205 (uint8_t *)smb_buf(req->outbuf))) {
2206 exit_server_cleanly("chain_reply: smb_splice_chain failed\n");
2207 }
2208 TALLOC_FREE(req->outbuf);
2209
2210 smb_setlen((char *)(req->chain_outbuf),
2211 talloc_get_size(req->chain_outbuf) - 4);
2212
2213 show_msg((char *)(req->chain_outbuf));
2214
2215 if (!srv_send_smb(req->sconn, (char *)req->chain_outbuf,
2216 true, req->seqnum+1,
2217 IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
2218 &req->pcd)) {
2219 exit_server_cleanly("chain_reply: srv_send_smb failed.");
2220 }
2221 TALLOC_FREE(req->chain_outbuf);
2222 req->done = true;
2223}
2224
2225/****************************************************************************
2226 Check if services need reloading.
2227****************************************************************************/
2228
2229static void check_reload(struct smbd_server_connection *sconn, time_t t)
2230{
2231
2232 if (last_smb_conf_reload_time == 0) {
2233 last_smb_conf_reload_time = t;
2234 }
2235
2236 if (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK) {
2237 reload_services(sconn->msg_ctx, sconn->sock, True);
2238 last_smb_conf_reload_time = t;
2239 }
2240}
2241
2242static bool fd_is_readable(int fd)
2243{
2244 int ret, revents;
2245
2246 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2247
2248 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2249
2250}
2251
2252static void smbd_server_connection_write_handler(struct smbd_server_connection *conn)
2253{
2254 /* TODO: make write nonblocking */
2255}
2256
2257static void smbd_server_connection_read_handler(
2258 struct smbd_server_connection *conn, int fd)
2259{
2260 uint8_t *inbuf = NULL;
2261 size_t inbuf_len = 0;
2262 size_t unread_bytes = 0;
2263 bool encrypted = false;
2264 TALLOC_CTX *mem_ctx = talloc_tos();
2265 NTSTATUS status;
2266 uint32_t seqnum;
2267
2268 bool from_client = (conn->sock == fd);
2269
2270 if (from_client) {
2271 smbd_lock_socket(conn);
2272
2273 if (lp_async_smb_echo_handler() && !fd_is_readable(fd)) {
2274 DEBUG(10,("the echo listener was faster\n"));
2275 smbd_unlock_socket(conn);
2276 return;
2277 }
2278
2279 /* TODO: make this completely nonblocking */
2280 status = receive_smb_talloc(mem_ctx, conn, fd,
2281 (char **)(void *)&inbuf,
2282 0, /* timeout */
2283 &unread_bytes,
2284 &encrypted,
2285 &inbuf_len, &seqnum,
2286 false /* trusted channel */);
2287 smbd_unlock_socket(conn);
2288 } else {
2289 /* TODO: make this completely nonblocking */
2290 status = receive_smb_talloc(mem_ctx, conn, fd,
2291 (char **)(void *)&inbuf,
2292 0, /* timeout */
2293 &unread_bytes,
2294 &encrypted,
2295 &inbuf_len, &seqnum,
2296 true /* trusted channel */);
2297 }
2298
2299 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2300 goto process;
2301 }
2302 if (NT_STATUS_IS_ERR(status)) {
2303 exit_server_cleanly("failed to receive smb request");
2304 }
2305 if (!NT_STATUS_IS_OK(status)) {
2306 return;
2307 }
2308
2309process:
2310 process_smb(conn, inbuf, inbuf_len, unread_bytes,
2311 seqnum, encrypted, NULL);
2312}
2313
2314static void smbd_server_connection_handler(struct event_context *ev,
2315 struct fd_event *fde,
2316 uint16_t flags,
2317 void *private_data)
2318{
2319 struct smbd_server_connection *conn = talloc_get_type(private_data,
2320 struct smbd_server_connection);
2321
2322 if (flags & EVENT_FD_WRITE) {
2323 smbd_server_connection_write_handler(conn);
2324 return;
2325 }
2326 if (flags & EVENT_FD_READ) {
2327 smbd_server_connection_read_handler(conn, conn->sock);
2328 return;
2329 }
2330}
2331
2332static void smbd_server_echo_handler(struct event_context *ev,
2333 struct fd_event *fde,
2334 uint16_t flags,
2335 void *private_data)
2336{
2337 struct smbd_server_connection *conn = talloc_get_type(private_data,
2338 struct smbd_server_connection);
2339
2340 if (flags & EVENT_FD_WRITE) {
2341 smbd_server_connection_write_handler(conn);
2342 return;
2343 }
2344 if (flags & EVENT_FD_READ) {
2345 smbd_server_connection_read_handler(
2346 conn, conn->smb1.echo_handler.trusted_fd);
2347 return;
2348 }
2349}
2350
2351/****************************************************************************
2352received when we should release a specific IP
2353****************************************************************************/
2354static void release_ip(const char *ip, void *priv)
2355{
2356 const char *addr = (const char *)priv;
2357 const char *p = addr;
2358
2359 if (strncmp("::ffff:", addr, 7) == 0) {
2360 p = addr + 7;
2361 }
2362
2363 DEBUG(10, ("Got release IP message for %s, "
2364 "our address is %s\n", ip, p));
2365
2366 if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
2367 /* we can't afford to do a clean exit - that involves
2368 database writes, which would potentially mean we
2369 are still running after the failover has finished -
2370 we have to get rid of this process ID straight
2371 away */
2372 DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
2373 ip));
2374 /* note we must exit with non-zero status so the unclean handler gets
2375 called in the parent, so that the brl database is tickled */
2376 _exit(1);
2377 }
2378}
2379
2380static void msg_release_ip(struct messaging_context *msg_ctx, void *private_data,
2381 uint32_t msg_type, struct server_id server_id, DATA_BLOB *data)
2382{
2383 struct smbd_server_connection *sconn = talloc_get_type_abort(
2384 private_data, struct smbd_server_connection);
2385
2386 release_ip((char *)data->data, sconn->client_id.addr);
2387}
2388
2389#ifdef CLUSTER_SUPPORT
2390static int client_get_tcp_info(int sock, struct sockaddr_storage *server,
2391 struct sockaddr_storage *client)
2392{
2393 socklen_t length;
2394 length = sizeof(*server);
2395 if (getsockname(sock, (struct sockaddr *)server, &length) != 0) {
2396 return -1;
2397 }
2398 length = sizeof(*client);
2399 if (getpeername(sock, (struct sockaddr *)client, &length) != 0) {
2400 return -1;
2401 }
2402 return 0;
2403}
2404#endif
2405
2406/*
2407 * Send keepalive packets to our client
2408 */
2409static bool keepalive_fn(const struct timeval *now, void *private_data)
2410{
2411 struct smbd_server_connection *sconn = smbd_server_conn;
2412 bool ret;
2413
2414 if (sconn->using_smb2) {
2415 /* Don't do keepalives on an SMB2 connection. */
2416 return false;
2417 }
2418
2419 smbd_lock_socket(smbd_server_conn);
2420 ret = send_keepalive(sconn->sock);
2421 smbd_unlock_socket(smbd_server_conn);
2422
2423 if (!ret) {
2424 char addr[INET6_ADDRSTRLEN];
2425 /*
2426 * Try and give an error message saying what
2427 * client failed.
2428 */
2429 DEBUG(0, ("send_keepalive failed for client %s. "
2430 "Error %s - exiting\n",
2431 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2432 strerror(errno)));
2433 return False;
2434 }
2435 return True;
2436}
2437
2438/*
2439 * Do the recurring check if we're idle
2440 */
2441static bool deadtime_fn(const struct timeval *now, void *private_data)
2442{
2443 struct smbd_server_connection *sconn =
2444 (struct smbd_server_connection *)private_data;
2445
2446 if ((conn_num_open(sconn) == 0)
2447 || (conn_idle_all(sconn, now->tv_sec))) {
2448 DEBUG( 2, ( "Closing idle connection\n" ) );
2449 messaging_send(sconn->msg_ctx,
2450 messaging_server_id(sconn->msg_ctx),
2451 MSG_SHUTDOWN, &data_blob_null);
2452 return False;
2453 }
2454
2455 return True;
2456}
2457
2458/*
2459 * Do the recurring log file and smb.conf reload checks.
2460 */
2461
2462static bool housekeeping_fn(const struct timeval *now, void *private_data)
2463{
2464 struct smbd_server_connection *sconn = talloc_get_type_abort(
2465 private_data, struct smbd_server_connection);
2466
2467 DEBUG(5, ("housekeeping\n"));
2468
2469 change_to_root_user();
2470
2471 /* update printer queue caches if necessary */
2472 update_monitored_printq_cache(sconn->msg_ctx);
2473
2474 /* check if we need to reload services */
2475 check_reload(sconn, time_mono(NULL));
2476
2477 /* Change machine password if neccessary. */
2478 attempt_machine_password_change();
2479
2480 /*
2481 * Force a log file check.
2482 */
2483 force_check_log_size();
2484 check_log_size();
2485 return true;
2486}
2487
2488static int create_unlink_tmp(const char *dir)
2489{
2490 char *fname;
2491 int fd;
2492
2493 fname = talloc_asprintf(talloc_tos(), "%s/listenerlock_XXXXXX", dir);
2494 if (fname == NULL) {
2495 errno = ENOMEM;
2496 return -1;
2497 }
2498 fd = mkstemp(fname);
2499 if (fd == -1) {
2500 TALLOC_FREE(fname);
2501 return -1;
2502 }
2503 if (unlink(fname) == -1) {
2504 int sys_errno = errno;
2505 close(fd);
2506 TALLOC_FREE(fname);
2507 errno = sys_errno;
2508 return -1;
2509 }
2510 TALLOC_FREE(fname);
2511 return fd;
2512}
2513
2514struct smbd_echo_state {
2515 struct tevent_context *ev;
2516 struct iovec *pending;
2517 struct smbd_server_connection *sconn;
2518 int parent_pipe;
2519
2520 struct tevent_fd *parent_fde;
2521
2522 struct tevent_fd *read_fde;
2523 struct tevent_req *write_req;
2524};
2525
2526static void smbd_echo_writer_done(struct tevent_req *req);
2527
2528static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2529{
2530 int num_pending;
2531
2532 if (state->write_req != NULL) {
2533 return;
2534 }
2535
2536 num_pending = talloc_array_length(state->pending);
2537 if (num_pending == 0) {
2538 return;
2539 }
2540
2541 state->write_req = writev_send(state, state->ev, NULL,
2542 state->parent_pipe, false,
2543 state->pending, num_pending);
2544 if (state->write_req == NULL) {
2545 DEBUG(1, ("writev_send failed\n"));
2546 exit(1);
2547 }
2548
2549 talloc_steal(state->write_req, state->pending);
2550 state->pending = NULL;
2551
2552 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2553 state);
2554}
2555
2556static void smbd_echo_writer_done(struct tevent_req *req)
2557{
2558 struct smbd_echo_state *state = tevent_req_callback_data(
2559 req, struct smbd_echo_state);
2560 ssize_t written;
2561 int err;
2562
2563 written = writev_recv(req, &err);
2564 TALLOC_FREE(req);
2565 state->write_req = NULL;
2566 if (written == -1) {
2567 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2568 exit(1);
2569 }
2570 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)sys_getpid()));
2571 smbd_echo_activate_writer(state);
2572}
2573
2574static bool smbd_echo_reply(uint8_t *inbuf, size_t inbuf_len,
2575 uint32_t seqnum)
2576{
2577 struct smb_request req;
2578 uint16_t num_replies;
2579 size_t out_len;
2580 char *outbuf;
2581 bool ok;
2582
2583 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == SMBkeepalive)) {
2584 DEBUG(10, ("Got netbios keepalive\n"));
2585 /*
2586 * Just swallow it
2587 */
2588 return true;
2589 }
2590
2591 if (inbuf_len < smb_size) {
2592 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2593 return false;
2594 }
2595 if (!valid_smb_header(inbuf)) {
2596 DEBUG(10, ("Got invalid SMB header\n"));
2597 return false;
2598 }
2599
2600 if (!init_smb_request(&req, smbd_server_conn, inbuf, 0, false,
2601 seqnum)) {
2602 return false;
2603 }
2604 req.inbuf = inbuf;
2605
2606 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2607 smb_messages[req.cmd].name
2608 ? smb_messages[req.cmd].name : "unknown"));
2609
2610 if (req.cmd != SMBecho) {
2611 return false;
2612 }
2613 if (req.wct < 1) {
2614 return false;
2615 }
2616
2617 num_replies = SVAL(req.vwv+0, 0);
2618 if (num_replies != 1) {
2619 /* Not a Windows "Hey, you're still there?" request */
2620 return false;
2621 }
2622
2623 if (!create_outbuf(talloc_tos(), &req, (char *)req.inbuf, &outbuf,
2624 1, req.buflen)) {
2625 DEBUG(10, ("create_outbuf failed\n"));
2626 return false;
2627 }
2628 req.outbuf = (uint8_t *)outbuf;
2629
2630 SSVAL(req.outbuf, smb_vwv0, num_replies);
2631
2632 if (req.buflen > 0) {
2633 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2634 }
2635
2636 out_len = smb_len(req.outbuf) + 4;
2637
2638 ok = srv_send_smb(req.sconn,
2639 (char *)outbuf,
2640 true, seqnum+1,
2641 false, &req.pcd);
2642 TALLOC_FREE(outbuf);
2643 if (!ok) {
2644 exit(1);
2645 }
2646
2647 return true;
2648}
2649
2650static void smbd_echo_exit(struct tevent_context *ev,
2651 struct tevent_fd *fde, uint16_t flags,
2652 void *private_data)
2653{
2654 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2655 exit(0);
2656}
2657
2658static void smbd_echo_reader(struct tevent_context *ev,
2659 struct tevent_fd *fde, uint16_t flags,
2660 void *private_data)
2661{
2662 struct smbd_echo_state *state = talloc_get_type_abort(
2663 private_data, struct smbd_echo_state);
2664 struct smbd_server_connection *sconn = state->sconn;
2665 size_t unread, num_pending;
2666 NTSTATUS status;
2667 struct iovec *tmp;
2668 size_t iov_len;
2669 uint32_t seqnum = 0;
2670 bool reply;
2671 bool ok;
2672 bool encrypted = false;
2673
2674 smb_msleep(1000);
2675
2676 ok = smbd_lock_socket_internal(sconn);
2677 if (!ok) {
2678 DEBUG(0, ("%s: failed to lock socket\n",
2679 __location__));
2680 exit(1);
2681 }
2682
2683 if (!fd_is_readable(sconn->sock)) {
2684 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2685 (int)sys_getpid()));
2686 ok = smbd_unlock_socket_internal(sconn);
2687 if (!ok) {
2688 DEBUG(1, ("%s: failed to unlock socket in\n",
2689 __location__));
2690 exit(1);
2691 }
2692 return;
2693 }
2694
2695 num_pending = talloc_array_length(state->pending);
2696 tmp = talloc_realloc(state, state->pending, struct iovec,
2697 num_pending+1);
2698 if (tmp == NULL) {
2699 DEBUG(1, ("talloc_realloc failed\n"));
2700 exit(1);
2701 }
2702 state->pending = tmp;
2703
2704 DEBUG(10,("echo_handler[%d]: reading pdu\n", (int)sys_getpid()));
2705
2706 status = receive_smb_talloc(state->pending, sconn, sconn->sock,
2707 (char **)(void *)&state->pending[num_pending].iov_base,
2708 0 /* timeout */,
2709 &unread,
2710 &encrypted,
2711 &iov_len,
2712 &seqnum,
2713 false /* trusted_channel*/);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2716 (int)sys_getpid(), nt_errstr(status)));
2717 exit(1);
2718 }
2719 state->pending[num_pending].iov_len = iov_len;
2720
2721 ok = smbd_unlock_socket_internal(sconn);
2722 if (!ok) {
2723 DEBUG(1, ("%s: failed to unlock socket in\n",
2724 __location__));
2725 exit(1);
2726 }
2727
2728 reply = smbd_echo_reply((uint8_t *)state->pending[num_pending].iov_base,
2729 state->pending[num_pending].iov_len,
2730 seqnum);
2731 if (reply) {
2732 DEBUG(10,("echo_handler[%d]: replied to client\n", (int)sys_getpid()));
2733 /* no check, shrinking by some bytes does not fail */
2734 state->pending = talloc_realloc(state, state->pending,
2735 struct iovec,
2736 num_pending);
2737 return;
2738 }
2739
2740 if (state->pending[num_pending].iov_len >= smb_size) {
2741 /*
2742 * place the seqnum in the packet so that the main process
2743 * can reply with signing
2744 */
2745 SIVAL((uint8_t *)state->pending[num_pending].iov_base,
2746 smb_ss_field, seqnum);
2747 SIVAL((uint8_t *)state->pending[num_pending].iov_base,
2748 smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2749 }
2750
2751 DEBUG(10,("echo_handler[%d]: forward to main\n", (int)sys_getpid()));
2752 smbd_echo_activate_writer(state);
2753}
2754
2755static void smbd_echo_loop(struct smbd_server_connection *sconn,
2756 int parent_pipe)
2757{
2758 struct smbd_echo_state *state;
2759
2760 state = talloc_zero(sconn, struct smbd_echo_state);
2761 if (state == NULL) {
2762 DEBUG(1, ("talloc failed\n"));
2763 return;
2764 }
2765 state->sconn = sconn;
2766 state->parent_pipe = parent_pipe;
2767 state->ev = s3_tevent_context_init(state);
2768 if (state->ev == NULL) {
2769 DEBUG(1, ("tevent_context_init failed\n"));
2770 TALLOC_FREE(state);
2771 return;
2772 }
2773 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2774 TEVENT_FD_READ, smbd_echo_exit,
2775 state);
2776 if (state->parent_fde == NULL) {
2777 DEBUG(1, ("tevent_add_fd failed\n"));
2778 TALLOC_FREE(state);
2779 return;
2780 }
2781 state->read_fde = tevent_add_fd(state->ev, state, sconn->sock,
2782 TEVENT_FD_READ, smbd_echo_reader,
2783 state);
2784 if (state->read_fde == NULL) {
2785 DEBUG(1, ("tevent_add_fd failed\n"));
2786 TALLOC_FREE(state);
2787 return;
2788 }
2789
2790 while (true) {
2791 if (tevent_loop_once(state->ev) == -1) {
2792 DEBUG(1, ("tevent_loop_once failed: %s\n",
2793 strerror(errno)));
2794 break;
2795 }
2796 }
2797 TALLOC_FREE(state);
2798}
2799
2800/*
2801 * Handle SMBecho requests in a forked child process
2802 */
2803static bool fork_echo_handler(struct smbd_server_connection *sconn)
2804{
2805 int listener_pipe[2];
2806 int res;
2807 pid_t child;
2808
2809 res = pipe(listener_pipe);
2810 if (res == -1) {
2811 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2812 return false;
2813 }
2814 sconn->smb1.echo_handler.socket_lock_fd = create_unlink_tmp(lp_lockdir());
2815 if (sconn->smb1.echo_handler.socket_lock_fd == -1) {
2816 DEBUG(1, ("Could not create lock fd: %s\n", strerror(errno)));
2817 goto fail;
2818 }
2819
2820 child = sys_fork();
2821 if (child == 0) {
2822 NTSTATUS status;
2823
2824 close(listener_pipe[0]);
2825 set_blocking(listener_pipe[1], false);
2826
2827 status = reinit_after_fork(sconn->msg_ctx,
2828 smbd_event_context(),
2829 procid_self(), false);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 DEBUG(1, ("reinit_after_fork failed: %s\n",
2832 nt_errstr(status)));
2833 exit(1);
2834 }
2835 smbd_echo_loop(sconn, listener_pipe[1]);
2836 exit(0);
2837 }
2838 close(listener_pipe[1]);
2839 listener_pipe[1] = -1;
2840 sconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2841
2842 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)sys_getpid(), child));
2843
2844 /*
2845 * Without smb signing this is the same as the normal smbd
2846 * listener. This needs to change once signing comes in.
2847 */
2848 sconn->smb1.echo_handler.trusted_fde = event_add_fd(smbd_event_context(),
2849 sconn,
2850 sconn->smb1.echo_handler.trusted_fd,
2851 EVENT_FD_READ,
2852 smbd_server_echo_handler,
2853 sconn);
2854 if (sconn->smb1.echo_handler.trusted_fde == NULL) {
2855 DEBUG(1, ("event_add_fd failed\n"));
2856 goto fail;
2857 }
2858
2859 return true;
2860
2861fail:
2862 if (listener_pipe[0] != -1) {
2863 close(listener_pipe[0]);
2864 }
2865 if (listener_pipe[1] != -1) {
2866 close(listener_pipe[1]);
2867 }
2868 sconn->smb1.echo_handler.trusted_fd = -1;
2869 if (sconn->smb1.echo_handler.socket_lock_fd != -1) {
2870 close(sconn->smb1.echo_handler.socket_lock_fd);
2871 }
2872 sconn->smb1.echo_handler.trusted_fd = -1;
2873 sconn->smb1.echo_handler.socket_lock_fd = -1;
2874 return false;
2875}
2876
2877#if CLUSTER_SUPPORT
2878
2879static NTSTATUS smbd_register_ips(struct smbd_server_connection *sconn,
2880 struct sockaddr_storage *srv,
2881 struct sockaddr_storage *clnt)
2882{
2883 struct ctdbd_connection *cconn;
2884 char tmp_addr[INET6_ADDRSTRLEN];
2885 char *addr;
2886
2887 cconn = messaging_ctdbd_connection();
2888 if (cconn == NULL) {
2889 return NT_STATUS_NO_MEMORY;
2890 }
2891
2892 client_socket_addr(sconn->sock, tmp_addr, sizeof(tmp_addr));
2893 addr = talloc_strdup(cconn, tmp_addr);
2894 if (addr == NULL) {
2895 return NT_STATUS_NO_MEMORY;
2896 }
2897 return ctdbd_register_ips(cconn, srv, clnt, release_ip, addr);
2898}
2899
2900#endif
2901
2902/****************************************************************************
2903 Process commands from the client
2904****************************************************************************/
2905
2906void smbd_process(struct smbd_server_connection *sconn)
2907{
2908 TALLOC_CTX *frame = talloc_stackframe();
2909 struct sockaddr_storage ss;
2910 struct sockaddr *sa = NULL;
2911 socklen_t sa_socklen;
2912 struct tsocket_address *local_address = NULL;
2913 struct tsocket_address *remote_address = NULL;
2914 const char *remaddr = NULL;
2915 int ret;
2916
2917 if (lp_maxprotocol() == PROTOCOL_SMB2 &&
2918 !lp_async_smb_echo_handler()) {
2919 /*
2920 * We're not making the decision here,
2921 * we're just allowing the client
2922 * to decide between SMB1 and SMB2
2923 * with the first negprot
2924 * packet.
2925 */
2926 sconn->using_smb2 = true;
2927 }
2928
2929 /* Ensure child is set to blocking mode */
2930 set_blocking(sconn->sock,True);
2931
2932 set_socket_options(sconn->sock, "SO_KEEPALIVE");
2933 set_socket_options(sconn->sock, lp_socket_options());
2934
2935 sa = (struct sockaddr *)(void *)&ss;
2936 sa_socklen = sizeof(ss);
2937 ret = getpeername(sconn->sock, sa, &sa_socklen);
2938 if (ret != 0) {
2939 int level = (errno == ENOTCONN)?2:0;
2940 DEBUG(level,("getpeername() failed - %s\n", strerror(errno)));
2941 exit_server_cleanly("getpeername() failed.\n");
2942 }
2943 ret = tsocket_address_bsd_from_sockaddr(sconn,
2944 sa, sa_socklen,
2945 &remote_address);
2946 if (ret != 0) {
2947 DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
2948 __location__, strerror(errno)));
2949 exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n");
2950 }
2951
2952 sa = (struct sockaddr *)(void *)&ss;
2953 sa_socklen = sizeof(ss);
2954 ret = getsockname(sconn->sock, sa, &sa_socklen);
2955 if (ret != 0) {
2956 int level = (errno == ENOTCONN)?2:0;
2957 DEBUG(level,("getsockname() failed - %s\n", strerror(errno)));
2958 exit_server_cleanly("getsockname() failed.\n");
2959 }
2960 ret = tsocket_address_bsd_from_sockaddr(sconn,
2961 sa, sa_socklen,
2962 &local_address);
2963 if (ret != 0) {
2964 DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
2965 __location__, strerror(errno)));
2966 exit_server_cleanly("tsocket_address_bsd_from_sockaddr remote failed.\n");
2967 }
2968
2969 sconn->local_address = local_address;
2970 sconn->remote_address = remote_address;
2971
2972 if (tsocket_address_is_inet(remote_address, "ip")) {
2973 remaddr = tsocket_address_inet_addr_string(
2974 sconn->remote_address,
2975 talloc_tos());
2976 if (remaddr == NULL) {
2977
2978 }
2979 } else {
2980 remaddr = "0.0.0.0";
2981 }
2982
2983 /* this is needed so that we get decent entries
2984 in smbstatus for port 445 connects */
2985 set_remote_machine_name(remaddr, false);
2986 reload_services(sconn->msg_ctx, sconn->sock, true);
2987
2988 /*
2989 * Before the first packet, check the global hosts allow/ hosts deny
2990 * parameters before doing any parsing of packets passed to us by the
2991 * client. This prevents attacks on our parsing code from hosts not in
2992 * the hosts allow list.
2993 */
2994
2995 if (!allow_access(lp_hostsdeny(-1), lp_hostsallow(-1),
2996 sconn->client_id.name,
2997 sconn->client_id.addr)) {
2998 /*
2999 * send a negative session response "not listening on calling
3000 * name"
3001 */
3002 unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
3003 DEBUG( 1, ("Connection denied from %s to %s\n",
3004 tsocket_address_string(remote_address, talloc_tos()),
3005 tsocket_address_string(local_address, talloc_tos())));
3006 (void)srv_send_smb(sconn,(char *)buf, false,
3007 0, false, NULL);
3008 exit_server_cleanly("connection denied");
3009 }
3010
3011 DEBUG(10, ("Connection allowed from %s to %s\n",
3012 tsocket_address_string(remote_address, talloc_tos()),
3013 tsocket_address_string(local_address, talloc_tos())));
3014
3015 init_modules();
3016
3017 smb_perfcount_init();
3018
3019 if (!init_account_policy()) {
3020 exit_server("Could not open account policy tdb.\n");
3021 }
3022
3023 if (*lp_rootdir()) {
3024 if (chroot(lp_rootdir()) != 0) {
3025 DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
3026 exit_server("Failed to chroot()");
3027 }
3028 if (chdir("/") == -1) {
3029 DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
3030 exit_server("Failed to chroot()");
3031 }
3032 DEBUG(0,("Changed root to %s\n", lp_rootdir()));
3033 }
3034
3035 if (!srv_init_signing(sconn)) {
3036 exit_server("Failed to init smb_signing");
3037 }
3038
3039 if (lp_async_smb_echo_handler() && !fork_echo_handler(sconn)) {
3040 exit_server("Failed to fork echo handler");
3041 }
3042
3043 /* Setup oplocks */
3044 if (!init_oplocks(sconn->msg_ctx))
3045 exit_server("Failed to init oplocks");
3046
3047 /* register our message handlers */
3048 messaging_register(sconn->msg_ctx, NULL,
3049 MSG_SMB_FORCE_TDIS, msg_force_tdis);
3050 messaging_register(sconn->msg_ctx, sconn,
3051 MSG_SMB_RELEASE_IP, msg_release_ip);
3052 messaging_register(sconn->msg_ctx, NULL,
3053 MSG_SMB_CLOSE_FILE, msg_close_file);
3054
3055 /*
3056 * Use the default MSG_DEBUG handler to avoid rebroadcasting
3057 * MSGs to all child processes
3058 */
3059 messaging_deregister(sconn->msg_ctx,
3060 MSG_DEBUG, NULL);
3061 messaging_register(sconn->msg_ctx, NULL,
3062 MSG_DEBUG, debug_message);
3063
3064 if ((lp_keepalive() != 0)
3065 && !(event_add_idle(smbd_event_context(), NULL,
3066 timeval_set(lp_keepalive(), 0),
3067 "keepalive", keepalive_fn,
3068 NULL))) {
3069 DEBUG(0, ("Could not add keepalive event\n"));
3070 exit(1);
3071 }
3072
3073 if (!(event_add_idle(smbd_event_context(), NULL,
3074 timeval_set(IDLE_CLOSED_TIMEOUT, 0),
3075 "deadtime", deadtime_fn, sconn))) {
3076 DEBUG(0, ("Could not add deadtime event\n"));
3077 exit(1);
3078 }
3079
3080 if (!(event_add_idle(smbd_event_context(), NULL,
3081 timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
3082 "housekeeping", housekeeping_fn, sconn))) {
3083 DEBUG(0, ("Could not add housekeeping event\n"));
3084 exit(1);
3085 }
3086
3087#ifdef CLUSTER_SUPPORT
3088
3089 if (lp_clustering()) {
3090 /*
3091 * We need to tell ctdb about our client's TCP
3092 * connection, so that for failover ctdbd can send
3093 * tickle acks, triggering a reconnection by the
3094 * client.
3095 */
3096
3097 struct sockaddr_storage srv, clnt;
3098
3099 if (client_get_tcp_info(sconn->sock, &srv, &clnt) == 0) {
3100 NTSTATUS status;
3101 status = smbd_register_ips(sconn, &srv, &clnt);
3102 if (!NT_STATUS_IS_OK(status)) {
3103 DEBUG(0, ("ctdbd_register_ips failed: %s\n",
3104 nt_errstr(status)));
3105 }
3106 } else
3107 {
3108 DEBUG(0,("Unable to get tcp info for "
3109 "CTDB_CONTROL_TCP_CLIENT: %s\n",
3110 strerror(errno)));
3111 }
3112 }
3113
3114#endif
3115
3116 sconn->nbt.got_session = false;
3117
3118 sconn->smb1.negprot.max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
3119
3120 sconn->smb1.sessions.done_sesssetup = false;
3121 sconn->smb1.sessions.max_send = BUFFER_SIZE;
3122 sconn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
3123 /* users from session setup */
3124 sconn->smb1.sessions.session_userlist = NULL;
3125 /* workgroup from session setup. */
3126 sconn->smb1.sessions.session_workgroup = NULL;
3127 /* this holds info on user ids that are already validated for this VC */
3128 sconn->smb1.sessions.validated_users = NULL;
3129 sconn->smb1.sessions.next_vuid = VUID_OFFSET;
3130 sconn->smb1.sessions.num_validated_vuids = 0;
3131
3132 conn_init(sconn);
3133 if (!init_dptrs(sconn)) {
3134 exit_server("init_dptrs() failed");
3135 }
3136
3137 sconn->smb1.fde = event_add_fd(smbd_event_context(),
3138 sconn,
3139 sconn->sock,
3140 EVENT_FD_READ,
3141 smbd_server_connection_handler,
3142 sconn);
3143 if (!sconn->smb1.fde) {
3144 exit_server("failed to create smbd_server_connection fde");
3145 }
3146
3147 TALLOC_FREE(frame);
3148
3149 while (True) {
3150 NTSTATUS status;
3151
3152 frame = talloc_stackframe_pool(8192);
3153
3154 errno = 0;
3155
3156 status = smbd_server_connection_loop_once(sconn);
3157 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY) &&
3158 !NT_STATUS_IS_OK(status)) {
3159 DEBUG(3, ("smbd_server_connection_loop_once failed: %s,"
3160 " exiting\n", nt_errstr(status)));
3161 break;
3162 }
3163
3164 TALLOC_FREE(frame);
3165 }
3166
3167 exit_server_cleanly(NULL);
3168}
3169
3170bool req_is_in_chain(struct smb_request *req)
3171{
3172 if (req->vwv != (uint16_t *)(req->inbuf+smb_vwv)) {
3173 /*
3174 * We're right now handling a subsequent request, so we must
3175 * be in a chain
3176 */
3177 return true;
3178 }
3179
3180 if (!is_andx_req(req->cmd)) {
3181 return false;
3182 }
3183
3184 if (req->wct < 2) {
3185 /*
3186 * Okay, an illegal request, but definitely not chained :-)
3187 */
3188 return false;
3189 }
3190
3191 return (CVAL(req->vwv+0, 0) != 0xFF);
3192}
Note: See TracBrowser for help on using the repository browser.