Line data Source code
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 "source3/smbd/smbXsrv_session.h"
27 : #include "smbd/smbXsrv_open.h"
28 : #include "librpc/gen_ndr/netlogon.h"
29 : #include "../lib/async_req/async_sock.h"
30 : #include "ctdbd_conn.h"
31 : #include "../lib/util/select.h"
32 : #include "printing/queue_process.h"
33 : #include "system/select.h"
34 : #include "passdb.h"
35 : #include "auth.h"
36 : #include "messages.h"
37 : #include "lib/messages_ctdb.h"
38 : #include "smbprofile.h"
39 : #include "rpc_server/spoolss/srv_spoolss_nt.h"
40 : #include "../lib/util/tevent_ntstatus.h"
41 : #include "../libcli/security/dom_sid.h"
42 : #include "../libcli/security/security_token.h"
43 : #include "lib/id_cache.h"
44 : #include "lib/util/sys_rw_data.h"
45 : #include "system/threads.h"
46 : #include "lib/pthreadpool/pthreadpool_tevent.h"
47 : #include "util_event.h"
48 : #include "libcli/smb/smbXcli_base.h"
49 : #include "lib/util/time_basic.h"
50 : #include "source3/lib/substitute.h"
51 : #include "lib/util/util_process.h"
52 :
53 : /* Internal message queue for deferred opens. */
54 : struct 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;
58 : struct smbXsrv_connection *xconn;
59 : struct tevent_timer *te;
60 : uint32_t seqnum;
61 : bool encrypted;
62 : bool processed;
63 : DATA_BLOB buf;
64 : struct deferred_open_record *open_rec;
65 : };
66 :
67 : static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
68 :
69 32669 : void smbd_echo_init(struct smbXsrv_connection *xconn)
70 : {
71 32669 : xconn->smb1.echo_handler.trusted_fd = -1;
72 32669 : xconn->smb1.echo_handler.socket_lock_fd = -1;
73 : #ifdef HAVE_ROBUST_MUTEXES
74 32669 : xconn->smb1.echo_handler.socket_mutex = NULL;
75 : #endif
76 32669 : }
77 :
78 1307936 : static bool smbd_echo_active(struct smbXsrv_connection *xconn)
79 : {
80 1307936 : if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
81 0 : return true;
82 : }
83 :
84 : #ifdef HAVE_ROBUST_MUTEXES
85 1307936 : if (xconn->smb1.echo_handler.socket_mutex != NULL) {
86 0 : return true;
87 : }
88 : #endif
89 :
90 1292212 : return false;
91 : }
92 :
93 653968 : static bool smbd_lock_socket_internal(struct smbXsrv_connection *xconn)
94 : {
95 653968 : if (!smbd_echo_active(xconn)) {
96 646106 : return true;
97 : }
98 :
99 0 : xconn->smb1.echo_handler.ref_count++;
100 :
101 0 : if (xconn->smb1.echo_handler.ref_count > 1) {
102 0 : return true;
103 : }
104 :
105 0 : DEBUG(10,("pid[%d] wait for socket lock\n", (int)getpid()));
106 :
107 : #ifdef HAVE_ROBUST_MUTEXES
108 0 : if (xconn->smb1.echo_handler.socket_mutex != NULL) {
109 0 : int ret = EINTR;
110 :
111 0 : while (ret == EINTR) {
112 0 : ret = pthread_mutex_lock(
113 : xconn->smb1.echo_handler.socket_mutex);
114 0 : if (ret == 0) {
115 0 : break;
116 : }
117 : }
118 0 : if (ret != 0) {
119 0 : DEBUG(1, ("pthread_mutex_lock failed: %s\n",
120 : strerror(ret)));
121 0 : return false;
122 : }
123 : }
124 : #endif
125 :
126 0 : if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
127 0 : bool ok;
128 :
129 0 : do {
130 0 : ok = fcntl_lock(
131 : xconn->smb1.echo_handler.socket_lock_fd,
132 : F_SETLKW, 0, 0, F_WRLCK);
133 0 : } while (!ok && (errno == EINTR));
134 :
135 0 : if (!ok) {
136 0 : DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
137 0 : return false;
138 : }
139 : }
140 :
141 0 : DEBUG(10,("pid[%d] got socket lock\n", (int)getpid()));
142 :
143 0 : return true;
144 : }
145 :
146 653968 : void smbd_lock_socket(struct smbXsrv_connection *xconn)
147 : {
148 653968 : if (!smbd_lock_socket_internal(xconn)) {
149 0 : exit_server_cleanly("failed to lock socket");
150 : }
151 653968 : }
152 :
153 653968 : static bool smbd_unlock_socket_internal(struct smbXsrv_connection *xconn)
154 : {
155 653968 : if (!smbd_echo_active(xconn)) {
156 646106 : return true;
157 : }
158 :
159 0 : xconn->smb1.echo_handler.ref_count--;
160 :
161 0 : if (xconn->smb1.echo_handler.ref_count > 0) {
162 0 : return true;
163 : }
164 :
165 : #ifdef HAVE_ROBUST_MUTEXES
166 0 : if (xconn->smb1.echo_handler.socket_mutex != NULL) {
167 0 : int ret;
168 0 : ret = pthread_mutex_unlock(
169 : xconn->smb1.echo_handler.socket_mutex);
170 0 : if (ret != 0) {
171 0 : DEBUG(1, ("pthread_mutex_unlock failed: %s\n",
172 : strerror(ret)));
173 0 : return false;
174 : }
175 : }
176 : #endif
177 :
178 0 : if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
179 0 : bool ok;
180 :
181 0 : do {
182 0 : ok = fcntl_lock(
183 : xconn->smb1.echo_handler.socket_lock_fd,
184 : F_SETLKW, 0, 0, F_UNLCK);
185 0 : } while (!ok && (errno == EINTR));
186 :
187 0 : if (!ok) {
188 0 : DEBUG(1, ("fcntl_lock failed: %s\n", strerror(errno)));
189 0 : return false;
190 : }
191 : }
192 :
193 0 : DEBUG(10,("pid[%d] unlocked socket\n", (int)getpid()));
194 :
195 0 : return true;
196 : }
197 :
198 653968 : void smbd_unlock_socket(struct smbXsrv_connection *xconn)
199 : {
200 653968 : if (!smbd_unlock_socket_internal(xconn)) {
201 0 : exit_server_cleanly("failed to unlock socket");
202 : }
203 653968 : }
204 :
205 : /* Accessor function for smb_read_error for smbd functions. */
206 :
207 : /****************************************************************************
208 : Send an smb to a fd.
209 : ****************************************************************************/
210 :
211 653929 : bool smb1_srv_send(struct smbXsrv_connection *xconn,
212 : char *buffer,
213 : bool do_signing,
214 : uint32_t seqnum,
215 : bool do_encrypt)
216 : {
217 653929 : size_t len = 0;
218 7859 : ssize_t ret;
219 653929 : char *buf_out = buffer;
220 :
221 653929 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
222 : /*
223 : * we're not supposed to do any io
224 : */
225 42 : return true;
226 : }
227 :
228 653887 : smbd_lock_socket(xconn);
229 :
230 653887 : if (do_signing) {
231 7851 : NTSTATUS status;
232 :
233 : /* Sign the outgoing packet if required. */
234 652227 : status = smb1_srv_calculate_sign_mac(xconn, buf_out, seqnum);
235 652227 : if (!NT_STATUS_IS_OK(status)) {
236 0 : DBG_ERR("Failed to calculate signing mac: %s\n",
237 : nt_errstr(status));
238 0 : return false;
239 : }
240 : }
241 :
242 653887 : if (do_encrypt) {
243 185883 : NTSTATUS status = srv_encrypt_buffer(xconn, buffer, &buf_out);
244 185883 : if (!NT_STATUS_IS_OK(status)) {
245 0 : DEBUG(0, ("send_smb: SMB encryption failed "
246 : "on outgoing packet! Error %s\n",
247 : nt_errstr(status) ));
248 0 : ret = -1;
249 0 : goto out;
250 : }
251 : }
252 :
253 653887 : len = smb_len_large(buf_out) + 4;
254 :
255 653887 : ret = write_data(xconn->transport.sock, buf_out, len);
256 653887 : if (ret <= 0) {
257 83 : int saved_errno = errno;
258 : /*
259 : * Try and give an error message saying what
260 : * client failed.
261 : */
262 83 : DEBUG(1,("pid[%d] Error writing %d bytes to client %s. %d. (%s)\n",
263 : (int)getpid(), (int)len,
264 : smbXsrv_connection_dbg(xconn),
265 : (int)ret, strerror(saved_errno)));
266 83 : errno = saved_errno;
267 :
268 83 : srv_free_enc_buffer(xconn, buf_out);
269 83 : goto out;
270 : }
271 :
272 653804 : srv_free_enc_buffer(xconn, buf_out);
273 653887 : out:
274 653887 : smbd_unlock_socket(xconn);
275 653887 : return (ret > 0);
276 : }
277 :
278 : /* Socket functions for smbd packet processing. */
279 :
280 654040 : static bool valid_packet_size(size_t len)
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 :
287 654040 : if (len > (LARGE_WRITEX_BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
288 0 : DEBUG(0,("Invalid packet length! (%lu bytes).\n",
289 : (unsigned long)len));
290 0 : return false;
291 : }
292 646181 : return true;
293 : }
294 :
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 :
311 0 : static NTSTATUS receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx,
312 : const char lenbuf[4],
313 : struct smbXsrv_connection *xconn,
314 : int sock,
315 : char **buffer,
316 : unsigned int timeout,
317 : size_t *p_unread,
318 : size_t *len_ret)
319 : {
320 : /* Size of a WRITEX call (+4 byte len). */
321 0 : char writeX_header[4 + STANDARD_WRITE_AND_X_HEADER_SIZE];
322 0 : ssize_t len = smb_len_large(lenbuf); /* Could be a UNIX large writeX. */
323 0 : ssize_t toread;
324 0 : NTSTATUS status;
325 :
326 0 : memcpy(writeX_header, lenbuf, 4);
327 :
328 0 : status = read_fd_with_timeout(
329 : sock, writeX_header + 4,
330 : STANDARD_WRITE_AND_X_HEADER_SIZE,
331 : STANDARD_WRITE_AND_X_HEADER_SIZE,
332 : timeout, NULL);
333 :
334 0 : if (!NT_STATUS_IS_OK(status)) {
335 0 : DEBUG(0, ("read_fd_with_timeout failed for client %s read "
336 : "error = %s.\n",
337 : smbXsrv_connection_dbg(xconn),
338 : nt_errstr(status)));
339 0 : return status;
340 : }
341 :
342 : /*
343 : * Ok - now try and see if this is a possible
344 : * valid writeX call.
345 : */
346 :
347 0 : if (is_valid_writeX_buffer(xconn, (uint8_t *)writeX_header)) {
348 : /*
349 : * If the data offset is beyond what
350 : * we've read, drain the extra bytes.
351 : */
352 0 : uint16_t doff = SVAL(writeX_header,smb_vwv11);
353 0 : ssize_t newlen;
354 :
355 0 : if (doff > STANDARD_WRITE_AND_X_HEADER_SIZE) {
356 0 : size_t drain = doff - STANDARD_WRITE_AND_X_HEADER_SIZE;
357 0 : if (drain_socket(sock, drain) != drain) {
358 0 : smb_panic("receive_smb_raw_talloc_partial_read:"
359 : " failed to drain pending bytes");
360 : }
361 : } else {
362 0 : doff = STANDARD_WRITE_AND_X_HEADER_SIZE;
363 : }
364 :
365 : /* Spoof down the length and null out the bcc. */
366 0 : set_message_bcc(writeX_header, 0);
367 0 : newlen = smb_len(writeX_header);
368 :
369 : /* Copy the header we've written. */
370 :
371 0 : *buffer = (char *)talloc_memdup(mem_ctx,
372 : writeX_header,
373 : sizeof(writeX_header));
374 :
375 0 : if (*buffer == NULL) {
376 0 : DEBUG(0, ("Could not allocate inbuf of length %d\n",
377 : (int)sizeof(writeX_header)));
378 0 : return NT_STATUS_NO_MEMORY;
379 : }
380 :
381 : /* Work out the remaining bytes. */
382 0 : *p_unread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
383 0 : *len_ret = newlen + 4;
384 0 : return NT_STATUS_OK;
385 : }
386 :
387 0 : if (!valid_packet_size(len)) {
388 0 : return NT_STATUS_INVALID_PARAMETER;
389 : }
390 :
391 : /*
392 : * Not a valid writeX call. Just do the standard
393 : * talloc and return.
394 : */
395 :
396 0 : *buffer = talloc_array(mem_ctx, char, len+4);
397 :
398 0 : if (*buffer == NULL) {
399 0 : DEBUG(0, ("Could not allocate inbuf of length %d\n",
400 : (int)len+4));
401 0 : return NT_STATUS_NO_MEMORY;
402 : }
403 :
404 : /* Copy in what we already read. */
405 0 : memcpy(*buffer,
406 : writeX_header,
407 : 4 + STANDARD_WRITE_AND_X_HEADER_SIZE);
408 0 : toread = len - STANDARD_WRITE_AND_X_HEADER_SIZE;
409 :
410 0 : if(toread > 0) {
411 0 : status = read_packet_remainder(
412 : sock,
413 0 : (*buffer) + 4 + STANDARD_WRITE_AND_X_HEADER_SIZE,
414 : timeout, toread);
415 :
416 0 : if (!NT_STATUS_IS_OK(status)) {
417 0 : DEBUG(10, ("receive_smb_raw_talloc_partial_read: %s\n",
418 : nt_errstr(status)));
419 0 : return status;
420 : }
421 : }
422 :
423 0 : *len_ret = len + 4;
424 0 : return NT_STATUS_OK;
425 : }
426 :
427 659778 : static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx,
428 : struct smbXsrv_connection *xconn,
429 : int sock,
430 : char **buffer, unsigned int timeout,
431 : size_t *p_unread, size_t *plen)
432 : {
433 7992 : char lenbuf[4];
434 7992 : size_t len;
435 659778 : int min_recv_size = lp_min_receive_file_size();
436 7992 : NTSTATUS status;
437 :
438 659778 : *p_unread = 0;
439 :
440 659778 : status = read_smb_length_return_keepalive(sock, lenbuf, timeout,
441 : &len);
442 659778 : if (!NT_STATUS_IS_OK(status)) {
443 5738 : return status;
444 : }
445 :
446 654040 : if (CVAL(lenbuf,0) == 0 && min_recv_size &&
447 0 : (smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
448 0 : (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
449 0 : !smb1_srv_is_signing_active(xconn) &&
450 0 : xconn->smb1.echo_handler.trusted_fde == NULL) {
451 :
452 0 : return receive_smb_raw_talloc_partial_read(
453 : mem_ctx, lenbuf, xconn, sock, buffer, timeout,
454 : p_unread, plen);
455 : }
456 :
457 654040 : if (!valid_packet_size(len)) {
458 0 : return NT_STATUS_INVALID_PARAMETER;
459 : }
460 :
461 : /*
462 : * The +4 here can't wrap, we've checked the length above already.
463 : */
464 :
465 654040 : *buffer = talloc_array(mem_ctx, char, len+4);
466 :
467 654040 : if (*buffer == NULL) {
468 0 : DEBUG(0, ("Could not allocate inbuf of length %d\n",
469 : (int)len+4));
470 0 : return NT_STATUS_NO_MEMORY;
471 : }
472 :
473 654040 : memcpy(*buffer, lenbuf, sizeof(lenbuf));
474 :
475 654040 : status = read_packet_remainder(sock, (*buffer)+4, timeout, len);
476 654040 : if (!NT_STATUS_IS_OK(status)) {
477 0 : return status;
478 : }
479 :
480 654040 : *plen = len + 4;
481 654040 : return NT_STATUS_OK;
482 : }
483 :
484 659778 : NTSTATUS 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)
492 : {
493 659778 : size_t len = 0;
494 7992 : NTSTATUS status;
495 :
496 659778 : *p_encrypted = false;
497 :
498 659778 : status = receive_smb_raw_talloc(mem_ctx, xconn, sock, buffer, timeout,
499 : p_unread, &len);
500 659778 : if (!NT_STATUS_IS_OK(status)) {
501 5738 : 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",
504 : smbXsrv_connection_dbg(xconn),
505 : nt_errstr(status)) );
506 5738 : return status;
507 : }
508 :
509 654040 : if (is_encrypted_packet((uint8_t *)*buffer)) {
510 185879 : status = srv_decrypt_buffer(xconn, *buffer);
511 185879 : if (!NT_STATUS_IS_OK(status)) {
512 0 : DEBUG(0, ("receive_smb_talloc: SMB decryption failed on "
513 : "incoming packet! Error %s\n",
514 : nt_errstr(status) ));
515 0 : return status;
516 : }
517 185879 : *p_encrypted = true;
518 : }
519 :
520 : /* Check the incoming SMB signature. */
521 654040 : if (!smb1_srv_check_sign_mac(xconn, *buffer, seqnum, trusted_channel)) {
522 0 : DEBUG(0, ("receive_smb: SMB Signature verification failed on "
523 : "incoming packet!\n"));
524 0 : return NT_STATUS_INVALID_NETWORK_RESPONSE;
525 : }
526 :
527 654040 : *p_len = len;
528 654040 : return NT_STATUS_OK;
529 : }
530 :
531 : /****************************************************************************
532 : Function to push a message onto the tail of a linked list of smb messages ready
533 : for processing.
534 : ****************************************************************************/
535 :
536 3992 : static bool push_queued_message(struct smb_request *req,
537 : struct timeval request_time,
538 : struct timeval end_time,
539 : struct deferred_open_record *open_rec)
540 : {
541 3992 : int msg_len = smb_len(req->inbuf) + 4;
542 17 : struct pending_message_list *msg;
543 :
544 3992 : msg = talloc_zero(NULL, struct pending_message_list);
545 :
546 3992 : if(msg == NULL) {
547 0 : DEBUG(0,("push_message: malloc fail (1)\n"));
548 0 : return False;
549 : }
550 3992 : msg->sconn = req->sconn;
551 3992 : msg->xconn = req->xconn;
552 :
553 3992 : msg->buf = data_blob_talloc(msg, req->inbuf, msg_len);
554 3992 : if(msg->buf.data == NULL) {
555 0 : DEBUG(0,("push_message: malloc fail (2)\n"));
556 0 : TALLOC_FREE(msg);
557 0 : return False;
558 : }
559 :
560 3992 : msg->request_time = request_time;
561 3992 : msg->seqnum = req->seqnum;
562 3992 : msg->encrypted = req->encrypted;
563 3992 : msg->processed = false;
564 :
565 3992 : if (open_rec) {
566 3992 : msg->open_rec = talloc_move(msg, &open_rec);
567 : }
568 :
569 : #if 0
570 : msg->te = tevent_add_timer(msg->sconn->ev_ctx,
571 : msg,
572 : end_time,
573 : smbd_deferred_open_timer,
574 : msg);
575 : if (!msg->te) {
576 : DEBUG(0,("push_message: event_add_timed failed\n"));
577 : TALLOC_FREE(msg);
578 : return false;
579 : }
580 : #endif
581 :
582 3992 : DLIST_ADD_END(req->sconn->deferred_open_queue, msg);
583 :
584 3992 : DEBUG(10,("push_message: pushed message length %u on "
585 : "deferred_open_queue\n", (unsigned int)msg_len));
586 :
587 3975 : return True;
588 : }
589 :
590 : /****************************************************************************
591 : Function to push a deferred open smb message onto a linked list of local smb
592 : messages ready for processing.
593 : ****************************************************************************/
594 :
595 3992 : bool 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)
599 : {
600 17 : struct timeval_buf tvbuf;
601 17 : struct timeval end_time;
602 :
603 3992 : if (req->unread_bytes) {
604 0 : DEBUG(0,("push_deferred_open_message_smb: logic error ! "
605 : "unread_bytes = %u\n",
606 : (unsigned int)req->unread_bytes ));
607 0 : smb_panic("push_deferred_open_message_smb: "
608 : "logic error unread_bytes != 0" );
609 : }
610 :
611 3992 : end_time = timeval_sum(&req->request_time, &timeout);
612 :
613 3992 : 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));
617 :
618 3992 : return push_queued_message(req, req->request_time, end_time, open_rec);
619 : }
620 :
621 : /*
622 : * Only allow 5 outstanding trans requests. We're allocating memory, so
623 : * prevent a DoS.
624 : */
625 :
626 56439 : NTSTATUS allow_new_trans(struct trans_state *list, uint64_t mid)
627 : {
628 56439 : int count = 0;
629 56439 : for (; list != NULL; list = list->next) {
630 :
631 0 : if (list->mid == mid) {
632 0 : return NT_STATUS_INVALID_PARAMETER;
633 : }
634 :
635 0 : count += 1;
636 : }
637 56439 : if (count > 5) {
638 0 : return NT_STATUS_INSUFFICIENT_RESOURCES;
639 : }
640 :
641 56439 : return NT_STATUS_OK;
642 : }
643 :
644 : /*
645 : These flags determine some of the permissions required to do an operation
646 :
647 : Note that I don't set NEED_WRITE on some write operations because they
648 : are used by some brain-dead clients when printing, and I don't want to
649 : force write permissions on print services.
650 : */
651 : #define AS_USER (1<<0)
652 : #define NEED_WRITE (1<<1) /* Must be paired with AS_USER */
653 : #define TIME_INIT (1<<2)
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 */
656 : #define DO_CHDIR (1<<6)
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 : */
663 : static const struct smb_message_struct {
664 : const char *name;
665 : void (*fn)(struct smb_request *req);
666 : int flags;
667 : } smb_messages[256] = {
668 :
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 },
720 : /* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
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 }
925 :
926 : };
927 :
928 :
929 : /*******************************************************************
930 : Dump a packet to a file.
931 : ********************************************************************/
932 :
933 657755 : static void smb_dump(const char *name, int type, const char *data)
934 : {
935 7878 : size_t len;
936 7878 : int fd, i;
937 657755 : char *fname = NULL;
938 657755 : if (DEBUGLEVEL < 50) {
939 649877 : return;
940 : }
941 :
942 0 : len = smb_len_tcp(data)+4;
943 0 : for (i=1;i<100;i++) {
944 0 : fname = talloc_asprintf(talloc_tos(),
945 : "/tmp/%s.%d.%s",
946 : name,
947 : i,
948 : type ? "req" : "resp");
949 0 : if (fname == NULL) {
950 0 : return;
951 : }
952 0 : fd = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0644);
953 0 : if (fd != -1 || errno != EEXIST) break;
954 0 : TALLOC_FREE(fname);
955 : }
956 0 : if (fd != -1) {
957 0 : ssize_t ret = write(fd, data, len);
958 0 : if (ret != len)
959 0 : DEBUG(0,("smb_dump: problem: write returned %d\n", (int)ret ));
960 0 : close(fd);
961 0 : DEBUG(0,("created %s len %lu\n", fname, (unsigned long)len));
962 : }
963 0 : TALLOC_FREE(fname);
964 : }
965 :
966 644442 : static 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 644442 : connection_struct *conn = req->conn;
973 644442 : struct smbXsrv_tcon *tcon = conn ? conn->tcon : NULL;
974 644442 : uint8_t encrypt_flag = SMBXSRV_PROCESSED_UNENCRYPTED_PACKET;
975 644442 : uint8_t sign_flag = SMBXSRV_PROCESSED_UNSIGNED_PACKET;
976 644442 : bool update_session = false;
977 644442 : bool update_tcon = false;
978 :
979 644442 : if (req->encrypted) {
980 185905 : encrypt_flag = SMBXSRV_PROCESSED_ENCRYPTED_PACKET;
981 : }
982 :
983 644442 : if (smb1_srv_is_signing_active(req->xconn)) {
984 69127 : sign_flag = SMBXSRV_PROCESSED_SIGNED_PACKET;
985 567713 : } else if ((type == SMBecho) || (type == SMBsesssetupX)) {
986 : /*
987 : * echo can be unsigned. Session setup except final
988 : * session setup response too
989 : */
990 5834 : sign_flag &= ~SMBXSRV_PROCESSED_UNSIGNED_PACKET;
991 : }
992 :
993 1288884 : update_session |= smbXsrv_set_crypto_flag(
994 644442 : &session->global->encryption_flags, encrypt_flag);
995 1288884 : update_session |= smbXsrv_set_crypto_flag(
996 644442 : &session->global->signing_flags, sign_flag);
997 :
998 644442 : if (tcon) {
999 1254130 : update_tcon |= smbXsrv_set_crypto_flag(
1000 627065 : &tcon->global->encryption_flags, encrypt_flag);
1001 627065 : update_tcon |= smbXsrv_set_crypto_flag(
1002 627065 : &tcon->global->signing_flags, sign_flag);
1003 : }
1004 :
1005 644442 : if (update_session) {
1006 12273 : session->global->channels[0].encryption_cipher = SMB_ENCRYPTION_GSSAPI;
1007 : }
1008 :
1009 644442 : *update_session_globalp = update_session;
1010 644442 : *update_tcon_globalp = update_tcon;
1011 644442 : return;
1012 : }
1013 :
1014 356837 : static void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
1015 : {
1016 7314 : int snum;
1017 7314 : enum remote_arch_types ra_type;
1018 :
1019 356837 : SMB_ASSERT(conn != NULL);
1020 356837 : SMB_ASSERT(!conn_using_smb2(conn->sconn));
1021 :
1022 356837 : snum = SNUM(conn);
1023 :
1024 : /*
1025 : * Obey the client case sensitivity requests - only for clients that
1026 : * support it. */
1027 356837 : switch (lp_case_sensitive(snum)) {
1028 354429 : case Auto:
1029 : /*
1030 : * We need this ugliness due to DOS/Win9x clients that lie
1031 : * about case insensitivity. */
1032 354429 : ra_type = get_remote_arch();
1033 354429 : if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
1034 : /*
1035 : * Client can't support per-packet case sensitive
1036 : * pathnames. */
1037 8 : conn->case_sensitive = false;
1038 : } else {
1039 354421 : conn->case_sensitive =
1040 354421 : !(flags & FLAG_CASELESS_PATHNAMES);
1041 : }
1042 347115 : break;
1043 2408 : case True:
1044 2408 : conn->case_sensitive = true;
1045 2408 : break;
1046 0 : default:
1047 0 : conn->case_sensitive = false;
1048 0 : break;
1049 : }
1050 356837 : }
1051 :
1052 : /****************************************************************************
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.
1063 : ****************************************************************************/
1064 :
1065 657755 : static connection_struct *switch_message(uint8_t type, struct smb_request *req)
1066 : {
1067 7878 : const struct loadparm_substitution *lp_sub =
1068 657755 : loadparm_s3_global_substitution();
1069 7878 : int flags;
1070 7878 : uint64_t session_tag;
1071 657755 : connection_struct *conn = NULL;
1072 657755 : struct smbXsrv_connection *xconn = req->xconn;
1073 657755 : NTTIME now = timeval_to_nttime(&req->request_time);
1074 657755 : struct smbXsrv_session *session = NULL;
1075 7878 : NTSTATUS status;
1076 :
1077 657755 : errno = 0;
1078 :
1079 657755 : if (!xconn->smb1.negprot.done) {
1080 6140 : 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 5999 : case SMBnegprot:
1087 : case SMBsendstrt:
1088 : case SMBsendend:
1089 : case SMBsendtxt:
1090 5999 : break;
1091 0 : default:
1092 0 : exit_server_cleanly("The first request "
1093 : "should be a negprot");
1094 : }
1095 : }
1096 :
1097 657755 : if (smb_messages[type].fn == NULL) {
1098 0 : DEBUG(0,("Unknown message type %d!\n",type));
1099 0 : smb_dump("Unknown", 1, (const char *)req->inbuf);
1100 0 : reply_unknown_new(req, type);
1101 0 : return NULL;
1102 : }
1103 :
1104 657755 : flags = smb_messages[type].flags;
1105 :
1106 : /* In share mode security we must ignore the vuid. */
1107 657755 : session_tag = req->vuid;
1108 657755 : conn = req->conn;
1109 :
1110 657755 : DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type),
1111 : (int)getpid(), (unsigned long)conn));
1112 :
1113 657755 : smb_dump(smb_fn_name(type), 1, (const char *)req->inbuf);
1114 :
1115 : /* Ensure this value is replaced in the incoming packet. */
1116 657755 : SSVAL(discard_const_p(uint8_t, req->inbuf),smb_uid,session_tag);
1117 :
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
1123 : * know what you're doing... :-).
1124 : * JRA.
1125 : */
1126 :
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 : */
1133 657755 : status = smb1srv_session_lookup(xconn,
1134 : session_tag,
1135 : now,
1136 : &session);
1137 657755 : if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
1138 8 : switch (type) {
1139 4 : case SMBsesssetupX:
1140 4 : status = NT_STATUS_OK;
1141 4 : break;
1142 4 : default:
1143 4 : DEBUG(1,("Error: session %llu is expired, mid=%llu.\n",
1144 : (unsigned long long)session_tag,
1145 : (unsigned long long)req->mid));
1146 4 : reply_nterror(req, NT_STATUS_NETWORK_SESSION_EXPIRED);
1147 4 : return conn;
1148 : }
1149 : }
1150 :
1151 657751 : if (session != NULL &&
1152 644469 : session->global->auth_session_info != NULL &&
1153 638258 : !(flags & AS_USER))
1154 : {
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 : */
1162 281429 : set_current_user_info(
1163 281140 : session->global->auth_session_info->unix_info->sanitized_username,
1164 281429 : session->global->auth_session_info->unix_info->unix_name,
1165 281429 : session->global->auth_session_info->info->domain_name);
1166 : }
1167 :
1168 : /* Does this call need to be run as the connected user? */
1169 657751 : if (flags & AS_USER) {
1170 :
1171 : /* Does this call need a valid tree connection? */
1172 356858 : if (!conn) {
1173 : /*
1174 : * Amazingly, the error code depends on the command
1175 : * (from Samba4).
1176 : */
1177 21 : if (type == SMBntcreateX) {
1178 0 : reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1179 : } else {
1180 21 : reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
1181 : }
1182 21 : return NULL;
1183 : }
1184 :
1185 356837 : set_current_case_sensitive(conn, SVAL(req->inbuf,smb_flg));
1186 :
1187 : /*
1188 : * change_to_user() implies set_current_user_info()
1189 : * and chdir_connect_service().
1190 : */
1191 356837 : if (!change_to_user_and_service(conn,session_tag)) {
1192 17 : DEBUG(0, ("Error: Could not change to user. Removing "
1193 : "deferred open, mid=%llu.\n",
1194 : (unsigned long long)req->mid));
1195 17 : reply_force_doserror(req, ERRSRV, ERRbaduid);
1196 17 : return conn;
1197 : }
1198 :
1199 : /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */
1200 :
1201 : /* Does it need write permission? */
1202 356820 : if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) {
1203 4 : reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED);
1204 4 : return conn;
1205 : }
1206 :
1207 : /* IPC services are limited */
1208 356816 : if (IS_IPC(conn) && !(flags & CAN_IPC)) {
1209 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1210 0 : return conn;
1211 : }
1212 300893 : } 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 18 : if (!change_to_guest()) {
1218 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1219 0 : return conn;
1220 : }
1221 : } else {
1222 : /* This call needs to be run as root */
1223 300875 : change_to_root_user();
1224 : }
1225 :
1226 : /* load service specific parameters */
1227 657709 : if (conn) {
1228 627085 : if (req->encrypted) {
1229 185661 : conn->encrypted_tid = true;
1230 : /* encrypted required from now on. */
1231 185661 : conn->encrypt_level = SMB_SIGNING_REQUIRED;
1232 441424 : } else if (ENCRYPTION_REQUIRED(conn)) {
1233 14 : if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) {
1234 14 : DEBUG(1,("service[%s] requires encryption"
1235 : "%s ACCESS_DENIED. mid=%llu\n",
1236 : lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
1237 : smb_fn_name(type),
1238 : (unsigned long long)req->mid));
1239 14 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1240 14 : return conn;
1241 : }
1242 : }
1243 :
1244 627071 : if (flags & DO_CHDIR) {
1245 16 : bool ok;
1246 :
1247 7120 : ok = chdir_current_service(conn);
1248 7120 : if (!ok) {
1249 0 : reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1250 0 : return conn;
1251 : }
1252 : }
1253 627071 : conn->num_smb_operations++;
1254 : }
1255 :
1256 : /*
1257 : * Update encryption and signing state tracking flags that are
1258 : * used by smbstatus to display signing and encryption status.
1259 : */
1260 657695 : if (session != NULL) {
1261 644442 : bool update_session_global = false;
1262 644442 : bool update_tcon_global = false;
1263 :
1264 644442 : req->session = session;
1265 :
1266 644442 : smb1srv_update_crypto_flags(session, req, type,
1267 : &update_session_global,
1268 : &update_tcon_global);
1269 :
1270 644442 : if (update_session_global) {
1271 12273 : status = smbXsrv_session_update(session);
1272 12273 : if (!NT_STATUS_IS_OK(status)) {
1273 0 : reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1274 0 : return conn;
1275 : }
1276 : }
1277 :
1278 644442 : if (update_tcon_global) {
1279 9391 : status = smbXsrv_tcon_update(req->conn->tcon);
1280 9391 : if (!NT_STATUS_IS_OK(status)) {
1281 0 : reply_nterror(req, NT_STATUS_UNSUCCESSFUL);
1282 0 : return conn;
1283 : }
1284 : }
1285 : }
1286 :
1287 657695 : smb_messages[type].fn(req);
1288 657689 : return req->conn;
1289 : }
1290 :
1291 : /****************************************************************************
1292 : Construct a reply to the incoming packet.
1293 : ****************************************************************************/
1294 :
1295 657686 : void construct_reply(struct smbXsrv_connection *xconn,
1296 : char *inbuf,
1297 : int size,
1298 : size_t unread_bytes,
1299 : uint32_t seqnum,
1300 : bool encrypted)
1301 : {
1302 657686 : struct smbd_server_connection *sconn = xconn->client->sconn;
1303 7873 : struct smb_request *req;
1304 :
1305 657686 : if (!(req = talloc(talloc_tos(), struct smb_request))) {
1306 0 : smb_panic("could not allocate smb_request");
1307 : }
1308 :
1309 657686 : if (!init_smb1_request(req, sconn, xconn, (uint8_t *)inbuf, unread_bytes,
1310 : encrypted, seqnum)) {
1311 0 : exit_server_cleanly("Invalid SMB request");
1312 : }
1313 :
1314 657686 : req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
1315 :
1316 657686 : req->conn = switch_message(req->cmd, req);
1317 :
1318 657680 : if (req->outbuf == NULL) {
1319 : /*
1320 : * Request has suspended itself, will come
1321 : * back here.
1322 : */
1323 209444 : return;
1324 : }
1325 446727 : if (CVAL(req->outbuf,0) == 0) {
1326 446727 : show_msg((char *)req->outbuf);
1327 : }
1328 446727 : smb_request_done(req);
1329 : }
1330 :
1331 39 : static void construct_reply_chain(struct smbXsrv_connection *xconn,
1332 : char *inbuf,
1333 : int size,
1334 : uint32_t seqnum,
1335 : bool encrypted)
1336 : {
1337 39 : struct smb_request **reqs = NULL;
1338 3 : struct smb_request *req;
1339 3 : unsigned num_reqs;
1340 3 : bool ok;
1341 :
1342 39 : ok = smb1_parse_chain(xconn, (uint8_t *)inbuf, xconn, encrypted,
1343 : seqnum, &reqs, &num_reqs);
1344 39 : if (!ok) {
1345 0 : char errbuf[smb_size];
1346 0 : error_packet(errbuf, 0, 0, NT_STATUS_INVALID_PARAMETER,
1347 : __LINE__, __FILE__);
1348 0 : if (!smb1_srv_send(xconn, errbuf, true, seqnum, encrypted)) {
1349 0 : exit_server_cleanly("construct_reply_chain: "
1350 : "smb1_srv_send failed.");
1351 : }
1352 0 : return;
1353 : }
1354 :
1355 39 : req = reqs[0];
1356 39 : req->inbuf = (uint8_t *)talloc_move(reqs, &inbuf);
1357 :
1358 39 : req->conn = switch_message(req->cmd, req);
1359 :
1360 39 : if (req->outbuf == NULL) {
1361 : /*
1362 : * Request has suspended itself, will come
1363 : * back here.
1364 : */
1365 12 : return;
1366 : }
1367 27 : smb_request_done(req);
1368 : }
1369 :
1370 : /*
1371 : * To be called from an async SMB handler that is potentially chained
1372 : * when it is finished for shipping.
1373 : */
1374 :
1375 455721 : void smb_request_done(struct smb_request *req)
1376 : {
1377 455721 : struct smb_request **reqs = NULL;
1378 6512 : struct smb_request *first_req;
1379 6512 : size_t i, num_reqs, next_index;
1380 6512 : NTSTATUS status;
1381 :
1382 455721 : if (req->chain == NULL) {
1383 455694 : first_req = req;
1384 455694 : goto shipit;
1385 : }
1386 :
1387 27 : reqs = req->chain;
1388 27 : num_reqs = talloc_array_length(reqs);
1389 :
1390 27 : for (i=0; i<num_reqs; i++) {
1391 27 : if (reqs[i] == req) {
1392 24 : break;
1393 : }
1394 : }
1395 27 : if (i == num_reqs) {
1396 : /*
1397 : * Invalid chain, should not happen
1398 : */
1399 0 : status = NT_STATUS_INTERNAL_ERROR;
1400 0 : goto error;
1401 : }
1402 27 : next_index = i+1;
1403 :
1404 57 : while ((next_index < num_reqs) && (IVAL(req->outbuf, smb_rcls) == 0)) {
1405 30 : struct smb_request *next = reqs[next_index];
1406 2 : struct smbXsrv_tcon *tcon;
1407 30 : NTTIME now = timeval_to_nttime(&req->request_time);
1408 :
1409 30 : next->vuid = SVAL(req->outbuf, smb_uid);
1410 30 : next->tid = SVAL(req->outbuf, smb_tid);
1411 30 : status = smb1srv_tcon_lookup(req->xconn, next->tid,
1412 : now, &tcon);
1413 :
1414 30 : if (NT_STATUS_IS_OK(status)) {
1415 26 : next->conn = tcon->compat;
1416 : } else {
1417 4 : next->conn = NULL;
1418 : }
1419 30 : next->chain_fsp = req->chain_fsp;
1420 30 : next->inbuf = req->inbuf;
1421 :
1422 30 : req = next;
1423 30 : req->conn = switch_message(req->cmd, req);
1424 :
1425 30 : if (req->outbuf == NULL) {
1426 : /*
1427 : * Request has suspended itself, will come
1428 : * back here.
1429 : */
1430 0 : return;
1431 : }
1432 30 : next_index += 1;
1433 : }
1434 :
1435 27 : first_req = reqs[0];
1436 :
1437 57 : for (i=1; i<next_index; i++) {
1438 2 : bool ok;
1439 :
1440 30 : ok = smb_splice_chain(&first_req->outbuf, reqs[i]->outbuf);
1441 30 : if (!ok) {
1442 0 : status = NT_STATUS_INTERNAL_ERROR;
1443 0 : goto error;
1444 : }
1445 : }
1446 :
1447 27 : SSVAL(first_req->outbuf, smb_uid, SVAL(req->outbuf, smb_uid));
1448 27 : SSVAL(first_req->outbuf, smb_tid, SVAL(req->outbuf, smb_tid));
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 27 : SSVAL(first_req->outbuf, smb_flg2,
1456 : (SVAL(first_req->outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
1457 : |(SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
1458 :
1459 : /*
1460 : * Transfer the error codes from the subrequest to the main one
1461 : */
1462 27 : SSVAL(first_req->outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
1463 27 : SSVAL(first_req->outbuf, smb_err, SVAL(req->outbuf, smb_err));
1464 :
1465 27 : _smb_setlen_large(
1466 : first_req->outbuf, talloc_get_size(first_req->outbuf) - 4);
1467 :
1468 455721 : shipit:
1469 455721 : if (!smb1_srv_send(first_req->xconn,
1470 455721 : (char *)first_req->outbuf,
1471 : true,
1472 455721 : first_req->seqnum + 1,
1473 769657 : IS_CONN_ENCRYPTED(req->conn) ||
1474 320448 : first_req->encrypted)) {
1475 80 : exit_server_cleanly("construct_reply_chain: smb1_srv_send "
1476 : "failed.");
1477 : }
1478 455641 : TALLOC_FREE(req); /* non-chained case */
1479 455641 : TALLOC_FREE(reqs); /* chained case */
1480 449129 : return;
1481 :
1482 0 : error:
1483 : {
1484 0 : char errbuf[smb_size];
1485 0 : error_packet(errbuf, 0, 0, status, __LINE__, __FILE__);
1486 0 : if (!smb1_srv_send(req->xconn,
1487 : errbuf,
1488 : true,
1489 0 : req->seqnum + 1,
1490 0 : req->encrypted)) {
1491 0 : exit_server_cleanly("construct_reply_chain: "
1492 : "smb1_srv_send failed.");
1493 : }
1494 : }
1495 0 : TALLOC_FREE(req); /* non-chained case */
1496 0 : TALLOC_FREE(reqs); /* chained case */
1497 : }
1498 :
1499 : /****************************************************************************
1500 : Process an smb from the client
1501 : ****************************************************************************/
1502 :
1503 657737 : void process_smb1(struct smbXsrv_connection *xconn,
1504 : uint8_t *inbuf,
1505 : size_t nread,
1506 : size_t unread_bytes,
1507 : uint32_t seqnum,
1508 : bool encrypted)
1509 : {
1510 657737 : 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. */
1514 657737 : if ((nread < (smb_size - 4)) || !valid_smb1_header(inbuf)) {
1515 12 : DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",
1516 : smb_len(inbuf)));
1517 :
1518 : /* special magic for immediate exit */
1519 12 : if ((nread == 9) &&
1520 24 : (IVAL(inbuf, 4) == SMB_SUICIDE_PACKET) &&
1521 12 : lp_parm_bool(-1, "smbd", "suicide mode", false)) {
1522 12 : uint8_t exitcode = CVAL(inbuf, 8);
1523 12 : DBG_WARNING("SUICIDE: Exiting immediately with code %d\n",
1524 : (int)exitcode);
1525 12 : exit(exitcode);
1526 : }
1527 :
1528 0 : exit_server_cleanly("Non-SMB packet");
1529 : }
1530 :
1531 657725 : show_msg((char *)inbuf);
1532 :
1533 657725 : if ((unread_bytes == 0) && smb1_is_chain(inbuf)) {
1534 39 : construct_reply_chain(xconn,
1535 : (char *)inbuf,
1536 : nread,
1537 : seqnum,
1538 : encrypted);
1539 : } else {
1540 657686 : construct_reply(xconn,
1541 : (char *)inbuf,
1542 : nread,
1543 : unread_bytes,
1544 : seqnum,
1545 : encrypted);
1546 : }
1547 :
1548 657639 : sconn->trans_num++;
1549 657639 : }
1550 :
1551 : /****************************************************************************
1552 : Return a string containing the function name of a SMB command.
1553 : ****************************************************************************/
1554 :
1555 657769 : const char *smb_fn_name(int type)
1556 : {
1557 657769 : const char *unknown_name = "SMBunknown";
1558 :
1559 657769 : if (smb_messages[type].name == NULL)
1560 0 : return(unknown_name);
1561 :
1562 649891 : return(smb_messages[type].name);
1563 : }
1564 :
1565 : /****************************************************************************
1566 : Helper functions for contruct_reply.
1567 : ****************************************************************************/
1568 :
1569 5679 : void add_to_common_flags2(uint32_t v)
1570 : {
1571 5679 : common_flags2 |= v;
1572 5679 : }
1573 :
1574 32 : void remove_from_common_flags2(uint32_t v)
1575 : {
1576 32 : common_flags2 &= ~v;
1577 32 : }
1578 :
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 :
1589 30 : static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
1590 : {
1591 2 : uint8_t cmd;
1592 2 : size_t ofs;
1593 :
1594 30 : cmd = CVAL(buf, smb_com);
1595 :
1596 30 : if (!smb1cli_is_andx_req(cmd)) {
1597 0 : return false;
1598 : }
1599 :
1600 28 : ofs = smb_vwv0;
1601 :
1602 38 : while (CVAL(buf, ofs) != 0xff) {
1603 :
1604 8 : if (!smb1cli_is_andx_req(CVAL(buf, ofs))) {
1605 0 : 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 8 : ofs = SVAL(buf, ofs+2) + 4 + 1;
1613 :
1614 8 : if (ofs+4 >= talloc_get_size(buf)) {
1615 0 : return false;
1616 : }
1617 : }
1618 :
1619 30 : *pofs = ofs;
1620 30 : 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
1626 : * @param[in] andx_buf Buffer to be appended
1627 : */
1628 :
1629 30 : static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf)
1630 : {
1631 30 : uint8_t smb_command = CVAL(andx_buf, smb_com);
1632 30 : uint8_t wct = CVAL(andx_buf, smb_wct);
1633 30 : const uint16_t *vwv = (const uint16_t *)(andx_buf + smb_vwv);
1634 30 : uint32_t num_bytes = smb_buflen(andx_buf);
1635 30 : const uint8_t *bytes = (const uint8_t *)smb_buf_const(andx_buf);
1636 :
1637 2 : uint8_t *outbuf;
1638 2 : size_t old_size, new_size;
1639 2 : size_t ofs;
1640 30 : size_t chain_padding = 0;
1641 2 : size_t andx_cmd_ofs;
1642 :
1643 :
1644 30 : old_size = talloc_get_size(*poutbuf);
1645 :
1646 30 : if ((old_size % 4) != 0) {
1647 : /*
1648 : * Align the wct field of subsequent requests to a 4-byte
1649 : * boundary
1650 : */
1651 30 : chain_padding = 4 - (old_size % 4);
1652 : }
1653 :
1654 : /*
1655 : * After the old request comes the new wct field (1 byte), the vwv's
1656 : * and the num_bytes field.
1657 : */
1658 :
1659 30 : new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
1660 30 : new_size += num_bytes;
1661 :
1662 30 : if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
1663 0 : DEBUG(1, ("smb_splice_chain: %u bytes won't fit\n",
1664 : (unsigned)new_size));
1665 0 : return false;
1666 : }
1667 :
1668 30 : outbuf = talloc_realloc(NULL, *poutbuf, uint8_t, new_size);
1669 30 : if (outbuf == NULL) {
1670 0 : DEBUG(0, ("talloc failed\n"));
1671 0 : return false;
1672 : }
1673 30 : *poutbuf = outbuf;
1674 :
1675 30 : if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
1676 0 : DEBUG(1, ("invalid command chain\n"));
1677 0 : *poutbuf = talloc_realloc(NULL, *poutbuf, uint8_t, old_size);
1678 0 : return false;
1679 : }
1680 :
1681 30 : if (chain_padding != 0) {
1682 30 : memset(outbuf + old_size, 0, chain_padding);
1683 30 : old_size += chain_padding;
1684 : }
1685 :
1686 30 : SCVAL(outbuf, andx_cmd_ofs, smb_command);
1687 30 : SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
1688 :
1689 30 : ofs = old_size;
1690 :
1691 : /*
1692 : * Push the chained request:
1693 : *
1694 : * wct field
1695 : */
1696 :
1697 30 : SCVAL(outbuf, ofs, wct);
1698 30 : ofs += 1;
1699 :
1700 : /*
1701 : * vwv array
1702 : */
1703 :
1704 30 : memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
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 30 : if (smb_command == SMBreadX) {
1720 2 : uint8_t *bytes_addr;
1721 :
1722 10 : if (wct < 7) {
1723 : /*
1724 : * Invalid read&x response
1725 : */
1726 0 : return false;
1727 : }
1728 :
1729 10 : bytes_addr = outbuf + ofs /* vwv start */
1730 10 : + sizeof(uint16_t) * wct /* vwv array */
1731 : + sizeof(uint16_t) /* bcc */
1732 10 : + 1; /* padding byte */
1733 :
1734 10 : SSVAL(outbuf + ofs, 6 * sizeof(uint16_t),
1735 : bytes_addr - outbuf - 4);
1736 : }
1737 :
1738 30 : ofs += sizeof(uint16_t) * wct;
1739 :
1740 : /*
1741 : * bcc (byte count)
1742 : */
1743 :
1744 30 : SSVAL(outbuf, ofs, num_bytes);
1745 30 : ofs += sizeof(uint16_t);
1746 :
1747 : /*
1748 : * The bytes field
1749 : */
1750 :
1751 30 : memcpy(outbuf + ofs, bytes, num_bytes);
1752 :
1753 30 : return true;
1754 : }
1755 :
1756 657725 : bool smb1_is_chain(const uint8_t *buf)
1757 : {
1758 7876 : uint8_t cmd, wct, andx_cmd;
1759 :
1760 657725 : cmd = CVAL(buf, smb_com);
1761 657725 : if (!smb1cli_is_andx_req(cmd)) {
1762 434924 : return false;
1763 : }
1764 215935 : wct = CVAL(buf, smb_wct);
1765 215935 : if (wct < 2) {
1766 0 : return false;
1767 : }
1768 215935 : andx_cmd = CVAL(buf, smb_vwv);
1769 215935 : return (andx_cmd != 0xFF);
1770 : }
1771 :
1772 39 : bool 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 39 : size_t smblen = smb_len(buf);
1780 39 : const char *smb_buf = smb_base(buf);
1781 3 : uint8_t cmd, chain_cmd;
1782 3 : uint8_t wct;
1783 3 : const uint16_t *vwv;
1784 3 : uint16_t num_bytes;
1785 3 : const uint8_t *bytes;
1786 :
1787 39 : cmd = CVAL(buf, smb_com);
1788 39 : wct = CVAL(buf, smb_wct);
1789 39 : vwv = (const uint16_t *)(buf + smb_vwv);
1790 39 : num_bytes = smb_buflen(buf);
1791 39 : bytes = (const uint8_t *)smb_buf_const(buf);
1792 :
1793 39 : if (!fn(cmd, wct, vwv, num_bytes, bytes, private_data)) {
1794 0 : return false;
1795 : }
1796 :
1797 39 : if (!smb1cli_is_andx_req(cmd)) {
1798 0 : return true;
1799 : }
1800 39 : if (wct < 2) {
1801 0 : return false;
1802 : }
1803 :
1804 39 : chain_cmd = CVAL(vwv, 0);
1805 :
1806 78 : while (chain_cmd != 0xff) {
1807 3 : uint32_t chain_offset; /* uint32_t to avoid overflow */
1808 3 : size_t length_needed;
1809 3 : ptrdiff_t vwv_offset;
1810 :
1811 51 : 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 51 : vwv_offset = ((const char *)vwv - smb_buf);
1833 51 : if (chain_offset <= vwv_offset) {
1834 0 : 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 51 : length_needed = chain_offset+1; /* wct */
1843 51 : if (length_needed > smblen) {
1844 0 : 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 51 : wct = CVAL(smb_buf, chain_offset);
1854 :
1855 51 : if (smb1cli_is_andx_req(chain_cmd) && (wct < 2)) {
1856 0 : return false;
1857 : }
1858 :
1859 : /*
1860 : * Next consistency check: Make the new vwv array fits
1861 : * in the overall smb request.
1862 : */
1863 :
1864 51 : length_needed += (wct+1)*sizeof(uint16_t); /* vwv+buflen */
1865 51 : if (length_needed > smblen) {
1866 0 : return false;
1867 : }
1868 51 : vwv = (const uint16_t *)(smb_buf + chain_offset + 1);
1869 :
1870 : /*
1871 : * Now grab the new byte buffer....
1872 : */
1873 :
1874 51 : num_bytes = SVAL(vwv+wct, 0);
1875 :
1876 : /*
1877 : * .. and check that it fits.
1878 : */
1879 :
1880 51 : length_needed += num_bytes;
1881 51 : if (length_needed > smblen) {
1882 0 : return false;
1883 : }
1884 51 : bytes = (const uint8_t *)(vwv+wct+1);
1885 :
1886 51 : if (!fn(chain_cmd, wct, vwv, num_bytes, bytes, private_data)) {
1887 0 : return false;
1888 : }
1889 :
1890 51 : if (!smb1cli_is_andx_req(chain_cmd)) {
1891 12 : return true;
1892 : }
1893 39 : chain_cmd = CVAL(vwv, 0);
1894 : }
1895 24 : return true;
1896 : }
1897 :
1898 0 : static 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 0 : unsigned *count = (unsigned *)private_data;
1904 0 : *count += 1;
1905 0 : return true;
1906 : }
1907 :
1908 0 : unsigned smb1_chain_length(const uint8_t *buf)
1909 : {
1910 0 : unsigned count = 0;
1911 :
1912 0 : if (!smb1_walk_chain(buf, smb1_chain_length_cb, &count)) {
1913 0 : return 0;
1914 : }
1915 0 : return count;
1916 : }
1917 :
1918 : struct smb1_parse_chain_state {
1919 : TALLOC_CTX *mem_ctx;
1920 : const uint8_t *buf;
1921 : struct smbd_server_connection *sconn;
1922 : struct smbXsrv_connection *xconn;
1923 : bool encrypted;
1924 : uint32_t seqnum;
1925 :
1926 : struct smb_request **reqs;
1927 : unsigned num_reqs;
1928 : };
1929 :
1930 90 : static 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 90 : struct smb1_parse_chain_state *state =
1936 : (struct smb1_parse_chain_state *)private_data;
1937 6 : struct smb_request **reqs;
1938 6 : struct smb_request *req;
1939 6 : bool ok;
1940 :
1941 90 : reqs = talloc_realloc(state->mem_ctx, state->reqs,
1942 : struct smb_request *, state->num_reqs+1);
1943 90 : if (reqs == NULL) {
1944 0 : return false;
1945 : }
1946 90 : state->reqs = reqs;
1947 :
1948 90 : req = talloc(reqs, struct smb_request);
1949 90 : if (req == NULL) {
1950 0 : return false;
1951 : }
1952 :
1953 96 : ok = init_smb1_request(req, state->sconn, state->xconn, state->buf, 0,
1954 90 : state->encrypted, state->seqnum);
1955 90 : if (!ok) {
1956 0 : return false;
1957 : }
1958 90 : req->cmd = cmd;
1959 90 : req->wct = wct;
1960 90 : req->vwv = vwv;
1961 90 : req->buflen = num_bytes;
1962 90 : req->buf = bytes;
1963 :
1964 90 : reqs[state->num_reqs] = req;
1965 90 : state->num_reqs += 1;
1966 90 : return true;
1967 : }
1968 :
1969 39 : bool smb1_parse_chain(TALLOC_CTX *mem_ctx, const uint8_t *buf,
1970 : struct smbXsrv_connection *xconn,
1971 : bool encrypted, uint32_t seqnum,
1972 : struct smb_request ***reqs, unsigned *num_reqs)
1973 : {
1974 39 : struct smbd_server_connection *sconn = NULL;
1975 3 : struct smb1_parse_chain_state state;
1976 3 : unsigned i;
1977 :
1978 39 : if (xconn != NULL) {
1979 39 : sconn = xconn->client->sconn;
1980 : }
1981 :
1982 39 : state.mem_ctx = mem_ctx;
1983 39 : state.buf = buf;
1984 39 : state.sconn = sconn;
1985 39 : state.xconn = xconn;
1986 39 : state.encrypted = encrypted;
1987 39 : state.seqnum = seqnum;
1988 39 : state.reqs = NULL;
1989 39 : state.num_reqs = 0;
1990 :
1991 39 : if (!smb1_walk_chain(buf, smb1_parse_chain_cb, &state)) {
1992 0 : TALLOC_FREE(state.reqs);
1993 0 : return false;
1994 : }
1995 129 : for (i=0; i<state.num_reqs; i++) {
1996 90 : state.reqs[i]->chain = state.reqs;
1997 : }
1998 39 : *reqs = state.reqs;
1999 39 : *num_reqs = state.num_reqs;
2000 39 : return true;
2001 : }
2002 :
2003 0 : static bool fd_is_readable(int fd)
2004 : {
2005 0 : int ret, revents;
2006 :
2007 0 : ret = poll_one_fd(fd, POLLIN|POLLHUP, 0, &revents);
2008 :
2009 0 : return ((ret > 0) && ((revents & (POLLIN|POLLHUP|POLLERR)) != 0));
2010 :
2011 : }
2012 :
2013 0 : static void smbd_server_connection_write_handler(
2014 : struct smbXsrv_connection *xconn)
2015 : {
2016 : /* TODO: make write nonblocking */
2017 0 : }
2018 :
2019 659778 : void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
2020 : int fd)
2021 : {
2022 659778 : uint8_t *inbuf = NULL;
2023 659778 : size_t inbuf_len = 0;
2024 659778 : size_t unread_bytes = 0;
2025 659778 : bool encrypted = false;
2026 659778 : TALLOC_CTX *mem_ctx = talloc_tos();
2027 7992 : NTSTATUS status;
2028 7992 : uint32_t seqnum;
2029 :
2030 659778 : bool async_echo = lp_async_smb_echo_handler();
2031 659778 : bool from_client = false;
2032 :
2033 659778 : if (async_echo) {
2034 0 : if (fd_is_readable(xconn->smb1.echo_handler.trusted_fd)) {
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 : */
2040 0 : fd = xconn->smb1.echo_handler.trusted_fd;
2041 : }
2042 : }
2043 :
2044 659778 : from_client = (xconn->transport.sock == fd);
2045 :
2046 659778 : if (async_echo && from_client) {
2047 0 : smbd_lock_socket(xconn);
2048 :
2049 0 : if (!fd_is_readable(fd)) {
2050 0 : DEBUG(10,("the echo listener was faster\n"));
2051 0 : smbd_unlock_socket(xconn);
2052 0 : return;
2053 : }
2054 : }
2055 :
2056 : /* TODO: make this completely nonblocking */
2057 667770 : status = receive_smb_talloc(mem_ctx, xconn, fd,
2058 : (char **)(void *)&inbuf,
2059 : 0, /* timeout */
2060 : &unread_bytes,
2061 : &encrypted,
2062 : &inbuf_len, &seqnum,
2063 659778 : !from_client /* trusted channel */);
2064 :
2065 659778 : if (async_echo && from_client) {
2066 0 : smbd_unlock_socket(xconn);
2067 : }
2068 :
2069 659778 : if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
2070 0 : goto process;
2071 : }
2072 659778 : if (NT_STATUS_IS_ERR(status)) {
2073 5738 : exit_server_cleanly("failed to receive smb request");
2074 : }
2075 654040 : if (!NT_STATUS_IS_OK(status)) {
2076 0 : return;
2077 : }
2078 :
2079 654040 : process:
2080 654040 : process_smb(xconn, inbuf, inbuf_len, unread_bytes, seqnum, encrypted);
2081 : }
2082 :
2083 0 : static void smbd_server_echo_handler(struct tevent_context *ev,
2084 : struct tevent_fd *fde,
2085 : uint16_t flags,
2086 : void *private_data)
2087 : {
2088 0 : struct smbXsrv_connection *xconn =
2089 0 : talloc_get_type_abort(private_data,
2090 : struct smbXsrv_connection);
2091 :
2092 0 : if (!NT_STATUS_IS_OK(xconn->transport.status)) {
2093 : /*
2094 : * we're not supposed to do any io
2095 : */
2096 0 : TEVENT_FD_NOT_READABLE(xconn->smb1.echo_handler.trusted_fde);
2097 0 : TEVENT_FD_NOT_WRITEABLE(xconn->smb1.echo_handler.trusted_fde);
2098 0 : return;
2099 : }
2100 :
2101 0 : if (flags & TEVENT_FD_WRITE) {
2102 0 : smbd_server_connection_write_handler(xconn);
2103 0 : return;
2104 : }
2105 0 : if (flags & TEVENT_FD_READ) {
2106 0 : smbd_smb1_server_connection_read_handler(
2107 : xconn, xconn->smb1.echo_handler.trusted_fd);
2108 0 : return;
2109 : }
2110 : }
2111 :
2112 : /*
2113 : * Send keepalive packets to our client
2114 : */
2115 33 : bool keepalive_fn(const struct timeval *now, void *private_data)
2116 : {
2117 33 : struct smbd_server_connection *sconn = talloc_get_type_abort(
2118 : private_data, struct smbd_server_connection);
2119 33 : struct smbXsrv_connection *xconn = NULL;
2120 0 : bool ret;
2121 :
2122 33 : if (conn_using_smb2(sconn)) {
2123 : /* Don't do keepalives on an SMB2 connection. */
2124 33 : return false;
2125 : }
2126 :
2127 : /*
2128 : * With SMB1 we only have 1 connection
2129 : */
2130 0 : xconn = sconn->client->connections;
2131 0 : smbd_lock_socket(xconn);
2132 0 : ret = send_keepalive(xconn->transport.sock);
2133 0 : smbd_unlock_socket(xconn);
2134 :
2135 0 : if (!ret) {
2136 0 : int saved_errno = errno;
2137 : /*
2138 : * Try and give an error message saying what
2139 : * client failed.
2140 : */
2141 0 : DEBUG(0, ("send_keepalive failed for client %s. "
2142 : "Error %s - exiting\n",
2143 : smbXsrv_connection_dbg(xconn),
2144 : strerror(saved_errno)));
2145 0 : errno = saved_errno;
2146 0 : return False;
2147 : }
2148 0 : return True;
2149 : }
2150 :
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 :
2156 : struct smbd_echo_read_state {
2157 : struct tevent_context *ev;
2158 : struct smbXsrv_connection *xconn;
2159 :
2160 : char *buf;
2161 : size_t buflen;
2162 : uint32_t seqnum;
2163 : };
2164 :
2165 : static void smbd_echo_read_readable(struct tevent_req *subreq);
2166 : static void smbd_echo_read_waited(struct tevent_req *subreq);
2167 :
2168 0 : static struct tevent_req *smbd_echo_read_send(
2169 : TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2170 : struct smbXsrv_connection *xconn)
2171 : {
2172 0 : struct tevent_req *req, *subreq;
2173 0 : struct smbd_echo_read_state *state;
2174 :
2175 0 : req = tevent_req_create(mem_ctx, &state,
2176 : struct smbd_echo_read_state);
2177 0 : if (req == NULL) {
2178 0 : return NULL;
2179 : }
2180 0 : state->ev = ev;
2181 0 : state->xconn = xconn;
2182 :
2183 0 : subreq = wait_for_read_send(state, ev, xconn->transport.sock, false);
2184 0 : if (tevent_req_nomem(subreq, req)) {
2185 0 : return tevent_req_post(req, ev);
2186 : }
2187 0 : tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2188 0 : return req;
2189 : }
2190 :
2191 0 : static void smbd_echo_read_readable(struct tevent_req *subreq)
2192 : {
2193 0 : struct tevent_req *req = tevent_req_callback_data(
2194 : subreq, struct tevent_req);
2195 0 : struct smbd_echo_read_state *state = tevent_req_data(
2196 : req, struct smbd_echo_read_state);
2197 0 : bool ok;
2198 0 : int err;
2199 :
2200 0 : ok = wait_for_read_recv(subreq, &err);
2201 0 : TALLOC_FREE(subreq);
2202 0 : if (!ok) {
2203 0 : tevent_req_nterror(req, map_nt_error_from_unix(err));
2204 0 : return;
2205 : }
2206 :
2207 : /*
2208 : * Give the parent smbd one second to step in
2209 : */
2210 :
2211 0 : subreq = tevent_wakeup_send(
2212 : state, state->ev, timeval_current_ofs(1, 0));
2213 0 : if (tevent_req_nomem(subreq, req)) {
2214 0 : return;
2215 : }
2216 0 : tevent_req_set_callback(subreq, smbd_echo_read_waited, req);
2217 : }
2218 :
2219 0 : static void smbd_echo_read_waited(struct tevent_req *subreq)
2220 : {
2221 0 : struct tevent_req *req = tevent_req_callback_data(
2222 : subreq, struct tevent_req);
2223 0 : struct smbd_echo_read_state *state = tevent_req_data(
2224 : req, struct smbd_echo_read_state);
2225 0 : struct smbXsrv_connection *xconn = state->xconn;
2226 0 : bool ok;
2227 0 : NTSTATUS status;
2228 0 : size_t unread = 0;
2229 0 : bool encrypted;
2230 :
2231 0 : ok = tevent_wakeup_recv(subreq);
2232 0 : TALLOC_FREE(subreq);
2233 0 : if (!ok) {
2234 0 : tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
2235 0 : return;
2236 : }
2237 :
2238 0 : ok = smbd_lock_socket_internal(xconn);
2239 0 : if (!ok) {
2240 0 : tevent_req_nterror(req, map_nt_error_from_unix(errno));
2241 0 : DEBUG(0, ("%s: failed to lock socket\n", __location__));
2242 0 : return;
2243 : }
2244 :
2245 0 : if (!fd_is_readable(xconn->transport.sock)) {
2246 0 : DEBUG(10,("echo_handler[%d] the parent smbd was faster\n",
2247 : (int)getpid()));
2248 :
2249 0 : ok = smbd_unlock_socket_internal(xconn);
2250 0 : if (!ok) {
2251 0 : tevent_req_nterror(req, map_nt_error_from_unix(errno));
2252 0 : DEBUG(1, ("%s: failed to unlock socket\n",
2253 : __location__));
2254 0 : return;
2255 : }
2256 :
2257 0 : subreq = wait_for_read_send(state, state->ev,
2258 : xconn->transport.sock, false);
2259 0 : if (tevent_req_nomem(subreq, req)) {
2260 0 : return;
2261 : }
2262 0 : tevent_req_set_callback(subreq, smbd_echo_read_readable, req);
2263 0 : return;
2264 : }
2265 :
2266 0 : status = receive_smb_talloc(state, xconn,
2267 : xconn->transport.sock,
2268 : &state->buf,
2269 : 0 /* timeout */,
2270 : &unread,
2271 : &encrypted,
2272 : &state->buflen,
2273 : &state->seqnum,
2274 : false /* trusted_channel*/);
2275 :
2276 0 : if (tevent_req_nterror(req, status)) {
2277 0 : tevent_req_nterror(req, status);
2278 0 : DEBUG(1, ("echo_handler[%d]: receive_smb_raw_talloc failed: %s\n",
2279 : (int)getpid(), nt_errstr(status)));
2280 0 : return;
2281 : }
2282 :
2283 0 : ok = smbd_unlock_socket_internal(xconn);
2284 0 : if (!ok) {
2285 0 : tevent_req_nterror(req, map_nt_error_from_unix(errno));
2286 0 : DEBUG(1, ("%s: failed to unlock socket\n", __location__));
2287 0 : return;
2288 : }
2289 0 : tevent_req_done(req);
2290 : }
2291 :
2292 0 : static NTSTATUS smbd_echo_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
2293 : char **pbuf, size_t *pbuflen, uint32_t *pseqnum)
2294 : {
2295 0 : struct smbd_echo_read_state *state = tevent_req_data(
2296 : req, struct smbd_echo_read_state);
2297 0 : NTSTATUS status;
2298 :
2299 0 : if (tevent_req_is_nterror(req, &status)) {
2300 0 : return status;
2301 : }
2302 0 : *pbuf = talloc_move(mem_ctx, &state->buf);
2303 0 : *pbuflen = state->buflen;
2304 0 : *pseqnum = state->seqnum;
2305 0 : return NT_STATUS_OK;
2306 : }
2307 :
2308 : struct smbd_echo_state {
2309 : struct tevent_context *ev;
2310 : struct iovec *pending;
2311 : struct smbd_server_connection *sconn;
2312 : struct smbXsrv_connection *xconn;
2313 : int parent_pipe;
2314 :
2315 : struct tevent_fd *parent_fde;
2316 :
2317 : struct tevent_req *write_req;
2318 : };
2319 :
2320 : static void smbd_echo_writer_done(struct tevent_req *req);
2321 :
2322 0 : static void smbd_echo_activate_writer(struct smbd_echo_state *state)
2323 : {
2324 0 : int num_pending;
2325 :
2326 0 : if (state->write_req != NULL) {
2327 0 : return;
2328 : }
2329 :
2330 0 : num_pending = talloc_array_length(state->pending);
2331 0 : if (num_pending == 0) {
2332 0 : return;
2333 : }
2334 :
2335 0 : state->write_req = writev_send(state, state->ev, NULL,
2336 : state->parent_pipe, false,
2337 : state->pending, num_pending);
2338 0 : if (state->write_req == NULL) {
2339 0 : DEBUG(1, ("writev_send failed\n"));
2340 0 : exit(1);
2341 : }
2342 :
2343 0 : talloc_steal(state->write_req, state->pending);
2344 0 : state->pending = NULL;
2345 :
2346 0 : tevent_req_set_callback(state->write_req, smbd_echo_writer_done,
2347 : state);
2348 : }
2349 :
2350 0 : static void smbd_echo_writer_done(struct tevent_req *req)
2351 : {
2352 0 : struct smbd_echo_state *state = tevent_req_callback_data(
2353 : req, struct smbd_echo_state);
2354 0 : ssize_t written;
2355 0 : int err;
2356 :
2357 0 : written = writev_recv(req, &err);
2358 0 : TALLOC_FREE(req);
2359 0 : state->write_req = NULL;
2360 0 : if (written == -1) {
2361 0 : DEBUG(1, ("writev to parent failed: %s\n", strerror(err)));
2362 0 : exit(1);
2363 : }
2364 0 : DEBUG(10,("echo_handler[%d]: forwarded pdu to main\n", (int)getpid()));
2365 0 : smbd_echo_activate_writer(state);
2366 0 : }
2367 :
2368 0 : static bool smbd_echo_reply(struct smbd_echo_state *state,
2369 : uint8_t *inbuf, size_t inbuf_len,
2370 : uint32_t seqnum)
2371 : {
2372 0 : struct smb_request req;
2373 0 : uint16_t num_replies;
2374 0 : char *outbuf;
2375 0 : bool ok;
2376 :
2377 0 : if ((inbuf_len == 4) && (CVAL(inbuf, 0) == NBSSkeepalive)) {
2378 0 : DEBUG(10, ("Got netbios keepalive\n"));
2379 : /*
2380 : * Just swallow it
2381 : */
2382 0 : return true;
2383 : }
2384 :
2385 0 : if (inbuf_len < smb_size) {
2386 0 : DEBUG(10, ("Got short packet: %d bytes\n", (int)inbuf_len));
2387 0 : return false;
2388 : }
2389 0 : if (!valid_smb1_header(inbuf)) {
2390 0 : DEBUG(10, ("Got invalid SMB header\n"));
2391 0 : return false;
2392 : }
2393 :
2394 0 : if (!init_smb1_request(&req, state->sconn, state->xconn, inbuf, 0, false,
2395 : seqnum)) {
2396 0 : return false;
2397 : }
2398 0 : req.inbuf = inbuf;
2399 :
2400 0 : DEBUG(10, ("smbecho handler got cmd %d (%s)\n", (int)req.cmd,
2401 : smb_fn_name(req.cmd)));
2402 :
2403 0 : if (req.cmd != SMBecho) {
2404 0 : return false;
2405 : }
2406 0 : if (req.wct < 1) {
2407 0 : return false;
2408 : }
2409 :
2410 0 : num_replies = SVAL(req.vwv+0, 0);
2411 0 : if (num_replies != 1) {
2412 : /* Not a Windows "Hey, you're still there?" request */
2413 0 : return false;
2414 : }
2415 :
2416 0 : if (!create_smb1_outbuf(talloc_tos(), &req, req.inbuf, &outbuf,
2417 0 : 1, req.buflen)) {
2418 0 : DEBUG(10, ("create_smb1_outbuf failed\n"));
2419 0 : return false;
2420 : }
2421 0 : req.outbuf = (uint8_t *)outbuf;
2422 :
2423 0 : SSVAL(req.outbuf, smb_vwv0, num_replies);
2424 :
2425 0 : if (req.buflen > 0) {
2426 0 : memcpy(smb_buf(req.outbuf), req.buf, req.buflen);
2427 : }
2428 :
2429 0 : ok = smb1_srv_send(req.xconn, (char *)outbuf, true, seqnum + 1, false);
2430 0 : TALLOC_FREE(outbuf);
2431 0 : if (!ok) {
2432 0 : exit(1);
2433 : }
2434 :
2435 0 : return true;
2436 : }
2437 :
2438 0 : static void smbd_echo_exit(struct tevent_context *ev,
2439 : struct tevent_fd *fde, uint16_t flags,
2440 : void *private_data)
2441 : {
2442 0 : DEBUG(2, ("smbd_echo_exit: lost connection to parent\n"));
2443 0 : exit(0);
2444 : }
2445 :
2446 : static void smbd_echo_got_packet(struct tevent_req *req);
2447 :
2448 0 : static void smbd_echo_loop(struct smbXsrv_connection *xconn,
2449 : int parent_pipe)
2450 : {
2451 0 : struct smbd_echo_state *state;
2452 0 : struct tevent_req *read_req;
2453 :
2454 0 : state = talloc_zero(xconn, struct smbd_echo_state);
2455 0 : if (state == NULL) {
2456 0 : DEBUG(1, ("talloc failed\n"));
2457 0 : return;
2458 : }
2459 0 : state->xconn = xconn;
2460 0 : state->parent_pipe = parent_pipe;
2461 0 : state->ev = samba_tevent_context_init(state);
2462 0 : if (state->ev == NULL) {
2463 0 : DEBUG(1, ("samba_tevent_context_init failed\n"));
2464 0 : TALLOC_FREE(state);
2465 0 : return;
2466 : }
2467 0 : state->parent_fde = tevent_add_fd(state->ev, state, parent_pipe,
2468 : TEVENT_FD_READ, smbd_echo_exit,
2469 : state);
2470 0 : if (state->parent_fde == NULL) {
2471 0 : DEBUG(1, ("tevent_add_fd failed\n"));
2472 0 : TALLOC_FREE(state);
2473 0 : return;
2474 : }
2475 :
2476 0 : read_req = smbd_echo_read_send(state, state->ev, xconn);
2477 0 : if (read_req == NULL) {
2478 0 : DEBUG(1, ("smbd_echo_read_send failed\n"));
2479 0 : TALLOC_FREE(state);
2480 0 : return;
2481 : }
2482 0 : tevent_req_set_callback(read_req, smbd_echo_got_packet, state);
2483 :
2484 0 : while (true) {
2485 0 : if (tevent_loop_once(state->ev) == -1) {
2486 0 : DEBUG(1, ("tevent_loop_once failed: %s\n",
2487 : strerror(errno)));
2488 0 : break;
2489 : }
2490 : }
2491 0 : TALLOC_FREE(state);
2492 : }
2493 :
2494 0 : static void smbd_echo_got_packet(struct tevent_req *req)
2495 : {
2496 0 : struct smbd_echo_state *state = tevent_req_callback_data(
2497 : req, struct smbd_echo_state);
2498 0 : NTSTATUS status;
2499 0 : char *buf = NULL;
2500 0 : size_t buflen = 0;
2501 0 : uint32_t seqnum = 0;
2502 0 : bool reply;
2503 :
2504 0 : status = smbd_echo_read_recv(req, state, &buf, &buflen, &seqnum);
2505 0 : TALLOC_FREE(req);
2506 0 : if (!NT_STATUS_IS_OK(status)) {
2507 0 : DEBUG(1, ("smbd_echo_read_recv returned %s\n",
2508 : nt_errstr(status)));
2509 0 : exit(1);
2510 : }
2511 :
2512 0 : reply = smbd_echo_reply(state, (uint8_t *)buf, buflen, seqnum);
2513 0 : if (!reply) {
2514 0 : size_t num_pending;
2515 0 : struct iovec *tmp;
2516 0 : struct iovec *iov;
2517 :
2518 0 : num_pending = talloc_array_length(state->pending);
2519 0 : tmp = talloc_realloc(state, state->pending, struct iovec,
2520 : num_pending+1);
2521 0 : if (tmp == NULL) {
2522 0 : DEBUG(1, ("talloc_realloc failed\n"));
2523 0 : exit(1);
2524 : }
2525 0 : state->pending = tmp;
2526 :
2527 0 : if (buflen >= smb_size) {
2528 : /*
2529 : * place the seqnum in the packet so that the main process
2530 : * can reply with signing
2531 : */
2532 0 : SIVAL(buf, smb_ss_field, seqnum);
2533 0 : SIVAL(buf, smb_ss_field+4, NT_STATUS_V(NT_STATUS_OK));
2534 : }
2535 :
2536 0 : iov = &state->pending[num_pending];
2537 0 : iov->iov_base = talloc_move(state->pending, &buf);
2538 0 : iov->iov_len = buflen;
2539 :
2540 0 : DEBUG(10,("echo_handler[%d]: forward to main\n",
2541 : (int)getpid()));
2542 0 : smbd_echo_activate_writer(state);
2543 : }
2544 :
2545 0 : req = smbd_echo_read_send(state, state->ev, state->xconn);
2546 0 : if (req == NULL) {
2547 0 : DEBUG(1, ("smbd_echo_read_send failed\n"));
2548 0 : exit(1);
2549 : }
2550 0 : tevent_req_set_callback(req, smbd_echo_got_packet, state);
2551 0 : }
2552 :
2553 :
2554 : /*
2555 : * Handle SMBecho requests in a forked child process
2556 : */
2557 0 : bool fork_echo_handler(struct smbXsrv_connection *xconn)
2558 : {
2559 0 : int listener_pipe[2];
2560 0 : int res;
2561 0 : pid_t child;
2562 0 : bool use_mutex = false;
2563 :
2564 0 : res = pipe(listener_pipe);
2565 0 : if (res == -1) {
2566 0 : DEBUG(1, ("pipe() failed: %s\n", strerror(errno)));
2567 0 : return false;
2568 : }
2569 :
2570 : #ifdef HAVE_ROBUST_MUTEXES
2571 0 : use_mutex = tdb_runtime_check_for_robust_mutexes();
2572 :
2573 0 : if (use_mutex) {
2574 0 : pthread_mutexattr_t a;
2575 :
2576 0 : xconn->smb1.echo_handler.socket_mutex =
2577 0 : anonymous_shared_allocate(sizeof(pthread_mutex_t));
2578 0 : if (xconn->smb1.echo_handler.socket_mutex == NULL) {
2579 0 : DEBUG(1, ("Could not create mutex shared memory: %s\n",
2580 : strerror(errno)));
2581 0 : goto fail;
2582 : }
2583 :
2584 0 : res = pthread_mutexattr_init(&a);
2585 0 : if (res != 0) {
2586 0 : DEBUG(1, ("pthread_mutexattr_init failed: %s\n",
2587 : strerror(res)));
2588 0 : goto fail;
2589 : }
2590 0 : res = pthread_mutexattr_settype(&a, PTHREAD_MUTEX_ERRORCHECK);
2591 0 : if (res != 0) {
2592 0 : DEBUG(1, ("pthread_mutexattr_settype failed: %s\n",
2593 : strerror(res)));
2594 0 : pthread_mutexattr_destroy(&a);
2595 0 : goto fail;
2596 : }
2597 0 : res = pthread_mutexattr_setpshared(&a, PTHREAD_PROCESS_SHARED);
2598 0 : if (res != 0) {
2599 0 : DEBUG(1, ("pthread_mutexattr_setpshared failed: %s\n",
2600 : strerror(res)));
2601 0 : pthread_mutexattr_destroy(&a);
2602 0 : goto fail;
2603 : }
2604 0 : res = pthread_mutexattr_setrobust(&a, PTHREAD_MUTEX_ROBUST);
2605 0 : if (res != 0) {
2606 0 : DEBUG(1, ("pthread_mutexattr_setrobust failed: "
2607 : "%s\n", strerror(res)));
2608 0 : pthread_mutexattr_destroy(&a);
2609 0 : goto fail;
2610 : }
2611 0 : res = pthread_mutex_init(xconn->smb1.echo_handler.socket_mutex,
2612 : &a);
2613 0 : pthread_mutexattr_destroy(&a);
2614 0 : if (res != 0) {
2615 0 : DEBUG(1, ("pthread_mutex_init failed: %s\n",
2616 : strerror(res)));
2617 0 : goto fail;
2618 : }
2619 : }
2620 : #endif
2621 :
2622 0 : if (!use_mutex) {
2623 0 : xconn->smb1.echo_handler.socket_lock_fd =
2624 0 : create_unlink_tmp(lp_lock_directory());
2625 0 : if (xconn->smb1.echo_handler.socket_lock_fd == -1) {
2626 0 : DEBUG(1, ("Could not create lock fd: %s\n",
2627 : strerror(errno)));
2628 0 : goto fail;
2629 : }
2630 : }
2631 :
2632 0 : child = fork();
2633 0 : if (child == 0) {
2634 0 : NTSTATUS status;
2635 :
2636 0 : close(listener_pipe[0]);
2637 0 : set_blocking(listener_pipe[1], false);
2638 :
2639 0 : status = smbd_reinit_after_fork(xconn->client->msg_ctx,
2640 0 : xconn->client->raw_ev_ctx,
2641 : true);
2642 0 : if (!NT_STATUS_IS_OK(status)) {
2643 0 : DEBUG(1, ("reinit_after_fork failed: %s\n",
2644 : nt_errstr(status)));
2645 0 : exit(1);
2646 : }
2647 0 : process_set_title("smbd-echo", "echo handler");
2648 0 : initialize_password_db(true, xconn->client->raw_ev_ctx);
2649 0 : smbd_echo_loop(xconn, listener_pipe[1]);
2650 0 : exit(0);
2651 : }
2652 0 : close(listener_pipe[1]);
2653 0 : listener_pipe[1] = -1;
2654 0 : xconn->smb1.echo_handler.trusted_fd = listener_pipe[0];
2655 :
2656 0 : DEBUG(10,("fork_echo_handler: main[%d] echo_child[%d]\n", (int)getpid(), (int)child));
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 : */
2662 0 : xconn->smb1.echo_handler.trusted_fde = tevent_add_fd(
2663 : xconn->client->raw_ev_ctx,
2664 : xconn,
2665 : xconn->smb1.echo_handler.trusted_fd,
2666 : TEVENT_FD_READ,
2667 : smbd_server_echo_handler,
2668 : xconn);
2669 0 : if (xconn->smb1.echo_handler.trusted_fde == NULL) {
2670 0 : DEBUG(1, ("event_add_fd failed\n"));
2671 0 : goto fail;
2672 : }
2673 :
2674 0 : return true;
2675 :
2676 0 : fail:
2677 0 : if (listener_pipe[0] != -1) {
2678 0 : close(listener_pipe[0]);
2679 : }
2680 0 : if (listener_pipe[1] != -1) {
2681 0 : close(listener_pipe[1]);
2682 : }
2683 0 : if (xconn->smb1.echo_handler.socket_lock_fd != -1) {
2684 0 : close(xconn->smb1.echo_handler.socket_lock_fd);
2685 : }
2686 : #ifdef HAVE_ROBUST_MUTEXES
2687 0 : if (xconn->smb1.echo_handler.socket_mutex != NULL) {
2688 0 : pthread_mutex_destroy(xconn->smb1.echo_handler.socket_mutex);
2689 0 : anonymous_shared_free(xconn->smb1.echo_handler.socket_mutex);
2690 : }
2691 : #endif
2692 0 : smbd_echo_init(xconn);
2693 :
2694 0 : return false;
2695 : }
2696 :
2697 151736 : bool req_is_in_chain(const struct smb_request *req)
2698 : {
2699 151736 : if (req->vwv != (const uint16_t *)(req->inbuf+smb_vwv)) {
2700 : /*
2701 : * We're right now handling a subsequent request, so we must
2702 : * be in a chain
2703 : */
2704 32 : return true;
2705 : }
2706 :
2707 151698 : if (!smb1cli_is_andx_req(req->cmd)) {
2708 32 : return false;
2709 : }
2710 :
2711 151666 : if (req->wct < 2) {
2712 : /*
2713 : * Okay, an illegal request, but definitely not chained :-)
2714 : */
2715 0 : return false;
2716 : }
2717 :
2718 151666 : return (CVAL(req->vwv+0, 0) != 0xFF);
2719 : }
|