]> git.ipfire.org Git - thirdparty/samba.git/blame - source3/smbd/smb1_process.c
smbd: Remove sconn->using_smb2
[thirdparty/samba.git] / source3 / smbd / smb1_process.c
CommitLineData
c3effa8b 1/*
cd68afe3 2 Unix SMB/CIFS implementation.
c3effa8b
AT
3 process incoming packets - main loop
4 Copyright (C) Andrew Tridgell 1992-1998
b91704d4 5 Copyright (C) Volker Lendecke 2005-2007
8af7400d 6
c3effa8b
AT
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
d824b98f 9 the Free Software Foundation; either version 3 of the License, or
c3effa8b 10 (at your option) any later version.
8af7400d 11
c3effa8b
AT
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.
8af7400d 16
c3effa8b 17 You should have received a copy of the GNU General Public License
5e54558c 18 along with this program. If not, see <http://www.gnu.org/licenses/>.
c3effa8b
AT
19*/
20
21#include "includes.h"
12476223 22#include "../lib/tsocket/tsocket.h"
0e771263 23#include "system/filesys.h"
8c24ebf3 24#include "smbd/smbd.h"
3dde0cbb 25#include "smbd/globals.h"
965fec35 26#include "source3/smbd/smbXsrv_session.h"
ca8afc66 27#include "smbd/smbXsrv_open.h"
aff002e8 28#include "librpc/gen_ndr/netlogon.h"
c7fe04ab 29#include "../lib/async_req/async_sock.h"
8e16d6db 30#include "ctdbd_conn.h"
b38d0542 31#include "../lib/util/select.h"
2e8a85ec 32#include "printing/queue_process.h"
9758afd4 33#include "system/select.h"
235f1485 34#include "passdb.h"
af300a9f 35#include "auth.h"
b2af281e 36#include "messages.h"
af63c0b3 37#include "lib/messages_ctdb.h"
165521e2 38#include "smbprofile.h"
c233c214 39#include "rpc_server/spoolss/srv_spoolss_nt.h"
27afb891 40#include "../lib/util/tevent_ntstatus.h"
715933a3
SM
41#include "../libcli/security/dom_sid.h"
42#include "../libcli/security/security_token.h"
43#include "lib/id_cache.h"
258ce91f 44#include "lib/util/sys_rw_data.h"
f01af728 45#include "system/threads.h"
74590c67 46#include "lib/pthreadpool/pthreadpool_tevent.h"
d7cfb12b 47#include "util_event.h"
3eee4394 48#include "libcli/smb/smbXcli_base.h"
303c4829 49#include "lib/util/time_basic.h"
25043ebb 50#include "source3/lib/substitute.h"
62cc0bba 51#include "lib/util/util_process.h"
c3effa8b 52
6d84b24d
SM
53/* Internal message queue for deferred opens. */
54struct pending_message_list {
55 struct pending_message_list *next, *prev;
56 struct timeval request_time; /* When was this first issued? */
57 struct smbd_server_connection *sconn;
b87ec64c 58 struct smbXsrv_connection *xconn;
ae1cb5ca 59 struct tevent_timer *te;
6d84b24d
SM
60 uint32_t seqnum;
61 bool encrypted;
62 bool processed;
63 DATA_BLOB buf;
0ead434b 64 struct deferred_open_record *open_rec;
6d84b24d
SM
65};
66
3b2c9beb 67static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
5a33e906 68
6f792afe 69void smbd_echo_init(struct smbXsrv_connection *xconn)
8de85546 70{
b0fe6c5c
SM
71 xconn->smb1.echo_handler.trusted_fd = -1;
72 xconn->smb1.echo_handler.socket_lock_fd = -1;
f01af728 73#ifdef HAVE_ROBUST_MUTEXES
b0fe6c5c 74 xconn->smb1.echo_handler.socket_mutex = NULL;
f01af728
CS
75#endif
76}
77
b0fe6c5c 78static bool smbd_echo_active(struct smbXsrv_connection *xconn)
f01af728 79{
b0fe6c5c 80 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
f01af728
CS
81 return true;
82 }
83
84#ifdef HAVE_ROBUST_MUTEXES
b0fe6c5c 85 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
f01af728
CS
86 return true;
87 }
88#endif
cad0c004 89
f01af728
CS
90 return false;
91}
92
6905bb6c 93static bool smbd_lock_socket_internal(struct smbXsrv_connection *xconn)
f01af728 94{
b0fe6c5c 95 if (!smbd_echo_active(xconn)) {
cad0c004
VL
96 return true;
97 }
98
b0fe6c5c 99 xconn->smb1.echo_handler.ref_count++;
6800fdbb 100
b0fe6c5c 101 if (xconn->smb1.echo_handler.ref_count > 1) {
6800fdbb
JA
102 return true;
103 }
104
c0288e06 105 DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
cad0c004 106
f01af728 107#ifdef HAVE_ROBUST_MUTEXES
b0fe6c5c 108 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
f01af728 109 int ret = EINTR;
da00021a 110
f01af728
CS
111 while (ret == EINTR) {
112 ret = pthread_mutex_lock(
b0fe6c5c 113 xconn->smb1.echo_handler.socket_mutex);
f01af728
CS
114 if (ret == 0) {
115 break;
116 }
117 }
118 if (ret != 0) {
119 DEBUG(1, ("pthread_mutex_lock failed: %s\n",
120 strerror(ret)));
121 return false;
122 }
123 }
124#endif
125
b0fe6c5c 126 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
f01af728
CS
127 bool ok;
128
129 do {
130 ok = fcntl_lock(
b0fe6c5c 131 xconn->smb1.echo_handler.socket_lock_fd,
f01af728
CS
132 F_SETLKW, 0, 0, F_WRLCK);
133 } while (!ok && (errno == EINTR));
134
135 if (!ok) {
136 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
137 return false;
138 }
cad0c004
VL
139 }
140
7b0b1d6d 141 DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
cad0c004 142
8de85546
SM
143 return true;
144}
145
bb8e6d45 146void smbd_lock_socket(struct smbXsrv_connection *xconn)
6800fdbb 147{
6905bb6c 148 if (!smbd_lock_socket_internal(xconn)) {
6800fdbb
JA
149 exit_server_cleanly("failed to lock socket");
150 }
151}
152
6905bb6c 153static bool smbd_unlock_socket_internal(struct smbXsrv_connection *xconn)
8de85546 154{
b0fe6c5c 155 if (!smbd_echo_active(xconn)) {
cad0c004
VL
156 return true;
157 }
158
b0fe6c5c 159 xconn->smb1.echo_handler.ref_count--;
6800fdbb 160
b0fe6c5c 161 if (xconn->smb1.echo_handler.ref_count > 0) {
6800fdbb
JA
162 return true;
163 }
164
f01af728 165#ifdef HAVE_ROBUST_MUTEXES
b0fe6c5c 166 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
d40891a1
VL
167 int ret;
168 ret = pthread_mutex_unlock(
169 xconn->smb1.echo_handler.socket_mutex);
f01af728
CS
170 if (ret != 0) {
171 DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
172 strerror(ret)));
173 return false;
174 }
175 }
176#endif
177
b0fe6c5c 178 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
f01af728
CS
179 bool ok;
180
181 do {
182 ok = fcntl_lock(
b0fe6c5c 183 xconn->smb1.echo_handler.socket_lock_fd,
f01af728
CS
184 F_SETLKW, 0, 0, F_UNLCK);
185 } while (!ok && (errno == EINTR));
186
187 if (!ok) {
188 DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
189 return false;
190 }
cad0c004
VL
191 }
192
c0288e06 193 DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
cad0c004 194
8de85546
SM
195 return true;
196}
197
bb8e6d45 198void smbd_unlock_socket(struct smbXsrv_connection *xconn)
6800fdbb 199{
6905bb6c 200 if (!smbd_unlock_socket_internal(xconn)) {
6800fdbb
JA
201 exit_server_cleanly("failed to unlock socket");
202 }
203}
204
36441da4
JA
205/* Accessor function for smb_read_error for smbd functions. */
206
9254bb4e
JA
207/****************************************************************************
208 Send an smb to a fd.
209****************************************************************************/
210
12f1d94a
VL
211bool smb1_srv_send(struct smbXsrv_connection *xconn,
212 char *buffer,
213 bool do_signing,
214 uint32_t seqnum,
215 bool do_encrypt)
9254bb4e 216{
54c51a66 217 size_t len = 0;
9254bb4e
JA
218 ssize_t ret;
219 char *buf_out = buffer;
977aa660 220
b05b4cab 221 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
52ccb40d
SM
222 /*
223 * we're not supposed to do any io
224 */
225 return true;
226 }
227
bb8e6d45 228 smbd_lock_socket(xconn);
9254bb4e 229
c16c90a1 230 if (do_signing) {
2772c92e
AS
231 NTSTATUS status;
232
c16c90a1 233 /* Sign the outgoing packet if required. */
fa9c48ae 234 status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
2772c92e
AS
235 if (!NT_STATUS_IS_OK(status)) {
236 DBG_ERR("Failed to calculate signing mac: %s\n",
237 nt_errstr(status));
238 return false;
239 }
c16c90a1 240 }
9254bb4e
JA
241
242 if (do_encrypt) {
68fb12cb 243 NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &buf_out);
9254bb4e
JA
244 if (!NT_STATUS_IS_OK(status)) {
245 DEBUG(0, ("send_smb: SMB encryption failed "
246 "on outgoing packet! Error %s\n",
247 nt_errstr(status) ));
cc983c9a 248 ret = -1;
54c51a66 249 goto out;
9254bb4e
JA
250 }
251 }
252
d5693d99 253 len = smb_len_large(buf_out) + 4;
9254bb4e 254
0ccffffe 255 ret = write_data(xconn->transport.sock, buf_out, len);
c344ad30 256 if (ret <= 0) {
2fd53228 257 int saved_errno = errno;
40ae8b74
VL
258 /*
259 * Try and give an error message saying what
260 * client failed.
261 */
51bc104c 262 DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
c0288e06 263 (int)getpid(), (int)len,
2fd53228
SM
264 smbXsrv_connection_dbg(xconn),
265 (int)ret, strerror(saved_errno)));
266 errno = saved_errno;
40ae8b74 267
245e3959 268 srv_free_enc_buffer(xconn, buf_out);
c344ad30 269 goto out;
9254bb4e
JA
270 }
271
245e3959 272 srv_free_enc_buffer(xconn, buf_out);
54c51a66 273out:
bb8e6d45 274 smbd_unlock_socket(xconn);
852c9ac3 275 return (ret > 0);
9254bb4e
JA
276}
277
695c4a7a
JA
278/* Socket functions for smbd packet processing. */
279
58fbb512 280static bool valid_packet_size(size_t len)
695c4a7a
JA
281{
282 /*
283 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
284 * of header. Don't print the error if this fits.... JRA.
285 */
286
032621d5 287 if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
695c4a7a
JA
288 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
289 (unsigned long)len));
d36434f3 290 return false;
695c4a7a
JA
291 }
292 return true;
293}
294
695c4a7a
JA
295/****************************************************************************
296 Attempt a zerocopy writeX read. We know here that len > smb_size-4
297****************************************************************************/
298
299/*
300 * Unfortunately, earlier versions of smbclient/libsmbclient
301 * don't send this "standard" writeX header. I've fixed this
302 * for 3.2 but we'll use the old method with earlier versions.
303 * Windows and CIFSFS at least use this standard size. Not
304 * sure about MacOSX.
305 */
306
307#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
308 (2*14) + /* word count (including bcc) */ \
309 1 /* pad byte */)
310
250b2b64
VL
311static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
312 const char lenbuf[4],
e3ab0a05 313 struct smbXsrv_connection *xconn,
8b5d163d 314 int sock,
fa0de395 315 char **buffer,
250b2b64
VL
316 unsigned int timeout,
317 size_t *p_unread,
318 size_t *len_ret)
695c4a7a
JA
319{
320 /* Size of a WRITEX call (+4 byte len). */
321 char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
322 ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
323 ssize_t toread;
250b2b64 324 NTSTATUS status;
695c4a7a 325
227718cd 326 memcpy(writeX_header, lenbuf, 4);
695c4a7a 327
43c766a1 328 status = read_fd_with_timeout(
8b5d163d 329 sock, writeX_header + 4,
250b2b64
VL
330 STANDARD_WRITE_AND_X_HEADER_SIZE,
331 STANDARD_WRITE_AND_X_HEADER_SIZE,
332 timeout, NULL);
695c4a7a 333
250b2b64 334 if (!NT_STATUS_IS_OK(status)) {
9671547d 335 DEBUG(0, ("read_fd_with_timeout failed for client %s read "
a513086c 336 "error = %s.\n",
93f7e625 337 smbXsrv_connection_dbg(xconn),
9671547d 338 nt_errstr(status)));
250b2b64 339 return status;
695c4a7a
JA
340 }
341
342 /*
343 * Ok - now try and see if this is a possible
344 * valid writeX call.
345 */
346
8c457da2 347 if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
695c4a7a
JA
348 /*
349 * If the data offset is beyond what
350 * we've read, drain the extra bytes.
351 */
352 uint16_t doff = SVAL(writeX_header,smb_vwv11);
353 ssize_t newlen;
354
355 if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
356 size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
8b5d163d 357 if (drain_socket(sock, drain) != drain) {
695c4a7a
JA
358 smb_panic("receive_smb_raw_talloc_partial_read:"
359 " failed to drain pending bytes");
360 }
361 } else {
362 doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
363 }
364
365 /* Spoof down the length and null out the bcc. */
366 set_message_bcc(writeX_header, 0);
367 newlen = smb_len(writeX_header);
368
369 /* Copy the header we've written. */
370
8d4a8389 371 *buffer = (char *)talloc_memdup(mem_ctx,
695c4a7a
JA
372 writeX_header,
373 sizeof(writeX_header));
374
375 if (*buffer == NULL) {
376 DEBUG(0, ("Could not allocate inbuf of length %d\n",
377 (int)sizeof(writeX_header)));
250b2b64 378 return NT_STATUS_NO_MEMORY;
695c4a7a
JA
379 }
380
381 /* Work out the remaining bytes. */
382 *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
250b2b64
VL
383 *len_ret = newlen + 4;
384 return NT_STATUS_OK;
695c4a7a
JA
385 }
386
387 if (!valid_packet_size(len)) {
250b2b64 388 return NT_STATUS_INVALID_PARAMETER;
695c4a7a
JA
389 }
390
391 /*
392 * Not a valid writeX call. Just do the standard
393 * talloc and return.
394 */
395
3d151376 396 *buffer = talloc_array(mem_ctx, char, len+4);
695c4a7a
JA
397
398 if (*buffer == NULL) {
399 DEBUG(0, ("Could not allocate inbuf of length %d\n",
400 (int)len+4));
250b2b64 401 return NT_STATUS_NO_MEMORY;
695c4a7a
JA
402 }
403
404 /* Copy in what we already read. */
405 memcpy(*buffer,
406 writeX_header,
407 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
408 toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
409
410 if(toread > 0) {
e604e137 411 status = read_packet_remainder(
8b5d163d 412 sock,
fa0de395 413 (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
e604e137
VL
414 timeout, toread);
415
416 if (!NT_STATUS_IS_OK(status)) {
8ca459e0
JA
417 DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
418 nt_errstr(status)));
250b2b64 419 return status;
695c4a7a
JA
420 }
421 }
422
250b2b64
VL
423 *len_ret = len + 4;
424 return NT_STATUS_OK;
695c4a7a
JA
425}
426
a2db154c 427static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
e3ab0a05 428 struct smbXsrv_connection *xconn,
8b5d163d 429 int sock,
9fe66ddd
VL
430 char **buffer, unsigned int timeout,
431 size_t *p_unread, size_t *plen)
695c4a7a
JA
432{
433 char lenbuf[4];
0afbfa42 434 size_t len;
695c4a7a 435 int min_recv_size = lp_min_receive_file_size();
0afbfa42 436 NTSTATUS status;
695c4a7a 437
695c4a7a
JA
438 *p_unread = 0;
439
8b5d163d 440 status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
a2db154c 441 &len);
0afbfa42 442 if (!NT_STATUS_IS_OK(status)) {
9fe66ddd 443 return status;
695c4a7a
JA
444 }
445
dea223ba
TP
446 if (CVAL(lenbuf,0) == 0 && min_recv_size &&
447 (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
448 (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
e0ad956c 449 !smb1_srv_is_signing_active(xconn) &&
b0fe6c5c 450 xconn->smb1.echo_handler.trusted_fde == NULL) {
695c4a7a 451
8ca459e0 452 return receive_smb_raw_talloc_partial_read(
e3ab0a05 453 mem_ctx, lenbuf, xconn, sock, buffer, timeout,
fa0de395 454 p_unread, plen);
695c4a7a
JA
455 }
456
457 if (!valid_packet_size(len)) {
9fe66ddd 458 return NT_STATUS_INVALID_PARAMETER;
695c4a7a
JA
459 }
460
461 /*
462 * The +4 here can't wrap, we've checked the length above already.
463 */
464
3d151376 465 *buffer = talloc_array(mem_ctx, char, len+4);
695c4a7a
JA
466
467 if (*buffer == NULL) {
468 DEBUG(0, ("Could not allocate inbuf of length %d\n",
469 (int)len+4));
9fe66ddd 470 return NT_STATUS_NO_MEMORY;
695c4a7a
JA
471 }
472
473 memcpy(*buffer, lenbuf, sizeof(lenbuf));
474
8b5d163d 475 status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
e604e137 476 if (!NT_STATUS_IS_OK(status)) {
9fe66ddd 477 return status;
695c4a7a
JA
478 }
479
9fe66ddd
VL
480 *plen = len + 4;
481 return NT_STATUS_OK;
695c4a7a
JA
482}
483
7e55512a
DM
484NTSTATUS smb1_receive_talloc(TALLOC_CTX *mem_ctx,
485 struct smbXsrv_connection *xconn,
486 int sock,
487 char **buffer, unsigned int timeout,
488 size_t *p_unread, bool *p_encrypted,
489 size_t *p_len,
490 uint32_t *seqnum,
491 bool trusted_channel)
695c4a7a 492{
47666c93 493 size_t len = 0;
9fe66ddd 494 NTSTATUS status;
695c4a7a 495
9254bb4e
JA
496 *p_encrypted = false;
497
e3ab0a05 498 status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
63e08ef8 499 p_unread, &len);
9fe66ddd 500 if (!NT_STATUS_IS_OK(status)) {
b99becd4
CA
501 DEBUG(NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)?5:1,
502 ("receive_smb_raw_talloc failed for client %s "
503 "read error = %s.\n",
9fe66659 504 smbXsrv_connection_dbg(xconn),
b99becd4 505 nt_errstr(status)) );
e514cd0a 506 return status;
695c4a7a
JA
507 }
508
07605559 509 if (is_encrypted_packet((uint8_t *)*buffer)) {
245e3959 510 status = srv_decrypt_buffer(xconn, *buffer);
afc93255
JA
511 if (!NT_STATUS_IS_OK(status)) {
512 DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
513 "incoming packet! Error %s\n",
514 nt_errstr(status) ));
e514cd0a 515 return status;
afc93255 516 }
9254bb4e 517 *p_encrypted = true;
afc93255
JA
518 }
519
695c4a7a 520 /* Check the incoming SMB signature. */
777fbb37 521 if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
695c4a7a
JA
522 DEBUG(0, ("receive_smb: SMB Signature verification failed on "
523 "incoming packet!\n"));
e514cd0a 524 return NT_STATUS_INVALID_NETWORK_RESPONSE;
695c4a7a
JA
525 }
526
e514cd0a
VL
527 *p_len = len;
528 return NT_STATUS_OK;
695c4a7a
JA
529}
530
aab2fe02 531/****************************************************************************
e5a95132
GJC
532 Function to push a message onto the tail of a linked list of smb messages ready
533 for processing.
aab2fe02
JA
534****************************************************************************/
535
30191d1a 536static bool push_queued_message(struct smb_request *req,
54abd2aa
GC
537 struct timeval request_time,
538 struct timeval end_time,
0ead434b 539 struct deferred_open_record *open_rec)
aab2fe02 540{
b578db69 541 int msg_len = smb_len(req->inbuf) + 4;
54abd2aa
GC
542 struct pending_message_list *msg;
543
ad0a07c5 544 msg = talloc_zero(NULL, struct pending_message_list);
aab2fe02 545
1eff0523
JA
546 if(msg == NULL) {
547 DEBUG(0,("push_message: malloc fail (1)\n"));
548 return False;
549 }
8b2b7d1c 550 msg->sconn = req->sconn;
b87ec64c 551 msg->xconn = req->xconn;
aab2fe02 552
b578db69 553 msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
2fc57c9a 554 if(msg->buf.data == NULL) {
1eff0523 555 DEBUG(0,("push_message: malloc fail (2)\n"));
fb5362c0 556 TALLOC_FREE(msg);
1eff0523
JA
557 return False;
558 }
aab2fe02 559
54abd2aa 560 msg->request_time = request_time;
c16c90a1 561 msg->seqnum = req->seqnum;
9254bb4e 562 msg->encrypted = req->encrypted;
8a6b90d4 563 msg->processed = false;
2fc57c9a 564
0ead434b
VL
565 if (open_rec) {
566 msg->open_rec = talloc_move(msg, &open_rec);
2fc57c9a 567 }
aab2fe02 568
4e437616 569#if 0
16cfc724
SM
570 msg->te = tevent_add_timer(msg->sconn->ev_ctx,
571 msg,
572 end_time,
573 smbd_deferred_open_timer,
574 msg);
aeb798c3
SM
575 if (!msg->te) {
576 DEBUG(0,("push_message: event_add_timed failed\n"));
577 TALLOC_FREE(msg);
578 return false;
579 }
4e437616 580#endif
aeb798c3 581
476672b6 582 DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
aab2fe02 583
54abd2aa
GC
584 DEBUG(10,("push_message: pushed message length %u on "
585 "deferred_open_queue\n", (unsigned int)msg_len));
2fc57c9a 586
1eff0523 587 return True;
aab2fe02
JA
588}
589
2fc57c9a 590/****************************************************************************
54abd2aa
GC
591 Function to push a deferred open smb message onto a linked list of local smb
592 messages ready for processing.
593****************************************************************************/
594
5582077b
DM
595bool push_deferred_open_message_smb1(struct smb_request *req,
596 struct timeval timeout,
597 struct file_id id,
598 struct deferred_open_record *open_rec)
54abd2aa 599{
303c4829 600 struct timeval_buf tvbuf;
54abd2aa
GC
601 struct timeval end_time;
602
c3250149 603 if (req->unread_bytes) {
e15939b4 604 DEBUG(0,("push_deferred_open_message_smb: logic error ! "
c3250149
JA
605 "unread_bytes = %u\n",
606 (unsigned int)req->unread_bytes ));
e15939b4 607 smb_panic("push_deferred_open_message_smb: "
c3250149
JA
608 "logic error unread_bytes != 0" );
609 }
610
bb81b9a7 611 end_time = timeval_sum(&req->request_time, &timeout);
54abd2aa 612
303c4829
VL
613 DBG_DEBUG("pushing message len %u mid %"PRIu64" timeout time [%s]\n",
614 (unsigned int) smb_len(req->inbuf)+4,
615 req->mid,
616 timeval_str_buf(&end_time, false, true, &tvbuf));
54abd2aa 617
bb81b9a7 618 return push_queued_message(req, req->request_time, end_time, open_rec);
54abd2aa
GC
619}
620
22dbd677
JA
621/*
622 * Only allow 5 outstanding trans requests. We're allocating memory, so
623 * prevent a DoS.
624 */
aab2fe02 625
79842437 626NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
c3effa8b 627{
22dbd677
JA
628 int count = 0;
629 for (; list != NULL; list = list->next) {
c3effa8b 630
22dbd677
JA
631 if (list->mid == mid) {
632 return NT_STATUS_INVALID_PARAMETER;
633 }
634
635 count += 1;
636 }
637 if (count > 5) {
638 return NT_STATUS_INSUFFICIENT_RESOURCES;
639 }
c3effa8b 640
22dbd677 641 return NT_STATUS_OK;
c3effa8b
AT
642}
643
c3effa8b
AT
644/*
645These flags determine some of the permissions required to do an operation
646
647Note that I don't set NEED_WRITE on some write operations because they
648are used by some brain-dead clients when printing, and I don't want to
649force write permissions on print services.
650*/
651#define AS_USER (1<<0)
ce61fb21 652#define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
c3effa8b 653#define TIME_INIT (1<<2)
ce61fb21
JA
654#define CAN_IPC (1<<3) /* Must be paired with AS_USER */
655#define AS_GUEST (1<<5) /* Must *NOT* be paired with AS_USER */
54abd2aa 656#define DO_CHDIR (1<<6)
c3effa8b
AT
657
658/*
659 define a list of possible SMB messages and their corresponding
660 functions. Any message that has a NULL function is unimplemented -
661 please feel free to contribute implementations!
662*/
1eff0523
JA
663static const struct smb_message_struct {
664 const char *name;
48d3a1d2 665 void (*fn)(struct smb_request *req);
1eff0523
JA
666 int flags;
667} smb_messages[256] = {
918c3ebe 668
b578db69
VL
669/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
670/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
671/* 0x02 */ { "SMBopen",reply_open,AS_USER },
672/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
673/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
674/* 0x05 */ { "SMBflush",reply_flush,AS_USER},
675/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE },
676/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
677/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
678/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
679/* 0x0a */ { "SMBread",reply_read,AS_USER},
680/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
681/* 0x0c */ { "SMBlock",reply_lock,AS_USER},
682/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
683/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
684/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER},
685/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER},
686/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
687/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER},
688/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER},
689/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER},
690/* 0x15 */ { NULL, NULL, 0 },
691/* 0x16 */ { NULL, NULL, 0 },
692/* 0x17 */ { NULL, NULL, 0 },
693/* 0x18 */ { NULL, NULL, 0 },
694/* 0x19 */ { NULL, NULL, 0 },
695/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER},
696/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER},
697/* 0x1c */ { "SMBreadBs",reply_readbs,AS_USER },
698/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER},
699/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER},
700/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER},
701/* 0x20 */ { "SMBwritec", NULL,0},
702/* 0x21 */ { NULL, NULL, 0 },
703/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE },
704/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER },
705/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER },
706/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC },
707/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC},
708/* 0x27 */ { "SMBioctl",reply_ioctl,0},
709/* 0x28 */ { "SMBioctls", NULL,AS_USER},
710/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
711/* 0x2a */ { "SMBmove", NULL,AS_USER | NEED_WRITE },
712/* 0x2b */ { "SMBecho",reply_echo,0},
713/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
714/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
715/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
716/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
717/* 0x30 */ { NULL, NULL, 0 },
718/* 0x31 */ { NULL, NULL, 0 },
719/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
7716ad68 720/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
b578db69
VL
721/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
722/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
723/* 0x36 */ { NULL, NULL, 0 },
724/* 0x37 */ { NULL, NULL, 0 },
725/* 0x38 */ { NULL, NULL, 0 },
726/* 0x39 */ { NULL, NULL, 0 },
727/* 0x3a */ { NULL, NULL, 0 },
728/* 0x3b */ { NULL, NULL, 0 },
729/* 0x3c */ { NULL, NULL, 0 },
730/* 0x3d */ { NULL, NULL, 0 },
731/* 0x3e */ { NULL, NULL, 0 },
732/* 0x3f */ { NULL, NULL, 0 },
733/* 0x40 */ { NULL, NULL, 0 },
734/* 0x41 */ { NULL, NULL, 0 },
735/* 0x42 */ { NULL, NULL, 0 },
736/* 0x43 */ { NULL, NULL, 0 },
737/* 0x44 */ { NULL, NULL, 0 },
738/* 0x45 */ { NULL, NULL, 0 },
739/* 0x46 */ { NULL, NULL, 0 },
740/* 0x47 */ { NULL, NULL, 0 },
741/* 0x48 */ { NULL, NULL, 0 },
742/* 0x49 */ { NULL, NULL, 0 },
743/* 0x4a */ { NULL, NULL, 0 },
744/* 0x4b */ { NULL, NULL, 0 },
745/* 0x4c */ { NULL, NULL, 0 },
746/* 0x4d */ { NULL, NULL, 0 },
747/* 0x4e */ { NULL, NULL, 0 },
748/* 0x4f */ { NULL, NULL, 0 },
749/* 0x50 */ { NULL, NULL, 0 },
750/* 0x51 */ { NULL, NULL, 0 },
751/* 0x52 */ { NULL, NULL, 0 },
752/* 0x53 */ { NULL, NULL, 0 },
753/* 0x54 */ { NULL, NULL, 0 },
754/* 0x55 */ { NULL, NULL, 0 },
755/* 0x56 */ { NULL, NULL, 0 },
756/* 0x57 */ { NULL, NULL, 0 },
757/* 0x58 */ { NULL, NULL, 0 },
758/* 0x59 */ { NULL, NULL, 0 },
759/* 0x5a */ { NULL, NULL, 0 },
760/* 0x5b */ { NULL, NULL, 0 },
761/* 0x5c */ { NULL, NULL, 0 },
762/* 0x5d */ { NULL, NULL, 0 },
763/* 0x5e */ { NULL, NULL, 0 },
764/* 0x5f */ { NULL, NULL, 0 },
765/* 0x60 */ { NULL, NULL, 0 },
766/* 0x61 */ { NULL, NULL, 0 },
767/* 0x62 */ { NULL, NULL, 0 },
768/* 0x63 */ { NULL, NULL, 0 },
769/* 0x64 */ { NULL, NULL, 0 },
770/* 0x65 */ { NULL, NULL, 0 },
771/* 0x66 */ { NULL, NULL, 0 },
772/* 0x67 */ { NULL, NULL, 0 },
773/* 0x68 */ { NULL, NULL, 0 },
774/* 0x69 */ { NULL, NULL, 0 },
775/* 0x6a */ { NULL, NULL, 0 },
776/* 0x6b */ { NULL, NULL, 0 },
777/* 0x6c */ { NULL, NULL, 0 },
778/* 0x6d */ { NULL, NULL, 0 },
779/* 0x6e */ { NULL, NULL, 0 },
780/* 0x6f */ { NULL, NULL, 0 },
781/* 0x70 */ { "SMBtcon",reply_tcon,0},
782/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR},
783/* 0x72 */ { "SMBnegprot",reply_negprot,0},
784/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0},
785/* 0x74 */ { "SMBulogoffX",reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */
786/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0},
787/* 0x76 */ { NULL, NULL, 0 },
788/* 0x77 */ { NULL, NULL, 0 },
789/* 0x78 */ { NULL, NULL, 0 },
790/* 0x79 */ { NULL, NULL, 0 },
791/* 0x7a */ { NULL, NULL, 0 },
792/* 0x7b */ { NULL, NULL, 0 },
793/* 0x7c */ { NULL, NULL, 0 },
794/* 0x7d */ { NULL, NULL, 0 },
795/* 0x7e */ { NULL, NULL, 0 },
796/* 0x7f */ { NULL, NULL, 0 },
797/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER},
798/* 0x81 */ { "SMBsearch",reply_search,AS_USER},
799/* 0x82 */ { "SMBffirst",reply_search,AS_USER},
800/* 0x83 */ { "SMBfunique",reply_search,AS_USER},
801/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER},
802/* 0x85 */ { NULL, NULL, 0 },
803/* 0x86 */ { NULL, NULL, 0 },
804/* 0x87 */ { NULL, NULL, 0 },
805/* 0x88 */ { NULL, NULL, 0 },
806/* 0x89 */ { NULL, NULL, 0 },
807/* 0x8a */ { NULL, NULL, 0 },
808/* 0x8b */ { NULL, NULL, 0 },
809/* 0x8c */ { NULL, NULL, 0 },
810/* 0x8d */ { NULL, NULL, 0 },
811/* 0x8e */ { NULL, NULL, 0 },
812/* 0x8f */ { NULL, NULL, 0 },
813/* 0x90 */ { NULL, NULL, 0 },
814/* 0x91 */ { NULL, NULL, 0 },
815/* 0x92 */ { NULL, NULL, 0 },
816/* 0x93 */ { NULL, NULL, 0 },
817/* 0x94 */ { NULL, NULL, 0 },
818/* 0x95 */ { NULL, NULL, 0 },
819/* 0x96 */ { NULL, NULL, 0 },
820/* 0x97 */ { NULL, NULL, 0 },
821/* 0x98 */ { NULL, NULL, 0 },
822/* 0x99 */ { NULL, NULL, 0 },
823/* 0x9a */ { NULL, NULL, 0 },
824/* 0x9b */ { NULL, NULL, 0 },
825/* 0x9c */ { NULL, NULL, 0 },
826/* 0x9d */ { NULL, NULL, 0 },
827/* 0x9e */ { NULL, NULL, 0 },
828/* 0x9f */ { NULL, NULL, 0 },
829/* 0xa0 */ { "SMBnttrans",reply_nttrans, AS_USER | CAN_IPC },
830/* 0xa1 */ { "SMBnttranss",reply_nttranss, AS_USER | CAN_IPC },
831/* 0xa2 */ { "SMBntcreateX",reply_ntcreate_and_X, AS_USER | CAN_IPC },
832/* 0xa3 */ { NULL, NULL, 0 },
833/* 0xa4 */ { "SMBntcancel",reply_ntcancel, 0 },
834/* 0xa5 */ { "SMBntrename",reply_ntrename, AS_USER | NEED_WRITE },
835/* 0xa6 */ { NULL, NULL, 0 },
836/* 0xa7 */ { NULL, NULL, 0 },
837/* 0xa8 */ { NULL, NULL, 0 },
838/* 0xa9 */ { NULL, NULL, 0 },
839/* 0xaa */ { NULL, NULL, 0 },
840/* 0xab */ { NULL, NULL, 0 },
841/* 0xac */ { NULL, NULL, 0 },
842/* 0xad */ { NULL, NULL, 0 },
843/* 0xae */ { NULL, NULL, 0 },
844/* 0xaf */ { NULL, NULL, 0 },
845/* 0xb0 */ { NULL, NULL, 0 },
846/* 0xb1 */ { NULL, NULL, 0 },
847/* 0xb2 */ { NULL, NULL, 0 },
848/* 0xb3 */ { NULL, NULL, 0 },
849/* 0xb4 */ { NULL, NULL, 0 },
850/* 0xb5 */ { NULL, NULL, 0 },
851/* 0xb6 */ { NULL, NULL, 0 },
852/* 0xb7 */ { NULL, NULL, 0 },
853/* 0xb8 */ { NULL, NULL, 0 },
854/* 0xb9 */ { NULL, NULL, 0 },
855/* 0xba */ { NULL, NULL, 0 },
856/* 0xbb */ { NULL, NULL, 0 },
857/* 0xbc */ { NULL, NULL, 0 },
858/* 0xbd */ { NULL, NULL, 0 },
859/* 0xbe */ { NULL, NULL, 0 },
860/* 0xbf */ { NULL, NULL, 0 },
861/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
862/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
863/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
864/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
865/* 0xc4 */ { NULL, NULL, 0 },
866/* 0xc5 */ { NULL, NULL, 0 },
867/* 0xc6 */ { NULL, NULL, 0 },
868/* 0xc7 */ { NULL, NULL, 0 },
869/* 0xc8 */ { NULL, NULL, 0 },
870/* 0xc9 */ { NULL, NULL, 0 },
871/* 0xca */ { NULL, NULL, 0 },
872/* 0xcb */ { NULL, NULL, 0 },
873/* 0xcc */ { NULL, NULL, 0 },
874/* 0xcd */ { NULL, NULL, 0 },
875/* 0xce */ { NULL, NULL, 0 },
876/* 0xcf */ { NULL, NULL, 0 },
877/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST},
878/* 0xd1 */ { "SMBsendb", NULL,AS_GUEST},
879/* 0xd2 */ { "SMBfwdname", NULL,AS_GUEST},
880/* 0xd3 */ { "SMBcancelf", NULL,AS_GUEST},
881/* 0xd4 */ { "SMBgetmac", NULL,AS_GUEST},
882/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST},
883/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST},
884/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST},
885/* 0xd8 */ { NULL, NULL, 0 },
886/* 0xd9 */ { NULL, NULL, 0 },
887/* 0xda */ { NULL, NULL, 0 },
888/* 0xdb */ { NULL, NULL, 0 },
889/* 0xdc */ { NULL, NULL, 0 },
890/* 0xdd */ { NULL, NULL, 0 },
891/* 0xde */ { NULL, NULL, 0 },
892/* 0xdf */ { NULL, NULL, 0 },
893/* 0xe0 */ { NULL, NULL, 0 },
894/* 0xe1 */ { NULL, NULL, 0 },
895/* 0xe2 */ { NULL, NULL, 0 },
896/* 0xe3 */ { NULL, NULL, 0 },
897/* 0xe4 */ { NULL, NULL, 0 },
898/* 0xe5 */ { NULL, NULL, 0 },
899/* 0xe6 */ { NULL, NULL, 0 },
900/* 0xe7 */ { NULL, NULL, 0 },
901/* 0xe8 */ { NULL, NULL, 0 },
902/* 0xe9 */ { NULL, NULL, 0 },
903/* 0xea */ { NULL, NULL, 0 },
904/* 0xeb */ { NULL, NULL, 0 },
905/* 0xec */ { NULL, NULL, 0 },
906/* 0xed */ { NULL, NULL, 0 },
907/* 0xee */ { NULL, NULL, 0 },
908/* 0xef */ { NULL, NULL, 0 },
909/* 0xf0 */ { NULL, NULL, 0 },
910/* 0xf1 */ { NULL, NULL, 0 },
911/* 0xf2 */ { NULL, NULL, 0 },
912/* 0xf3 */ { NULL, NULL, 0 },
913/* 0xf4 */ { NULL, NULL, 0 },
914/* 0xf5 */ { NULL, NULL, 0 },
915/* 0xf6 */ { NULL, NULL, 0 },
916/* 0xf7 */ { NULL, NULL, 0 },
917/* 0xf8 */ { NULL, NULL, 0 },
918/* 0xf9 */ { NULL, NULL, 0 },
919/* 0xfa */ { NULL, NULL, 0 },
920/* 0xfb */ { NULL, NULL, 0 },
921/* 0xfc */ { NULL, NULL, 0 },
922/* 0xfd */ { NULL, NULL, 0 },
923/* 0xfe */ { NULL, NULL, 0 },
924/* 0xff */ { NULL, NULL, 0 }
918c3ebe
JA
925
926};
c3effa8b 927
cc6a4101 928
712a30ed 929/*******************************************************************
a834a73e
GC
930 Dump a packet to a file.
931********************************************************************/
932
c99d2455 933static void smb_dump(const char *name, int type, const char *data)
712a30ed 934{
c99d2455 935 size_t len;
712a30ed 936 int fd, i;
d068bc64
JA
937 char *fname = NULL;
938 if (DEBUGLEVEL < 50) {
939 return;
940 }
712a30ed 941
c99d2455 942 len = smb_len_tcp(data)+4;
712a30ed 943 for (i=1;i<100;i++) {
86a80cf4
JA
944 fname = talloc_asprintf(talloc_tos(),
945 "/tmp/%s.%d.%s",
946 name,
947 i,
948 type ? "req" : "resp");
949 if (fname == NULL) {
d068bc64
JA
950 return;
951 }
712a30ed
LL
952 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
953 if (fd != -1 || errno != EEXIST) break;
86a80cf4 954 TALLOC_FREE(fname);
712a30ed
LL
955 }
956 if (fd != -1) {
e400bfce
JA
957 ssize_t ret = write(fd, data, len);
958 if (ret != len)
959 DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
712a30ed 960 close(fd);
9c8d23e5 961 DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
712a30ed 962 }
86a80cf4 963 TALLOC_FREE(fname);
712a30ed
LL
964}
965
b74bef8f
RB
966static void smb1srv_update_crypto_flags(struct smbXsrv_session *session,
967 struct smb_request *req,
968 uint8_t type,
969 bool *update_session_globalp,
970 bool *update_tcon_globalp)
971{
972 connection_struct *conn = req->conn;
973 struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
974 uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
975 uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
976 bool update_session = false;
977 bool update_tcon = false;
978
979 if (req->encrypted) {
980 encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
981 }
982
e0ad956c 983 if (smb1_srv_is_signing_active(req->xconn)) {
b74bef8f
RB
984 sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
985 } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
986 /*
7077ae40 987 * echo can be unsigned. Session setup except final
b74bef8f
RB
988 * session setup response too
989 */
990 sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
991 }
992
993 update_session |= smbXsrv_set_crypto_flag(
994 &session->global->encryption_flags, encrypt_flag);
995 update_session |= smbXsrv_set_crypto_flag(
996 &session->global->signing_flags, sign_flag);
997
998 if (tcon) {
999 update_tcon |= smbXsrv_set_crypto_flag(
1000 &tcon->global->encryption_flags, encrypt_flag);
1001 update_tcon |= smbXsrv_set_crypto_flag(
1002 &tcon->global->signing_flags, sign_flag);
1003 }
1004
1005 if (update_session) {
1006 session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1007 }
1008
1009 *update_session_globalp = update_session;
1010 *update_tcon_globalp = update_tcon;
1011 return;
1012}
1013
49fdf8f9
VL
1014static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1015{
1016 int snum;
1017 enum remote_arch_types ra_type;
1018
1019 SMB_ASSERT(conn != NULL);
80cd127b 1020 SMB_ASSERT(!conn_using_smb2(conn->sconn));
49fdf8f9
VL
1021
1022 snum = SNUM(conn);
1023
49fdf8f9
VL
1024 /*
1025 * Obey the client case sensitivity requests - only for clients that
1026 * support it. */
1027 switch (lp_case_sensitive(snum)) {
1028 case Auto:
1029 /*
7077ae40 1030 * We need this ugliness due to DOS/Win9x clients that lie
49fdf8f9
VL
1031 * about case insensitivity. */
1032 ra_type = get_remote_arch();
d4848111 1033 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49fdf8f9
VL
1034 /*
1035 * Client can't support per-packet case sensitive
1036 * pathnames. */
1037 conn->case_sensitive = false;
1038 } else {
1039 conn->case_sensitive =
1040 !(flags & FLAG_CASELESS_PATHNAMES);
1041 }
1042 break;
1043 case True:
1044 conn->case_sensitive = true;
1045 break;
1046 default:
1047 conn->case_sensitive = false;
1048 break;
1049 }
49fdf8f9
VL
1050}
1051
c3effa8b 1052/****************************************************************************
cc6a4101
VL
1053 Prepare everything for calling the actual request function, and potentially
1054 call the request function via the "new" interface.
1055
1056 Return False if the "legacy" function needs to be called, everything is
1057 prepared.
1058
1059 Return True if we're done.
1060
1061 I know this API sucks, but it is the one with the least code change I could
1062 find.
c3effa8b 1063****************************************************************************/
a834a73e 1064
6abd9867 1065static connection_struct *switch_message(uint8_t type, struct smb_request *req)
c3effa8b 1066{
b5c6964a
RB
1067 const struct loadparm_substitution *lp_sub =
1068 loadparm_s3_global_substitution();
941db29a 1069 int flags;
02d9ba6e 1070 uint64_t session_tag;
9254bb4e 1071 connection_struct *conn = NULL;
4c9c53f5 1072 struct smbXsrv_connection *xconn = req->xconn;
e7700025
SM
1073 NTTIME now = timeval_to_nttime(&req->request_time);
1074 struct smbXsrv_session *session = NULL;
1075 NTSTATUS status;
24f8e973 1076
a834a73e 1077 errno = 0;
0557c6cb 1078
dec0243c
SM
1079 if (!xconn->smb1.negprot.done) {
1080 switch (type) {
1081 /*
1082 * Without a negprot the request must
1083 * either be a negprot, or one of the
1084 * evil old SMB mailslot messaging types.
1085 */
1086 case SMBnegprot:
1087 case SMBsendstrt:
1088 case SMBsendend:
1089 case SMBsendtxt:
1090 break;
1091 default:
1092 exit_server_cleanly("The first request "
1093 "should be a negprot");
1094 }
1095 }
1096
48d3a1d2 1097 if (smb_messages[type].fn == NULL) {
a834a73e 1098 DEBUG(0,("Unknown message type %d!\n",type));
c99d2455 1099 smb_dump("Unknown", 1, (const char *)req->inbuf);
cc6a4101 1100 reply_unknown_new(req, type);
9254bb4e 1101 return NULL;
941db29a 1102 }
a834a73e 1103
941db29a 1104 flags = smb_messages[type].flags;
a834a73e 1105
941db29a 1106 /* In share mode security we must ignore the vuid. */
d7bb9618 1107 session_tag = req->vuid;
9254bb4e 1108 conn = req->conn;
918c3ebe 1109
8579dd4d 1110 DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
c0288e06 1111 (int)getpid(), (unsigned long)conn));
941db29a 1112
c99d2455 1113 smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
918c3ebe 1114
941db29a 1115 /* Ensure this value is replaced in the incoming packet. */
4f41be35 1116 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
918c3ebe 1117
941db29a
VL
1118 /*
1119 * Ensure the correct username is in current_user_info. This is a
1120 * really ugly bugfix for problems with multiple session_setup_and_X's
1121 * being done and allowing %U and %G substitutions to work correctly.
1122 * There is a reason this code is done here, don't move it unless you
8579dd4d
VL
1123 * know what you're doing... :-).
1124 * JRA.
941db29a
VL
1125 */
1126
e7700025
SM
1127 /*
1128 * lookup an existing session
1129 *
1130 * Note: for now we only check for NT_STATUS_NETWORK_SESSION_EXPIRED
1131 * here, the main check is still in change_to_user()
1132 */
4c9c53f5 1133 status = smb1srv_session_lookup(xconn,
e7700025
SM
1134 session_tag,
1135 now,
1136 &session);
1137 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1138 switch (type) {
1139 case SMBsesssetupX:
1140 status = NT_STATUS_OK;
1141 break;
1142 default:
1143 DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1144 (unsigned long long)session_tag,
1145 (unsigned long long)req->mid));
1146 reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1147 return conn;
1148 }
1149 }
1150
a22b5038
RB
1151 if (session != NULL &&
1152 session->global->auth_session_info != NULL &&
1153 !(flags & AS_USER))
1154 {
60dbaa49
SM
1155 /*
1156 * change_to_user() implies set_current_user_info()
1157 * and chdir_connect_service().
1158 *
1159 * So we only call set_current_user_info if
1160 * we don't have AS_USER specified.
1161 */
a22b5038
RB
1162 set_current_user_info(
1163 session->global->auth_session_info->unix_info->sanitized_username,
1164 session->global->auth_session_info->unix_info->unix_name,
1165 session->global->auth_session_info->info->domain_name);
941db29a 1166 }
d57e67f9 1167
941db29a
VL
1168 /* Does this call need to be run as the connected user? */
1169 if (flags & AS_USER) {
fcda2645 1170
941db29a
VL
1171 /* Does this call need a valid tree connection? */
1172 if (!conn) {
8579dd4d
VL
1173 /*
1174 * Amazingly, the error code depends on the command
1175 * (from Samba4).
1176 */
941db29a 1177 if (type == SMBntcreateX) {
cc6a4101 1178 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
941db29a 1179 } else {
642101ac 1180 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
ce61fb21 1181 }
9254bb4e 1182 return NULL;
941db29a 1183 }
d57e67f9 1184
ffe1918e
SM
1185 set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1186
60dbaa49
SM
1187 /*
1188 * change_to_user() implies set_current_user_info()
1189 * and chdir_connect_service().
1190 */
d836f4a7 1191 if (!change_to_user_and_service(conn,session_tag)) {
5e9aade5 1192 DEBUG(0, ("Error: Could not change to user. Removing "
79842437
JA
1193 "deferred open, mid=%llu.\n",
1194 (unsigned long long)req->mid));
74deee3c 1195 reply_force_doserror(req, ERRSRV, ERRbaduid);
9254bb4e 1196 return conn;
941db29a 1197 }
c3effa8b 1198
941db29a 1199 /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
918c3ebe 1200
941db29a
VL
1201 /* Does it need write permission? */
1202 if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
cc6a4101 1203 reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
9254bb4e 1204 return conn;
ce61fb21 1205 }
918c3ebe 1206
941db29a
VL
1207 /* IPC services are limited */
1208 if (IS_IPC(conn) && !(flags & CAN_IPC)) {
642101ac 1209 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9254bb4e 1210 return conn;
f60ad8de 1211 }
5ef67759
SM
1212 } else if (flags & AS_GUEST) {
1213 /*
1214 * Does this protocol need to be run as guest? (Only archane
1215 * messenger service requests have this...)
1216 */
1217 if (!change_to_guest()) {
1218 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1219 return conn;
1220 }
941db29a
VL
1221 } else {
1222 /* This call needs to be run as root */
1223 change_to_root_user();
1224 }
918c3ebe 1225
941db29a
VL
1226 /* load service specific parameters */
1227 if (conn) {
9254bb4e
JA
1228 if (req->encrypted) {
1229 conn->encrypted_tid = true;
1230 /* encrypted required from now on. */
e5d4e8df 1231 conn->encrypt_level = SMB_SIGNING_REQUIRED;
9254bb4e 1232 } else if (ENCRYPTION_REQUIRED(conn)) {
7808a259 1233 if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
9f1dfd8f
SM
1234 DEBUG(1,("service[%s] requires encryption"
1235 "%s ACCESS_DENIED. mid=%llu\n",
b5c6964a 1236 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
9f1dfd8f
SM
1237 smb_fn_name(type),
1238 (unsigned long long)req->mid));
1239 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9254bb4e
JA
1240 return conn;
1241 }
1242 }
1243
4a97448c
SM
1244 if (flags & DO_CHDIR) {
1245 bool ok;
1246
1247 ok = chdir_current_service(conn);
1248 if (!ok) {
1249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1250 return conn;
1251 }
afce2b24 1252 }
941db29a
VL
1253 conn->num_smb_operations++;
1254 }
918c3ebe 1255
b74bef8f
RB
1256 /*
1257 * Update encryption and signing state tracking flags that are
1258 * used by smbstatus to display signing and encryption status.
1259 */
1260 if (session != NULL) {
1261 bool update_session_global = false;
1262 bool update_tcon_global = false;
1263
aa27bcef
RB
1264 req->session = session;
1265
b74bef8f
RB
1266 smb1srv_update_crypto_flags(session, req, type,
1267 &update_session_global,
1268 &update_tcon_global);
1269
1270 if (update_session_global) {
1271 status = smbXsrv_session_update(session);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1274 return conn;
1275 }
1276 }
1277
1278 if (update_tcon_global) {
1279 status = smbXsrv_tcon_update(req->conn->tcon);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1282 return conn;
1283 }
1284 }
1285 }
1286
48d3a1d2 1287 smb_messages[type].fn(req);
9254bb4e 1288 return req->conn;
e9ea36e4
AT
1289}
1290
e9ea36e4 1291/****************************************************************************
a834a73e 1292 Construct a reply to the incoming packet.
e9ea36e4 1293****************************************************************************/
a834a73e 1294
6f792afe 1295void construct_reply(struct smbXsrv_connection *xconn,
15503566
VL
1296 char *inbuf,
1297 int size,
1298 size_t unread_bytes,
1299 uint32_t seqnum,
1300 bool encrypted)
e9ea36e4 1301{
d83ecf5b 1302 struct smbd_server_connection *sconn = xconn->client->sconn;
cc6a4101 1303 struct smb_request *req;
e9ea36e4 1304
929e1d99 1305 if (!(req = talloc(talloc_tos(), struct smb_request))) {
cc6a4101
VL
1306 smb_panic("could not allocate smb_request");
1307 }
54c51a66 1308
0de91444 1309 if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
c2533f94 1310 encrypted, seqnum)) {
b7898148
VL
1311 exit_server_cleanly("Invalid SMB request");
1312 }
1313
b8125663 1314 req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
e9ea36e4 1315
95bd7928 1316 req->conn = switch_message(req->cmd, req);
e9ea36e4 1317
b578db69 1318 if (req->outbuf == NULL) {
95bd7928
SM
1319 /*
1320 * Request has suspended itself, will come
1321 * back here.
1322 */
b578db69 1323 return;
cc6a4101 1324 }
b578db69
VL
1325 if (CVAL(req->outbuf,0) == 0) {
1326 show_msg((char *)req->outbuf);
1327 }
95bd7928 1328 smb_request_done(req);
e9ea36e4
AT
1329}
1330
7408736d 1331static void construct_reply_chain(struct smbXsrv_connection *xconn,
625056af
VL
1332 char *inbuf,
1333 int size,
1334 uint32_t seqnum,
1335 bool encrypted)
3b2c9beb 1336{
3b2c9beb 1337 struct smb_request **reqs = NULL;
8f93068c
VL
1338 struct smb_request *req;
1339 unsigned num_reqs;
3b2c9beb
VL
1340 bool ok;
1341
5fe76a54 1342 ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
3b2c9beb
VL
1343 seqnum, &reqs, &num_reqs);
1344 if (!ok) {
8f93068c
VL
1345 char errbuf[smb_size];
1346 error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1347 __LINE__, __FILE__);
12f1d94a 1348 if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted)) {
8f93068c 1349 exit_server_cleanly("construct_reply_chain: "
a48bf243 1350 "smb1_srv_send failed.");
8f93068c
VL
1351 }
1352 return;
3b2c9beb
VL
1353 }
1354
8f93068c
VL
1355 req = reqs[0];
1356 req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
3b2c9beb 1357
8f93068c 1358 req->conn = switch_message(req->cmd, req);
3b2c9beb 1359
8f93068c
VL
1360 if (req->outbuf == NULL) {
1361 /*
1362 * Request has suspended itself, will come
1363 * back here.
1364 */
1365 return;
1366 }
1367 smb_request_done(req);
1368}
3b2c9beb 1369
8f93068c
VL
1370/*
1371 * To be called from an async SMB handler that is potentially chained
1372 * when it is finished for shipping.
1373 */
1374
1375void smb_request_done(struct smb_request *req)
1376{
1377 struct smb_request **reqs = NULL;
1378 struct smb_request *first_req;
1379 size_t i, num_reqs, next_index;
1380 NTSTATUS status;
1381
1382 if (req->chain == NULL) {
1383 first_req = req;
1384 goto shipit;
3b2c9beb
VL
1385 }
1386
8f93068c
VL
1387 reqs = req->chain;
1388 num_reqs = talloc_array_length(reqs);
3b2c9beb 1389
8f93068c
VL
1390 for (i=0; i<num_reqs; i++) {
1391 if (reqs[i] == req) {
1392 break;
1393 }
1394 }
1395 if (i == num_reqs) {
3b2c9beb 1396 /*
8f93068c 1397 * Invalid chain, should not happen
3b2c9beb 1398 */
8f93068c
VL
1399 status = NT_STATUS_INTERNAL_ERROR;
1400 goto error;
1401 }
1402 next_index = i+1;
1403
1404 while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1405 struct smb_request *next = reqs[next_index];
faa8edcc
SM
1406 struct smbXsrv_tcon *tcon;
1407 NTTIME now = timeval_to_nttime(&req->request_time);
8f93068c
VL
1408
1409 next->vuid = SVAL(req->outbuf, smb_uid);
1410 next->tid = SVAL(req->outbuf, smb_tid);
deda0438 1411 status = smb1srv_tcon_lookup(req->xconn, next->tid,
faa8edcc 1412 now, &tcon);
deda0438 1413
faa8edcc 1414 if (NT_STATUS_IS_OK(status)) {
deda0438 1415 next->conn = tcon->compat;
faa8edcc 1416 } else {
deda0438 1417 next->conn = NULL;
faa8edcc 1418 }
8f93068c 1419 next->chain_fsp = req->chain_fsp;
fc5e5845 1420 next->inbuf = req->inbuf;
8f93068c
VL
1421
1422 req = next;
1423 req->conn = switch_message(req->cmd, req);
1424
1425 if (req->outbuf == NULL) {
1426 /*
1427 * Request has suspended itself, will come
1428 * back here.
1429 */
1430 return;
1431 }
1432 next_index += 1;
3b2c9beb
VL
1433 }
1434
8f93068c
VL
1435 first_req = reqs[0];
1436
3b2c9beb 1437 for (i=1; i<next_index; i++) {
8f93068c 1438 bool ok;
3b2c9beb 1439
8f93068c 1440 ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
3b2c9beb
VL
1441 if (!ok) {
1442 status = NT_STATUS_INTERNAL_ERROR;
1443 goto error;
1444 }
3b2c9beb
VL
1445 }
1446
8f93068c
VL
1447 SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1448 SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
3b2c9beb
VL
1449
1450 /*
1451 * This scary statement intends to set the
1452 * FLAGS2_32_BIT_ERROR_CODES flg2 field in first_req->outbuf
1453 * to the value last_req->outbuf carries
1454 */
1455 SSVAL(first_req->outbuf, smb_flg2,
1456 (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
8f93068c 1457 |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
3b2c9beb
VL
1458
1459 /*
1460 * Transfer the error codes from the subrequest to the main one
1461 */
8f93068c
VL
1462 SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1463 SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
3b2c9beb 1464
8f93068c
VL
1465 _smb_setlen_large(
1466 first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
3b2c9beb
VL
1467
1468shipit:
a48bf243 1469 if (!smb1_srv_send(first_req->xconn,
12f1d94a
VL
1470 (char *)first_req->outbuf,
1471 true,
1472 first_req->seqnum + 1,
1473 IS_CONN_ENCRYPTED(req->conn) ||
1474 first_req->encrypted)) {
a48bf243 1475 exit_server_cleanly("construct_reply_chain: smb1_srv_send "
3b2c9beb
VL
1476 "failed.");
1477 }
8f93068c
VL
1478 TALLOC_FREE(req); /* non-chained case */
1479 TALLOC_FREE(reqs); /* chained case */
3b2c9beb
VL
1480 return;
1481
1482error:
1483 {
1484 char errbuf[smb_size];
1485 error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
12f1d94a
VL
1486 if (!smb1_srv_send(req->xconn,
1487 errbuf,
1488 true,
1489 req->seqnum + 1,
1490 req->encrypted)) {
3b2c9beb 1491 exit_server_cleanly("construct_reply_chain: "
a48bf243 1492 "smb1_srv_send failed.");
3b2c9beb
VL
1493 }
1494 }
8f93068c
VL
1495 TALLOC_FREE(req); /* non-chained case */
1496 TALLOC_FREE(reqs); /* chained case */
3b2c9beb
VL
1497}
1498
e9ea36e4 1499/****************************************************************************
49ecd176 1500 Process an smb from the client
e9ea36e4 1501****************************************************************************/
e8c36c25 1502
f2fc4227 1503void process_smb1(struct smbXsrv_connection *xconn,
5adbc366
VL
1504 uint8_t *inbuf,
1505 size_t nread,
1506 size_t unread_bytes,
1507 uint32_t seqnum,
1508 bool encrypted)
e8c36c25
DM
1509{
1510 struct smbd_server_connection *sconn = xconn->client->sconn;
1511
1512 /* Make sure this is an SMB packet. smb_size contains NetBIOS header
1513 * so subtract 4 from it. */
d949073e 1514 if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
e8c36c25
DM
1515 DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1516 smb_len(inbuf)));
1517
1518 /* special magic for immediate exit */
1519 if ((nread == 9) &&
1520 (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1521 lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1522 uint8_t exitcode = CVAL(inbuf, 8);
1523 DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1524 (int)exitcode);
1525 exit(exitcode);
1526 }
1527
1528 exit_server_cleanly("Non-SMB packet");
1529 }
1530
1531 show_msg((char *)inbuf);
1532
1533 if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
625056af
VL
1534 construct_reply_chain(xconn,
1535 (char *)inbuf,
1536 nread,
1537 seqnum,
1538 encrypted);
e8c36c25 1539 } else {
15503566
VL
1540 construct_reply(xconn,
1541 (char *)inbuf,
1542 nread,
1543 unread_bytes,
1544 seqnum,
1545 encrypted);
e8c36c25
DM
1546 }
1547
1548 sconn->trans_num++;
1549}
1550
e9ea36e4 1551/****************************************************************************
1eff0523 1552 Return a string containing the function name of a SMB command.
e9ea36e4 1553****************************************************************************/
1eff0523 1554
127e77e6 1555const char *smb_fn_name(int type)
e9ea36e4 1556{
634c5431 1557 const char *unknown_name = "SMBunknown";
e9ea36e4 1558
918c3ebe 1559 if (smb_messages[type].name == NULL)
e9ea36e4
AT
1560 return(unknown_name);
1561
918c3ebe 1562 return(smb_messages[type].name);
c3effa8b
AT
1563}
1564
dc76502c 1565/****************************************************************************
6bb8f54e 1566 Helper functions for contruct_reply.
dc76502c
JA
1567****************************************************************************/
1568
6abd9867 1569void add_to_common_flags2(uint32_t v)
6219c997
JA
1570{
1571 common_flags2 |= v;
1572}
6bb8f54e 1573
6abd9867 1574void remove_from_common_flags2(uint32_t v)
6bb8f54e 1575{
27891bde 1576 common_flags2 &= ~v;
6bb8f54e
JA
1577}
1578
b6f446ca
VL
1579/**
1580 * @brief Find the smb_cmd offset of the last command pushed
1581 * @param[in] buf The buffer we're building up
1582 * @retval Where can we put our next andx cmd?
1583 *
1584 * While chaining requests, the "next" request we're looking at needs to put
1585 * its SMB_Command before the data the previous request already built up added
1586 * to the chain. Find the offset to the place where we have to put our cmd.
1587 */
1588
1589static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1590{
1591 uint8_t cmd;
1592 size_t ofs;
1593
1594 cmd = CVAL(buf, smb_com);
1595
888bff50 1596 if (!smb1cli_is_andx_req(cmd)) {
947a8bc4
VL
1597 return false;
1598 }
b6f446ca
VL
1599
1600 ofs = smb_vwv0;
1601
1602 while (CVAL(buf, ofs) != 0xff) {
1603
888bff50 1604 if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
b6f446ca
VL
1605 return false;
1606 }
1607
1608 /*
1609 * ofs is from start of smb header, so add the 4 length
1610 * bytes. The next cmd is right after the wct field.
1611 */
1612 ofs = SVAL(buf, ofs+2) + 4 + 1;
1613
947a8bc4
VL
1614 if (ofs+4 >= talloc_get_size(buf)) {
1615 return false;
1616 }
b6f446ca
VL
1617 }
1618
1619 *pofs = ofs;
1620 return true;
1621}
1622
1623/**
1624 * @brief Do the smb chaining at a buffer level
1625 * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
da322e4f 1626 * @param[in] andx_buf Buffer to be appended
b6f446ca
VL
1627 */
1628
da322e4f 1629static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
b6f446ca 1630{
da322e4f
VL
1631 uint8_t smb_command = CVAL(andx_buf, smb_com);
1632 uint8_t wct = CVAL(andx_buf, smb_wct);
1633 const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
da322e4f 1634 uint32_t num_bytes = smb_buflen(andx_buf);
adac8858 1635 const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
da322e4f 1636
b6f446ca
VL
1637 uint8_t *outbuf;
1638 size_t old_size, new_size;
1639 size_t ofs;
1640 size_t chain_padding = 0;
61953ab3
VL
1641 size_t andx_cmd_ofs;
1642
b6f446ca
VL
1643
1644 old_size = talloc_get_size(*poutbuf);
1645
b07ae1ab 1646 if ((old_size % 4) != 0) {
b6f446ca
VL
1647 /*
1648 * Align the wct field of subsequent requests to a 4-byte
1649 * boundary
1650 */
1651 chain_padding = 4 - (old_size % 4);
1652 }
1653
1654 /*
1655 * After the old request comes the new wct field (1 byte), the vwv's
5b7609db 1656 * and the num_bytes field.
b6f446ca
VL
1657 */
1658
1659 new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
4708b97c 1660 new_size += num_bytes;
b6f446ca
VL
1661
1662 if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
28901acd 1663 DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
b6f446ca
VL
1664 (unsigned)new_size));
1665 return false;
1666 }
1667
73b37743 1668 outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
b6f446ca
VL
1669 if (outbuf == NULL) {
1670 DEBUG(0, ("talloc failed\n"));
1671 return false;
1672 }
1673 *poutbuf = outbuf;
1674
61953ab3
VL
1675 if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1676 DEBUG(1, ("invalid command chain\n"));
1677 *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1678 return false;
1679 }
b6f446ca 1680
61953ab3
VL
1681 if (chain_padding != 0) {
1682 memset(outbuf + old_size, 0, chain_padding);
1683 old_size += chain_padding;
b6f446ca
VL
1684 }
1685
61953ab3
VL
1686 SCVAL(outbuf, andx_cmd_ofs, smb_command);
1687 SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1688
b6f446ca
VL
1689 ofs = old_size;
1690
1691 /*
1692 * Push the chained request:
1693 *
1694 * wct field
1695 */
1696
1697 SCVAL(outbuf, ofs, wct);
1698 ofs += 1;
1699
1700 /*
1701 * vwv array
1702 */
1703
1704 memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
12068d4a
VL
1705
1706 /*
1707 * HACK ALERT
1708 *
1709 * Read&X has an offset into its data buffer at
1710 * vwv[6]. reply_read_andx has no idea anymore that it's
1711 * running from within a chain, so we have to fix up the
1712 * offset here.
1713 *
1714 * Although it looks disgusting at this place, I want to keep
1715 * it here. The alternative would be to push knowledge about
1716 * the andx chain down into read&x again.
1717 */
1718
1719 if (smb_command == SMBreadX) {
1720 uint8_t *bytes_addr;
1721
1722 if (wct < 7) {
1723 /*
1724 * Invalid read&x response
1725 */
1726 return false;
1727 }
1728
1729 bytes_addr = outbuf + ofs /* vwv start */
1730 + sizeof(uint16_t) * wct /* vwv array */
2132acb4
CS
1731 + sizeof(uint16_t) /* bcc */
1732 + 1; /* padding byte */
12068d4a
VL
1733
1734 SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1735 bytes_addr - outbuf - 4);
1736 }
1737
b6f446ca
VL
1738 ofs += sizeof(uint16_t) * wct;
1739
1740 /*
1741 * bcc (byte count)
1742 */
1743
4708b97c 1744 SSVAL(outbuf, ofs, num_bytes);
b6f446ca
VL
1745 ofs += sizeof(uint16_t);
1746
b6f446ca
VL
1747 /*
1748 * The bytes field
1749 */
1750
1751 memcpy(outbuf + ofs, bytes, num_bytes);
1752
1753 return true;
1754}
1755
c9870a62
VL
1756bool smb1_is_chain(const uint8_t *buf)
1757{
1758 uint8_t cmd, wct, andx_cmd;
1759
1760 cmd = CVAL(buf, smb_com);
888bff50 1761 if (!smb1cli_is_andx_req(cmd)) {
c9870a62
VL
1762 return false;
1763 }
1764 wct = CVAL(buf, smb_wct);
1765 if (wct < 2) {
1766 return false;
1767 }
1768 andx_cmd = CVAL(buf, smb_vwv);
1769 return (andx_cmd != 0xFF);
1770}
1771
1772bool smb1_walk_chain(const uint8_t *buf,
1773 bool (*fn)(uint8_t cmd,
1774 uint8_t wct, const uint16_t *vwv,
1775 uint16_t num_bytes, const uint8_t *bytes,
1776 void *private_data),
1777 void *private_data)
1778{
1779 size_t smblen = smb_len(buf);
1780 const char *smb_buf = smb_base(buf);
1781 uint8_t cmd, chain_cmd;
1782 uint8_t wct;
1783 const uint16_t *vwv;
1784 uint16_t num_bytes;
1785 const uint8_t *bytes;
1786
1787 cmd = CVAL(buf, smb_com);
1788 wct = CVAL(buf, smb_wct);
1789 vwv = (const uint16_t *)(buf + smb_vwv);
1790 num_bytes = smb_buflen(buf);
1b740e50 1791 bytes = (const uint8_t *)smb_buf_const(buf);
c9870a62
VL
1792
1793 if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1794 return false;
1795 }
1796
888bff50 1797 if (!smb1cli_is_andx_req(cmd)) {
c9870a62
VL
1798 return true;
1799 }
1800 if (wct < 2) {
1801 return false;
1802 }
1803
1804 chain_cmd = CVAL(vwv, 0);
1805
1806 while (chain_cmd != 0xff) {
1807 uint32_t chain_offset; /* uint32_t to avoid overflow */
1808 size_t length_needed;
1809 ptrdiff_t vwv_offset;
1810
1811 chain_offset = SVAL(vwv+1, 0);
1812
1813 /*
1814 * Check if the client tries to fool us. The chain
1815 * offset needs to point beyond the current request in
1816 * the chain, it needs to strictly grow. Otherwise we
1817 * might be tricked into an endless loop always
1818 * processing the same request over and over again. We
1819 * used to assume that vwv and the byte buffer array
1820 * in a chain are always attached, but OS/2 the
1821 * Write&X/Read&X chain puts the Read&X vwv array
1822 * right behind the Write&X vwv chain. The Write&X bcc
1823 * array is put behind the Read&X vwv array. So now we
1824 * check whether the chain offset points strictly
1825 * behind the previous vwv array. req->buf points
1826 * right after the vwv array of the previous
1827 * request. See
1828 * https://bugzilla.samba.org/show_bug.cgi?id=8360 for
1829 * more information.
1830 */
1831
1832 vwv_offset = ((const char *)vwv - smb_buf);
1833 if (chain_offset <= vwv_offset) {
1834 return false;
1835 }
1836
1837 /*
1838 * Next check: Make sure the chain offset does not
1839 * point beyond the overall smb request length.
1840 */
1841
1842 length_needed = chain_offset+1; /* wct */
1843 if (length_needed > smblen) {
1844 return false;
1845 }
1846
1847 /*
1848 * Now comes the pointer magic. Goal here is to set up
1849 * vwv and buf correctly again. The chain offset (the
1850 * former vwv[1]) points at the new wct field.
1851 */
1852
1853 wct = CVAL(smb_buf, chain_offset);
1854
888bff50 1855 if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
c9870a62
VL
1856 return false;
1857 }
1858
1859 /*
1860 * Next consistency check: Make the new vwv array fits
1861 * in the overall smb request.
1862 */
1863
1864 length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1865 if (length_needed > smblen) {
1866 return false;
1867 }
1868 vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1869
1870 /*
1871 * Now grab the new byte buffer....
1872 */
1873
1874 num_bytes = SVAL(vwv+wct, 0);
1875
1876 /*
1877 * .. and check that it fits.
1878 */
1879
1880 length_needed += num_bytes;
1881 if (length_needed > smblen) {
1882 return false;
1883 }
1884 bytes = (const uint8_t *)(vwv+wct+1);
1885
1886 if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1887 return false;
1888 }
1889
888bff50 1890 if (!smb1cli_is_andx_req(chain_cmd)) {
c9870a62
VL
1891 return true;
1892 }
1893 chain_cmd = CVAL(vwv, 0);
1894 }
1895 return true;
1896}
1897
1898static bool smb1_chain_length_cb(uint8_t cmd,
1899 uint8_t wct, const uint16_t *vwv,
1900 uint16_t num_bytes, const uint8_t *bytes,
1901 void *private_data)
1902{
1903 unsigned *count = (unsigned *)private_data;
1904 *count += 1;
1905 return true;
1906}
1907
1908unsigned smb1_chain_length(const uint8_t *buf)
1909{
1910 unsigned count = 0;
1911
1912 if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1913 return 0;
1914 }
1915 return count;
1916}
1917
1918struct smb1_parse_chain_state {
1919 TALLOC_CTX *mem_ctx;
1920 const uint8_t *buf;
1921 struct smbd_server_connection *sconn;
6669a84a 1922 struct smbXsrv_connection *xconn;
c9870a62
VL
1923 bool encrypted;
1924 uint32_t seqnum;
1925
1926 struct smb_request **reqs;
1927 unsigned num_reqs;
1928};
1929
1930static bool smb1_parse_chain_cb(uint8_t cmd,
1931 uint8_t wct, const uint16_t *vwv,
1932 uint16_t num_bytes, const uint8_t *bytes,
1933 void *private_data)
1934{
1935 struct smb1_parse_chain_state *state =
1936 (struct smb1_parse_chain_state *)private_data;
1937 struct smb_request **reqs;
1938 struct smb_request *req;
1939 bool ok;
1940
1941 reqs = talloc_realloc(state->mem_ctx, state->reqs,
1942 struct smb_request *, state->num_reqs+1);
1943 if (reqs == NULL) {
1944 return false;
1945 }
1946 state->reqs = reqs;
1947
1948 req = talloc(reqs, struct smb_request);
1949 if (req == NULL) {
1950 return false;
1951 }
1952
0de91444 1953 ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
c9870a62
VL
1954 state->encrypted, state->seqnum);
1955 if (!ok) {
1956 return false;
1957 }
1958 req->cmd = cmd;
1959 req->wct = wct;
1960 req->vwv = vwv;
1961 req->buflen = num_bytes;
1962 req->buf = bytes;
1963
1964 reqs[state->num_reqs] = req;
1965 state->num_reqs += 1;
1966 return true;
1967}
1968
1969bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
3a26bd1a 1970 struct smbXsrv_connection *xconn,
c9870a62
VL
1971 bool encrypted, uint32_t seqnum,
1972 struct smb_request ***reqs, unsigned *num_reqs)
1973{
3a26bd1a 1974 struct smbd_server_connection *sconn = NULL;
c9870a62 1975 struct smb1_parse_chain_state state;
8f93068c 1976 unsigned i;
c9870a62 1977
3a26bd1a 1978 if (xconn != NULL) {
981fb261 1979 sconn = xconn->client->sconn;
3a26bd1a
SM
1980 }
1981
c9870a62
VL
1982 state.mem_ctx = mem_ctx;
1983 state.buf = buf;
1984 state.sconn = sconn;
6669a84a 1985 state.xconn = xconn;
c9870a62
VL
1986 state.encrypted = encrypted;
1987 state.seqnum = seqnum;
1988 state.reqs = NULL;
1989 state.num_reqs = 0;
1990
1991 if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1992 TALLOC_FREE(state.reqs);
1993 return false;
1994 }
8f93068c
VL
1995 for (i=0; i<state.num_reqs; i++) {
1996 state.reqs[i]->chain = state.reqs;
1997 }
c9870a62
VL
1998 *reqs = state.reqs;
1999 *num_reqs = state.num_reqs;
2000 return true;
2001}
2002
cad0c004
VL
2003static bool fd_is_readable(int fd)
2004{
0f082de5 2005 int ret, revents;
cad0c004 2006
0f082de5
VL
2007 ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2008
2009 return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
cad0c004 2010
cad0c004
VL
2011}
2012
fc79169c 2013static void smbd_server_connection_write_handler(
96ef921b 2014 struct smbXsrv_connection *xconn)
aeb798c3
SM
2015{
2016 /* TODO: make write nonblocking */
2017}
2018
6f792afe
DM
2019void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2020 int fd)
aeb798c3
SM
2021{
2022 uint8_t *inbuf = NULL;
2023 size_t inbuf_len = 0;
2024 size_t unread_bytes = 0;
2025 bool encrypted = false;
2026 TALLOC_CTX *mem_ctx = talloc_tos();
2027 NTSTATUS status;
c16c90a1 2028 uint32_t seqnum;
aeb798c3 2029
0c7f36d2
SM
2030 bool async_echo = lp_async_smb_echo_handler();
2031 bool from_client = false;
5e0258fc 2032
0c7f36d2 2033 if (async_echo) {
b0fe6c5c 2034 if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
0c7f36d2
SM
2035 /*
2036 * This is the super-ugly hack to prefer the packets
2037 * forwarded by the echo handler over the ones by the
2038 * client directly
2039 */
b0fe6c5c 2040 fd = xconn->smb1.echo_handler.trusted_fd;
0c7f36d2 2041 }
5e0258fc
VL
2042 }
2043
0ccffffe 2044 from_client = (xconn->transport.sock == fd);
977aa660 2045
0c7f36d2 2046 if (async_echo && from_client) {
bb8e6d45 2047 smbd_lock_socket(xconn);
cad0c004 2048
5e0258fc
VL
2049 if (!fd_is_readable(fd)) {
2050 DEBUG(10,("the echo listener was faster\n"));
bb8e6d45 2051 smbd_unlock_socket(xconn);
5e0258fc 2052 return;
cad0c004 2053 }
5e0258fc
VL
2054 }
2055
2056 /* TODO: make this completely nonblocking */
e3ab0a05 2057 status = receive_smb_talloc(mem_ctx, xconn, fd,
5e0258fc
VL
2058 (char **)(void *)&inbuf,
2059 0, /* timeout */
2060 &unread_bytes,
2061 &encrypted,
2062 &inbuf_len, &seqnum,
5aa9e552 2063 !from_client /* trusted channel */);
cad0c004 2064
0c7f36d2 2065 if (async_echo && from_client) {
bb8e6d45 2066 smbd_unlock_socket(xconn);
977aa660
SM
2067 }
2068
aeb798c3
SM
2069 if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2070 goto process;
2071 }
2072 if (NT_STATUS_IS_ERR(status)) {
2073 exit_server_cleanly("failed to receive smb request");
2074 }
2075 if (!NT_STATUS_IS_OK(status)) {
2076 return;
2077 }
2078
2079process:
d2dcc0fd 2080 process_smb(xconn, inbuf, inbuf_len, unread_bytes, seqnum, encrypted);
aeb798c3
SM
2081}
2082
415e8e05 2083static void smbd_server_echo_handler(struct tevent_context *ev,
a0d96b53 2084 struct tevent_fd *fde,
cad0c004
VL
2085 uint16_t flags,
2086 void *private_data)
2087{
96ef921b
SM
2088 struct smbXsrv_connection *xconn =
2089 talloc_get_type_abort(private_data,
2090 struct smbXsrv_connection);
cad0c004 2091
b05b4cab 2092 if (!NT_STATUS_IS_OK(xconn->transport.status)) {
52ccb40d
SM
2093 /*
2094 * we're not supposed to do any io
2095 */
b0fe6c5c
SM
2096 TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2097 TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
52ccb40d
SM
2098 return;
2099 }
2100
2672c37a 2101 if (flags & TEVENT_FD_WRITE) {
96ef921b 2102 smbd_server_connection_write_handler(xconn);
c672797a
VL
2103 return;
2104 }
2672c37a 2105 if (flags & TEVENT_FD_READ) {
4f4c40bc 2106 smbd_smb1_server_connection_read_handler(
96ef921b 2107 xconn, xconn->smb1.echo_handler.trusted_fd);
c672797a 2108 return;
cad0c004
VL
2109 }
2110}
27f812f3 2111
27f812f3
SM
2112/*
2113 * Send keepalive packets to our client
2114 */
43672e15 2115bool keepalive_fn(const struct timeval *now, void *private_data)
27f812f3 2116{
d911bd5c
VL
2117 struct smbd_server_connection *sconn = talloc_get_type_abort(
2118 private_data, struct smbd_server_connection);
555b3d18 2119 struct smbXsrv_connection *xconn = NULL;
c1653e3b
SM
2120 bool ret;
2121
80cd127b 2122 if (conn_using_smb2(sconn)) {
efd0c35a
JA
2123 /* Don't do keepalives on an SMB2 connection. */
2124 return false;
2125 }
2126
555b3d18
SM
2127 /*
2128 * With SMB1 we only have 1 connection
2129 */
2130 xconn = sconn->client->connections;
bb8e6d45 2131 smbd_lock_socket(xconn);
0ccffffe 2132 ret = send_keepalive(xconn->transport.sock);
bb8e6d45 2133 smbd_unlock_socket(xconn);
c1653e3b
SM
2134
2135 if (!ret) {
2fd53228 2136 int saved_errno = errno;
40ae8b74
VL
2137 /*
2138 * Try and give an error message saying what
2139 * client failed.
2140 */
2141 DEBUG(0, ("send_keepalive failed for client %s. "
2142 "Error %s - exiting\n",
2fd53228
SM
2143 smbXsrv_connection_dbg(xconn),
2144 strerror(saved_errno)));
2145 errno = saved_errno;
27f812f3
SM
2146 return False;
2147 }
2148 return True;
2149}
2150
27afb891
VL
2151/*
2152 * Read an smb packet in the echo handler child, giving the parent
2153 * smbd one second to react once the socket becomes readable.
2154 */
2155
2156struct smbd_echo_read_state {
2157 struct tevent_context *ev;
0b99a8ac 2158 struct smbXsrv_connection *xconn;
27afb891
VL
2159
2160 char *buf;
2161 size_t buflen;
2162 uint32_t seqnum;
2163};
2164
2165static void smbd_echo_read_readable(struct tevent_req *subreq);
2166static void smbd_echo_read_waited(struct tevent_req *subreq);
2167
2168static struct tevent_req *smbd_echo_read_send(
2169 TALLOC_CTX *mem_ctx, struct tevent_context *ev,
0b99a8ac 2170 struct smbXsrv_connection *xconn)
27afb891
VL
2171{
2172 struct tevent_req *req, *subreq;
2173 struct smbd_echo_read_state *state;
2174
2175 req = tevent_req_create(mem_ctx, &state,
2176 struct smbd_echo_read_state);
2177 if (req == NULL) {
2178 return NULL;
2179 }
2180 state->ev = ev;
0b99a8ac 2181 state->xconn = xconn;
27afb891 2182
0c6dc1ec 2183 subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
27afb891
VL
2184 if (tevent_req_nomem(subreq, req)) {
2185 return tevent_req_post(req, ev);
2186 }
2187 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2188 return req;
2189}
2190
2191static void smbd_echo_read_readable(struct tevent_req *subreq)
2192{
2193 struct tevent_req *req = tevent_req_callback_data(
2194 subreq, struct tevent_req);
2195 struct smbd_echo_read_state *state = tevent_req_data(
2196 req, struct smbd_echo_read_state);
2197 bool ok;
2198 int err;
2199
2200 ok = wait_for_read_recv(subreq, &err);
2201 TALLOC_FREE(subreq);
2202 if (!ok) {
2203 tevent_req_nterror(req, map_nt_error_from_unix(err));
2204 return;
2205 }
2206
2207 /*
2208 * Give the parent smbd one second to step in
2209 */
2210
2211 subreq = tevent_wakeup_send(
2212 state, state->ev, timeval_current_ofs(1, 0));
2213 if (tevent_req_nomem(subreq, req)) {
2214 return;
2215 }
2216 tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2217}
2218
2219static void smbd_echo_read_waited(struct tevent_req *subreq)
2220{
2221 struct tevent_req *req = tevent_req_callback_data(
2222 subreq, struct tevent_req);
2223 struct smbd_echo_read_state *state = tevent_req_data(
2224 req, struct smbd_echo_read_state);
0b99a8ac 2225 struct smbXsrv_connection *xconn = state->xconn;
27afb891
VL
2226 bool ok;
2227 NTSTATUS status;
2228 size_t unread = 0;
2229 bool encrypted;
2230
2231 ok = tevent_wakeup_recv(subreq);
2232 TALLOC_FREE(subreq);
2233 if (!ok) {
2234 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2235 return;
2236 }
2237
6905bb6c 2238 ok = smbd_lock_socket_internal(xconn);
27afb891
VL
2239 if (!ok) {
2240 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2241 DEBUG(0, ("%s: failed to lock socket\n", __location__));
2242 return;
2243 }
2244
0ccffffe 2245 if (!fd_is_readable(xconn->transport.sock)) {
27afb891 2246 DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
c0288e06 2247 (int)getpid()));
27afb891 2248
6905bb6c 2249 ok = smbd_unlock_socket_internal(xconn);
27afb891
VL
2250 if (!ok) {
2251 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2252 DEBUG(1, ("%s: failed to unlock socket\n",
2253 __location__));
2254 return;
2255 }
2256
0ccffffe 2257 subreq = wait_for_read_send(state, state->ev,
0c6dc1ec 2258 xconn->transport.sock, false);
27afb891
VL
2259 if (tevent_req_nomem(subreq, req)) {
2260 return;
2261 }
2262 tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2263 return;
2264 }
2265
e3ab0a05 2266 status = receive_smb_talloc(state, xconn,
0ccffffe
SM
2267 xconn->transport.sock,
2268 &state->buf,
27afb891
VL
2269 0 /* timeout */,
2270 &unread,
2271 &encrypted,
2272 &state->buflen,
2273 &state->seqnum,
2274 false /* trusted_channel*/);
2275
2276 if (tevent_req_nterror(req, status)) {
2277 tevent_req_nterror(req, status);
2278 DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
c0288e06 2279 (int)getpid(), nt_errstr(status)));
27afb891
VL
2280 return;
2281 }
2282
6905bb6c 2283 ok = smbd_unlock_socket_internal(xconn);
27afb891
VL
2284 if (!ok) {
2285 tevent_req_nterror(req, map_nt_error_from_unix(errno));
2286 DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2287 return;
2288 }
2289 tevent_req_done(req);
2290}
2291
2292static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2293 char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2294{
2295 struct smbd_echo_read_state *state = tevent_req_data(
2296 req, struct smbd_echo_read_state);
2297 NTSTATUS status;
2298
2299 if (tevent_req_is_nterror(req, &status)) {
2300 return status;
2301 }
2302 *pbuf = talloc_move(mem_ctx, &state->buf);
2303 *pbuflen = state->buflen;
2304 *pseqnum = state->seqnum;
2305 return NT_STATUS_OK;
2306}
2307
cad0c004
VL
2308struct smbd_echo_state {
2309 struct tevent_context *ev;
2310 struct iovec *pending;
2311 struct smbd_server_connection *sconn;
6669a84a 2312 struct smbXsrv_connection *xconn;
cad0c004
VL
2313 int parent_pipe;
2314
2315 struct tevent_fd *parent_fde;
2316
cad0c004
VL
2317 struct tevent_req *write_req;
2318};
2319
2320static void smbd_echo_writer_done(struct tevent_req *req);
2321
2322static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2323{
2324 int num_pending;
2325
2326 if (state->write_req != NULL) {
2327 return;
2328 }
2329
2330 num_pending = talloc_array_length(state->pending);
2331 if (num_pending == 0) {
2332 return;
2333 }
2334
2335 state->write_req = writev_send(state, state->ev, NULL,
2336 state->parent_pipe, false,
2337 state->pending, num_pending);
2338 if (state->write_req == NULL) {
2339 DEBUG(1, ("writev_send failed\n"));
2340 exit(1);
2341 }
2342
2343 talloc_steal(state->write_req, state->pending);
2344 state->pending = NULL;
2345
2346 tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2347 state);
2348}
2349
2350static void smbd_echo_writer_done(struct tevent_req *req)
2351{
2352 struct smbd_echo_state *state = tevent_req_callback_data(
2353 req, struct smbd_echo_state);
2354 ssize_t written;
2355 int err;
2356
2357 written = writev_recv(req, &err);
2358 TALLOC_FREE(req);
2359 state->write_req = NULL;
2360 if (written == -1) {
2361 DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2362 exit(1);
2363 }
c0288e06 2364 DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
cad0c004
VL
2365 smbd_echo_activate_writer(state);
2366}
2367
0b8eeb1e
SM
2368static bool smbd_echo_reply(struct smbd_echo_state *state,
2369 uint8_t *inbuf, size_t inbuf_len,
cad0c004
VL
2370 uint32_t seqnum)
2371{
2372 struct smb_request req;
2373 uint16_t num_replies;
cad0c004
VL
2374 char *outbuf;
2375 bool ok;
2376
0633c0f6 2377 if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
fd9effce
VL
2378 DEBUG(10, ("Got netbios keepalive\n"));
2379 /*
2380 * Just swallow it
2381 */
2382 return true;
2383 }
2384
cad0c004
VL
2385 if (inbuf_len < smb_size) {
2386 DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2387 return false;
2388 }
d949073e 2389 if (!valid_smb1_header(inbuf)) {
cad0c004
VL
2390 DEBUG(10, ("Got invalid SMB header\n"));
2391 return false;
2392 }
2393
0de91444 2394 if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
d7bc5fe7 2395 seqnum)) {
cad0c004
VL
2396 return false;
2397 }
2398 req.inbuf = inbuf;
2399
2400 DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
9907fd3e 2401 smb_fn_name(req.cmd)));
cad0c004
VL
2402
2403 if (req.cmd != SMBecho) {
2404 return false;
2405 }
2406 if (req.wct < 1) {
2407 return false;
2408 }
2409
2410 num_replies = SVAL(req.vwv+0, 0);
2411 if (num_replies != 1) {
2412 /* Not a Windows "Hey, you're still there?" request */
2413 return false;
2414 }
2415
97fd5e56 2416 if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
cad0c004 2417 1, req.buflen)) {
97fd5e56 2418 DEBUG(10, ("create_smb1_outbuf failed\n"));
cad0c004
VL
2419 return false;
2420 }
2421 req.outbuf = (uint8_t *)outbuf;
2422
2423 SSVAL(req.outbuf, smb_vwv0, num_replies);
2424
2425 if (req.buflen > 0) {
2426 memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2427 }
2428
12f1d94a 2429 ok = smb1_srv_send(req.xconn, (char *)outbuf, true, seqnum + 1, false);
cad0c004
VL
2430 TALLOC_FREE(outbuf);
2431 if (!ok) {
2432 exit(1);
2433 }
2434
2435 return true;
2436}
2437
2438static void smbd_echo_exit(struct tevent_context *ev,
2439 struct tevent_fd *fde, uint16_t flags,
2440 void *private_data)
2441{
2442 DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2443 exit(0);
2444}
2445
710e5d92
VL
2446static void smbd_echo_got_packet(struct tevent_req *req);
2447
0b99a8ac 2448static void smbd_echo_loop(struct smbXsrv_connection *xconn,
cad0c004
VL
2449 int parent_pipe)
2450{
2451 struct smbd_echo_state *state;
710e5d92 2452 struct tevent_req *read_req;
cad0c004 2453
0b99a8ac 2454 state = talloc_zero(xconn, struct smbd_echo_state);
cad0c004
VL
2455 if (state == NULL) {
2456 DEBUG(1, ("talloc failed\n"));
2457 return;
2458 }
6669a84a 2459 state->xconn = xconn;
cad0c004 2460 state->parent_pipe = parent_pipe;
fbfea52e 2461 state->ev = samba_tevent_context_init(state);
cad0c004 2462 if (state->ev == NULL) {
fbfea52e 2463 DEBUG(1, ("samba_tevent_context_init failed\n"));
cad0c004
VL
2464 TALLOC_FREE(state);
2465 return;
2466 }
2467 state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2468 TEVENT_FD_READ, smbd_echo_exit,
2469 state);
2470 if (state->parent_fde == NULL) {
2471 DEBUG(1, ("tevent_add_fd failed\n"));
2472 TALLOC_FREE(state);
2473 return;
2474 }
710e5d92 2475
0b99a8ac 2476 read_req = smbd_echo_read_send(state, state->ev, xconn);
710e5d92
VL
2477 if (read_req == NULL) {
2478 DEBUG(1, ("smbd_echo_read_send failed\n"));
cad0c004
VL
2479 TALLOC_FREE(state);
2480 return;
2481 }
710e5d92 2482 tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
cad0c004
VL
2483
2484 while (true) {
2485 if (tevent_loop_once(state->ev) == -1) {
2486 DEBUG(1, ("tevent_loop_once failed: %s\n",
2487 strerror(errno)));
2488 break;
2489 }
2490 }
2491 TALLOC_FREE(state);
2492}
2493
710e5d92
VL
2494static void smbd_echo_got_packet(struct tevent_req *req)
2495{
2496 struct smbd_echo_state *state = tevent_req_callback_data(
2497 req, struct smbd_echo_state);
2498 NTSTATUS status;
2499 char *buf = NULL;
2500 size_t buflen = 0;
2501 uint32_t seqnum = 0;
2502 bool reply;
2503
2504 status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2505 TALLOC_FREE(req);
2506 if (!NT_STATUS_IS_OK(status)) {
2507 DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2508 nt_errstr(status)));
2509 exit(1);
2510 }
2511
0b8eeb1e 2512 reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
710e5d92
VL
2513 if (!reply) {
2514 size_t num_pending;
2515 struct iovec *tmp;
2516 struct iovec *iov;
2517
2518 num_pending = talloc_array_length(state->pending);
2519 tmp = talloc_realloc(state, state->pending, struct iovec,
2520 num_pending+1);
2521 if (tmp == NULL) {
2522 DEBUG(1, ("talloc_realloc failed\n"));
2523 exit(1);
2524 }
2525 state->pending = tmp;
2526
2527 if (buflen >= smb_size) {
2528 /*
2529 * place the seqnum in the packet so that the main process
2530 * can reply with signing
2531 */
2532 SIVAL(buf, smb_ss_field, seqnum);
2533 SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2534 }
2535
2536 iov = &state->pending[num_pending];
3d5c534f 2537 iov->iov_base = talloc_move(state->pending, &buf);
710e5d92
VL
2538 iov->iov_len = buflen;
2539
2540 DEBUG(10,("echo_handler[%d]: forward to main\n",
c0288e06 2541 (int)getpid()));
710e5d92
VL
2542 smbd_echo_activate_writer(state);
2543 }
2544
0b99a8ac 2545 req = smbd_echo_read_send(state, state->ev, state->xconn);
710e5d92
VL
2546 if (req == NULL) {
2547 DEBUG(1, ("smbd_echo_read_send failed\n"));
2548 exit(1);
2549 }
2550 tevent_req_set_callback(req, smbd_echo_got_packet, state);
2551}
2552
2553
cad0c004
VL
2554/*
2555 * Handle SMBecho requests in a forked child process
2556 */
0b99a8ac 2557bool fork_echo_handler(struct smbXsrv_connection *xconn)
cad0c004
VL
2558{
2559 int listener_pipe[2];
2560 int res;
2561 pid_t child;
f01af728 2562 bool use_mutex = false;
cad0c004
VL
2563
2564 res = pipe(listener_pipe);
2565 if (res == -1) {
2566 DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2567 return false;
2568 }
f01af728
CS
2569
2570#ifdef HAVE_ROBUST_MUTEXES
2571 use_mutex = tdb_runtime_check_for_robust_mutexes();
2572
2573 if (use_mutex) {
2574 pthread_mutexattr_t a;
2575
b0fe6c5c 2576 xconn->smb1.echo_handler.socket_mutex =
f01af728 2577 anonymous_shared_allocate(sizeof(pthread_mutex_t));
b0fe6c5c 2578 if (xconn->smb1.echo_handler.socket_mutex == NULL) {
f01af728
CS
2579 DEBUG(1, ("Could not create mutex shared memory: %s\n",
2580 strerror(errno)));
2581 goto fail;
2582 }
2583
2584 res = pthread_mutexattr_init(&a);
2585 if (res != 0) {
2586 DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2587 strerror(res)));
2588 goto fail;
2589 }
2590 res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2591 if (res != 0) {
2592 DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2593 strerror(res)));
2594 pthread_mutexattr_destroy(&a);
2595 goto fail;
2596 }
2597 res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2598 if (res != 0) {
2599 DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2600 strerror(res)));
2601 pthread_mutexattr_destroy(&a);
2602 goto fail;
2603 }
2604 res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2605 if (res != 0) {
2606 DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2607 "%s\n", strerror(res)));
2608 pthread_mutexattr_destroy(&a);
2609 goto fail;
2610 }
b0fe6c5c 2611 res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
f01af728
CS
2612 &a);
2613 pthread_mutexattr_destroy(&a);
2614 if (res != 0) {
2615 DEBUG(1, ("pthread_mutex_init failed: %s\n",
2616 strerror(res)));
2617 goto fail;
2618 }
2619 }
2620#endif
2621
2622 if (!use_mutex) {
b0fe6c5c 2623 xconn->smb1.echo_handler.socket_lock_fd =
f01af728 2624 create_unlink_tmp(lp_lock_directory());
b0fe6c5c 2625 if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
f01af728
CS
2626 DEBUG(1, ("Could not create lock fd: %s\n",
2627 strerror(errno)));
2628 goto fail;
2629 }
cad0c004
VL
2630 }
2631
c0288e06 2632 child = fork();
cad0c004
VL
2633 if (child == 0) {
2634 NTSTATUS status;
2635
2636 close(listener_pipe[0]);
342c79e2 2637 set_blocking(listener_pipe[1], false);
cad0c004 2638
d2adcebd 2639 status = smbd_reinit_after_fork(xconn->client->msg_ctx,
d39f6ce3 2640 xconn->client->raw_ev_ctx,
38ba7d14 2641 true);
cad0c004
VL
2642 if (!NT_STATUS_IS_OK(status)) {
2643 DEBUG(1, ("reinit_after_fork failed: %s\n",
2644 nt_errstr(status)));
2645 exit(1);
2646 }
62cc0bba 2647 process_set_title("smbd-echo", "echo handler");
d39f6ce3 2648 initialize_password_db(true, xconn->client->raw_ev_ctx);
0b99a8ac 2649 smbd_echo_loop(xconn, listener_pipe[1]);
cad0c004
VL
2650 exit(0);
2651 }
2652 close(listener_pipe[1]);
2653 listener_pipe[1] = -1;
b0fe6c5c 2654 xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
cad0c004 2655
1fba1406 2656 DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
cad0c004
VL
2657
2658 /*
2659 * Without smb signing this is the same as the normal smbd
2660 * listener. This needs to change once signing comes in.
2661 */
d39f6ce3
SM
2662 xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2663 xconn->client->raw_ev_ctx,
96ef921b 2664 xconn,
b0fe6c5c 2665 xconn->smb1.echo_handler.trusted_fd,
bf8cce18 2666 TEVENT_FD_READ,
cad0c004 2667 smbd_server_echo_handler,
96ef921b 2668 xconn);
b0fe6c5c 2669 if (xconn->smb1.echo_handler.trusted_fde == NULL) {
cad0c004
VL
2670 DEBUG(1, ("event_add_fd failed\n"));
2671 goto fail;
2672 }
2673
2674 return true;
2675
2676fail:
2677 if (listener_pipe[0] != -1) {
2678 close(listener_pipe[0]);
2679 }
2680 if (listener_pipe[1] != -1) {
2681 close(listener_pipe[1]);
2682 }
b0fe6c5c
SM
2683 if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2684 close(xconn->smb1.echo_handler.socket_lock_fd);
cad0c004 2685 }
f01af728 2686#ifdef HAVE_ROBUST_MUTEXES
b0fe6c5c
SM
2687 if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2688 pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2689 anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
f01af728
CS
2690 }
2691#endif
b0fe6c5c 2692 smbd_echo_init(xconn);
f01af728 2693
cad0c004
VL
2694 return false;
2695}
2696
b80111ad 2697bool req_is_in_chain(const struct smb_request *req)
d94e9c80 2698{
4f41be35 2699 if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
d94e9c80
VL
2700 /*
2701 * We're right now handling a subsequent request, so we must
2702 * be in a chain
2703 */
2704 return true;
2705 }
2706
888bff50 2707 if (!smb1cli_is_andx_req(req->cmd)) {
d94e9c80
VL
2708 return false;
2709 }
2710
2711 if (req->wct < 2) {
2712 /*
2713 * Okay, an illegal request, but definitely not chained :-)
2714 */
2715 return false;
2716 }
2717
2718 return (CVAL(req->vwv+0, 0) != 0xFF);
2719}