source: vendor/current/source3/smbd/reply.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 214.6 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22/*
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
25*/
26
27#include "includes.h"
28#include "system/filesys.h"
29#include "printing.h"
30#include "smbd/smbd.h"
31#include "smbd/globals.h"
32#include "fake_file.h"
33#include "rpc_client/rpc_client.h"
34#include "../librpc/gen_ndr/ndr_spoolss_c.h"
35#include "../librpc/gen_ndr/open_files.h"
36#include "rpc_client/cli_spoolss.h"
37#include "rpc_client/init_spoolss.h"
38#include "rpc_server/rpc_ncacn_np.h"
39#include "libcli/security/security.h"
40#include "libsmb/nmblib.h"
41#include "auth.h"
42#include "smbprofile.h"
43#include "../lib/tsocket/tsocket.h"
44#include "lib/tevent_wait.h"
45#include "libcli/smb/smb_signing.h"
46#include "lib/util/sys_rw_data.h"
47
48/****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 set.
54****************************************************************************/
55
56/* Custom version for processing POSIX paths. */
57#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58
59static NTSTATUS check_path_syntax_internal(char *path,
60 bool posix_path,
61 bool *p_last_component_contains_wcard)
62{
63 char *d = path;
64 const char *s = path;
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
68
69 *p_last_component_contains_wcard = False;
70
71 while (*s) {
72 if (stream_started) {
73 switch (*s) {
74 case '/':
75 case '\\':
76 return NT_STATUS_OBJECT_NAME_INVALID;
77 case ':':
78 if (s[1] == '\0') {
79 return NT_STATUS_OBJECT_NAME_INVALID;
80 }
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
83 }
84 break;
85 }
86 }
87
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
91 }
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
96 JRA.
97 */
98 stream_started = true;
99 start_of_name_component = false;
100 posix_path = true;
101
102 if (s[1] == '\0') {
103 return NT_STATUS_OBJECT_NAME_INVALID;
104 }
105 }
106
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108 /*
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
111 */
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
114 s++;
115 }
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
118 *d++ = '/';
119 }
120
121 start_of_name_component = True;
122 /* New component. */
123 *p_last_component_contains_wcard = False;
124 continue;
125 }
126
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
130
131 /*
132 * No mb char starts with '.' so we're safe checking the directory separator here.
133 */
134
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
137 *(d-1) = '\0';
138 d--;
139 }
140
141 /* Are we at the start ? Can't go back further if so. */
142 if (d <= path) {
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
144 break;
145 }
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
151 if (*d == '/')
152 break;
153 }
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
156 continue;
157
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
159 if (posix_path) {
160 /* Eat the '.' */
161 s++;
162 continue;
163 }
164 }
165
166 }
167
168 if (!(*s & 0x80)) {
169 if (!posix_path) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
172 }
173 switch (*s) {
174 case '*':
175 case '?':
176 case '<':
177 case '>':
178 case '"':
179 *p_last_component_contains_wcard = True;
180 break;
181 default:
182 break;
183 }
184 }
185 *d++ = *s++;
186 } else {
187 size_t siz;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
190 switch(siz) {
191 case 5:
192 *d++ = *s++;
193 /*fall through*/
194 case 4:
195 *d++ = *s++;
196 /*fall through*/
197 case 3:
198 *d++ = *s++;
199 /*fall through*/
200 case 2:
201 *d++ = *s++;
202 /*fall through*/
203 case 1:
204 *d++ = *s++;
205 break;
206 default:
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 *d = '\0';
209 return NT_STATUS_INVALID_PARAMETER;
210 }
211 }
212 start_of_name_component = False;
213 }
214
215 *d = '\0';
216
217 return ret;
218}
219
220/****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223****************************************************************************/
224
225NTSTATUS check_path_syntax(char *path)
226{
227 bool ignore;
228 return check_path_syntax_internal(path, False, &ignore);
229}
230
231/****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 a wildcard.
235****************************************************************************/
236
237NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238{
239 return check_path_syntax_internal(path, False, p_contains_wcard);
240}
241
242/****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246****************************************************************************/
247
248NTSTATUS check_path_syntax_posix(char *path)
249{
250 bool ignore;
251 return check_path_syntax_internal(path, True, &ignore);
252}
253
254/****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 Passes in posix flag.
257****************************************************************************/
258
259static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
260 const char *base_ptr,
261 uint16_t smb_flags2,
262 char **pp_dest,
263 const char *src,
264 size_t src_len,
265 int flags,
266 bool posix_pathnames,
267 NTSTATUS *err,
268 bool *contains_wcard)
269{
270 size_t ret;
271
272 *pp_dest = NULL;
273
274 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
275 src_len, flags);
276
277 if (!*pp_dest) {
278 *err = NT_STATUS_INVALID_PARAMETER;
279 return ret;
280 }
281
282 *contains_wcard = False;
283
284 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
285 /*
286 * For a DFS path the function parse_dfs_path()
287 * will do the path processing, just make a copy.
288 */
289 *err = NT_STATUS_OK;
290 return ret;
291 }
292
293 if (posix_pathnames) {
294 *err = check_path_syntax_posix(*pp_dest);
295 } else {
296 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
297 }
298
299 return ret;
300}
301
302/****************************************************************************
303 Pull a string and check the path allowing a wilcard - provide for error return.
304****************************************************************************/
305
306size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
307 const char *base_ptr,
308 uint16_t smb_flags2,
309 char **pp_dest,
310 const char *src,
311 size_t src_len,
312 int flags,
313 NTSTATUS *err,
314 bool *contains_wcard)
315{
316 return srvstr_get_path_wcard_internal(ctx,
317 base_ptr,
318 smb_flags2,
319 pp_dest,
320 src,
321 src_len,
322 flags,
323 false,
324 err,
325 contains_wcard);
326}
327
328/****************************************************************************
329 Pull a string and check the path allowing a wilcard - provide for error return.
330 posix_pathnames version.
331****************************************************************************/
332
333size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
334 const char *base_ptr,
335 uint16_t smb_flags2,
336 char **pp_dest,
337 const char *src,
338 size_t src_len,
339 int flags,
340 NTSTATUS *err,
341 bool *contains_wcard)
342{
343 return srvstr_get_path_wcard_internal(ctx,
344 base_ptr,
345 smb_flags2,
346 pp_dest,
347 src,
348 src_len,
349 flags,
350 true,
351 err,
352 contains_wcard);
353}
354
355/****************************************************************************
356 Pull a string and check the path - provide for error return.
357****************************************************************************/
358
359size_t srvstr_get_path(TALLOC_CTX *ctx,
360 const char *base_ptr,
361 uint16_t smb_flags2,
362 char **pp_dest,
363 const char *src,
364 size_t src_len,
365 int flags,
366 NTSTATUS *err)
367{
368 bool ignore;
369 return srvstr_get_path_wcard_internal(ctx,
370 base_ptr,
371 smb_flags2,
372 pp_dest,
373 src,
374 src_len,
375 flags,
376 false,
377 err,
378 &ignore);
379}
380
381/****************************************************************************
382 Pull a string and check the path - provide for error return.
383 posix_pathnames version.
384****************************************************************************/
385
386size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
387 const char *base_ptr,
388 uint16_t smb_flags2,
389 char **pp_dest,
390 const char *src,
391 size_t src_len,
392 int flags,
393 NTSTATUS *err)
394{
395 bool ignore;
396 return srvstr_get_path_wcard_internal(ctx,
397 base_ptr,
398 smb_flags2,
399 pp_dest,
400 src,
401 src_len,
402 flags,
403 true,
404 err,
405 &ignore);
406}
407
408
409size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
410 char **pp_dest, const char *src, int flags,
411 NTSTATUS *err, bool *contains_wcard)
412{
413 ssize_t bufrem = smbreq_bufrem(req, src);
414
415 if (bufrem < 0) {
416 *err = NT_STATUS_INVALID_PARAMETER;
417 return 0;
418 }
419
420 if (req->posix_pathnames) {
421 return srvstr_get_path_wcard_internal(mem_ctx,
422 (const char *)req->inbuf,
423 req->flags2,
424 pp_dest,
425 src,
426 bufrem,
427 flags,
428 true,
429 err,
430 contains_wcard);
431 } else {
432 return srvstr_get_path_wcard_internal(mem_ctx,
433 (const char *)req->inbuf,
434 req->flags2,
435 pp_dest,
436 src,
437 bufrem,
438 flags,
439 false,
440 err,
441 contains_wcard);
442 }
443}
444
445size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
446 char **pp_dest, const char *src, int flags,
447 NTSTATUS *err)
448{
449 bool ignore;
450 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
451 flags, err, &ignore);
452}
453
454/**
455 * pull a string from the smb_buf part of a packet. In this case the
456 * string can either be null terminated or it can be terminated by the
457 * end of the smbbuf area
458 */
459size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
460 char **dest, const uint8_t *src, int flags)
461{
462 ssize_t bufrem = smbreq_bufrem(req, src);
463
464 if (bufrem < 0) {
465 return 0;
466 }
467
468 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
469 bufrem, flags);
470}
471
472/****************************************************************************
473 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
474****************************************************************************/
475
476bool check_fsp_open(connection_struct *conn, struct smb_request *req,
477 files_struct *fsp)
478{
479 if ((fsp == NULL) || (conn == NULL)) {
480 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
481 return False;
482 }
483 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
485 return False;
486 }
487 return True;
488}
489
490/****************************************************************************
491 Check if we have a correct fsp pointing to a file.
492****************************************************************************/
493
494bool check_fsp(connection_struct *conn, struct smb_request *req,
495 files_struct *fsp)
496{
497 if (!check_fsp_open(conn, req, fsp)) {
498 return False;
499 }
500 if (fsp->is_directory) {
501 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
502 return False;
503 }
504 if (fsp->fh->fd == -1) {
505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
506 return False;
507 }
508 fsp->num_smb_operations++;
509 return True;
510}
511
512/****************************************************************************
513 Check if we have a correct fsp pointing to a quota fake file. Replacement for
514 the CHECK_NTQUOTA_HANDLE_OK macro.
515****************************************************************************/
516
517bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
518 files_struct *fsp)
519{
520 if (!check_fsp_open(conn, req, fsp)) {
521 return false;
522 }
523
524 if (fsp->is_directory) {
525 return false;
526 }
527
528 if (fsp->fake_file_handle == NULL) {
529 return false;
530 }
531
532 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
533 return false;
534 }
535
536 if (fsp->fake_file_handle->private_data == NULL) {
537 return false;
538 }
539
540 return true;
541}
542
543static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
544 const char *name, int name_type)
545{
546 char *trim_name;
547 char *trim_name_type;
548 const char *retarget_parm;
549 char *retarget;
550 char *p;
551 int retarget_type = 0x20;
552 int retarget_port = NBT_SMB_PORT;
553 struct sockaddr_storage retarget_addr;
554 struct sockaddr_in *in_addr;
555 bool ret = false;
556 uint8_t outbuf[10];
557
558 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
559 return false;
560 }
561
562 trim_name = talloc_strdup(talloc_tos(), name);
563 if (trim_name == NULL) {
564 goto fail;
565 }
566 trim_char(trim_name, ' ', ' ');
567
568 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
569 name_type);
570 if (trim_name_type == NULL) {
571 goto fail;
572 }
573
574 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
575 trim_name_type, NULL);
576 if (retarget_parm == NULL) {
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578 trim_name, NULL);
579 }
580 if (retarget_parm == NULL) {
581 goto fail;
582 }
583
584 retarget = talloc_strdup(trim_name, retarget_parm);
585 if (retarget == NULL) {
586 goto fail;
587 }
588
589 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
590
591 p = strchr(retarget, ':');
592 if (p != NULL) {
593 *p++ = '\0';
594 retarget_port = atoi(p);
595 }
596
597 p = strchr_m(retarget, '#');
598 if (p != NULL) {
599 *p++ = '\0';
600 if (sscanf(p, "%x", &retarget_type) != 1) {
601 goto fail;
602 }
603 }
604
605 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
606 if (!ret) {
607 DEBUG(10, ("could not resolve %s\n", retarget));
608 goto fail;
609 }
610
611 if (retarget_addr.ss_family != AF_INET) {
612 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
613 goto fail;
614 }
615
616 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
617
618 _smb_setlen(outbuf, 6);
619 SCVAL(outbuf, 0, 0x84);
620 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
621 *(uint16_t *)(outbuf+8) = htons(retarget_port);
622
623 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
624 NULL)) {
625 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
626 "failed.");
627 }
628
629 ret = true;
630 fail:
631 TALLOC_FREE(trim_name);
632 return ret;
633}
634
635static void reply_called_name_not_present(char *outbuf)
636{
637 smb_setlen(outbuf, 1);
638 SCVAL(outbuf, 0, 0x83);
639 SCVAL(outbuf, 4, 0x82);
640}
641
642/****************************************************************************
643 Reply to a (netbios-level) special message.
644****************************************************************************/
645
646void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
647{
648 struct smbd_server_connection *sconn = xconn->client->sconn;
649 int msg_type = CVAL(inbuf,0);
650 int msg_flags = CVAL(inbuf,1);
651 /*
652 * We only really use 4 bytes of the outbuf, but for the smb_setlen
653 * calculation & friends (srv_send_smb uses that) we need the full smb
654 * header.
655 */
656 char outbuf[smb_size];
657
658 memset(outbuf, '\0', sizeof(outbuf));
659
660 smb_setlen(outbuf,0);
661
662 switch (msg_type) {
663 case NBSSrequest: /* session request */
664 {
665 /* inbuf_size is guarenteed to be at least 4. */
666 fstring name1,name2;
667 int name_type1, name_type2;
668 int name_len1, name_len2;
669
670 *name1 = *name2 = 0;
671
672 if (xconn->transport.nbt.got_session) {
673 exit_server_cleanly("multiple session request not permitted");
674 }
675
676 SCVAL(outbuf,0,NBSSpositive);
677 SCVAL(outbuf,3,0);
678
679 /* inbuf_size is guaranteed to be at least 4. */
680 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
681 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
682 DEBUG(0,("Invalid name length in session request\n"));
683 reply_called_name_not_present(outbuf);
684 break;
685 }
686 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
687 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
688 DEBUG(0,("Invalid name length in session request\n"));
689 reply_called_name_not_present(outbuf);
690 break;
691 }
692
693 name_type1 = name_extract((unsigned char *)inbuf,
694 inbuf_size,(unsigned int)4,name1);
695 name_type2 = name_extract((unsigned char *)inbuf,
696 inbuf_size,(unsigned int)(4 + name_len1),name2);
697
698 if (name_type1 == -1 || name_type2 == -1) {
699 DEBUG(0,("Invalid name type in session request\n"));
700 reply_called_name_not_present(outbuf);
701 break;
702 }
703
704 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
705 name1, name_type1, name2, name_type2));
706
707 if (netbios_session_retarget(xconn, name1, name_type1)) {
708 exit_server_cleanly("retargeted client");
709 }
710
711 /*
712 * Windows NT/2k uses "*SMBSERVER" and XP uses
713 * "*SMBSERV" arrggg!!!
714 */
715 if (strequal(name1, "*SMBSERVER ")
716 || strequal(name1, "*SMBSERV ")) {
717 char *raddr;
718
719 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
720 talloc_tos());
721 if (raddr == NULL) {
722 exit_server_cleanly("could not allocate raddr");
723 }
724
725 fstrcpy(name1, raddr);
726 }
727
728 set_local_machine_name(name1, True);
729 set_remote_machine_name(name2, True);
730
731 if (is_ipaddress(sconn->remote_hostname)) {
732 char *p = discard_const_p(char, sconn->remote_hostname);
733
734 talloc_free(p);
735
736 sconn->remote_hostname = talloc_strdup(sconn,
737 get_remote_machine_name());
738 if (sconn->remote_hostname == NULL) {
739 exit_server_cleanly("could not copy remote name");
740 }
741 xconn->remote_hostname = sconn->remote_hostname;
742 }
743
744 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
745 get_local_machine_name(), get_remote_machine_name(),
746 name_type2));
747
748 if (name_type2 == 'R') {
749 /* We are being asked for a pathworks session ---
750 no thanks! */
751 reply_called_name_not_present(outbuf);
752 break;
753 }
754
755 reload_services(sconn, conn_snum_used, true);
756 reopen_logs();
757
758 xconn->transport.nbt.got_session = true;
759 break;
760 }
761
762 case 0x89: /* session keepalive request
763 (some old clients produce this?) */
764 SCVAL(outbuf,0,NBSSkeepalive);
765 SCVAL(outbuf,3,0);
766 break;
767
768 case NBSSpositive: /* positive session response */
769 case NBSSnegative: /* negative session response */
770 case NBSSretarget: /* retarget session response */
771 DEBUG(0,("Unexpected session response\n"));
772 break;
773
774 case NBSSkeepalive: /* session keepalive */
775 default:
776 return;
777 }
778
779 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
780 msg_type, msg_flags));
781
782 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
783
784 if (CVAL(outbuf, 0) != 0x82) {
785 exit_server_cleanly("invalid netbios session");
786 }
787 return;
788}
789
790/****************************************************************************
791 Reply to a tcon.
792 conn POINTER CAN BE NULL HERE !
793****************************************************************************/
794
795void reply_tcon(struct smb_request *req)
796{
797 connection_struct *conn = req->conn;
798 const char *service;
799 char *service_buf = NULL;
800 char *password = NULL;
801 char *dev = NULL;
802 int pwlen=0;
803 NTSTATUS nt_status;
804 const uint8_t *p;
805 const char *p2;
806 TALLOC_CTX *ctx = talloc_tos();
807 struct smbXsrv_connection *xconn = req->xconn;
808 NTTIME now = timeval_to_nttime(&req->request_time);
809
810 START_PROFILE(SMBtcon);
811
812 if (req->buflen < 4) {
813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
814 END_PROFILE(SMBtcon);
815 return;
816 }
817
818 p = req->buf + 1;
819 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
820 p += 1;
821 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
822 p += pwlen+1;
823 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
824 p += 1;
825
826 if (service_buf == NULL || password == NULL || dev == NULL) {
827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
828 END_PROFILE(SMBtcon);
829 return;
830 }
831 p2 = strrchr_m(service_buf,'\\');
832 if (p2) {
833 service = p2+1;
834 } else {
835 service = service_buf;
836 }
837
838 conn = make_connection(req, now, service, dev,
839 req->vuid,&nt_status);
840 req->conn = conn;
841
842 if (!conn) {
843 reply_nterror(req, nt_status);
844 END_PROFILE(SMBtcon);
845 return;
846 }
847
848 reply_outbuf(req, 2, 0);
849 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
850 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
851 SSVAL(req->outbuf,smb_tid,conn->cnum);
852
853 DEBUG(3,("tcon service=%s cnum=%d\n",
854 service, conn->cnum));
855
856 END_PROFILE(SMBtcon);
857 return;
858}
859
860/****************************************************************************
861 Reply to a tcon and X.
862 conn POINTER CAN BE NULL HERE !
863****************************************************************************/
864
865void reply_tcon_and_X(struct smb_request *req)
866{
867 connection_struct *conn = req->conn;
868 const char *service = NULL;
869 TALLOC_CTX *ctx = talloc_tos();
870 /* what the cleint thinks the device is */
871 char *client_devicetype = NULL;
872 /* what the server tells the client the share represents */
873 const char *server_devicetype;
874 NTSTATUS nt_status;
875 int passlen;
876 char *path = NULL;
877 const uint8_t *p;
878 const char *q;
879 uint16_t tcon_flags;
880 struct smbXsrv_session *session = NULL;
881 NTTIME now = timeval_to_nttime(&req->request_time);
882 bool session_key_updated = false;
883 uint16_t optional_support = 0;
884 struct smbXsrv_connection *xconn = req->xconn;
885
886 START_PROFILE(SMBtconX);
887
888 if (req->wct < 4) {
889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
890 END_PROFILE(SMBtconX);
891 return;
892 }
893
894 passlen = SVAL(req->vwv+3, 0);
895 tcon_flags = SVAL(req->vwv+2, 0);
896
897 /* we might have to close an old one */
898 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
899 struct smbXsrv_tcon *tcon;
900 NTSTATUS status;
901
902 tcon = conn->tcon;
903 req->conn = NULL;
904 conn = NULL;
905
906 /*
907 * TODO: cancel all outstanding requests on the tcon
908 */
909 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
910 if (!NT_STATUS_IS_OK(status)) {
911 DEBUG(0, ("reply_tcon_and_X: "
912 "smbXsrv_tcon_disconnect() failed: %s\n",
913 nt_errstr(status)));
914 /*
915 * If we hit this case, there is something completely
916 * wrong, so we better disconnect the transport connection.
917 */
918 END_PROFILE(SMBtconX);
919 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
920 return;
921 }
922
923 TALLOC_FREE(tcon);
924 }
925
926 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
927 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
928 END_PROFILE(SMBtconX);
929 return;
930 }
931
932 if (xconn->smb1.negprot.encrypted_passwords) {
933 p = req->buf + passlen;
934 } else {
935 p = req->buf + passlen + 1;
936 }
937
938 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
939
940 if (path == NULL) {
941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
942 END_PROFILE(SMBtconX);
943 return;
944 }
945
946 /*
947 * the service name can be either: \\server\share
948 * or share directly like on the DELL PowerVault 705
949 */
950 if (*path=='\\') {
951 q = strchr_m(path+2,'\\');
952 if (!q) {
953 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
954 END_PROFILE(SMBtconX);
955 return;
956 }
957 service = q+1;
958 } else {
959 service = path;
960 }
961
962 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
963 &client_devicetype, p,
964 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
965
966 if (client_devicetype == NULL) {
967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
968 END_PROFILE(SMBtconX);
969 return;
970 }
971
972 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
973
974 nt_status = smb1srv_session_lookup(xconn,
975 req->vuid, now, &session);
976 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
977 reply_force_doserror(req, ERRSRV, ERRbaduid);
978 END_PROFILE(SMBtconX);
979 return;
980 }
981 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
982 reply_nterror(req, nt_status);
983 END_PROFILE(SMBtconX);
984 return;
985 }
986 if (!NT_STATUS_IS_OK(nt_status)) {
987 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
988 END_PROFILE(SMBtconX);
989 return;
990 }
991
992 if (session->global->auth_session_info == NULL) {
993 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
994 END_PROFILE(SMBtconX);
995 return;
996 }
997
998 /*
999 * If there is no application key defined yet
1000 * we create one.
1001 *
1002 * This means we setup the application key on the
1003 * first tcon that happens via the given session.
1004 *
1005 * Once the application key is defined, it does not
1006 * change any more.
1007 */
1008 if (session->global->application_key.length == 0 &&
1009 session->global->signing_key.length > 0)
1010 {
1011 struct smbXsrv_session *x = session;
1012 struct auth_session_info *session_info =
1013 session->global->auth_session_info;
1014 uint8_t session_key[16];
1015
1016 ZERO_STRUCT(session_key);
1017 memcpy(session_key, x->global->signing_key.data,
1018 MIN(x->global->signing_key.length, sizeof(session_key)));
1019
1020 /*
1021 * The application key is truncated/padded to 16 bytes
1022 */
1023 x->global->application_key = data_blob_talloc(x->global,
1024 session_key,
1025 sizeof(session_key));
1026 ZERO_STRUCT(session_key);
1027 if (x->global->application_key.data == NULL) {
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029 END_PROFILE(SMBtconX);
1030 return;
1031 }
1032
1033 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1034 smb_key_derivation(x->global->application_key.data,
1035 x->global->application_key.length,
1036 x->global->application_key.data);
1037 optional_support |= SMB_EXTENDED_SIGNATURES;
1038 }
1039
1040 /*
1041 * Place the application key into the session_info
1042 */
1043 data_blob_clear_free(&session_info->session_key);
1044 session_info->session_key = data_blob_dup_talloc(session_info,
1045 x->global->application_key);
1046 if (session_info->session_key.data == NULL) {
1047 data_blob_clear_free(&x->global->application_key);
1048 reply_nterror(req, NT_STATUS_NO_MEMORY);
1049 END_PROFILE(SMBtconX);
1050 return;
1051 }
1052 session_key_updated = true;
1053 }
1054
1055 conn = make_connection(req, now, service, client_devicetype,
1056 req->vuid, &nt_status);
1057 req->conn =conn;
1058
1059 if (!conn) {
1060 if (session_key_updated) {
1061 struct smbXsrv_session *x = session;
1062 struct auth_session_info *session_info =
1063 session->global->auth_session_info;
1064 data_blob_clear_free(&x->global->application_key);
1065 data_blob_clear_free(&session_info->session_key);
1066 }
1067 reply_nterror(req, nt_status);
1068 END_PROFILE(SMBtconX);
1069 return;
1070 }
1071
1072 if ( IS_IPC(conn) )
1073 server_devicetype = "IPC";
1074 else if ( IS_PRINT(conn) )
1075 server_devicetype = "LPT1:";
1076 else
1077 server_devicetype = "A:";
1078
1079 if (get_Protocol() < PROTOCOL_NT1) {
1080 reply_outbuf(req, 2, 0);
1081 if (message_push_string(&req->outbuf, server_devicetype,
1082 STR_TERMINATE|STR_ASCII) == -1) {
1083 reply_nterror(req, NT_STATUS_NO_MEMORY);
1084 END_PROFILE(SMBtconX);
1085 return;
1086 }
1087 } else {
1088 /* NT sets the fstype of IPC$ to the null string */
1089 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1090
1091 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1092 /* Return permissions. */
1093 uint32_t perm1 = 0;
1094 uint32_t perm2 = 0;
1095
1096 reply_outbuf(req, 7, 0);
1097
1098 if (IS_IPC(conn)) {
1099 perm1 = FILE_ALL_ACCESS;
1100 perm2 = FILE_ALL_ACCESS;
1101 } else {
1102 perm1 = conn->share_access;
1103 }
1104
1105 SIVAL(req->outbuf, smb_vwv3, perm1);
1106 SIVAL(req->outbuf, smb_vwv5, perm2);
1107 } else {
1108 reply_outbuf(req, 3, 0);
1109 }
1110
1111 if ((message_push_string(&req->outbuf, server_devicetype,
1112 STR_TERMINATE|STR_ASCII) == -1)
1113 || (message_push_string(&req->outbuf, fstype,
1114 STR_TERMINATE) == -1)) {
1115 reply_nterror(req, NT_STATUS_NO_MEMORY);
1116 END_PROFILE(SMBtconX);
1117 return;
1118 }
1119
1120 /* what does setting this bit do? It is set by NT4 and
1121 may affect the ability to autorun mounted cdroms */
1122 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1123 optional_support |=
1124 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1125
1126 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1127 DEBUG(2,("Serving %s as a Dfs root\n",
1128 lp_servicename(ctx, SNUM(conn)) ));
1129 optional_support |= SMB_SHARE_IN_DFS;
1130 }
1131
1132 SSVAL(req->outbuf, smb_vwv2, optional_support);
1133 }
1134
1135 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1136 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1137
1138 DEBUG(3,("tconX service=%s \n",
1139 service));
1140
1141 /* set the incoming and outgoing tid to the just created one */
1142 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1143 SSVAL(req->outbuf,smb_tid,conn->cnum);
1144
1145 END_PROFILE(SMBtconX);
1146
1147 req->tid = conn->cnum;
1148}
1149
1150/****************************************************************************
1151 Reply to an unknown type.
1152****************************************************************************/
1153
1154void reply_unknown_new(struct smb_request *req, uint8_t type)
1155{
1156 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1157 smb_fn_name(type), type, type));
1158 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1159 return;
1160}
1161
1162/****************************************************************************
1163 Reply to an ioctl.
1164 conn POINTER CAN BE NULL HERE !
1165****************************************************************************/
1166
1167void reply_ioctl(struct smb_request *req)
1168{
1169 connection_struct *conn = req->conn;
1170 uint16_t device;
1171 uint16_t function;
1172 uint32_t ioctl_code;
1173 int replysize;
1174 char *p;
1175
1176 START_PROFILE(SMBioctl);
1177
1178 if (req->wct < 3) {
1179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1180 END_PROFILE(SMBioctl);
1181 return;
1182 }
1183
1184 device = SVAL(req->vwv+1, 0);
1185 function = SVAL(req->vwv+2, 0);
1186 ioctl_code = (device << 16) + function;
1187
1188 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1189
1190 switch (ioctl_code) {
1191 case IOCTL_QUERY_JOB_INFO:
1192 replysize = 32;
1193 break;
1194 default:
1195 reply_force_doserror(req, ERRSRV, ERRnosupport);
1196 END_PROFILE(SMBioctl);
1197 return;
1198 }
1199
1200 reply_outbuf(req, 8, replysize+1);
1201 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1202 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1203 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1204 p = smb_buf(req->outbuf);
1205 memset(p, '\0', replysize+1); /* valgrind-safe. */
1206 p += 1; /* Allow for alignment */
1207
1208 switch (ioctl_code) {
1209 case IOCTL_QUERY_JOB_INFO:
1210 {
1211 NTSTATUS status;
1212 size_t len = 0;
1213 files_struct *fsp = file_fsp(
1214 req, SVAL(req->vwv+0, 0));
1215 if (!fsp) {
1216 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1217 END_PROFILE(SMBioctl);
1218 return;
1219 }
1220 /* Job number */
1221 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1222
1223 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1224 lp_netbios_name(), 15,
1225 STR_TERMINATE|STR_ASCII, &len);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 reply_nterror(req, status);
1228 END_PROFILE(SMBioctl);
1229 return;
1230 }
1231 if (conn) {
1232 status = srvstr_push((char *)req->outbuf, req->flags2,
1233 p+18,
1234 lp_servicename(talloc_tos(),
1235 SNUM(conn)),
1236 13, STR_TERMINATE|STR_ASCII, &len);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 reply_nterror(req, status);
1239 END_PROFILE(SMBioctl);
1240 return;
1241 }
1242 } else {
1243 memset(p+18, 0, 13);
1244 }
1245 break;
1246 }
1247 }
1248
1249 END_PROFILE(SMBioctl);
1250 return;
1251}
1252
1253/****************************************************************************
1254 Strange checkpath NTSTATUS mapping.
1255****************************************************************************/
1256
1257static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1258{
1259 /* Strange DOS error code semantics only for checkpath... */
1260 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1261 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1262 /* We need to map to ERRbadpath */
1263 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1264 }
1265 }
1266 return status;
1267}
1268
1269/****************************************************************************
1270 Reply to a checkpath.
1271****************************************************************************/
1272
1273void reply_checkpath(struct smb_request *req)
1274{
1275 connection_struct *conn = req->conn;
1276 struct smb_filename *smb_fname = NULL;
1277 char *name = NULL;
1278 NTSTATUS status;
1279 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1280 TALLOC_CTX *ctx = talloc_tos();
1281
1282 START_PROFILE(SMBcheckpath);
1283
1284 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1285 STR_TERMINATE, &status);
1286
1287 if (!NT_STATUS_IS_OK(status)) {
1288 status = map_checkpath_error(req->flags2, status);
1289 reply_nterror(req, status);
1290 END_PROFILE(SMBcheckpath);
1291 return;
1292 }
1293
1294 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1295
1296 status = filename_convert(ctx,
1297 conn,
1298 req->flags2 & FLAGS2_DFS_PATHNAMES,
1299 name,
1300 ucf_flags,
1301 NULL,
1302 &smb_fname);
1303
1304 if (!NT_STATUS_IS_OK(status)) {
1305 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1306 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1307 ERRSRV, ERRbadpath);
1308 END_PROFILE(SMBcheckpath);
1309 return;
1310 }
1311 goto path_err;
1312 }
1313
1314 if (!VALID_STAT(smb_fname->st) &&
1315 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1316 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1317 smb_fname_str_dbg(smb_fname), strerror(errno)));
1318 status = map_nt_error_from_unix(errno);
1319 goto path_err;
1320 }
1321
1322 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1323 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1324 ERRDOS, ERRbadpath);
1325 goto out;
1326 }
1327
1328 reply_outbuf(req, 0, 0);
1329
1330 path_err:
1331 /* We special case this - as when a Windows machine
1332 is parsing a path is steps through the components
1333 one at a time - if a component fails it expects
1334 ERRbadpath, not ERRbadfile.
1335 */
1336 status = map_checkpath_error(req->flags2, status);
1337 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1338 /*
1339 * Windows returns different error codes if
1340 * the parent directory is valid but not the
1341 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1342 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1343 * if the path is invalid.
1344 */
1345 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1346 ERRDOS, ERRbadpath);
1347 goto out;
1348 }
1349
1350 reply_nterror(req, status);
1351
1352 out:
1353 TALLOC_FREE(smb_fname);
1354 END_PROFILE(SMBcheckpath);
1355 return;
1356}
1357
1358/****************************************************************************
1359 Reply to a getatr.
1360****************************************************************************/
1361
1362void reply_getatr(struct smb_request *req)
1363{
1364 connection_struct *conn = req->conn;
1365 struct smb_filename *smb_fname = NULL;
1366 char *fname = NULL;
1367 int mode=0;
1368 off_t size=0;
1369 time_t mtime=0;
1370 const char *p;
1371 NTSTATUS status;
1372 TALLOC_CTX *ctx = talloc_tos();
1373 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1374
1375 START_PROFILE(SMBgetatr);
1376
1377 p = (const char *)req->buf + 1;
1378 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 reply_nterror(req, status);
1381 goto out;
1382 }
1383
1384 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1385 under WfWg - weird! */
1386 if (*fname == '\0') {
1387 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1388 if (!CAN_WRITE(conn)) {
1389 mode |= FILE_ATTRIBUTE_READONLY;
1390 }
1391 size = 0;
1392 mtime = 0;
1393 } else {
1394 uint32_t ucf_flags = (req->posix_pathnames ?
1395 UCF_POSIX_PATHNAMES : 0);
1396 status = filename_convert(ctx,
1397 conn,
1398 req->flags2 & FLAGS2_DFS_PATHNAMES,
1399 fname,
1400 ucf_flags,
1401 NULL,
1402 &smb_fname);
1403 if (!NT_STATUS_IS_OK(status)) {
1404 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1405 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1406 ERRSRV, ERRbadpath);
1407 goto out;
1408 }
1409 reply_nterror(req, status);
1410 goto out;
1411 }
1412 if (!VALID_STAT(smb_fname->st) &&
1413 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1414 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1415 smb_fname_str_dbg(smb_fname),
1416 strerror(errno)));
1417 reply_nterror(req, map_nt_error_from_unix(errno));
1418 goto out;
1419 }
1420
1421 mode = dos_mode(conn, smb_fname);
1422 size = smb_fname->st.st_ex_size;
1423
1424 if (ask_sharemode) {
1425 struct timespec write_time_ts;
1426 struct file_id fileid;
1427
1428 ZERO_STRUCT(write_time_ts);
1429 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1430 get_file_infos(fileid, 0, NULL, &write_time_ts);
1431 if (!null_timespec(write_time_ts)) {
1432 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1433 }
1434 }
1435
1436 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1437 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1438 size = 0;
1439 }
1440 }
1441
1442 reply_outbuf(req, 10, 0);
1443
1444 SSVAL(req->outbuf,smb_vwv0,mode);
1445 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1446 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1447 } else {
1448 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1449 }
1450 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1451
1452 if (get_Protocol() >= PROTOCOL_NT1) {
1453 SSVAL(req->outbuf, smb_flg2,
1454 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1455 }
1456
1457 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1458 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1459
1460 out:
1461 TALLOC_FREE(smb_fname);
1462 TALLOC_FREE(fname);
1463 END_PROFILE(SMBgetatr);
1464 return;
1465}
1466
1467/****************************************************************************
1468 Reply to a setatr.
1469****************************************************************************/
1470
1471void reply_setatr(struct smb_request *req)
1472{
1473 struct smb_file_time ft;
1474 connection_struct *conn = req->conn;
1475 struct smb_filename *smb_fname = NULL;
1476 char *fname = NULL;
1477 int mode;
1478 time_t mtime;
1479 const char *p;
1480 NTSTATUS status;
1481 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1482 TALLOC_CTX *ctx = talloc_tos();
1483
1484 START_PROFILE(SMBsetatr);
1485
1486 ZERO_STRUCT(ft);
1487
1488 if (req->wct < 2) {
1489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1490 goto out;
1491 }
1492
1493 p = (const char *)req->buf + 1;
1494 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1495 if (!NT_STATUS_IS_OK(status)) {
1496 reply_nterror(req, status);
1497 goto out;
1498 }
1499
1500 status = filename_convert(ctx,
1501 conn,
1502 req->flags2 & FLAGS2_DFS_PATHNAMES,
1503 fname,
1504 ucf_flags,
1505 NULL,
1506 &smb_fname);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1509 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1510 ERRSRV, ERRbadpath);
1511 goto out;
1512 }
1513 reply_nterror(req, status);
1514 goto out;
1515 }
1516
1517 if (smb_fname->base_name[0] == '.' &&
1518 smb_fname->base_name[1] == '\0') {
1519 /*
1520 * Not sure here is the right place to catch this
1521 * condition. Might be moved to somewhere else later -- vl
1522 */
1523 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1524 goto out;
1525 }
1526
1527 mode = SVAL(req->vwv+0, 0);
1528 mtime = srv_make_unix_date3(req->vwv+1);
1529
1530 if (mode != FILE_ATTRIBUTE_NORMAL) {
1531 if (VALID_STAT_OF_DIR(smb_fname->st))
1532 mode |= FILE_ATTRIBUTE_DIRECTORY;
1533 else
1534 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1535
1536 status = check_access(conn, NULL, smb_fname,
1537 FILE_WRITE_ATTRIBUTES);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 reply_nterror(req, status);
1540 goto out;
1541 }
1542
1543 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1544 false) != 0) {
1545 reply_nterror(req, map_nt_error_from_unix(errno));
1546 goto out;
1547 }
1548 }
1549
1550 ft.mtime = convert_time_t_to_timespec(mtime);
1551 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 reply_nterror(req, status);
1554 goto out;
1555 }
1556
1557 reply_outbuf(req, 0, 0);
1558
1559 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1560 mode));
1561 out:
1562 TALLOC_FREE(smb_fname);
1563 END_PROFILE(SMBsetatr);
1564 return;
1565}
1566
1567/****************************************************************************
1568 Reply to a dskattr.
1569****************************************************************************/
1570
1571void reply_dskattr(struct smb_request *req)
1572{
1573 connection_struct *conn = req->conn;
1574 uint64_t ret;
1575 uint64_t dfree,dsize,bsize;
1576 struct smb_filename smb_fname;
1577 START_PROFILE(SMBdskattr);
1578
1579 ZERO_STRUCT(smb_fname);
1580 smb_fname.base_name = discard_const_p(char, ".");
1581
1582 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1583 reply_nterror(req, map_nt_error_from_unix(errno));
1584 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1585 END_PROFILE(SMBdskattr);
1586 return;
1587 }
1588
1589 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1590 if (ret == (uint64_t)-1) {
1591 reply_nterror(req, map_nt_error_from_unix(errno));
1592 END_PROFILE(SMBdskattr);
1593 return;
1594 }
1595
1596 /*
1597 * Force max to fit in 16 bit fields.
1598 */
1599 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1600 dfree /= 2;
1601 dsize /= 2;
1602 bsize *= 2;
1603 if (bsize > (WORDMAX*512)) {
1604 bsize = (WORDMAX*512);
1605 if (dsize > WORDMAX)
1606 dsize = WORDMAX;
1607 if (dfree > WORDMAX)
1608 dfree = WORDMAX;
1609 break;
1610 }
1611 }
1612
1613 reply_outbuf(req, 5, 0);
1614
1615 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1616 double total_space, free_space;
1617 /* we need to scale this to a number that DOS6 can handle. We
1618 use floating point so we can handle large drives on systems
1619 that don't have 64 bit integers
1620
1621 we end up displaying a maximum of 2G to DOS systems
1622 */
1623 total_space = dsize * (double)bsize;
1624 free_space = dfree * (double)bsize;
1625
1626 dsize = (uint64_t)((total_space+63*512) / (64*512));
1627 dfree = (uint64_t)((free_space+63*512) / (64*512));
1628
1629 if (dsize > 0xFFFF) dsize = 0xFFFF;
1630 if (dfree > 0xFFFF) dfree = 0xFFFF;
1631
1632 SSVAL(req->outbuf,smb_vwv0,dsize);
1633 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1634 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1635 SSVAL(req->outbuf,smb_vwv3,dfree);
1636 } else {
1637 SSVAL(req->outbuf,smb_vwv0,dsize);
1638 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1639 SSVAL(req->outbuf,smb_vwv2,512);
1640 SSVAL(req->outbuf,smb_vwv3,dfree);
1641 }
1642
1643 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1644
1645 END_PROFILE(SMBdskattr);
1646 return;
1647}
1648
1649/*
1650 * Utility function to split the filename from the directory.
1651 */
1652static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1653 char **fname_dir_out,
1654 char **fname_mask_out)
1655{
1656 const char *p = NULL;
1657 char *fname_dir = NULL;
1658 char *fname_mask = NULL;
1659
1660 p = strrchr_m(fname_in, '/');
1661 if (!p) {
1662 fname_dir = talloc_strdup(ctx, ".");
1663 fname_mask = talloc_strdup(ctx, fname_in);
1664 } else {
1665 fname_dir = talloc_strndup(ctx, fname_in,
1666 PTR_DIFF(p, fname_in));
1667 fname_mask = talloc_strdup(ctx, p+1);
1668 }
1669
1670 if (!fname_dir || !fname_mask) {
1671 TALLOC_FREE(fname_dir);
1672 TALLOC_FREE(fname_mask);
1673 return NT_STATUS_NO_MEMORY;
1674 }
1675
1676 *fname_dir_out = fname_dir;
1677 *fname_mask_out = fname_mask;
1678 return NT_STATUS_OK;
1679}
1680
1681/****************************************************************************
1682 Make a dir struct.
1683****************************************************************************/
1684
1685static bool make_dir_struct(TALLOC_CTX *ctx,
1686 char *buf,
1687 const char *mask,
1688 const char *fname,
1689 off_t size,
1690 uint32_t mode,
1691 time_t date,
1692 bool uc)
1693{
1694 char *p;
1695 char *mask2 = talloc_strdup(ctx, mask);
1696
1697 if (!mask2) {
1698 return False;
1699 }
1700
1701 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1702 size = 0;
1703 }
1704
1705 memset(buf+1,' ',11);
1706 if ((p = strchr_m(mask2,'.')) != NULL) {
1707 *p = 0;
1708 push_ascii(buf+1,mask2,8, 0);
1709 push_ascii(buf+9,p+1,3, 0);
1710 *p = '.';
1711 } else {
1712 push_ascii(buf+1,mask2,11, 0);
1713 }
1714
1715 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1716 SCVAL(buf,21,mode);
1717 srv_put_dos_date(buf,22,date);
1718 SSVAL(buf,26,size & 0xFFFF);
1719 SSVAL(buf,28,(size >> 16)&0xFFFF);
1720 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1721 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1722 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1723 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1724 return True;
1725}
1726
1727/****************************************************************************
1728 Reply to a search.
1729 Can be called from SMBsearch, SMBffirst or SMBfunique.
1730****************************************************************************/
1731
1732void reply_search(struct smb_request *req)
1733{
1734 connection_struct *conn = req->conn;
1735 char *path = NULL;
1736 char *mask = NULL;
1737 char *directory = NULL;
1738 struct smb_filename *smb_fname = NULL;
1739 char *fname = NULL;
1740 off_t size;
1741 uint32_t mode;
1742 struct timespec date;
1743 uint32_t dirtype;
1744 unsigned int numentries = 0;
1745 unsigned int maxentries = 0;
1746 bool finished = False;
1747 const char *p;
1748 int status_len;
1749 char status[21];
1750 int dptr_num= -1;
1751 bool check_descend = False;
1752 bool expect_close = False;
1753 NTSTATUS nt_status;
1754 bool mask_contains_wcard = False;
1755 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1756 TALLOC_CTX *ctx = talloc_tos();
1757 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1758 struct dptr_struct *dirptr = NULL;
1759 struct smbXsrv_connection *xconn = req->xconn;
1760 struct smbd_server_connection *sconn = req->sconn;
1761
1762 START_PROFILE(SMBsearch);
1763
1764 if (req->wct < 2) {
1765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1766 goto out;
1767 }
1768
1769 if (req->posix_pathnames) {
1770 reply_unknown_new(req, req->cmd);
1771 goto out;
1772 }
1773
1774 /* If we were called as SMBffirst then we must expect close. */
1775 if(req->cmd == SMBffirst) {
1776 expect_close = True;
1777 }
1778
1779 reply_outbuf(req, 1, 3);
1780 maxentries = SVAL(req->vwv+0, 0);
1781 dirtype = SVAL(req->vwv+1, 0);
1782 p = (const char *)req->buf + 1;
1783 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1784 &nt_status, &mask_contains_wcard);
1785 if (!NT_STATUS_IS_OK(nt_status)) {
1786 reply_nterror(req, nt_status);
1787 goto out;
1788 }
1789
1790 p++;
1791 status_len = SVAL(p, 0);
1792 p += 2;
1793
1794 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1795
1796 if (status_len == 0) {
1797 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1798 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1799 nt_status = filename_convert(ctx, conn,
1800 req->flags2 & FLAGS2_DFS_PATHNAMES,
1801 path,
1802 ucf_flags,
1803 &mask_contains_wcard,
1804 &smb_fname);
1805 if (!NT_STATUS_IS_OK(nt_status)) {
1806 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1807 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1808 ERRSRV, ERRbadpath);
1809 goto out;
1810 }
1811 reply_nterror(req, nt_status);
1812 goto out;
1813 }
1814
1815 directory = smb_fname->base_name;
1816
1817 p = strrchr_m(directory,'/');
1818 if ((p != NULL) && (*directory != '/')) {
1819 mask = talloc_strdup(ctx, p + 1);
1820 directory = talloc_strndup(ctx, directory,
1821 PTR_DIFF(p, directory));
1822 } else {
1823 mask = talloc_strdup(ctx, directory);
1824 directory = talloc_strdup(ctx,".");
1825 }
1826
1827 if (!directory) {
1828 reply_nterror(req, NT_STATUS_NO_MEMORY);
1829 goto out;
1830 }
1831
1832 memset((char *)status,'\0',21);
1833 SCVAL(status,0,(dirtype & 0x1F));
1834
1835 nt_status = dptr_create(conn,
1836 NULL, /* req */
1837 NULL, /* fsp */
1838 directory,
1839 True,
1840 expect_close,
1841 req->smbpid,
1842 mask,
1843 mask_contains_wcard,
1844 dirtype,
1845 &dirptr);
1846 if (!NT_STATUS_IS_OK(nt_status)) {
1847 reply_nterror(req, nt_status);
1848 goto out;
1849 }
1850 dptr_num = dptr_dnum(dirptr);
1851 } else {
1852 int status_dirtype;
1853 const char *dirpath;
1854
1855 memcpy(status,p,21);
1856 status_dirtype = CVAL(status,0) & 0x1F;
1857 if (status_dirtype != (dirtype & 0x1F)) {
1858 dirtype = status_dirtype;
1859 }
1860
1861 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1862 if (!dirptr) {
1863 goto SearchEmpty;
1864 }
1865 dirpath = dptr_path(sconn, dptr_num);
1866 directory = talloc_strdup(ctx, dirpath);
1867 if (!directory) {
1868 reply_nterror(req, NT_STATUS_NO_MEMORY);
1869 goto out;
1870 }
1871
1872 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1873 if (!mask) {
1874 goto SearchEmpty;
1875 }
1876 /*
1877 * For a 'continue' search we have no string. So
1878 * check from the initial saved string.
1879 */
1880 if (!req->posix_pathnames) {
1881 mask_contains_wcard = ms_has_wild(mask);
1882 }
1883 dirtype = dptr_attr(sconn, dptr_num);
1884 }
1885
1886 DEBUG(4,("dptr_num is %d\n",dptr_num));
1887
1888 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1889 dptr_init_search_op(dirptr);
1890
1891 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1892 char buf[DIR_STRUCT_SIZE];
1893 memcpy(buf,status,21);
1894 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1895 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1896 reply_nterror(req, NT_STATUS_NO_MEMORY);
1897 goto out;
1898 }
1899 dptr_fill(sconn, buf+12,dptr_num);
1900 if (dptr_zero(buf+12) && (status_len==0)) {
1901 numentries = 1;
1902 } else {
1903 numentries = 0;
1904 }
1905 if (message_push_blob(&req->outbuf,
1906 data_blob_const(buf, sizeof(buf)))
1907 == -1) {
1908 reply_nterror(req, NT_STATUS_NO_MEMORY);
1909 goto out;
1910 }
1911 } else {
1912 unsigned int i;
1913 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1914 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1915
1916 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1917
1918 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1919 directory,lp_dont_descend(ctx, SNUM(conn))));
1920 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1921 check_descend = True;
1922 }
1923
1924 for (i=numentries;(i<maxentries) && !finished;i++) {
1925 finished = !get_dir_entry(ctx,
1926 dirptr,
1927 mask,
1928 dirtype,
1929 &fname,
1930 &size,
1931 &mode,
1932 &date,
1933 check_descend,
1934 ask_sharemode);
1935 if (!finished) {
1936 char buf[DIR_STRUCT_SIZE];
1937 memcpy(buf,status,21);
1938 if (!make_dir_struct(ctx,
1939 buf,
1940 mask,
1941 fname,
1942 size,
1943 mode,
1944 convert_timespec_to_time_t(date),
1945 !allow_long_path_components)) {
1946 reply_nterror(req, NT_STATUS_NO_MEMORY);
1947 goto out;
1948 }
1949 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1950 break;
1951 }
1952 if (message_push_blob(&req->outbuf,
1953 data_blob_const(buf, sizeof(buf)))
1954 == -1) {
1955 reply_nterror(req, NT_STATUS_NO_MEMORY);
1956 goto out;
1957 }
1958 numentries++;
1959 }
1960 }
1961 }
1962
1963 SearchEmpty:
1964
1965 /* If we were called as SMBffirst with smb_search_id == NULL
1966 and no entries were found then return error and close dirptr
1967 (X/Open spec) */
1968
1969 if (numentries == 0) {
1970 dptr_close(sconn, &dptr_num);
1971 } else if(expect_close && status_len == 0) {
1972 /* Close the dptr - we know it's gone */
1973 dptr_close(sconn, &dptr_num);
1974 }
1975
1976 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1977 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1978 dptr_close(sconn, &dptr_num);
1979 }
1980
1981 if ((numentries == 0) && !mask_contains_wcard) {
1982 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1983 goto out;
1984 }
1985
1986 SSVAL(req->outbuf,smb_vwv0,numentries);
1987 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1988 SCVAL(smb_buf(req->outbuf),0,5);
1989 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1990
1991 /* The replies here are never long name. */
1992 SSVAL(req->outbuf, smb_flg2,
1993 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1994 if (!allow_long_path_components) {
1995 SSVAL(req->outbuf, smb_flg2,
1996 SVAL(req->outbuf, smb_flg2)
1997 & (~FLAGS2_LONG_PATH_COMPONENTS));
1998 }
1999
2000 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2001 SSVAL(req->outbuf, smb_flg2,
2002 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2003
2004 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2005 smb_fn_name(req->cmd),
2006 mask,
2007 directory,
2008 dirtype,
2009 numentries,
2010 maxentries ));
2011 out:
2012 TALLOC_FREE(directory);
2013 TALLOC_FREE(mask);
2014 TALLOC_FREE(smb_fname);
2015 END_PROFILE(SMBsearch);
2016 return;
2017}
2018
2019/****************************************************************************
2020 Reply to a fclose (stop directory search).
2021****************************************************************************/
2022
2023void reply_fclose(struct smb_request *req)
2024{
2025 int status_len;
2026 char status[21];
2027 int dptr_num= -2;
2028 const char *p;
2029 char *path = NULL;
2030 NTSTATUS err;
2031 bool path_contains_wcard = False;
2032 TALLOC_CTX *ctx = talloc_tos();
2033 struct smbd_server_connection *sconn = req->sconn;
2034
2035 START_PROFILE(SMBfclose);
2036
2037 if (req->posix_pathnames) {
2038 reply_unknown_new(req, req->cmd);
2039 END_PROFILE(SMBfclose);
2040 return;
2041 }
2042
2043 p = (const char *)req->buf + 1;
2044 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2045 &err, &path_contains_wcard);
2046 if (!NT_STATUS_IS_OK(err)) {
2047 reply_nterror(req, err);
2048 END_PROFILE(SMBfclose);
2049 return;
2050 }
2051 p++;
2052 status_len = SVAL(p,0);
2053 p += 2;
2054
2055 if (status_len == 0) {
2056 reply_force_doserror(req, ERRSRV, ERRsrverror);
2057 END_PROFILE(SMBfclose);
2058 return;
2059 }
2060
2061 memcpy(status,p,21);
2062
2063 if(dptr_fetch(sconn, status+12,&dptr_num)) {
2064 /* Close the dptr - we know it's gone */
2065 dptr_close(sconn, &dptr_num);
2066 }
2067
2068 reply_outbuf(req, 1, 0);
2069 SSVAL(req->outbuf,smb_vwv0,0);
2070
2071 DEBUG(3,("search close\n"));
2072
2073 END_PROFILE(SMBfclose);
2074 return;
2075}
2076
2077/****************************************************************************
2078 Reply to an open.
2079****************************************************************************/
2080
2081void reply_open(struct smb_request *req)
2082{
2083 connection_struct *conn = req->conn;
2084 struct smb_filename *smb_fname = NULL;
2085 char *fname = NULL;
2086 uint32_t fattr=0;
2087 off_t size = 0;
2088 time_t mtime=0;
2089 int info;
2090 files_struct *fsp;
2091 int oplock_request;
2092 int deny_mode;
2093 uint32_t dos_attr;
2094 uint32_t access_mask;
2095 uint32_t share_mode;
2096 uint32_t create_disposition;
2097 uint32_t create_options = 0;
2098 uint32_t private_flags = 0;
2099 NTSTATUS status;
2100 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2101 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2102 TALLOC_CTX *ctx = talloc_tos();
2103
2104 START_PROFILE(SMBopen);
2105
2106 if (req->wct < 2) {
2107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2108 goto out;
2109 }
2110
2111 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2112 deny_mode = SVAL(req->vwv+0, 0);
2113 dos_attr = SVAL(req->vwv+1, 0);
2114
2115 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2116 STR_TERMINATE, &status);
2117 if (!NT_STATUS_IS_OK(status)) {
2118 reply_nterror(req, status);
2119 goto out;
2120 }
2121
2122 if (!map_open_params_to_ntcreate(fname, deny_mode,
2123 OPENX_FILE_EXISTS_OPEN, &access_mask,
2124 &share_mode, &create_disposition,
2125 &create_options, &private_flags)) {
2126 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2127 goto out;
2128 }
2129
2130 status = filename_convert(ctx,
2131 conn,
2132 req->flags2 & FLAGS2_DFS_PATHNAMES,
2133 fname,
2134 ucf_flags,
2135 NULL,
2136 &smb_fname);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2139 reply_botherror(req,
2140 NT_STATUS_PATH_NOT_COVERED,
2141 ERRSRV, ERRbadpath);
2142 goto out;
2143 }
2144 reply_nterror(req, status);
2145 goto out;
2146 }
2147
2148 status = SMB_VFS_CREATE_FILE(
2149 conn, /* conn */
2150 req, /* req */
2151 0, /* root_dir_fid */
2152 smb_fname, /* fname */
2153 access_mask, /* access_mask */
2154 share_mode, /* share_access */
2155 create_disposition, /* create_disposition*/
2156 create_options, /* create_options */
2157 dos_attr, /* file_attributes */
2158 oplock_request, /* oplock_request */
2159 NULL, /* lease */
2160 0, /* allocation_size */
2161 private_flags,
2162 NULL, /* sd */
2163 NULL, /* ea_list */
2164 &fsp, /* result */
2165 &info, /* pinfo */
2166 NULL, NULL); /* create context */
2167
2168 if (!NT_STATUS_IS_OK(status)) {
2169 if (open_was_deferred(req->xconn, req->mid)) {
2170 /* We have re-scheduled this call. */
2171 goto out;
2172 }
2173 reply_openerror(req, status);
2174 goto out;
2175 }
2176
2177 /* Ensure we're pointing at the correct stat struct. */
2178 TALLOC_FREE(smb_fname);
2179 smb_fname = fsp->fsp_name;
2180
2181 size = smb_fname->st.st_ex_size;
2182 fattr = dos_mode(conn, smb_fname);
2183
2184 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2185
2186 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2187 DEBUG(3,("attempt to open a directory %s\n",
2188 fsp_str_dbg(fsp)));
2189 close_file(req, fsp, ERROR_CLOSE);
2190 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2191 ERRDOS, ERRnoaccess);
2192 goto out;
2193 }
2194
2195 reply_outbuf(req, 7, 0);
2196 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2197 SSVAL(req->outbuf,smb_vwv1,fattr);
2198 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2199 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2200 } else {
2201 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2202 }
2203 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2204 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2205
2206 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2207 SCVAL(req->outbuf,smb_flg,
2208 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2209 }
2210
2211 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2212 SCVAL(req->outbuf,smb_flg,
2213 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2214 }
2215 out:
2216 END_PROFILE(SMBopen);
2217 return;
2218}
2219
2220/****************************************************************************
2221 Reply to an open and X.
2222****************************************************************************/
2223
2224void reply_open_and_X(struct smb_request *req)
2225{
2226 connection_struct *conn = req->conn;
2227 struct smb_filename *smb_fname = NULL;
2228 char *fname = NULL;
2229 uint16_t open_flags;
2230 int deny_mode;
2231 uint32_t smb_attr;
2232 /* Breakout the oplock request bits so we can set the
2233 reply bits separately. */
2234 int ex_oplock_request;
2235 int core_oplock_request;
2236 int oplock_request;
2237#if 0
2238 int smb_sattr = SVAL(req->vwv+4, 0);
2239 uint32_t smb_time = make_unix_date3(req->vwv+6);
2240#endif
2241 int smb_ofun;
2242 uint32_t fattr=0;
2243 int mtime=0;
2244 int smb_action = 0;
2245 files_struct *fsp;
2246 NTSTATUS status;
2247 uint64_t allocation_size;
2248 ssize_t retval = -1;
2249 uint32_t access_mask;
2250 uint32_t share_mode;
2251 uint32_t create_disposition;
2252 uint32_t create_options = 0;
2253 uint32_t private_flags = 0;
2254 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2255 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2256 TALLOC_CTX *ctx = talloc_tos();
2257
2258 START_PROFILE(SMBopenX);
2259
2260 if (req->wct < 15) {
2261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2262 goto out;
2263 }
2264
2265 open_flags = SVAL(req->vwv+2, 0);
2266 deny_mode = SVAL(req->vwv+3, 0);
2267 smb_attr = SVAL(req->vwv+5, 0);
2268 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2269 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2270 oplock_request = ex_oplock_request | core_oplock_request;
2271 smb_ofun = SVAL(req->vwv+8, 0);
2272 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2273
2274 /* If it's an IPC, pass off the pipe handler. */
2275 if (IS_IPC(conn)) {
2276 if (lp_nt_pipe_support()) {
2277 reply_open_pipe_and_X(conn, req);
2278 } else {
2279 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2280 }
2281 goto out;
2282 }
2283
2284 /* XXXX we need to handle passed times, sattr and flags */
2285 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2286 STR_TERMINATE, &status);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 reply_nterror(req, status);
2289 goto out;
2290 }
2291
2292 if (!map_open_params_to_ntcreate(fname, deny_mode,
2293 smb_ofun,
2294 &access_mask, &share_mode,
2295 &create_disposition,
2296 &create_options,
2297 &private_flags)) {
2298 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2299 goto out;
2300 }
2301
2302 status = filename_convert(ctx,
2303 conn,
2304 req->flags2 & FLAGS2_DFS_PATHNAMES,
2305 fname,
2306 ucf_flags,
2307 NULL,
2308 &smb_fname);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2311 reply_botherror(req,
2312 NT_STATUS_PATH_NOT_COVERED,
2313 ERRSRV, ERRbadpath);
2314 goto out;
2315 }
2316 reply_nterror(req, status);
2317 goto out;
2318 }
2319
2320 status = SMB_VFS_CREATE_FILE(
2321 conn, /* conn */
2322 req, /* req */
2323 0, /* root_dir_fid */
2324 smb_fname, /* fname */
2325 access_mask, /* access_mask */
2326 share_mode, /* share_access */
2327 create_disposition, /* create_disposition*/
2328 create_options, /* create_options */
2329 smb_attr, /* file_attributes */
2330 oplock_request, /* oplock_request */
2331 NULL, /* lease */
2332 0, /* allocation_size */
2333 private_flags,
2334 NULL, /* sd */
2335 NULL, /* ea_list */
2336 &fsp, /* result */
2337 &smb_action, /* pinfo */
2338 NULL, NULL); /* create context */
2339
2340 if (!NT_STATUS_IS_OK(status)) {
2341 if (open_was_deferred(req->xconn, req->mid)) {
2342 /* We have re-scheduled this call. */
2343 goto out;
2344 }
2345 reply_openerror(req, status);
2346 goto out;
2347 }
2348
2349 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2350 if the file is truncated or created. */
2351 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2352 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2353 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2354 close_file(req, fsp, ERROR_CLOSE);
2355 reply_nterror(req, NT_STATUS_DISK_FULL);
2356 goto out;
2357 }
2358 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2359 if (retval < 0) {
2360 close_file(req, fsp, ERROR_CLOSE);
2361 reply_nterror(req, NT_STATUS_DISK_FULL);
2362 goto out;
2363 }
2364 status = vfs_stat_fsp(fsp);
2365 if (!NT_STATUS_IS_OK(status)) {
2366 close_file(req, fsp, ERROR_CLOSE);
2367 reply_nterror(req, status);
2368 goto out;
2369 }
2370 }
2371
2372 fattr = dos_mode(conn, fsp->fsp_name);
2373 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2374 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2375 close_file(req, fsp, ERROR_CLOSE);
2376 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2377 goto out;
2378 }
2379
2380 /* If the caller set the extended oplock request bit
2381 and we granted one (by whatever means) - set the
2382 correct bit for extended oplock reply.
2383 */
2384
2385 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2386 smb_action |= EXTENDED_OPLOCK_GRANTED;
2387 }
2388
2389 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2390 smb_action |= EXTENDED_OPLOCK_GRANTED;
2391 }
2392
2393 /* If the caller set the core oplock request bit
2394 and we granted one (by whatever means) - set the
2395 correct bit for core oplock reply.
2396 */
2397
2398 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2399 reply_outbuf(req, 19, 0);
2400 } else {
2401 reply_outbuf(req, 15, 0);
2402 }
2403
2404 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2405 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2406
2407 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2408 SCVAL(req->outbuf, smb_flg,
2409 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2410 }
2411
2412 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2413 SCVAL(req->outbuf, smb_flg,
2414 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2415 }
2416
2417 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2418 SSVAL(req->outbuf,smb_vwv3,fattr);
2419 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2420 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2421 } else {
2422 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2423 }
2424 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2425 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2426 SSVAL(req->outbuf,smb_vwv11,smb_action);
2427
2428 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2429 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2430 }
2431
2432 out:
2433 TALLOC_FREE(smb_fname);
2434 END_PROFILE(SMBopenX);
2435 return;
2436}
2437
2438/****************************************************************************
2439 Reply to a SMBulogoffX.
2440****************************************************************************/
2441
2442void reply_ulogoffX(struct smb_request *req)
2443{
2444 struct smbd_server_connection *sconn = req->sconn;
2445 struct user_struct *vuser;
2446 struct smbXsrv_session *session = NULL;
2447 NTSTATUS status;
2448
2449 START_PROFILE(SMBulogoffX);
2450
2451 vuser = get_valid_user_struct(sconn, req->vuid);
2452
2453 if(vuser == NULL) {
2454 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2455 (unsigned long long)req->vuid));
2456
2457 req->vuid = UID_FIELD_INVALID;
2458 reply_force_doserror(req, ERRSRV, ERRbaduid);
2459 END_PROFILE(SMBulogoffX);
2460 return;
2461 }
2462
2463 session = vuser->session;
2464 vuser = NULL;
2465
2466 /*
2467 * TODO: cancel all outstanding requests on the session
2468 */
2469 status = smbXsrv_session_logoff(session);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 DEBUG(0, ("reply_ulogoff: "
2472 "smbXsrv_session_logoff() failed: %s\n",
2473 nt_errstr(status)));
2474 /*
2475 * If we hit this case, there is something completely
2476 * wrong, so we better disconnect the transport connection.
2477 */
2478 END_PROFILE(SMBulogoffX);
2479 exit_server(__location__ ": smbXsrv_session_logoff failed");
2480 return;
2481 }
2482
2483 TALLOC_FREE(session);
2484
2485 reply_outbuf(req, 2, 0);
2486 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2487 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2488
2489 DEBUG(3, ("ulogoffX vuid=%llu\n",
2490 (unsigned long long)req->vuid));
2491
2492 END_PROFILE(SMBulogoffX);
2493 req->vuid = UID_FIELD_INVALID;
2494}
2495
2496/****************************************************************************
2497 Reply to a mknew or a create.
2498****************************************************************************/
2499
2500void reply_mknew(struct smb_request *req)
2501{
2502 connection_struct *conn = req->conn;
2503 struct smb_filename *smb_fname = NULL;
2504 char *fname = NULL;
2505 uint32_t fattr = 0;
2506 struct smb_file_time ft;
2507 files_struct *fsp;
2508 int oplock_request = 0;
2509 NTSTATUS status;
2510 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2511 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2512 uint32_t create_disposition;
2513 uint32_t create_options = 0;
2514 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2515 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2516 TALLOC_CTX *ctx = talloc_tos();
2517
2518 START_PROFILE(SMBcreate);
2519 ZERO_STRUCT(ft);
2520
2521 if (req->wct < 3) {
2522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2523 goto out;
2524 }
2525
2526 fattr = SVAL(req->vwv+0, 0);
2527 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2528
2529 /* mtime. */
2530 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2531
2532 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2533 STR_TERMINATE, &status);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 reply_nterror(req, status);
2536 goto out;
2537 }
2538
2539 status = filename_convert(ctx,
2540 conn,
2541 req->flags2 & FLAGS2_DFS_PATHNAMES,
2542 fname,
2543 ucf_flags,
2544 NULL,
2545 &smb_fname);
2546 if (!NT_STATUS_IS_OK(status)) {
2547 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2548 reply_botherror(req,
2549 NT_STATUS_PATH_NOT_COVERED,
2550 ERRSRV, ERRbadpath);
2551 goto out;
2552 }
2553 reply_nterror(req, status);
2554 goto out;
2555 }
2556
2557 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2558 DEBUG(0,("Attempt to create file (%s) with volid set - "
2559 "please report this\n",
2560 smb_fname_str_dbg(smb_fname)));
2561 }
2562
2563 if(req->cmd == SMBmknew) {
2564 /* We should fail if file exists. */
2565 create_disposition = FILE_CREATE;
2566 } else {
2567 /* Create if file doesn't exist, truncate if it does. */
2568 create_disposition = FILE_OVERWRITE_IF;
2569 }
2570
2571 status = SMB_VFS_CREATE_FILE(
2572 conn, /* conn */
2573 req, /* req */
2574 0, /* root_dir_fid */
2575 smb_fname, /* fname */
2576 access_mask, /* access_mask */
2577 share_mode, /* share_access */
2578 create_disposition, /* create_disposition*/
2579 create_options, /* create_options */
2580 fattr, /* file_attributes */
2581 oplock_request, /* oplock_request */
2582 NULL, /* lease */
2583 0, /* allocation_size */
2584 0, /* private_flags */
2585 NULL, /* sd */
2586 NULL, /* ea_list */
2587 &fsp, /* result */
2588 NULL, /* pinfo */
2589 NULL, NULL); /* create context */
2590
2591 if (!NT_STATUS_IS_OK(status)) {
2592 if (open_was_deferred(req->xconn, req->mid)) {
2593 /* We have re-scheduled this call. */
2594 goto out;
2595 }
2596 reply_openerror(req, status);
2597 goto out;
2598 }
2599
2600 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2601 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2602 if (!NT_STATUS_IS_OK(status)) {
2603 END_PROFILE(SMBcreate);
2604 goto out;
2605 }
2606
2607 reply_outbuf(req, 1, 0);
2608 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2609
2610 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2611 SCVAL(req->outbuf,smb_flg,
2612 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2613 }
2614
2615 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2616 SCVAL(req->outbuf,smb_flg,
2617 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2618 }
2619
2620 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2621 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2622 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2623 (unsigned int)fattr));
2624
2625 out:
2626 TALLOC_FREE(smb_fname);
2627 END_PROFILE(SMBcreate);
2628 return;
2629}
2630
2631/****************************************************************************
2632 Reply to a create temporary file.
2633****************************************************************************/
2634
2635void reply_ctemp(struct smb_request *req)
2636{
2637 connection_struct *conn = req->conn;
2638 struct smb_filename *smb_fname = NULL;
2639 char *wire_name = NULL;
2640 char *fname = NULL;
2641 uint32_t fattr;
2642 files_struct *fsp;
2643 int oplock_request;
2644 char *s;
2645 NTSTATUS status;
2646 int i;
2647 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
2648 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2649 TALLOC_CTX *ctx = talloc_tos();
2650
2651 START_PROFILE(SMBctemp);
2652
2653 if (req->wct < 3) {
2654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2655 goto out;
2656 }
2657
2658 fattr = SVAL(req->vwv+0, 0);
2659 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2660
2661 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2662 STR_TERMINATE, &status);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 reply_nterror(req, status);
2665 goto out;
2666 }
2667
2668 for (i = 0; i < 10; i++) {
2669 if (*wire_name) {
2670 fname = talloc_asprintf(ctx,
2671 "%s/TMP%s",
2672 wire_name,
2673 generate_random_str_list(ctx, 5, "0123456789"));
2674 } else {
2675 fname = talloc_asprintf(ctx,
2676 "TMP%s",
2677 generate_random_str_list(ctx, 5, "0123456789"));
2678 }
2679
2680 if (!fname) {
2681 reply_nterror(req, NT_STATUS_NO_MEMORY);
2682 goto out;
2683 }
2684
2685 status = filename_convert(ctx, conn,
2686 req->flags2 & FLAGS2_DFS_PATHNAMES,
2687 fname,
2688 ucf_flags,
2689 NULL,
2690 &smb_fname);
2691 if (!NT_STATUS_IS_OK(status)) {
2692 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2693 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2694 ERRSRV, ERRbadpath);
2695 goto out;
2696 }
2697 reply_nterror(req, status);
2698 goto out;
2699 }
2700
2701 /* Create the file. */
2702 status = SMB_VFS_CREATE_FILE(
2703 conn, /* conn */
2704 req, /* req */
2705 0, /* root_dir_fid */
2706 smb_fname, /* fname */
2707 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2708 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2709 FILE_CREATE, /* create_disposition*/
2710 0, /* create_options */
2711 fattr, /* file_attributes */
2712 oplock_request, /* oplock_request */
2713 NULL, /* lease */
2714 0, /* allocation_size */
2715 0, /* private_flags */
2716 NULL, /* sd */
2717 NULL, /* ea_list */
2718 &fsp, /* result */
2719 NULL, /* pinfo */
2720 NULL, NULL); /* create context */
2721
2722 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2723 TALLOC_FREE(fname);
2724 TALLOC_FREE(smb_fname);
2725 continue;
2726 }
2727
2728 if (!NT_STATUS_IS_OK(status)) {
2729 if (open_was_deferred(req->xconn, req->mid)) {
2730 /* We have re-scheduled this call. */
2731 goto out;
2732 }
2733 reply_openerror(req, status);
2734 goto out;
2735 }
2736
2737 break;
2738 }
2739
2740 if (i == 10) {
2741 /* Collision after 10 times... */
2742 reply_nterror(req, status);
2743 goto out;
2744 }
2745
2746 reply_outbuf(req, 1, 0);
2747 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2748
2749 /* the returned filename is relative to the directory */
2750 s = strrchr_m(fsp->fsp_name->base_name, '/');
2751 if (!s) {
2752 s = fsp->fsp_name->base_name;
2753 } else {
2754 s++;
2755 }
2756
2757#if 0
2758 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2759 thing in the byte section. JRA */
2760 SSVALS(p, 0, -1); /* what is this? not in spec */
2761#endif
2762 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2763 == -1) {
2764 reply_nterror(req, NT_STATUS_NO_MEMORY);
2765 goto out;
2766 }
2767
2768 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2769 SCVAL(req->outbuf, smb_flg,
2770 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2771 }
2772
2773 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2774 SCVAL(req->outbuf, smb_flg,
2775 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2776 }
2777
2778 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2779 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2780 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2781 out:
2782 TALLOC_FREE(smb_fname);
2783 TALLOC_FREE(wire_name);
2784 END_PROFILE(SMBctemp);
2785 return;
2786}
2787
2788/*******************************************************************
2789 Check if a user is allowed to rename a file.
2790********************************************************************/
2791
2792static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2793 uint16_t dirtype)
2794{
2795 if (!CAN_WRITE(conn)) {
2796 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2797 }
2798
2799 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2800 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2801 /* Only bother to read the DOS attribute if we might deny the
2802 rename on the grounds of attribute mismatch. */
2803 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2804 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2805 return NT_STATUS_NO_SUCH_FILE;
2806 }
2807 }
2808
2809 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2810 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2811 return NT_STATUS_OK;
2812 }
2813
2814 /* If no pathnames are open below this
2815 directory, allow the rename. */
2816
2817 if (lp_strict_rename(SNUM(conn))) {
2818 /*
2819 * Strict rename, check open file db.
2820 */
2821 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2822 return NT_STATUS_ACCESS_DENIED;
2823 }
2824 } else if (file_find_subpath(fsp)) {
2825 /*
2826 * No strict rename, just look in local process.
2827 */
2828 return NT_STATUS_ACCESS_DENIED;
2829 }
2830 return NT_STATUS_OK;
2831 }
2832
2833 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2834 return NT_STATUS_OK;
2835 }
2836
2837 return NT_STATUS_ACCESS_DENIED;
2838}
2839
2840/*******************************************************************
2841 * unlink a file with all relevant access checks
2842 *******************************************************************/
2843
2844static NTSTATUS do_unlink(connection_struct *conn,
2845 struct smb_request *req,
2846 struct smb_filename *smb_fname,
2847 uint32_t dirtype)
2848{
2849 uint32_t fattr;
2850 files_struct *fsp;
2851 uint32_t dirtype_orig = dirtype;
2852 NTSTATUS status;
2853 int ret;
2854 bool posix_paths = (req != NULL && req->posix_pathnames);
2855
2856 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2857 smb_fname_str_dbg(smb_fname),
2858 dirtype));
2859
2860 if (!CAN_WRITE(conn)) {
2861 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2862 }
2863
2864 if (posix_paths) {
2865 ret = SMB_VFS_LSTAT(conn, smb_fname);
2866 } else {
2867 ret = SMB_VFS_STAT(conn, smb_fname);
2868 }
2869 if (ret != 0) {
2870 return map_nt_error_from_unix(errno);
2871 }
2872
2873 fattr = dos_mode(conn, smb_fname);
2874
2875 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2876 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2877 }
2878
2879 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2880 if (!dirtype) {
2881 return NT_STATUS_NO_SUCH_FILE;
2882 }
2883
2884 if (!dir_check_ftype(fattr, dirtype)) {
2885 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2886 return NT_STATUS_FILE_IS_A_DIRECTORY;
2887 }
2888 return NT_STATUS_NO_SUCH_FILE;
2889 }
2890
2891 if (dirtype_orig & 0x8000) {
2892 /* These will never be set for POSIX. */
2893 return NT_STATUS_NO_SUCH_FILE;
2894 }
2895
2896#if 0
2897 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2898 return NT_STATUS_FILE_IS_A_DIRECTORY;
2899 }
2900
2901 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2902 return NT_STATUS_NO_SUCH_FILE;
2903 }
2904
2905 if (dirtype & 0xFF00) {
2906 /* These will never be set for POSIX. */
2907 return NT_STATUS_NO_SUCH_FILE;
2908 }
2909
2910 dirtype &= 0xFF;
2911 if (!dirtype) {
2912 return NT_STATUS_NO_SUCH_FILE;
2913 }
2914
2915 /* Can't delete a directory. */
2916 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2917 return NT_STATUS_FILE_IS_A_DIRECTORY;
2918 }
2919#endif
2920
2921#if 0 /* JRATEST */
2922 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2923 return NT_STATUS_OBJECT_NAME_INVALID;
2924#endif /* JRATEST */
2925
2926 /* On open checks the open itself will check the share mode, so
2927 don't do it here as we'll get it wrong. */
2928
2929 status = SMB_VFS_CREATE_FILE
2930 (conn, /* conn */
2931 req, /* req */
2932 0, /* root_dir_fid */
2933 smb_fname, /* fname */
2934 DELETE_ACCESS, /* access_mask */
2935 FILE_SHARE_NONE, /* share_access */
2936 FILE_OPEN, /* create_disposition*/
2937 FILE_NON_DIRECTORY_FILE, /* create_options */
2938 /* file_attributes */
2939 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2940 FILE_ATTRIBUTE_NORMAL,
2941 0, /* oplock_request */
2942 NULL, /* lease */
2943 0, /* allocation_size */
2944 0, /* private_flags */
2945 NULL, /* sd */
2946 NULL, /* ea_list */
2947 &fsp, /* result */
2948 NULL, /* pinfo */
2949 NULL, NULL); /* create context */
2950
2951 if (!NT_STATUS_IS_OK(status)) {
2952 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2953 nt_errstr(status)));
2954 return status;
2955 }
2956
2957 status = can_set_delete_on_close(fsp, fattr);
2958 if (!NT_STATUS_IS_OK(status)) {
2959 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2960 "(%s)\n",
2961 smb_fname_str_dbg(smb_fname),
2962 nt_errstr(status)));
2963 close_file(req, fsp, NORMAL_CLOSE);
2964 return status;
2965 }
2966
2967 /* The set is across all open files on this dev/inode pair. */
2968 if (!set_delete_on_close(fsp, True,
2969 conn->session_info->security_token,
2970 conn->session_info->unix_token)) {
2971 close_file(req, fsp, NORMAL_CLOSE);
2972 return NT_STATUS_ACCESS_DENIED;
2973 }
2974
2975 return close_file(req, fsp, NORMAL_CLOSE);
2976}
2977
2978/****************************************************************************
2979 The guts of the unlink command, split out so it may be called by the NT SMB
2980 code.
2981****************************************************************************/
2982
2983NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2984 uint32_t dirtype, struct smb_filename *smb_fname,
2985 bool has_wild)
2986{
2987 char *fname_dir = NULL;
2988 char *fname_mask = NULL;
2989 int count=0;
2990 NTSTATUS status = NT_STATUS_OK;
2991 TALLOC_CTX *ctx = talloc_tos();
2992
2993 /* Split up the directory from the filename/mask. */
2994 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2995 &fname_dir, &fname_mask);
2996 if (!NT_STATUS_IS_OK(status)) {
2997 goto out;
2998 }
2999
3000 /*
3001 * We should only check the mangled cache
3002 * here if unix_convert failed. This means
3003 * that the path in 'mask' doesn't exist
3004 * on the file system and so we need to look
3005 * for a possible mangle. This patch from
3006 * Tine Smukavec <valentin.smukavec@hermes.si>.
3007 */
3008
3009 if (!VALID_STAT(smb_fname->st) &&
3010 mangle_is_mangled(fname_mask, conn->params)) {
3011 char *new_mask = NULL;
3012 mangle_lookup_name_from_8_3(ctx, fname_mask,
3013 &new_mask, conn->params);
3014 if (new_mask) {
3015 TALLOC_FREE(fname_mask);
3016 fname_mask = new_mask;
3017 }
3018 }
3019
3020 if (!has_wild) {
3021
3022 /*
3023 * Only one file needs to be unlinked. Append the mask back
3024 * onto the directory.
3025 */
3026 TALLOC_FREE(smb_fname->base_name);
3027 if (ISDOT(fname_dir)) {
3028 /* Ensure we use canonical names on open. */
3029 smb_fname->base_name = talloc_asprintf(smb_fname,
3030 "%s",
3031 fname_mask);
3032 } else {
3033 smb_fname->base_name = talloc_asprintf(smb_fname,
3034 "%s/%s",
3035 fname_dir,
3036 fname_mask);
3037 }
3038 if (!smb_fname->base_name) {
3039 status = NT_STATUS_NO_MEMORY;
3040 goto out;
3041 }
3042 if (dirtype == 0) {
3043 dirtype = FILE_ATTRIBUTE_NORMAL;
3044 }
3045
3046 status = check_name(conn, smb_fname->base_name);
3047 if (!NT_STATUS_IS_OK(status)) {
3048 goto out;
3049 }
3050
3051 status = do_unlink(conn, req, smb_fname, dirtype);
3052 if (!NT_STATUS_IS_OK(status)) {
3053 goto out;
3054 }
3055
3056 count++;
3057 } else {
3058 struct smb_Dir *dir_hnd = NULL;
3059 long offset = 0;
3060 const char *dname = NULL;
3061 char *talloced = NULL;
3062
3063 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3064 status = NT_STATUS_OBJECT_NAME_INVALID;
3065 goto out;
3066 }
3067 if (dirtype == 0) {
3068 dirtype = FILE_ATTRIBUTE_NORMAL;
3069 }
3070
3071 if (strequal(fname_mask,"????????.???")) {
3072 TALLOC_FREE(fname_mask);
3073 fname_mask = talloc_strdup(ctx, "*");
3074 if (!fname_mask) {
3075 status = NT_STATUS_NO_MEMORY;
3076 goto out;
3077 }
3078 }
3079
3080 status = check_name(conn, fname_dir);
3081 if (!NT_STATUS_IS_OK(status)) {
3082 goto out;
3083 }
3084
3085 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
3086 dirtype);
3087 if (dir_hnd == NULL) {
3088 status = map_nt_error_from_unix(errno);
3089 goto out;
3090 }
3091
3092 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3093 the pattern matches against the long name, otherwise the short name
3094 We don't implement this yet XXXX
3095 */
3096
3097 status = NT_STATUS_NO_SUCH_FILE;
3098
3099 while ((dname = ReadDirName(dir_hnd, &offset,
3100 &smb_fname->st, &talloced))) {
3101 TALLOC_CTX *frame = talloc_stackframe();
3102
3103 if (!is_visible_file(conn, fname_dir, dname,
3104 &smb_fname->st, true)) {
3105 TALLOC_FREE(frame);
3106 TALLOC_FREE(talloced);
3107 continue;
3108 }
3109
3110 /* Quick check for "." and ".." */
3111 if (ISDOT(dname) || ISDOTDOT(dname)) {
3112 TALLOC_FREE(frame);
3113 TALLOC_FREE(talloced);
3114 continue;
3115 }
3116
3117 if(!mask_match(dname, fname_mask,
3118 conn->case_sensitive)) {
3119 TALLOC_FREE(frame);
3120 TALLOC_FREE(talloced);
3121 continue;
3122 }
3123
3124 TALLOC_FREE(smb_fname->base_name);
3125 if (ISDOT(fname_dir)) {
3126 /* Ensure we use canonical names on open. */
3127 smb_fname->base_name =
3128 talloc_asprintf(smb_fname, "%s",
3129 dname);
3130 } else {
3131 smb_fname->base_name =
3132 talloc_asprintf(smb_fname, "%s/%s",
3133 fname_dir, dname);
3134 }
3135
3136 if (!smb_fname->base_name) {
3137 TALLOC_FREE(dir_hnd);
3138 status = NT_STATUS_NO_MEMORY;
3139 TALLOC_FREE(frame);
3140 TALLOC_FREE(talloced);
3141 goto out;
3142 }
3143
3144 status = check_name(conn, smb_fname->base_name);
3145 if (!NT_STATUS_IS_OK(status)) {
3146 TALLOC_FREE(dir_hnd);
3147 TALLOC_FREE(frame);
3148 TALLOC_FREE(talloced);
3149 goto out;
3150 }
3151
3152 status = do_unlink(conn, req, smb_fname, dirtype);
3153 if (!NT_STATUS_IS_OK(status)) {
3154 TALLOC_FREE(dir_hnd);
3155 TALLOC_FREE(frame);
3156 TALLOC_FREE(talloced);
3157 goto out;
3158 }
3159
3160 count++;
3161 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3162 smb_fname->base_name));
3163
3164 TALLOC_FREE(frame);
3165 TALLOC_FREE(talloced);
3166 }
3167 TALLOC_FREE(dir_hnd);
3168 }
3169
3170 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3171 status = map_nt_error_from_unix(errno);
3172 }
3173
3174 out:
3175 TALLOC_FREE(fname_dir);
3176 TALLOC_FREE(fname_mask);
3177 return status;
3178}
3179
3180/****************************************************************************
3181 Reply to a unlink
3182****************************************************************************/
3183
3184void reply_unlink(struct smb_request *req)
3185{
3186 connection_struct *conn = req->conn;
3187 char *name = NULL;
3188 struct smb_filename *smb_fname = NULL;
3189 uint32_t dirtype;
3190 NTSTATUS status;
3191 bool path_contains_wcard = False;
3192 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3193 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
3194 TALLOC_CTX *ctx = talloc_tos();
3195
3196 START_PROFILE(SMBunlink);
3197
3198 if (req->wct < 1) {
3199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3200 goto out;
3201 }
3202
3203 dirtype = SVAL(req->vwv+0, 0);
3204
3205 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3206 STR_TERMINATE, &status,
3207 &path_contains_wcard);
3208 if (!NT_STATUS_IS_OK(status)) {
3209 reply_nterror(req, status);
3210 goto out;
3211 }
3212
3213 status = filename_convert(ctx, conn,
3214 req->flags2 & FLAGS2_DFS_PATHNAMES,
3215 name,
3216 ucf_flags,
3217 &path_contains_wcard,
3218 &smb_fname);
3219 if (!NT_STATUS_IS_OK(status)) {
3220 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3221 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3222 ERRSRV, ERRbadpath);
3223 goto out;
3224 }
3225 reply_nterror(req, status);
3226 goto out;
3227 }
3228
3229 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3230
3231 status = unlink_internals(conn, req, dirtype, smb_fname,
3232 path_contains_wcard);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 if (open_was_deferred(req->xconn, req->mid)) {
3235 /* We have re-scheduled this call. */
3236 goto out;
3237 }
3238 reply_nterror(req, status);
3239 goto out;
3240 }
3241
3242 reply_outbuf(req, 0, 0);
3243 out:
3244 TALLOC_FREE(smb_fname);
3245 END_PROFILE(SMBunlink);
3246 return;
3247}
3248
3249/****************************************************************************
3250 Fail for readbraw.
3251****************************************************************************/
3252
3253static void fail_readraw(void)
3254{
3255 const char *errstr = talloc_asprintf(talloc_tos(),
3256 "FAIL ! reply_readbraw: socket write fail (%s)",
3257 strerror(errno));
3258 if (!errstr) {
3259 errstr = "";
3260 }
3261 exit_server_cleanly(errstr);
3262}
3263
3264/****************************************************************************
3265 Fake (read/write) sendfile. Returns -1 on read or write fail.
3266****************************************************************************/
3267
3268ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3269 off_t startpos, size_t nread)
3270{
3271 size_t bufsize;
3272 size_t tosend = nread;
3273 char *buf;
3274
3275 if (nread == 0) {
3276 return 0;
3277 }
3278
3279 bufsize = MIN(nread, 65536);
3280
3281 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3282 return -1;
3283 }
3284
3285 while (tosend > 0) {
3286 ssize_t ret;
3287 size_t cur_read;
3288
3289 cur_read = MIN(tosend, bufsize);
3290 ret = read_file(fsp,buf,startpos,cur_read);
3291 if (ret == -1) {
3292 SAFE_FREE(buf);
3293 return -1;
3294 }
3295
3296 /* If we had a short read, fill with zeros. */
3297 if (ret < cur_read) {
3298 memset(buf + ret, '\0', cur_read - ret);
3299 }
3300
3301 ret = write_data(xconn->transport.sock, buf, cur_read);
3302 if (ret != cur_read) {
3303 int saved_errno = errno;
3304 /*
3305 * Try and give an error message saying what
3306 * client failed.
3307 */
3308 DEBUG(0, ("write_data failed for client %s. "
3309 "Error %s\n",
3310 smbXsrv_connection_dbg(xconn),
3311 strerror(saved_errno)));
3312 SAFE_FREE(buf);
3313 errno = saved_errno;
3314 return -1;
3315 }
3316 tosend -= cur_read;
3317 startpos += cur_read;
3318 }
3319
3320 SAFE_FREE(buf);
3321 return (ssize_t)nread;
3322}
3323
3324/****************************************************************************
3325 Deal with the case of sendfile reading less bytes from the file than
3326 requested. Fill with zeros (all we can do). Returns 0 on success
3327****************************************************************************/
3328
3329ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3330 files_struct *fsp,
3331 ssize_t nread,
3332 size_t headersize,
3333 size_t smb_maxcnt)
3334{
3335#define SHORT_SEND_BUFSIZE 1024
3336 if (nread < headersize) {
3337 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3338 "header for file %s (%s). Terminating\n",
3339 fsp_str_dbg(fsp), strerror(errno)));
3340 return -1;
3341 }
3342
3343 nread -= headersize;
3344
3345 if (nread < smb_maxcnt) {
3346 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3347 if (!buf) {
3348 DEBUG(0,("sendfile_short_send: malloc failed "
3349 "for file %s (%s). Terminating\n",
3350 fsp_str_dbg(fsp), strerror(errno)));
3351 return -1;
3352 }
3353
3354 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3355 "with zeros !\n", fsp_str_dbg(fsp)));
3356
3357 while (nread < smb_maxcnt) {
3358 /*
3359 * We asked for the real file size and told sendfile
3360 * to not go beyond the end of the file. But it can
3361 * happen that in between our fstat call and the
3362 * sendfile call the file was truncated. This is very
3363 * bad because we have already announced the larger
3364 * number of bytes to the client.
3365 *
3366 * The best we can do now is to send 0-bytes, just as
3367 * a read from a hole in a sparse file would do.
3368 *
3369 * This should happen rarely enough that I don't care
3370 * about efficiency here :-)
3371 */
3372 size_t to_write;
3373 ssize_t ret;
3374
3375 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3376 ret = write_data(xconn->transport.sock, buf, to_write);
3377 if (ret != to_write) {
3378 int saved_errno = errno;
3379 /*
3380 * Try and give an error message saying what
3381 * client failed.
3382 */
3383 DEBUG(0, ("write_data failed for client %s. "
3384 "Error %s\n",
3385 smbXsrv_connection_dbg(xconn),
3386 strerror(saved_errno)));
3387 errno = saved_errno;
3388 return -1;
3389 }
3390 nread += to_write;
3391 }
3392 SAFE_FREE(buf);
3393 }
3394
3395 return 0;
3396}
3397
3398/****************************************************************************
3399 Return a readbraw error (4 bytes of zero).
3400****************************************************************************/
3401
3402static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3403{
3404 char header[4];
3405
3406 SIVAL(header,0,0);
3407
3408 smbd_lock_socket(xconn);
3409 if (write_data(xconn->transport.sock,header,4) != 4) {
3410 int saved_errno = errno;
3411 /*
3412 * Try and give an error message saying what
3413 * client failed.
3414 */
3415 DEBUG(0, ("write_data failed for client %s. "
3416 "Error %s\n",
3417 smbXsrv_connection_dbg(xconn),
3418 strerror(saved_errno)));
3419 errno = saved_errno;
3420
3421 fail_readraw();
3422 }
3423 smbd_unlock_socket(xconn);
3424}
3425
3426/****************************************************************************
3427 Use sendfile in readbraw.
3428****************************************************************************/
3429
3430static void send_file_readbraw(connection_struct *conn,
3431 struct smb_request *req,
3432 files_struct *fsp,
3433 off_t startpos,
3434 size_t nread,
3435 ssize_t mincount)
3436{
3437 struct smbXsrv_connection *xconn = req->xconn;
3438 char *outbuf = NULL;
3439 ssize_t ret=0;
3440
3441 /*
3442 * We can only use sendfile on a non-chained packet
3443 * but we can use on a non-oplocked file. tridge proved this
3444 * on a train in Germany :-). JRA.
3445 * reply_readbraw has already checked the length.
3446 */
3447
3448 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3449 (fsp->wcp == NULL) &&
3450 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3451 ssize_t sendfile_read = -1;
3452 char header[4];
3453 DATA_BLOB header_blob;
3454
3455 _smb_setlen(header,nread);
3456 header_blob = data_blob_const(header, 4);
3457
3458 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3459 &header_blob, startpos,
3460 nread);
3461 if (sendfile_read == -1) {
3462 /* Returning ENOSYS means no data at all was sent.
3463 * Do this as a normal read. */
3464 if (errno == ENOSYS) {
3465 goto normal_readbraw;
3466 }
3467
3468 /*
3469 * Special hack for broken Linux with no working sendfile. If we
3470 * return EINTR we sent the header but not the rest of the data.
3471 * Fake this up by doing read/write calls.
3472 */
3473 if (errno == EINTR) {
3474 /* Ensure we don't do this again. */
3475 set_use_sendfile(SNUM(conn), False);
3476 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3477
3478 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3479 DEBUG(0,("send_file_readbraw: "
3480 "fake_sendfile failed for "
3481 "file %s (%s).\n",
3482 fsp_str_dbg(fsp),
3483 strerror(errno)));
3484 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3485 }
3486 return;
3487 }
3488
3489 DEBUG(0,("send_file_readbraw: sendfile failed for "
3490 "file %s (%s). Terminating\n",
3491 fsp_str_dbg(fsp), strerror(errno)));
3492 exit_server_cleanly("send_file_readbraw sendfile failed");
3493 } else if (sendfile_read == 0) {
3494 /*
3495 * Some sendfile implementations return 0 to indicate
3496 * that there was a short read, but nothing was
3497 * actually written to the socket. In this case,
3498 * fallback to the normal read path so the header gets
3499 * the correct byte count.
3500 */
3501 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3502 "bytes falling back to the normal read: "
3503 "%s\n", fsp_str_dbg(fsp)));
3504 goto normal_readbraw;
3505 }
3506
3507 /* Deal with possible short send. */
3508 if (sendfile_read != 4+nread) {
3509 ret = sendfile_short_send(xconn, fsp,
3510 sendfile_read, 4, nread);
3511 if (ret == -1) {
3512 fail_readraw();
3513 }
3514 }
3515 return;
3516 }
3517
3518normal_readbraw:
3519
3520 outbuf = talloc_array(NULL, char, nread+4);
3521 if (!outbuf) {
3522 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3523 (unsigned)(nread+4)));
3524 reply_readbraw_error(xconn);
3525 return;
3526 }
3527
3528 if (nread > 0) {
3529 ret = read_file(fsp,outbuf+4,startpos,nread);
3530#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3531 if (ret < mincount)
3532 ret = 0;
3533#else
3534 if (ret < nread)
3535 ret = 0;
3536#endif
3537 }
3538
3539 _smb_setlen(outbuf,ret);
3540 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3541 int saved_errno = errno;
3542 /*
3543 * Try and give an error message saying what
3544 * client failed.
3545 */
3546 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3547 smbXsrv_connection_dbg(xconn),
3548 strerror(saved_errno)));
3549 errno = saved_errno;
3550
3551 fail_readraw();
3552 }
3553
3554 TALLOC_FREE(outbuf);
3555}
3556
3557/****************************************************************************
3558 Reply to a readbraw (core+ protocol).
3559****************************************************************************/
3560
3561void reply_readbraw(struct smb_request *req)
3562{
3563 connection_struct *conn = req->conn;
3564 struct smbXsrv_connection *xconn = req->xconn;
3565 ssize_t maxcount,mincount;
3566 size_t nread = 0;
3567 off_t startpos;
3568 files_struct *fsp;
3569 struct lock_struct lock;
3570 off_t size = 0;
3571
3572 START_PROFILE(SMBreadbraw);
3573
3574 if (srv_is_signing_active(xconn) || req->encrypted) {
3575 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3576 "raw reads/writes are disallowed.");
3577 }
3578
3579 if (req->wct < 8) {
3580 reply_readbraw_error(xconn);
3581 END_PROFILE(SMBreadbraw);
3582 return;
3583 }
3584
3585 if (xconn->smb1.echo_handler.trusted_fde) {
3586 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3587 "'async smb echo handler = yes'\n"));
3588 reply_readbraw_error(xconn);
3589 END_PROFILE(SMBreadbraw);
3590 return;
3591 }
3592
3593 /*
3594 * Special check if an oplock break has been issued
3595 * and the readraw request croses on the wire, we must
3596 * return a zero length response here.
3597 */
3598
3599 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3600
3601 /*
3602 * We have to do a check_fsp by hand here, as
3603 * we must always return 4 zero bytes on error,
3604 * not a NTSTATUS.
3605 */
3606
3607 if (!fsp || !conn || conn != fsp->conn ||
3608 req->vuid != fsp->vuid ||
3609 fsp->is_directory || fsp->fh->fd == -1) {
3610 /*
3611 * fsp could be NULL here so use the value from the packet. JRA.
3612 */
3613 DEBUG(3,("reply_readbraw: fnum %d not valid "
3614 "- cache prime?\n",
3615 (int)SVAL(req->vwv+0, 0)));
3616 reply_readbraw_error(xconn);
3617 END_PROFILE(SMBreadbraw);
3618 return;
3619 }
3620
3621 /* Do a "by hand" version of CHECK_READ. */
3622 if (!(fsp->can_read ||
3623 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3624 (fsp->access_mask & FILE_EXECUTE)))) {
3625 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3626 (int)SVAL(req->vwv+0, 0)));
3627 reply_readbraw_error(xconn);
3628 END_PROFILE(SMBreadbraw);
3629 return;
3630 }
3631
3632 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3633
3634 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3635 if(req->wct == 10) {
3636 /*
3637 * This is a large offset (64 bit) read.
3638 */
3639
3640 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3641
3642 if(startpos < 0) {
3643 DEBUG(0,("reply_readbraw: negative 64 bit "
3644 "readraw offset (%.0f) !\n",
3645 (double)startpos ));
3646 reply_readbraw_error(xconn);
3647 END_PROFILE(SMBreadbraw);
3648 return;
3649 }
3650 }
3651
3652 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3653 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3654
3655 /* ensure we don't overrun the packet size */
3656 maxcount = MIN(65535,maxcount);
3657
3658 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3659 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3660 &lock);
3661
3662 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3663 reply_readbraw_error(xconn);
3664 END_PROFILE(SMBreadbraw);
3665 return;
3666 }
3667
3668 if (fsp_stat(fsp) == 0) {
3669 size = fsp->fsp_name->st.st_ex_size;
3670 }
3671
3672 if (startpos >= size) {
3673 nread = 0;
3674 } else {
3675 nread = MIN(maxcount,(size - startpos));
3676 }
3677
3678#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3679 if (nread < mincount)
3680 nread = 0;
3681#endif
3682
3683 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3684 "min=%lu nread=%lu\n",
3685 fsp_fnum_dbg(fsp), (double)startpos,
3686 (unsigned long)maxcount,
3687 (unsigned long)mincount,
3688 (unsigned long)nread ) );
3689
3690 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3691
3692 DEBUG(5,("reply_readbraw finished\n"));
3693
3694 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3695
3696 END_PROFILE(SMBreadbraw);
3697 return;
3698}
3699
3700#undef DBGC_CLASS
3701#define DBGC_CLASS DBGC_LOCKING
3702
3703/****************************************************************************
3704 Reply to a lockread (core+ protocol).
3705****************************************************************************/
3706
3707void reply_lockread(struct smb_request *req)
3708{
3709 connection_struct *conn = req->conn;
3710 ssize_t nread = -1;
3711 char *data;
3712 off_t startpos;
3713 size_t numtoread;
3714 size_t maxtoread;
3715 NTSTATUS status;
3716 files_struct *fsp;
3717 struct byte_range_lock *br_lck = NULL;
3718 char *p = NULL;
3719 struct smbXsrv_connection *xconn = req->xconn;
3720
3721 START_PROFILE(SMBlockread);
3722
3723 if (req->wct < 5) {
3724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3725 END_PROFILE(SMBlockread);
3726 return;
3727 }
3728
3729 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3730
3731 if (!check_fsp(conn, req, fsp)) {
3732 END_PROFILE(SMBlockread);
3733 return;
3734 }
3735
3736 if (!CHECK_READ(fsp,req)) {
3737 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3738 END_PROFILE(SMBlockread);
3739 return;
3740 }
3741
3742 numtoread = SVAL(req->vwv+1, 0);
3743 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3744
3745 /*
3746 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3747 * protocol request that predates the read/write lock concept.
3748 * Thus instead of asking for a read lock here we need to ask
3749 * for a write lock. JRA.
3750 * Note that the requested lock size is unaffected by max_send.
3751 */
3752
3753 br_lck = do_lock(req->sconn->msg_ctx,
3754 fsp,
3755 (uint64_t)req->smbpid,
3756 (uint64_t)numtoread,
3757 (uint64_t)startpos,
3758 WRITE_LOCK,
3759 WINDOWS_LOCK,
3760 False, /* Non-blocking lock. */
3761 &status,
3762 NULL);
3763 TALLOC_FREE(br_lck);
3764
3765 if (NT_STATUS_V(status)) {
3766 reply_nterror(req, status);
3767 END_PROFILE(SMBlockread);
3768 return;
3769 }
3770
3771 /*
3772 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3773 */
3774 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3775
3776 if (numtoread > maxtoread) {
3777 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3778Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3779 (unsigned int)numtoread, (unsigned int)maxtoread,
3780 (unsigned int)xconn->smb1.sessions.max_send));
3781 numtoread = maxtoread;
3782 }
3783
3784 reply_outbuf(req, 5, numtoread + 3);
3785
3786 data = smb_buf(req->outbuf) + 3;
3787
3788 nread = read_file(fsp,data,startpos,numtoread);
3789
3790 if (nread < 0) {
3791 reply_nterror(req, map_nt_error_from_unix(errno));
3792 END_PROFILE(SMBlockread);
3793 return;
3794 }
3795
3796 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3797
3798 SSVAL(req->outbuf,smb_vwv0,nread);
3799 SSVAL(req->outbuf,smb_vwv5,nread+3);
3800 p = smb_buf(req->outbuf);
3801 SCVAL(p,0,0); /* pad byte. */
3802 SSVAL(p,1,nread);
3803
3804 DEBUG(3,("lockread %s num=%d nread=%d\n",
3805 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3806
3807 END_PROFILE(SMBlockread);
3808 return;
3809}
3810
3811#undef DBGC_CLASS
3812#define DBGC_CLASS DBGC_ALL
3813
3814/****************************************************************************
3815 Reply to a read.
3816****************************************************************************/
3817
3818void reply_read(struct smb_request *req)
3819{
3820 connection_struct *conn = req->conn;
3821 size_t numtoread;
3822 size_t maxtoread;
3823 ssize_t nread = 0;
3824 char *data;
3825 off_t startpos;
3826 files_struct *fsp;
3827 struct lock_struct lock;
3828 struct smbXsrv_connection *xconn = req->xconn;
3829
3830 START_PROFILE(SMBread);
3831
3832 if (req->wct < 3) {
3833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3834 END_PROFILE(SMBread);
3835 return;
3836 }
3837
3838 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3839
3840 if (!check_fsp(conn, req, fsp)) {
3841 END_PROFILE(SMBread);
3842 return;
3843 }
3844
3845 if (!CHECK_READ(fsp,req)) {
3846 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3847 END_PROFILE(SMBread);
3848 return;
3849 }
3850
3851 numtoread = SVAL(req->vwv+1, 0);
3852 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3853
3854 /*
3855 * The requested read size cannot be greater than max_send. JRA.
3856 */
3857 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3858
3859 if (numtoread > maxtoread) {
3860 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3861Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3862 (unsigned int)numtoread, (unsigned int)maxtoread,
3863 (unsigned int)xconn->smb1.sessions.max_send));
3864 numtoread = maxtoread;
3865 }
3866
3867 reply_outbuf(req, 5, numtoread+3);
3868
3869 data = smb_buf(req->outbuf) + 3;
3870
3871 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3872 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3873 &lock);
3874
3875 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3876 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3877 END_PROFILE(SMBread);
3878 return;
3879 }
3880
3881 if (numtoread > 0)
3882 nread = read_file(fsp,data,startpos,numtoread);
3883
3884 if (nread < 0) {
3885 reply_nterror(req, map_nt_error_from_unix(errno));
3886 goto strict_unlock;
3887 }
3888
3889 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3890
3891 SSVAL(req->outbuf,smb_vwv0,nread);
3892 SSVAL(req->outbuf,smb_vwv5,nread+3);
3893 SCVAL(smb_buf(req->outbuf),0,1);
3894 SSVAL(smb_buf(req->outbuf),1,nread);
3895
3896 DEBUG(3, ("read %s num=%d nread=%d\n",
3897 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3898
3899strict_unlock:
3900 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3901
3902 END_PROFILE(SMBread);
3903 return;
3904}
3905
3906/****************************************************************************
3907 Setup readX header.
3908****************************************************************************/
3909
3910int setup_readX_header(char *outbuf, size_t smb_maxcnt)
3911{
3912 int outsize;
3913
3914 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3915 False);
3916
3917 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3918
3919 SCVAL(outbuf,smb_vwv0,0xFF);
3920 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3921 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3922 SSVAL(outbuf,smb_vwv6,
3923 (smb_wct - 4) /* offset from smb header to wct */
3924 + 1 /* the wct field */
3925 + 12 * sizeof(uint16_t) /* vwv */
3926 + 2 /* the buflen field */
3927 + 1); /* padding byte */
3928 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3929 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3930 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3931 _smb_setlen_large(outbuf,
3932 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3933 return outsize;
3934}
3935
3936/****************************************************************************
3937 Reply to a read and X - possibly using sendfile.
3938****************************************************************************/
3939
3940static void send_file_readX(connection_struct *conn, struct smb_request *req,
3941 files_struct *fsp, off_t startpos,
3942 size_t smb_maxcnt)
3943{
3944 struct smbXsrv_connection *xconn = req->xconn;
3945 ssize_t nread = -1;
3946 struct lock_struct lock;
3947 int saved_errno = 0;
3948
3949 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3950 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3951 &lock);
3952
3953 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3954 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3955 return;
3956 }
3957
3958 /*
3959 * We can only use sendfile on a non-chained packet
3960 * but we can use on a non-oplocked file. tridge proved this
3961 * on a train in Germany :-). JRA.
3962 */
3963
3964 if (!req_is_in_chain(req) &&
3965 !req->encrypted &&
3966 (fsp->base_fsp == NULL) &&
3967 (fsp->wcp == NULL) &&
3968 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3969 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3970 DATA_BLOB header;
3971
3972 if(fsp_stat(fsp) == -1) {
3973 reply_nterror(req, map_nt_error_from_unix(errno));
3974 goto strict_unlock;
3975 }
3976
3977 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3978 (startpos > fsp->fsp_name->st.st_ex_size) ||
3979 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3980 /*
3981 * We already know that we would do a short read, so don't
3982 * try the sendfile() path.
3983 */
3984 goto nosendfile_read;
3985 }
3986
3987 /*
3988 * Set up the packet header before send. We
3989 * assume here the sendfile will work (get the
3990 * correct amount of data).
3991 */
3992
3993 header = data_blob_const(headerbuf, sizeof(headerbuf));
3994
3995 construct_reply_common_req(req, (char *)headerbuf);
3996 setup_readX_header((char *)headerbuf, smb_maxcnt);
3997
3998 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3999 startpos, smb_maxcnt);
4000 if (nread == -1) {
4001 saved_errno = errno;
4002
4003 /* Returning ENOSYS means no data at all was sent.
4004 Do this as a normal read. */
4005 if (errno == ENOSYS) {
4006 goto normal_read;
4007 }
4008
4009 /*
4010 * Special hack for broken Linux with no working sendfile. If we
4011 * return EINTR we sent the header but not the rest of the data.
4012 * Fake this up by doing read/write calls.
4013 */
4014
4015 if (errno == EINTR) {
4016 /* Ensure we don't do this again. */
4017 set_use_sendfile(SNUM(conn), False);
4018 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4019 nread = fake_sendfile(xconn, fsp, startpos,
4020 smb_maxcnt);
4021 if (nread == -1) {
4022 saved_errno = errno;
4023 DEBUG(0,("send_file_readX: "
4024 "fake_sendfile failed for "
4025 "file %s (%s) for client %s. "
4026 "Terminating\n",
4027 fsp_str_dbg(fsp),
4028 smbXsrv_connection_dbg(xconn),
4029 strerror(saved_errno)));
4030 errno = saved_errno;
4031 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4032 }
4033 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4034 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4035 /* No outbuf here means successful sendfile. */
4036 goto strict_unlock;
4037 }
4038
4039 DEBUG(0,("send_file_readX: sendfile failed for file "
4040 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4041 strerror(errno)));
4042 exit_server_cleanly("send_file_readX sendfile failed");
4043 } else if (nread == 0) {
4044 /*
4045 * Some sendfile implementations return 0 to indicate
4046 * that there was a short read, but nothing was
4047 * actually written to the socket. In this case,
4048 * fallback to the normal read path so the header gets
4049 * the correct byte count.
4050 */
4051 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4052 "falling back to the normal read: %s\n",
4053 fsp_str_dbg(fsp)));
4054 goto normal_read;
4055 }
4056
4057 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4058 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4059
4060 /* Deal with possible short send. */
4061 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4062 ssize_t ret;
4063
4064 ret = sendfile_short_send(xconn, fsp, nread,
4065 sizeof(headerbuf), smb_maxcnt);
4066 if (ret == -1) {
4067 const char *r;
4068 r = "send_file_readX: sendfile_short_send failed";
4069 DEBUG(0,("%s for file %s (%s).\n",
4070 r, fsp_str_dbg(fsp), strerror(errno)));
4071 exit_server_cleanly(r);
4072 }
4073 }
4074 /* No outbuf here means successful sendfile. */
4075 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4076 SMB_PERFCOUNT_END(&req->pcd);
4077 goto strict_unlock;
4078 }
4079
4080normal_read:
4081
4082 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4083 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4084 ssize_t ret;
4085
4086 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4087 (startpos > fsp->fsp_name->st.st_ex_size) ||
4088 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4089 /*
4090 * We already know that we would do a short
4091 * read, so don't try the sendfile() path.
4092 */
4093 goto nosendfile_read;
4094 }
4095
4096 construct_reply_common_req(req, (char *)headerbuf);
4097 setup_readX_header((char *)headerbuf, smb_maxcnt);
4098
4099 /* Send out the header. */
4100 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4101 sizeof(headerbuf));
4102 if (ret != sizeof(headerbuf)) {
4103 saved_errno = errno;
4104 /*
4105 * Try and give an error message saying what
4106 * client failed.
4107 */
4108 DEBUG(0,("send_file_readX: write_data failed for file "
4109 "%s (%s) for client %s. Terminating\n",
4110 fsp_str_dbg(fsp),
4111 smbXsrv_connection_dbg(xconn),
4112 strerror(saved_errno)));
4113 errno = saved_errno;
4114 exit_server_cleanly("send_file_readX sendfile failed");
4115 }
4116 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4117 if (nread == -1) {
4118 saved_errno = errno;
4119 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4120 "%s (%s) for client %s. Terminating\n",
4121 fsp_str_dbg(fsp),
4122 smbXsrv_connection_dbg(xconn),
4123 strerror(saved_errno)));
4124 errno = saved_errno;
4125 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4126 }
4127 goto strict_unlock;
4128 }
4129
4130nosendfile_read:
4131
4132 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4133 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4134 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4135
4136 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4137 startpos, smb_maxcnt);
4138 saved_errno = errno;
4139
4140 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4141
4142 if (nread < 0) {
4143 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4144 return;
4145 }
4146
4147 setup_readX_header((char *)req->outbuf, nread);
4148
4149 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4150 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4151 return;
4152
4153 strict_unlock:
4154 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4155 TALLOC_FREE(req->outbuf);
4156 return;
4157}
4158
4159/****************************************************************************
4160 Work out how much space we have for a read return.
4161****************************************************************************/
4162
4163static size_t calc_max_read_pdu(const struct smb_request *req)
4164{
4165 struct smbXsrv_connection *xconn = req->xconn;
4166
4167 if (xconn->protocol < PROTOCOL_NT1) {
4168 return xconn->smb1.sessions.max_send;
4169 }
4170
4171 if (!lp_large_readwrite()) {
4172 return xconn->smb1.sessions.max_send;
4173 }
4174
4175 if (req_is_in_chain(req)) {
4176 return xconn->smb1.sessions.max_send;
4177 }
4178
4179 if (req->encrypted) {
4180 /*
4181 * Don't take encrypted traffic up to the
4182 * limit. There are padding considerations
4183 * that make that tricky.
4184 */
4185 return xconn->smb1.sessions.max_send;
4186 }
4187
4188 if (srv_is_signing_active(xconn)) {
4189 return 0x1FFFF;
4190 }
4191
4192 if (!lp_unix_extensions()) {
4193 return 0x1FFFF;
4194 }
4195
4196 /*
4197 * We can do ultra-large POSIX reads.
4198 */
4199 return 0xFFFFFF;
4200}
4201
4202/****************************************************************************
4203 Calculate how big a read can be. Copes with all clients. It's always
4204 safe to return a short read - Windows does this.
4205****************************************************************************/
4206
4207static size_t calc_read_size(const struct smb_request *req,
4208 size_t upper_size,
4209 size_t lower_size)
4210{
4211 struct smbXsrv_connection *xconn = req->xconn;
4212 size_t max_pdu = calc_max_read_pdu(req);
4213 size_t total_size = 0;
4214 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4215 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4216
4217 /*
4218 * Windows explicitly ignores upper size of 0xFFFF.
4219 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4220 * We must do the same as these will never fit even in
4221 * an extended size NetBIOS packet.
4222 */
4223 if (upper_size == 0xFFFF) {
4224 upper_size = 0;
4225 }
4226
4227 if (xconn->protocol < PROTOCOL_NT1) {
4228 upper_size = 0;
4229 }
4230
4231 total_size = ((upper_size<<16) | lower_size);
4232
4233 /*
4234 * LARGE_READX test shows it's always safe to return
4235 * a short read. Windows does so.
4236 */
4237 return MIN(total_size, max_len);
4238}
4239
4240/****************************************************************************
4241 Reply to a read and X.
4242****************************************************************************/
4243
4244void reply_read_and_X(struct smb_request *req)
4245{
4246 connection_struct *conn = req->conn;
4247 files_struct *fsp;
4248 off_t startpos;
4249 size_t smb_maxcnt;
4250 size_t upper_size;
4251 bool big_readX = False;
4252#if 0
4253 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4254#endif
4255
4256 START_PROFILE(SMBreadX);
4257
4258 if ((req->wct != 10) && (req->wct != 12)) {
4259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4260 return;
4261 }
4262
4263 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4264 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4265 smb_maxcnt = SVAL(req->vwv+5, 0);
4266
4267 /* If it's an IPC, pass off the pipe handler. */
4268 if (IS_IPC(conn)) {
4269 reply_pipe_read_and_X(req);
4270 END_PROFILE(SMBreadX);
4271 return;
4272 }
4273
4274 if (!check_fsp(conn, req, fsp)) {
4275 END_PROFILE(SMBreadX);
4276 return;
4277 }
4278
4279 if (!CHECK_READ(fsp,req)) {
4280 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4281 END_PROFILE(SMBreadX);
4282 return;
4283 }
4284
4285 upper_size = SVAL(req->vwv+7, 0);
4286 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4287 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4288 /*
4289 * This is a heuristic to avoid keeping large
4290 * outgoing buffers around over long-lived aio
4291 * requests.
4292 */
4293 big_readX = True;
4294 }
4295
4296 if (req->wct == 12) {
4297 /*
4298 * This is a large offset (64 bit) read.
4299 */
4300 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4301
4302 }
4303
4304 if (!big_readX) {
4305 NTSTATUS status = schedule_aio_read_and_X(conn,
4306 req,
4307 fsp,
4308 startpos,
4309 smb_maxcnt);
4310 if (NT_STATUS_IS_OK(status)) {
4311 /* Read scheduled - we're done. */
4312 goto out;
4313 }
4314 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4315 /* Real error - report to client. */
4316 END_PROFILE(SMBreadX);
4317 reply_nterror(req, status);
4318 return;
4319 }
4320 /* NT_STATUS_RETRY - fall back to sync read. */
4321 }
4322
4323 smbd_lock_socket(req->xconn);
4324 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4325 smbd_unlock_socket(req->xconn);
4326
4327 out:
4328 END_PROFILE(SMBreadX);
4329 return;
4330}
4331
4332/****************************************************************************
4333 Error replies to writebraw must have smb_wct == 1. Fix this up.
4334****************************************************************************/
4335
4336void error_to_writebrawerr(struct smb_request *req)
4337{
4338 uint8_t *old_outbuf = req->outbuf;
4339
4340 reply_outbuf(req, 1, 0);
4341
4342 memcpy(req->outbuf, old_outbuf, smb_size);
4343 TALLOC_FREE(old_outbuf);
4344}
4345
4346/****************************************************************************
4347 Read 4 bytes of a smb packet and return the smb length of the packet.
4348 Store the result in the buffer. This version of the function will
4349 never return a session keepalive (length of zero).
4350 Timeout is in milliseconds.
4351****************************************************************************/
4352
4353static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4354 size_t *len)
4355{
4356 uint8_t msgtype = NBSSkeepalive;
4357
4358 while (msgtype == NBSSkeepalive) {
4359 NTSTATUS status;
4360
4361 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4362 len);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 char addr[INET6_ADDRSTRLEN];
4365 /* Try and give an error message
4366 * saying what client failed. */
4367 DEBUG(0, ("read_fd_with_timeout failed for "
4368 "client %s read error = %s.\n",
4369 get_peer_addr(fd,addr,sizeof(addr)),
4370 nt_errstr(status)));
4371 return status;
4372 }
4373
4374 msgtype = CVAL(inbuf, 0);
4375 }
4376
4377 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4378 (unsigned long)len));
4379
4380 return NT_STATUS_OK;
4381}
4382
4383/****************************************************************************
4384 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4385****************************************************************************/
4386
4387void reply_writebraw(struct smb_request *req)
4388{
4389 connection_struct *conn = req->conn;
4390 struct smbXsrv_connection *xconn = req->xconn;
4391 char *buf = NULL;
4392 ssize_t nwritten=0;
4393 ssize_t total_written=0;
4394 size_t numtowrite=0;
4395 size_t tcount;
4396 off_t startpos;
4397 const char *data=NULL;
4398 bool write_through;
4399 files_struct *fsp;
4400 struct lock_struct lock;
4401 NTSTATUS status;
4402
4403 START_PROFILE(SMBwritebraw);
4404
4405 /*
4406 * If we ever reply with an error, it must have the SMB command
4407 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4408 * we're finished.
4409 */
4410 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4411
4412 if (srv_is_signing_active(xconn)) {
4413 END_PROFILE(SMBwritebraw);
4414 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4415 "raw reads/writes are disallowed.");
4416 }
4417
4418 if (req->wct < 12) {
4419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4420 error_to_writebrawerr(req);
4421 END_PROFILE(SMBwritebraw);
4422 return;
4423 }
4424
4425 if (xconn->smb1.echo_handler.trusted_fde) {
4426 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4427 "'async smb echo handler = yes'\n"));
4428 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4429 error_to_writebrawerr(req);
4430 END_PROFILE(SMBwritebraw);
4431 return;
4432 }
4433
4434 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4435 if (!check_fsp(conn, req, fsp)) {
4436 error_to_writebrawerr(req);
4437 END_PROFILE(SMBwritebraw);
4438 return;
4439 }
4440
4441 if (!CHECK_WRITE(fsp)) {
4442 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4443 error_to_writebrawerr(req);
4444 END_PROFILE(SMBwritebraw);
4445 return;
4446 }
4447
4448 tcount = IVAL(req->vwv+1, 0);
4449 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4450 write_through = BITSETW(req->vwv+7,0);
4451
4452 /* We have to deal with slightly different formats depending
4453 on whether we are using the core+ or lanman1.0 protocol */
4454
4455 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4456 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4457 data = smb_buf_const(req->inbuf);
4458 } else {
4459 numtowrite = SVAL(req->vwv+10, 0);
4460 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4461 }
4462
4463 /* Ensure we don't write bytes past the end of this packet. */
4464 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4466 error_to_writebrawerr(req);
4467 END_PROFILE(SMBwritebraw);
4468 return;
4469 }
4470
4471 if (!fsp->print_file) {
4472 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4473 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4474 &lock);
4475
4476 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4477 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4478 error_to_writebrawerr(req);
4479 END_PROFILE(SMBwritebraw);
4480 return;
4481 }
4482 }
4483
4484 if (numtowrite>0) {
4485 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4486 }
4487
4488 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4489 "wrote=%d sync=%d\n",
4490 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4491 (int)nwritten, (int)write_through));
4492
4493 if (nwritten < (ssize_t)numtowrite) {
4494 reply_nterror(req, NT_STATUS_DISK_FULL);
4495 error_to_writebrawerr(req);
4496 goto strict_unlock;
4497 }
4498
4499 total_written = nwritten;
4500
4501 /* Allocate a buffer of 64k + length. */
4502 buf = talloc_array(NULL, char, 65540);
4503 if (!buf) {
4504 reply_nterror(req, NT_STATUS_NO_MEMORY);
4505 error_to_writebrawerr(req);
4506 goto strict_unlock;
4507 }
4508
4509 /* Return a SMBwritebraw message to the redirector to tell
4510 * it to send more bytes */
4511
4512 memcpy(buf, req->inbuf, smb_size);
4513 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4514 SCVAL(buf,smb_com,SMBwritebraw);
4515 SSVALS(buf,smb_vwv0,0xFFFF);
4516 show_msg(buf);
4517 if (!srv_send_smb(req->xconn,
4518 buf,
4519 false, 0, /* no signing */
4520 IS_CONN_ENCRYPTED(conn),
4521 &req->pcd)) {
4522 exit_server_cleanly("reply_writebraw: srv_send_smb "
4523 "failed.");
4524 }
4525
4526 /* Now read the raw data into the buffer and write it */
4527 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4528 &numtowrite);
4529 if (!NT_STATUS_IS_OK(status)) {
4530 exit_server_cleanly("secondary writebraw failed");
4531 }
4532
4533 /* Set up outbuf to return the correct size */
4534 reply_outbuf(req, 1, 0);
4535
4536 if (numtowrite != 0) {
4537
4538 if (numtowrite > 0xFFFF) {
4539 DEBUG(0,("reply_writebraw: Oversize secondary write "
4540 "raw requested (%u). Terminating\n",
4541 (unsigned int)numtowrite ));
4542 exit_server_cleanly("secondary writebraw failed");
4543 }
4544
4545 if (tcount > nwritten+numtowrite) {
4546 DEBUG(3,("reply_writebraw: Client overestimated the "
4547 "write %d %d %d\n",
4548 (int)tcount,(int)nwritten,(int)numtowrite));
4549 }
4550
4551 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4552 numtowrite);
4553
4554 if (!NT_STATUS_IS_OK(status)) {
4555 /* Try and give an error message
4556 * saying what client failed. */
4557 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4558 "raw read failed (%s) for client %s. "
4559 "Terminating\n", nt_errstr(status),
4560 smbXsrv_connection_dbg(xconn)));
4561 exit_server_cleanly("secondary writebraw failed");
4562 }
4563
4564 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4565 if (nwritten == -1) {
4566 TALLOC_FREE(buf);
4567 reply_nterror(req, map_nt_error_from_unix(errno));
4568 error_to_writebrawerr(req);
4569 goto strict_unlock;
4570 }
4571
4572 if (nwritten < (ssize_t)numtowrite) {
4573 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4574 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4575 }
4576
4577 if (nwritten > 0) {
4578 total_written += nwritten;
4579 }
4580 }
4581
4582 TALLOC_FREE(buf);
4583 SSVAL(req->outbuf,smb_vwv0,total_written);
4584
4585 status = sync_file(conn, fsp, write_through);
4586 if (!NT_STATUS_IS_OK(status)) {
4587 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4588 fsp_str_dbg(fsp), nt_errstr(status)));
4589 reply_nterror(req, status);
4590 error_to_writebrawerr(req);
4591 goto strict_unlock;
4592 }
4593
4594 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4595 "wrote=%d\n",
4596 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4597 (int)total_written));
4598
4599 if (!fsp->print_file) {
4600 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4601 }
4602
4603 /* We won't return a status if write through is not selected - this
4604 * follows what WfWg does */
4605 END_PROFILE(SMBwritebraw);
4606
4607 if (!write_through && total_written==tcount) {
4608
4609#if RABBIT_PELLET_FIX
4610 /*
4611 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4612 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4613 * JRA.
4614 */
4615 if (!send_keepalive(xconn->transport.sock)) {
4616 exit_server_cleanly("reply_writebraw: send of "
4617 "keepalive failed");
4618 }
4619#endif
4620 TALLOC_FREE(req->outbuf);
4621 }
4622 return;
4623
4624strict_unlock:
4625 if (!fsp->print_file) {
4626 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4627 }
4628
4629 END_PROFILE(SMBwritebraw);
4630 return;
4631}
4632
4633#undef DBGC_CLASS
4634#define DBGC_CLASS DBGC_LOCKING
4635
4636/****************************************************************************
4637 Reply to a writeunlock (core+).
4638****************************************************************************/
4639
4640void reply_writeunlock(struct smb_request *req)
4641{
4642 connection_struct *conn = req->conn;
4643 ssize_t nwritten = -1;
4644 size_t numtowrite;
4645 off_t startpos;
4646 const char *data;
4647 NTSTATUS status = NT_STATUS_OK;
4648 files_struct *fsp;
4649 struct lock_struct lock;
4650 int saved_errno = 0;
4651
4652 START_PROFILE(SMBwriteunlock);
4653
4654 if (req->wct < 5) {
4655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4656 END_PROFILE(SMBwriteunlock);
4657 return;
4658 }
4659
4660 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4661
4662 if (!check_fsp(conn, req, fsp)) {
4663 END_PROFILE(SMBwriteunlock);
4664 return;
4665 }
4666
4667 if (!CHECK_WRITE(fsp)) {
4668 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4669 END_PROFILE(SMBwriteunlock);
4670 return;
4671 }
4672
4673 numtowrite = SVAL(req->vwv+1, 0);
4674 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4675 data = (const char *)req->buf + 3;
4676
4677 if (!fsp->print_file && numtowrite > 0) {
4678 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4679 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4680 &lock);
4681
4682 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4683 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4684 END_PROFILE(SMBwriteunlock);
4685 return;
4686 }
4687 }
4688
4689 /* The special X/Open SMB protocol handling of
4690 zero length writes is *NOT* done for
4691 this call */
4692 if(numtowrite == 0) {
4693 nwritten = 0;
4694 } else {
4695 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4696 saved_errno = errno;
4697 }
4698
4699 status = sync_file(conn, fsp, False /* write through */);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4702 fsp_str_dbg(fsp), nt_errstr(status)));
4703 reply_nterror(req, status);
4704 goto strict_unlock;
4705 }
4706
4707 if(nwritten < 0) {
4708 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4709 goto strict_unlock;
4710 }
4711
4712 if((nwritten < numtowrite) && (numtowrite != 0)) {
4713 reply_nterror(req, NT_STATUS_DISK_FULL);
4714 goto strict_unlock;
4715 }
4716
4717 if (numtowrite && !fsp->print_file) {
4718 status = do_unlock(req->sconn->msg_ctx,
4719 fsp,
4720 (uint64_t)req->smbpid,
4721 (uint64_t)numtowrite,
4722 (uint64_t)startpos,
4723 WINDOWS_LOCK);
4724
4725 if (NT_STATUS_V(status)) {
4726 reply_nterror(req, status);
4727 goto strict_unlock;
4728 }
4729 }
4730
4731 reply_outbuf(req, 1, 0);
4732
4733 SSVAL(req->outbuf,smb_vwv0,nwritten);
4734
4735 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4736 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4737
4738strict_unlock:
4739 if (numtowrite && !fsp->print_file) {
4740 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4741 }
4742
4743 END_PROFILE(SMBwriteunlock);
4744 return;
4745}
4746
4747#undef DBGC_CLASS
4748#define DBGC_CLASS DBGC_ALL
4749
4750/****************************************************************************
4751 Reply to a write.
4752****************************************************************************/
4753
4754void reply_write(struct smb_request *req)
4755{
4756 connection_struct *conn = req->conn;
4757 size_t numtowrite;
4758 ssize_t nwritten = -1;
4759 off_t startpos;
4760 const char *data;
4761 files_struct *fsp;
4762 struct lock_struct lock;
4763 NTSTATUS status;
4764 int saved_errno = 0;
4765
4766 START_PROFILE(SMBwrite);
4767
4768 if (req->wct < 5) {
4769 END_PROFILE(SMBwrite);
4770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4771 return;
4772 }
4773
4774 /* If it's an IPC, pass off the pipe handler. */
4775 if (IS_IPC(conn)) {
4776 reply_pipe_write(req);
4777 END_PROFILE(SMBwrite);
4778 return;
4779 }
4780
4781 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4782
4783 if (!check_fsp(conn, req, fsp)) {
4784 END_PROFILE(SMBwrite);
4785 return;
4786 }
4787
4788 if (!CHECK_WRITE(fsp)) {
4789 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4790 END_PROFILE(SMBwrite);
4791 return;
4792 }
4793
4794 numtowrite = SVAL(req->vwv+1, 0);
4795 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4796 data = (const char *)req->buf + 3;
4797
4798 if (!fsp->print_file) {
4799 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4800 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4801 &lock);
4802
4803 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4804 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4805 END_PROFILE(SMBwrite);
4806 return;
4807 }
4808 }
4809
4810 /*
4811 * X/Open SMB protocol says that if smb_vwv1 is
4812 * zero then the file size should be extended or
4813 * truncated to the size given in smb_vwv[2-3].
4814 */
4815
4816 if(numtowrite == 0) {
4817 /*
4818 * This is actually an allocate call, and set EOF. JRA.
4819 */
4820 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4821 if (nwritten < 0) {
4822 reply_nterror(req, NT_STATUS_DISK_FULL);
4823 goto strict_unlock;
4824 }
4825 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4826 if (nwritten < 0) {
4827 reply_nterror(req, NT_STATUS_DISK_FULL);
4828 goto strict_unlock;
4829 }
4830 trigger_write_time_update_immediate(fsp);
4831 } else {
4832 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4833 }
4834
4835 status = sync_file(conn, fsp, False);
4836 if (!NT_STATUS_IS_OK(status)) {
4837 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4838 fsp_str_dbg(fsp), nt_errstr(status)));
4839 reply_nterror(req, status);
4840 goto strict_unlock;
4841 }
4842
4843 if(nwritten < 0) {
4844 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4845 goto strict_unlock;
4846 }
4847
4848 if((nwritten == 0) && (numtowrite != 0)) {
4849 reply_nterror(req, NT_STATUS_DISK_FULL);
4850 goto strict_unlock;
4851 }
4852
4853 reply_outbuf(req, 1, 0);
4854
4855 SSVAL(req->outbuf,smb_vwv0,nwritten);
4856
4857 if (nwritten < (ssize_t)numtowrite) {
4858 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4859 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4860 }
4861
4862 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4863
4864strict_unlock:
4865 if (!fsp->print_file) {
4866 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4867 }
4868
4869 END_PROFILE(SMBwrite);
4870 return;
4871}
4872
4873/****************************************************************************
4874 Ensure a buffer is a valid writeX for recvfile purposes.
4875****************************************************************************/
4876
4877#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4878 (2*14) + /* word count (including bcc) */ \
4879 1 /* pad byte */)
4880
4881bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4882 const uint8_t *inbuf)
4883{
4884 size_t numtowrite;
4885 unsigned int doff = 0;
4886 size_t len = smb_len_large(inbuf);
4887 uint16_t fnum;
4888 struct smbXsrv_open *op = NULL;
4889 struct files_struct *fsp = NULL;
4890 NTSTATUS status;
4891
4892 if (is_encrypted_packet(inbuf)) {
4893 /* Can't do this on encrypted
4894 * connections. */
4895 return false;
4896 }
4897
4898 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4899 return false;
4900 }
4901
4902 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4903 CVAL(inbuf,smb_wct) != 14) {
4904 DEBUG(10,("is_valid_writeX_buffer: chained or "
4905 "invalid word length.\n"));
4906 return false;
4907 }
4908
4909 fnum = SVAL(inbuf, smb_vwv2);
4910 status = smb1srv_open_lookup(xconn,
4911 fnum,
4912 0, /* now */
4913 &op);
4914 if (!NT_STATUS_IS_OK(status)) {
4915 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4916 return false;
4917 }
4918 fsp = op->compat;
4919 if (fsp == NULL) {
4920 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4921 return false;
4922 }
4923 if (fsp->conn == NULL) {
4924 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4925 return false;
4926 }
4927
4928 if (IS_IPC(fsp->conn)) {
4929 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4930 return false;
4931 }
4932 if (IS_PRINT(fsp->conn)) {
4933 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4934 return false;
4935 }
4936 doff = SVAL(inbuf,smb_vwv11);
4937
4938 numtowrite = SVAL(inbuf,smb_vwv10);
4939
4940 if (len > doff && len - doff > 0xFFFF) {
4941 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4942 }
4943
4944 if (numtowrite == 0) {
4945 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4946 return false;
4947 }
4948
4949 /* Ensure the sizes match up. */
4950 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4951 /* no pad byte...old smbclient :-( */
4952 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4953 (unsigned int)doff,
4954 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4955 return false;
4956 }
4957
4958 if (len - doff != numtowrite) {
4959 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4960 "len = %u, doff = %u, numtowrite = %u\n",
4961 (unsigned int)len,
4962 (unsigned int)doff,
4963 (unsigned int)numtowrite ));
4964 return false;
4965 }
4966
4967 DEBUG(10,("is_valid_writeX_buffer: true "
4968 "len = %u, doff = %u, numtowrite = %u\n",
4969 (unsigned int)len,
4970 (unsigned int)doff,
4971 (unsigned int)numtowrite ));
4972
4973 return true;
4974}
4975
4976/****************************************************************************
4977 Reply to a write and X.
4978****************************************************************************/
4979
4980void reply_write_and_X(struct smb_request *req)
4981{
4982 connection_struct *conn = req->conn;
4983 struct smbXsrv_connection *xconn = req->xconn;
4984 files_struct *fsp;
4985 struct lock_struct lock;
4986 off_t startpos;
4987 size_t numtowrite;
4988 bool write_through;
4989 ssize_t nwritten;
4990 unsigned int smb_doff;
4991 unsigned int smblen;
4992 const char *data;
4993 NTSTATUS status;
4994 int saved_errno = 0;
4995
4996 START_PROFILE(SMBwriteX);
4997
4998 if ((req->wct != 12) && (req->wct != 14)) {
4999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5000 goto out;
5001 }
5002
5003 numtowrite = SVAL(req->vwv+10, 0);
5004 smb_doff = SVAL(req->vwv+11, 0);
5005 smblen = smb_len(req->inbuf);
5006
5007 if (req->unread_bytes > 0xFFFF ||
5008 (smblen > smb_doff &&
5009 smblen - smb_doff > 0xFFFF)) {
5010 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5011 }
5012
5013 if (req->unread_bytes) {
5014 /* Can't do a recvfile write on IPC$ */
5015 if (IS_IPC(conn)) {
5016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5017 goto out;
5018 }
5019 if (numtowrite != req->unread_bytes) {
5020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5021 goto out;
5022 }
5023 } else {
5024 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5025 smb_doff + numtowrite > smblen) {
5026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5027 goto out;
5028 }
5029 }
5030
5031 /* If it's an IPC, pass off the pipe handler. */
5032 if (IS_IPC(conn)) {
5033 if (req->unread_bytes) {
5034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035 goto out;
5036 }
5037 reply_pipe_write_and_X(req);
5038 goto out;
5039 }
5040
5041 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5042 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5043 write_through = BITSETW(req->vwv+7,0);
5044
5045 if (!check_fsp(conn, req, fsp)) {
5046 goto out;
5047 }
5048
5049 if (!CHECK_WRITE(fsp)) {
5050 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5051 goto out;
5052 }
5053
5054 data = smb_base(req->inbuf) + smb_doff;
5055
5056 if(req->wct == 14) {
5057 /*
5058 * This is a large offset (64 bit) write.
5059 */
5060 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5061
5062 }
5063
5064 /* X/Open SMB protocol says that, unlike SMBwrite
5065 if the length is zero then NO truncation is
5066 done, just a write of zero. To truncate a file,
5067 use SMBwrite. */
5068
5069 if(numtowrite == 0) {
5070 nwritten = 0;
5071 } else {
5072 if (req->unread_bytes == 0) {
5073 status = schedule_aio_write_and_X(conn,
5074 req,
5075 fsp,
5076 data,
5077 startpos,
5078 numtowrite);
5079
5080 if (NT_STATUS_IS_OK(status)) {
5081 /* write scheduled - we're done. */
5082 goto out;
5083 }
5084 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5085 /* Real error - report to client. */
5086 reply_nterror(req, status);
5087 goto out;
5088 }
5089 /* NT_STATUS_RETRY - fall through to sync write. */
5090 }
5091
5092 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5093 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5094 &lock);
5095
5096 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5097 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5098 goto out;
5099 }
5100
5101 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5102 saved_errno = errno;
5103
5104 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5105 }
5106
5107 if(nwritten < 0) {
5108 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5109 goto out;
5110 }
5111
5112 if((nwritten == 0) && (numtowrite != 0)) {
5113 reply_nterror(req, NT_STATUS_DISK_FULL);
5114 goto out;
5115 }
5116
5117 reply_outbuf(req, 6, 0);
5118 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5119 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5120 SSVAL(req->outbuf,smb_vwv2,nwritten);
5121 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5122
5123 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5124 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5125
5126 status = sync_file(conn, fsp, write_through);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5129 fsp_str_dbg(fsp), nt_errstr(status)));
5130 reply_nterror(req, status);
5131 goto out;
5132 }
5133
5134 END_PROFILE(SMBwriteX);
5135 return;
5136
5137out:
5138 if (req->unread_bytes) {
5139 /* writeX failed. drain socket. */
5140 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5141 req->unread_bytes) {
5142 smb_panic("failed to drain pending bytes");
5143 }
5144 req->unread_bytes = 0;
5145 }
5146
5147 END_PROFILE(SMBwriteX);
5148 return;
5149}
5150
5151/****************************************************************************
5152 Reply to a lseek.
5153****************************************************************************/
5154
5155void reply_lseek(struct smb_request *req)
5156{
5157 connection_struct *conn = req->conn;
5158 off_t startpos;
5159 off_t res= -1;
5160 int mode,umode;
5161 files_struct *fsp;
5162
5163 START_PROFILE(SMBlseek);
5164
5165 if (req->wct < 4) {
5166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5167 END_PROFILE(SMBlseek);
5168 return;
5169 }
5170
5171 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5172
5173 if (!check_fsp(conn, req, fsp)) {
5174 return;
5175 }
5176
5177 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5178
5179 mode = SVAL(req->vwv+1, 0) & 3;
5180 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5181 startpos = (off_t)IVALS(req->vwv+2, 0);
5182
5183 switch (mode) {
5184 case 0:
5185 umode = SEEK_SET;
5186 res = startpos;
5187 break;
5188 case 1:
5189 umode = SEEK_CUR;
5190 res = fsp->fh->pos + startpos;
5191 break;
5192 case 2:
5193 umode = SEEK_END;
5194 break;
5195 default:
5196 umode = SEEK_SET;
5197 res = startpos;
5198 break;
5199 }
5200
5201 if (umode == SEEK_END) {
5202 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5203 if(errno == EINVAL) {
5204 off_t current_pos = startpos;
5205
5206 if(fsp_stat(fsp) == -1) {
5207 reply_nterror(req,
5208 map_nt_error_from_unix(errno));
5209 END_PROFILE(SMBlseek);
5210 return;
5211 }
5212
5213 current_pos += fsp->fsp_name->st.st_ex_size;
5214 if(current_pos < 0)
5215 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5216 }
5217 }
5218
5219 if(res == -1) {
5220 reply_nterror(req, map_nt_error_from_unix(errno));
5221 END_PROFILE(SMBlseek);
5222 return;
5223 }
5224 }
5225
5226 fsp->fh->pos = res;
5227
5228 reply_outbuf(req, 2, 0);
5229 SIVAL(req->outbuf,smb_vwv0,res);
5230
5231 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5232 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5233
5234 END_PROFILE(SMBlseek);
5235 return;
5236}
5237
5238/****************************************************************************
5239 Reply to a flush.
5240****************************************************************************/
5241
5242void reply_flush(struct smb_request *req)
5243{
5244 connection_struct *conn = req->conn;
5245 uint16_t fnum;
5246 files_struct *fsp;
5247
5248 START_PROFILE(SMBflush);
5249
5250 if (req->wct < 1) {
5251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5252 return;
5253 }
5254
5255 fnum = SVAL(req->vwv+0, 0);
5256 fsp = file_fsp(req, fnum);
5257
5258 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5259 return;
5260 }
5261
5262 if (!fsp) {
5263 file_sync_all(conn);
5264 } else {
5265 NTSTATUS status = sync_file(conn, fsp, True);
5266 if (!NT_STATUS_IS_OK(status)) {
5267 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5268 fsp_str_dbg(fsp), nt_errstr(status)));
5269 reply_nterror(req, status);
5270 END_PROFILE(SMBflush);
5271 return;
5272 }
5273 }
5274
5275 reply_outbuf(req, 0, 0);
5276
5277 DEBUG(3,("flush\n"));
5278 END_PROFILE(SMBflush);
5279 return;
5280}
5281
5282/****************************************************************************
5283 Reply to a exit.
5284 conn POINTER CAN BE NULL HERE !
5285****************************************************************************/
5286
5287void reply_exit(struct smb_request *req)
5288{
5289 START_PROFILE(SMBexit);
5290
5291 file_close_pid(req->sconn, req->smbpid, req->vuid);
5292
5293 reply_outbuf(req, 0, 0);
5294
5295 DEBUG(3,("exit\n"));
5296
5297 END_PROFILE(SMBexit);
5298 return;
5299}
5300
5301struct reply_close_state {
5302 files_struct *fsp;
5303 struct smb_request *smbreq;
5304};
5305
5306static void do_smb1_close(struct tevent_req *req);
5307
5308void reply_close(struct smb_request *req)
5309{
5310 connection_struct *conn = req->conn;
5311 NTSTATUS status = NT_STATUS_OK;
5312 files_struct *fsp = NULL;
5313 START_PROFILE(SMBclose);
5314
5315 if (req->wct < 3) {
5316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5317 END_PROFILE(SMBclose);
5318 return;
5319 }
5320
5321 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5322
5323 /*
5324 * We can only use check_fsp if we know it's not a directory.
5325 */
5326
5327 if (!check_fsp_open(conn, req, fsp)) {
5328 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5329 END_PROFILE(SMBclose);
5330 return;
5331 }
5332
5333 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5334 fsp->is_directory ? "directory" : "file",
5335 fsp->fh->fd, fsp_fnum_dbg(fsp),
5336 conn->num_files_open));
5337
5338 if (!fsp->is_directory) {
5339 time_t t;
5340
5341 /*
5342 * Take care of any time sent in the close.
5343 */
5344
5345 t = srv_make_unix_date3(req->vwv+1);
5346 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5347 }
5348
5349 if (fsp->num_aio_requests != 0) {
5350
5351 struct reply_close_state *state;
5352
5353 DEBUG(10, ("closing with aio %u requests pending\n",
5354 fsp->num_aio_requests));
5355
5356 /*
5357 * We depend on the aio_extra destructor to take care of this
5358 * close request once fsp->num_aio_request drops to 0.
5359 */
5360
5361 fsp->deferred_close = tevent_wait_send(
5362 fsp, fsp->conn->sconn->ev_ctx);
5363 if (fsp->deferred_close == NULL) {
5364 status = NT_STATUS_NO_MEMORY;
5365 goto done;
5366 }
5367
5368 state = talloc(fsp, struct reply_close_state);
5369 if (state == NULL) {
5370 TALLOC_FREE(fsp->deferred_close);
5371 status = NT_STATUS_NO_MEMORY;
5372 goto done;
5373 }
5374 state->fsp = fsp;
5375 state->smbreq = talloc_move(fsp, &req);
5376 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5377 state);
5378 END_PROFILE(SMBclose);
5379 return;
5380 }
5381
5382 /*
5383 * close_file() returns the unix errno if an error was detected on
5384 * close - normally this is due to a disk full error. If not then it
5385 * was probably an I/O error.
5386 */
5387
5388 status = close_file(req, fsp, NORMAL_CLOSE);
5389done:
5390 if (!NT_STATUS_IS_OK(status)) {
5391 reply_nterror(req, status);
5392 END_PROFILE(SMBclose);
5393 return;
5394 }
5395
5396 reply_outbuf(req, 0, 0);
5397 END_PROFILE(SMBclose);
5398 return;
5399}
5400
5401static void do_smb1_close(struct tevent_req *req)
5402{
5403 struct reply_close_state *state = tevent_req_callback_data(
5404 req, struct reply_close_state);
5405 struct smb_request *smbreq;
5406 NTSTATUS status;
5407 int ret;
5408
5409 ret = tevent_wait_recv(req);
5410 TALLOC_FREE(req);
5411 if (ret != 0) {
5412 DEBUG(10, ("tevent_wait_recv returned %s\n",
5413 strerror(ret)));
5414 /*
5415 * Continue anyway, this should never happen
5416 */
5417 }
5418
5419 /*
5420 * fsp->smb2_close_request right now is a talloc grandchild of
5421 * fsp. When we close_file(fsp), it would go with it. No chance to
5422 * reply...
5423 */
5424 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5425
5426 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5427 if (NT_STATUS_IS_OK(status)) {
5428 reply_outbuf(smbreq, 0, 0);
5429 } else {
5430 reply_nterror(smbreq, status);
5431 }
5432 if (!srv_send_smb(smbreq->xconn,
5433 (char *)smbreq->outbuf,
5434 true,
5435 smbreq->seqnum+1,
5436 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5437 NULL)) {
5438 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5439 "failed.");
5440 }
5441 TALLOC_FREE(smbreq);
5442}
5443
5444/****************************************************************************
5445 Reply to a writeclose (Core+ protocol).
5446****************************************************************************/
5447
5448void reply_writeclose(struct smb_request *req)
5449{
5450 connection_struct *conn = req->conn;
5451 size_t numtowrite;
5452 ssize_t nwritten = -1;
5453 NTSTATUS close_status = NT_STATUS_OK;
5454 off_t startpos;
5455 const char *data;
5456 struct timespec mtime;
5457 files_struct *fsp;
5458 struct lock_struct lock;
5459
5460 START_PROFILE(SMBwriteclose);
5461
5462 if (req->wct < 6) {
5463 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5464 END_PROFILE(SMBwriteclose);
5465 return;
5466 }
5467
5468 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5469
5470 if (!check_fsp(conn, req, fsp)) {
5471 END_PROFILE(SMBwriteclose);
5472 return;
5473 }
5474 if (!CHECK_WRITE(fsp)) {
5475 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5476 END_PROFILE(SMBwriteclose);
5477 return;
5478 }
5479
5480 numtowrite = SVAL(req->vwv+1, 0);
5481 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5482 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5483 data = (const char *)req->buf + 1;
5484
5485 if (fsp->print_file == NULL) {
5486 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5487 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5488 &lock);
5489
5490 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5491 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5492 END_PROFILE(SMBwriteclose);
5493 return;
5494 }
5495 }
5496
5497 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5498
5499 if (fsp->print_file == NULL) {
5500 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5501 }
5502
5503 set_close_write_time(fsp, mtime);
5504
5505 /*
5506 * More insanity. W2K only closes the file if writelen > 0.
5507 * JRA.
5508 */
5509
5510 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5511 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5512 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5513
5514 if (numtowrite) {
5515 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5516 "file %s\n", fsp_str_dbg(fsp)));
5517 close_status = close_file(req, fsp, NORMAL_CLOSE);
5518 fsp = NULL;
5519 }
5520
5521 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5522 reply_nterror(req, NT_STATUS_DISK_FULL);
5523 goto out;
5524 }
5525
5526 if(!NT_STATUS_IS_OK(close_status)) {
5527 reply_nterror(req, close_status);
5528 goto out;
5529 }
5530
5531 reply_outbuf(req, 1, 0);
5532
5533 SSVAL(req->outbuf,smb_vwv0,nwritten);
5534
5535out:
5536
5537 END_PROFILE(SMBwriteclose);
5538 return;
5539}
5540
5541#undef DBGC_CLASS
5542#define DBGC_CLASS DBGC_LOCKING
5543
5544/****************************************************************************
5545 Reply to a lock.
5546****************************************************************************/
5547
5548void reply_lock(struct smb_request *req)
5549{
5550 connection_struct *conn = req->conn;
5551 uint64_t count,offset;
5552 NTSTATUS status;
5553 files_struct *fsp;
5554 struct byte_range_lock *br_lck = NULL;
5555
5556 START_PROFILE(SMBlock);
5557
5558 if (req->wct < 5) {
5559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5560 END_PROFILE(SMBlock);
5561 return;
5562 }
5563
5564 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5565
5566 if (!check_fsp(conn, req, fsp)) {
5567 END_PROFILE(SMBlock);
5568 return;
5569 }
5570
5571 count = (uint64_t)IVAL(req->vwv+1, 0);
5572 offset = (uint64_t)IVAL(req->vwv+3, 0);
5573
5574 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5575 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5576
5577 br_lck = do_lock(req->sconn->msg_ctx,
5578 fsp,
5579 (uint64_t)req->smbpid,
5580 count,
5581 offset,
5582 WRITE_LOCK,
5583 WINDOWS_LOCK,
5584 False, /* Non-blocking lock. */
5585 &status,
5586 NULL);
5587
5588 TALLOC_FREE(br_lck);
5589
5590 if (NT_STATUS_V(status)) {
5591 reply_nterror(req, status);
5592 END_PROFILE(SMBlock);
5593 return;
5594 }
5595
5596 reply_outbuf(req, 0, 0);
5597
5598 END_PROFILE(SMBlock);
5599 return;
5600}
5601
5602/****************************************************************************
5603 Reply to a unlock.
5604****************************************************************************/
5605
5606void reply_unlock(struct smb_request *req)
5607{
5608 connection_struct *conn = req->conn;
5609 uint64_t count,offset;
5610 NTSTATUS status;
5611 files_struct *fsp;
5612
5613 START_PROFILE(SMBunlock);
5614
5615 if (req->wct < 5) {
5616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5617 END_PROFILE(SMBunlock);
5618 return;
5619 }
5620
5621 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5622
5623 if (!check_fsp(conn, req, fsp)) {
5624 END_PROFILE(SMBunlock);
5625 return;
5626 }
5627
5628 count = (uint64_t)IVAL(req->vwv+1, 0);
5629 offset = (uint64_t)IVAL(req->vwv+3, 0);
5630
5631 status = do_unlock(req->sconn->msg_ctx,
5632 fsp,
5633 (uint64_t)req->smbpid,
5634 count,
5635 offset,
5636 WINDOWS_LOCK);
5637
5638 if (NT_STATUS_V(status)) {
5639 reply_nterror(req, status);
5640 END_PROFILE(SMBunlock);
5641 return;
5642 }
5643
5644 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5645 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5646
5647 reply_outbuf(req, 0, 0);
5648
5649 END_PROFILE(SMBunlock);
5650 return;
5651}
5652
5653#undef DBGC_CLASS
5654#define DBGC_CLASS DBGC_ALL
5655
5656/****************************************************************************
5657 Reply to a tdis.
5658 conn POINTER CAN BE NULL HERE !
5659****************************************************************************/
5660
5661void reply_tdis(struct smb_request *req)
5662{
5663 NTSTATUS status;
5664 connection_struct *conn = req->conn;
5665 struct smbXsrv_tcon *tcon;
5666
5667 START_PROFILE(SMBtdis);
5668
5669 if (!conn) {
5670 DEBUG(4,("Invalid connection in tdis\n"));
5671 reply_force_doserror(req, ERRSRV, ERRinvnid);
5672 END_PROFILE(SMBtdis);
5673 return;
5674 }
5675
5676 tcon = conn->tcon;
5677 req->conn = NULL;
5678
5679 /*
5680 * TODO: cancel all outstanding requests on the tcon
5681 */
5682 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5683 if (!NT_STATUS_IS_OK(status)) {
5684 DEBUG(0, ("reply_tdis: "
5685 "smbXsrv_tcon_disconnect() failed: %s\n",
5686 nt_errstr(status)));
5687 /*
5688 * If we hit this case, there is something completely
5689 * wrong, so we better disconnect the transport connection.
5690 */
5691 END_PROFILE(SMBtdis);
5692 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5693 return;
5694 }
5695
5696 TALLOC_FREE(tcon);
5697
5698 reply_outbuf(req, 0, 0);
5699 END_PROFILE(SMBtdis);
5700 return;
5701}
5702
5703/****************************************************************************
5704 Reply to a echo.
5705 conn POINTER CAN BE NULL HERE !
5706****************************************************************************/
5707
5708void reply_echo(struct smb_request *req)
5709{
5710 connection_struct *conn = req->conn;
5711 struct smb_perfcount_data local_pcd;
5712 struct smb_perfcount_data *cur_pcd;
5713 int smb_reverb;
5714 int seq_num;
5715
5716 START_PROFILE(SMBecho);
5717
5718 smb_init_perfcount_data(&local_pcd);
5719
5720 if (req->wct < 1) {
5721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5722 END_PROFILE(SMBecho);
5723 return;
5724 }
5725
5726 smb_reverb = SVAL(req->vwv+0, 0);
5727
5728 reply_outbuf(req, 1, req->buflen);
5729
5730 /* copy any incoming data back out */
5731 if (req->buflen > 0) {
5732 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5733 }
5734
5735 if (smb_reverb > 100) {
5736 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5737 smb_reverb = 100;
5738 }
5739
5740 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5741
5742 /* this makes sure we catch the request pcd */
5743 if (seq_num == smb_reverb) {
5744 cur_pcd = &req->pcd;
5745 } else {
5746 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5747 cur_pcd = &local_pcd;
5748 }
5749
5750 SSVAL(req->outbuf,smb_vwv0,seq_num);
5751
5752 show_msg((char *)req->outbuf);
5753 if (!srv_send_smb(req->xconn,
5754 (char *)req->outbuf,
5755 true, req->seqnum+1,
5756 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5757 cur_pcd))
5758 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5759 }
5760
5761 DEBUG(3,("echo %d times\n", smb_reverb));
5762
5763 TALLOC_FREE(req->outbuf);
5764
5765 END_PROFILE(SMBecho);
5766 return;
5767}
5768
5769/****************************************************************************
5770 Reply to a printopen.
5771****************************************************************************/
5772
5773void reply_printopen(struct smb_request *req)
5774{
5775 connection_struct *conn = req->conn;
5776 files_struct *fsp;
5777 NTSTATUS status;
5778
5779 START_PROFILE(SMBsplopen);
5780
5781 if (req->wct < 2) {
5782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5783 END_PROFILE(SMBsplopen);
5784 return;
5785 }
5786
5787 if (!CAN_PRINT(conn)) {
5788 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5789 END_PROFILE(SMBsplopen);
5790 return;
5791 }
5792
5793 status = file_new(req, conn, &fsp);
5794 if(!NT_STATUS_IS_OK(status)) {
5795 reply_nterror(req, status);
5796 END_PROFILE(SMBsplopen);
5797 return;
5798 }
5799
5800 /* Open for exclusive use, write only. */
5801 status = print_spool_open(fsp, NULL, req->vuid);
5802
5803 if (!NT_STATUS_IS_OK(status)) {
5804 file_free(req, fsp);
5805 reply_nterror(req, status);
5806 END_PROFILE(SMBsplopen);
5807 return;
5808 }
5809
5810 reply_outbuf(req, 1, 0);
5811 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5812
5813 DEBUG(3,("openprint fd=%d %s\n",
5814 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5815
5816 END_PROFILE(SMBsplopen);
5817 return;
5818}
5819
5820/****************************************************************************
5821 Reply to a printclose.
5822****************************************************************************/
5823
5824void reply_printclose(struct smb_request *req)
5825{
5826 connection_struct *conn = req->conn;
5827 files_struct *fsp;
5828 NTSTATUS status;
5829
5830 START_PROFILE(SMBsplclose);
5831
5832 if (req->wct < 1) {
5833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5834 END_PROFILE(SMBsplclose);
5835 return;
5836 }
5837
5838 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5839
5840 if (!check_fsp(conn, req, fsp)) {
5841 END_PROFILE(SMBsplclose);
5842 return;
5843 }
5844
5845 if (!CAN_PRINT(conn)) {
5846 reply_force_doserror(req, ERRSRV, ERRerror);
5847 END_PROFILE(SMBsplclose);
5848 return;
5849 }
5850
5851 DEBUG(3,("printclose fd=%d %s\n",
5852 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5853
5854 status = close_file(req, fsp, NORMAL_CLOSE);
5855
5856 if(!NT_STATUS_IS_OK(status)) {
5857 reply_nterror(req, status);
5858 END_PROFILE(SMBsplclose);
5859 return;
5860 }
5861
5862 reply_outbuf(req, 0, 0);
5863
5864 END_PROFILE(SMBsplclose);
5865 return;
5866}
5867
5868/****************************************************************************
5869 Reply to a printqueue.
5870****************************************************************************/
5871
5872void reply_printqueue(struct smb_request *req)
5873{
5874 connection_struct *conn = req->conn;
5875 int max_count;
5876 int start_index;
5877
5878 START_PROFILE(SMBsplretq);
5879
5880 if (req->wct < 2) {
5881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5882 END_PROFILE(SMBsplretq);
5883 return;
5884 }
5885
5886 max_count = SVAL(req->vwv+0, 0);
5887 start_index = SVAL(req->vwv+1, 0);
5888
5889 /* we used to allow the client to get the cnum wrong, but that
5890 is really quite gross and only worked when there was only
5891 one printer - I think we should now only accept it if they
5892 get it right (tridge) */
5893 if (!CAN_PRINT(conn)) {
5894 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5895 END_PROFILE(SMBsplretq);
5896 return;
5897 }
5898
5899 reply_outbuf(req, 2, 3);
5900 SSVAL(req->outbuf,smb_vwv0,0);
5901 SSVAL(req->outbuf,smb_vwv1,0);
5902 SCVAL(smb_buf(req->outbuf),0,1);
5903 SSVAL(smb_buf(req->outbuf),1,0);
5904
5905 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5906 start_index, max_count));
5907
5908 {
5909 TALLOC_CTX *mem_ctx = talloc_tos();
5910 NTSTATUS status;
5911 WERROR werr;
5912 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5913 struct rpc_pipe_client *cli = NULL;
5914 struct dcerpc_binding_handle *b = NULL;
5915 struct policy_handle handle;
5916 struct spoolss_DevmodeContainer devmode_ctr;
5917 union spoolss_JobInfo *info;
5918 uint32_t count;
5919 uint32_t num_to_get;
5920 uint32_t first;
5921 uint32_t i;
5922
5923 ZERO_STRUCT(handle);
5924
5925 status = rpc_pipe_open_interface(conn,
5926 &ndr_table_spoolss,
5927 conn->session_info,
5928 conn->sconn->remote_address,
5929 conn->sconn->msg_ctx,
5930 &cli);
5931 if (!NT_STATUS_IS_OK(status)) {
5932 DEBUG(0, ("reply_printqueue: "
5933 "could not connect to spoolss: %s\n",
5934 nt_errstr(status)));
5935 reply_nterror(req, status);
5936 goto out;
5937 }
5938 b = cli->binding_handle;
5939
5940 ZERO_STRUCT(devmode_ctr);
5941
5942 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5943 sharename,
5944 NULL, devmode_ctr,
5945 SEC_FLAG_MAXIMUM_ALLOWED,
5946 &handle,
5947 &werr);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 reply_nterror(req, status);
5950 goto out;
5951 }
5952 if (!W_ERROR_IS_OK(werr)) {
5953 reply_nterror(req, werror_to_ntstatus(werr));
5954 goto out;
5955 }
5956
5957 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5958 &handle,
5959 0, /* firstjob */
5960 0xff, /* numjobs */
5961 2, /* level */
5962 0, /* offered */
5963 &count,
5964 &info);
5965 if (!W_ERROR_IS_OK(werr)) {
5966 reply_nterror(req, werror_to_ntstatus(werr));
5967 goto out;
5968 }
5969
5970 if (max_count > 0) {
5971 first = start_index;
5972 } else {
5973 first = start_index + max_count + 1;
5974 }
5975
5976 if (first >= count) {
5977 num_to_get = first;
5978 } else {
5979 num_to_get = first + MIN(ABS(max_count), count - first);
5980 }
5981
5982 for (i = first; i < num_to_get; i++) {
5983 char blob[28];
5984 char *p = blob;
5985 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5986 int qstatus;
5987 size_t len = 0;
5988 uint16_t qrapjobid = pjobid_to_rap(sharename,
5989 info[i].info2.job_id);
5990
5991 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5992 qstatus = 2;
5993 } else {
5994 qstatus = 3;
5995 }
5996
5997 srv_put_dos_date2(p, 0, qtime);
5998 SCVAL(p, 4, qstatus);
5999 SSVAL(p, 5, qrapjobid);
6000 SIVAL(p, 7, info[i].info2.size);
6001 SCVAL(p, 11, 0);
6002 status = srvstr_push(blob, req->flags2, p+12,
6003 info[i].info2.notify_name, 16, STR_ASCII, &len);
6004 if (!NT_STATUS_IS_OK(status)) {
6005 reply_nterror(req, status);
6006 goto out;
6007 }
6008 if (message_push_blob(
6009 &req->outbuf,
6010 data_blob_const(
6011 blob, sizeof(blob))) == -1) {
6012 reply_nterror(req, NT_STATUS_NO_MEMORY);
6013 goto out;
6014 }
6015 }
6016
6017 if (count > 0) {
6018 SSVAL(req->outbuf,smb_vwv0,count);
6019 SSVAL(req->outbuf,smb_vwv1,
6020 (max_count>0?first+count:first-1));
6021 SCVAL(smb_buf(req->outbuf),0,1);
6022 SSVAL(smb_buf(req->outbuf),1,28*count);
6023 }
6024
6025
6026 DEBUG(3, ("%u entries returned in queue\n",
6027 (unsigned)count));
6028
6029out:
6030 if (b && is_valid_policy_hnd(&handle)) {
6031 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6032 }
6033
6034 }
6035
6036 END_PROFILE(SMBsplretq);
6037 return;
6038}
6039
6040/****************************************************************************
6041 Reply to a printwrite.
6042****************************************************************************/
6043
6044void reply_printwrite(struct smb_request *req)
6045{
6046 connection_struct *conn = req->conn;
6047 int numtowrite;
6048 const char *data;
6049 files_struct *fsp;
6050
6051 START_PROFILE(SMBsplwr);
6052
6053 if (req->wct < 1) {
6054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6055 END_PROFILE(SMBsplwr);
6056 return;
6057 }
6058
6059 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6060
6061 if (!check_fsp(conn, req, fsp)) {
6062 END_PROFILE(SMBsplwr);
6063 return;
6064 }
6065
6066 if (!fsp->print_file) {
6067 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6068 END_PROFILE(SMBsplwr);
6069 return;
6070 }
6071
6072 if (!CHECK_WRITE(fsp)) {
6073 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6074 END_PROFILE(SMBsplwr);
6075 return;
6076 }
6077
6078 numtowrite = SVAL(req->buf, 1);
6079
6080 if (req->buflen < numtowrite + 3) {
6081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6082 END_PROFILE(SMBsplwr);
6083 return;
6084 }
6085
6086 data = (const char *)req->buf + 3;
6087
6088 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6089 reply_nterror(req, map_nt_error_from_unix(errno));
6090 END_PROFILE(SMBsplwr);
6091 return;
6092 }
6093
6094 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6095
6096 END_PROFILE(SMBsplwr);
6097 return;
6098}
6099
6100/****************************************************************************
6101 Reply to a mkdir.
6102****************************************************************************/
6103
6104void reply_mkdir(struct smb_request *req)
6105{
6106 connection_struct *conn = req->conn;
6107 struct smb_filename *smb_dname = NULL;
6108 char *directory = NULL;
6109 NTSTATUS status;
6110 uint32_t ucf_flags = UCF_PREP_CREATEFILE |
6111 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6112 TALLOC_CTX *ctx = talloc_tos();
6113
6114 START_PROFILE(SMBmkdir);
6115
6116 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6117 STR_TERMINATE, &status);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 reply_nterror(req, status);
6120 goto out;
6121 }
6122
6123 status = filename_convert(ctx, conn,
6124 req->flags2 & FLAGS2_DFS_PATHNAMES,
6125 directory,
6126 ucf_flags,
6127 NULL,
6128 &smb_dname);
6129 if (!NT_STATUS_IS_OK(status)) {
6130 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6131 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6132 ERRSRV, ERRbadpath);
6133 goto out;
6134 }
6135 reply_nterror(req, status);
6136 goto out;
6137 }
6138
6139 status = create_directory(conn, req, smb_dname);
6140
6141 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6142
6143 if (!NT_STATUS_IS_OK(status)) {
6144
6145 if (!use_nt_status()
6146 && NT_STATUS_EQUAL(status,
6147 NT_STATUS_OBJECT_NAME_COLLISION)) {
6148 /*
6149 * Yes, in the DOS error code case we get a
6150 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6151 * samba4 torture test.
6152 */
6153 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6154 }
6155
6156 reply_nterror(req, status);
6157 goto out;
6158 }
6159
6160 reply_outbuf(req, 0, 0);
6161
6162 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6163 out:
6164 TALLOC_FREE(smb_dname);
6165 END_PROFILE(SMBmkdir);
6166 return;
6167}
6168
6169/****************************************************************************
6170 Reply to a rmdir.
6171****************************************************************************/
6172
6173void reply_rmdir(struct smb_request *req)
6174{
6175 connection_struct *conn = req->conn;
6176 struct smb_filename *smb_dname = NULL;
6177 char *directory = NULL;
6178 NTSTATUS status;
6179 TALLOC_CTX *ctx = talloc_tos();
6180 files_struct *fsp = NULL;
6181 int info = 0;
6182 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6183 struct smbd_server_connection *sconn = req->sconn;
6184
6185 START_PROFILE(SMBrmdir);
6186
6187 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6188 STR_TERMINATE, &status);
6189 if (!NT_STATUS_IS_OK(status)) {
6190 reply_nterror(req, status);
6191 goto out;
6192 }
6193
6194 status = filename_convert(ctx, conn,
6195 req->flags2 & FLAGS2_DFS_PATHNAMES,
6196 directory,
6197 ucf_flags,
6198 NULL,
6199 &smb_dname);
6200 if (!NT_STATUS_IS_OK(status)) {
6201 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6202 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6203 ERRSRV, ERRbadpath);
6204 goto out;
6205 }
6206 reply_nterror(req, status);
6207 goto out;
6208 }
6209
6210 if (is_ntfs_stream_smb_fname(smb_dname)) {
6211 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6212 goto out;
6213 }
6214
6215 status = SMB_VFS_CREATE_FILE(
6216 conn, /* conn */
6217 req, /* req */
6218 0, /* root_dir_fid */
6219 smb_dname, /* fname */
6220 DELETE_ACCESS, /* access_mask */
6221 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6222 FILE_SHARE_DELETE),
6223 FILE_OPEN, /* create_disposition*/
6224 FILE_DIRECTORY_FILE, /* create_options */
6225 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6226 0, /* oplock_request */
6227 NULL, /* lease */
6228 0, /* allocation_size */
6229 0, /* private_flags */
6230 NULL, /* sd */
6231 NULL, /* ea_list */
6232 &fsp, /* result */
6233 &info, /* pinfo */
6234 NULL, NULL); /* create context */
6235
6236 if (!NT_STATUS_IS_OK(status)) {
6237 if (open_was_deferred(req->xconn, req->mid)) {
6238 /* We have re-scheduled this call. */
6239 goto out;
6240 }
6241 reply_nterror(req, status);
6242 goto out;
6243 }
6244
6245 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6246 if (!NT_STATUS_IS_OK(status)) {
6247 close_file(req, fsp, ERROR_CLOSE);
6248 reply_nterror(req, status);
6249 goto out;
6250 }
6251
6252 if (!set_delete_on_close(fsp, true,
6253 conn->session_info->security_token,
6254 conn->session_info->unix_token)) {
6255 close_file(req, fsp, ERROR_CLOSE);
6256 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6257 goto out;
6258 }
6259
6260 status = close_file(req, fsp, NORMAL_CLOSE);
6261 if (!NT_STATUS_IS_OK(status)) {
6262 reply_nterror(req, status);
6263 } else {
6264 reply_outbuf(req, 0, 0);
6265 }
6266
6267 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6268
6269 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6270 out:
6271 TALLOC_FREE(smb_dname);
6272 END_PROFILE(SMBrmdir);
6273 return;
6274}
6275
6276/*******************************************************************
6277 Resolve wildcards in a filename rename.
6278********************************************************************/
6279
6280static bool resolve_wildcards(TALLOC_CTX *ctx,
6281 const char *name1,
6282 const char *name2,
6283 char **pp_newname)
6284{
6285 char *name2_copy = NULL;
6286 char *root1 = NULL;
6287 char *root2 = NULL;
6288 char *ext1 = NULL;
6289 char *ext2 = NULL;
6290 char *p,*p2, *pname1, *pname2;
6291
6292 name2_copy = talloc_strdup(ctx, name2);
6293 if (!name2_copy) {
6294 return False;
6295 }
6296
6297 pname1 = strrchr_m(name1,'/');
6298 pname2 = strrchr_m(name2_copy,'/');
6299
6300 if (!pname1 || !pname2) {
6301 return False;
6302 }
6303
6304 /* Truncate the copy of name2 at the last '/' */
6305 *pname2 = '\0';
6306
6307 /* Now go past the '/' */
6308 pname1++;
6309 pname2++;
6310
6311 root1 = talloc_strdup(ctx, pname1);
6312 root2 = talloc_strdup(ctx, pname2);
6313
6314 if (!root1 || !root2) {
6315 return False;
6316 }
6317
6318 p = strrchr_m(root1,'.');
6319 if (p) {
6320 *p = 0;
6321 ext1 = talloc_strdup(ctx, p+1);
6322 } else {
6323 ext1 = talloc_strdup(ctx, "");
6324 }
6325 p = strrchr_m(root2,'.');
6326 if (p) {
6327 *p = 0;
6328 ext2 = talloc_strdup(ctx, p+1);
6329 } else {
6330 ext2 = talloc_strdup(ctx, "");
6331 }
6332
6333 if (!ext1 || !ext2) {
6334 return False;
6335 }
6336
6337 p = root1;
6338 p2 = root2;
6339 while (*p2) {
6340 if (*p2 == '?') {
6341 /* Hmmm. Should this be mb-aware ? */
6342 *p2 = *p;
6343 p2++;
6344 } else if (*p2 == '*') {
6345 *p2 = '\0';
6346 root2 = talloc_asprintf(ctx, "%s%s",
6347 root2,
6348 p);
6349 if (!root2) {
6350 return False;
6351 }
6352 break;
6353 } else {
6354 p2++;
6355 }
6356 if (*p) {
6357 p++;
6358 }
6359 }
6360
6361 p = ext1;
6362 p2 = ext2;
6363 while (*p2) {
6364 if (*p2 == '?') {
6365 /* Hmmm. Should this be mb-aware ? */
6366 *p2 = *p;
6367 p2++;
6368 } else if (*p2 == '*') {
6369 *p2 = '\0';
6370 ext2 = talloc_asprintf(ctx, "%s%s",
6371 ext2,
6372 p);
6373 if (!ext2) {
6374 return False;
6375 }
6376 break;
6377 } else {
6378 p2++;
6379 }
6380 if (*p) {
6381 p++;
6382 }
6383 }
6384
6385 if (*ext2) {
6386 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6387 name2_copy,
6388 root2,
6389 ext2);
6390 } else {
6391 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6392 name2_copy,
6393 root2);
6394 }
6395
6396 if (!*pp_newname) {
6397 return False;
6398 }
6399
6400 return True;
6401}
6402
6403/****************************************************************************
6404 Ensure open files have their names updated. Updated to notify other smbd's
6405 asynchronously.
6406****************************************************************************/
6407
6408static void rename_open_files(connection_struct *conn,
6409 struct share_mode_lock *lck,
6410 struct file_id id,
6411 uint32_t orig_name_hash,
6412 const struct smb_filename *smb_fname_dst)
6413{
6414 files_struct *fsp;
6415 bool did_rename = False;
6416 NTSTATUS status;
6417 uint32_t new_name_hash = 0;
6418
6419 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6420 fsp = file_find_di_next(fsp)) {
6421 /* fsp_name is a relative path under the fsp. To change this for other
6422 sharepaths we need to manipulate relative paths. */
6423 /* TODO - create the absolute path and manipulate the newname
6424 relative to the sharepath. */
6425 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6426 continue;
6427 }
6428 if (fsp->name_hash != orig_name_hash) {
6429 continue;
6430 }
6431 DEBUG(10, ("rename_open_files: renaming file %s "
6432 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6433 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6434 smb_fname_str_dbg(smb_fname_dst)));
6435
6436 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6437 if (NT_STATUS_IS_OK(status)) {
6438 did_rename = True;
6439 new_name_hash = fsp->name_hash;
6440 }
6441 }
6442
6443 if (!did_rename) {
6444 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6445 "for %s\n", file_id_string_tos(&id),
6446 smb_fname_str_dbg(smb_fname_dst)));
6447 }
6448
6449 /* Send messages to all smbd's (not ourself) that the name has changed. */
6450 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6451 orig_name_hash, new_name_hash,
6452 smb_fname_dst);
6453
6454}
6455
6456/****************************************************************************
6457 We need to check if the source path is a parent directory of the destination
6458 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6459 refuse the rename with a sharing violation. Under UNIX the above call can
6460 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6461 probably need to check that the client is a Windows one before disallowing
6462 this as a UNIX client (one with UNIX extensions) can know the source is a
6463 symlink and make this decision intelligently. Found by an excellent bug
6464 report from <AndyLiebman@aol.com>.
6465****************************************************************************/
6466
6467static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6468 const struct smb_filename *smb_fname_dst)
6469{
6470 const char *psrc = smb_fname_src->base_name;
6471 const char *pdst = smb_fname_dst->base_name;
6472 size_t slen;
6473
6474 if (psrc[0] == '.' && psrc[1] == '/') {
6475 psrc += 2;
6476 }
6477 if (pdst[0] == '.' && pdst[1] == '/') {
6478 pdst += 2;
6479 }
6480 if ((slen = strlen(psrc)) > strlen(pdst)) {
6481 return False;
6482 }
6483 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6484}
6485
6486/*
6487 * Do the notify calls from a rename
6488 */
6489
6490static void notify_rename(connection_struct *conn, bool is_dir,
6491 const struct smb_filename *smb_fname_src,
6492 const struct smb_filename *smb_fname_dst)
6493{
6494 char *parent_dir_src = NULL;
6495 char *parent_dir_dst = NULL;
6496 uint32_t mask;
6497
6498 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6499 : FILE_NOTIFY_CHANGE_FILE_NAME;
6500
6501 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6502 &parent_dir_src, NULL) ||
6503 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6504 &parent_dir_dst, NULL)) {
6505 goto out;
6506 }
6507
6508 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6509 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6510 smb_fname_src->base_name);
6511 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6512 smb_fname_dst->base_name);
6513 }
6514 else {
6515 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6516 smb_fname_src->base_name);
6517 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6518 smb_fname_dst->base_name);
6519 }
6520
6521 /* this is a strange one. w2k3 gives an additional event for
6522 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6523 files, but not directories */
6524 if (!is_dir) {
6525 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6526 FILE_NOTIFY_CHANGE_ATTRIBUTES
6527 |FILE_NOTIFY_CHANGE_CREATION,
6528 smb_fname_dst->base_name);
6529 }
6530 out:
6531 TALLOC_FREE(parent_dir_src);
6532 TALLOC_FREE(parent_dir_dst);
6533}
6534
6535/****************************************************************************
6536 Returns an error if the parent directory for a filename is open in an
6537 incompatible way.
6538****************************************************************************/
6539
6540static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6541 const struct smb_filename *smb_fname_dst_in)
6542{
6543 char *parent_dir = NULL;
6544 struct smb_filename smb_fname_parent;
6545 struct file_id id;
6546 files_struct *fsp = NULL;
6547 int ret;
6548
6549 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6550 &parent_dir, NULL)) {
6551 return NT_STATUS_NO_MEMORY;
6552 }
6553 ZERO_STRUCT(smb_fname_parent);
6554 smb_fname_parent.base_name = parent_dir;
6555
6556 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6557 if (ret == -1) {
6558 return map_nt_error_from_unix(errno);
6559 }
6560
6561 /*
6562 * We're only checking on this smbd here, mostly good
6563 * enough.. and will pass tests.
6564 */
6565
6566 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6567 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6568 fsp = file_find_di_next(fsp)) {
6569 if (fsp->access_mask & DELETE_ACCESS) {
6570 return NT_STATUS_SHARING_VIOLATION;
6571 }
6572 }
6573 return NT_STATUS_OK;
6574}
6575
6576/****************************************************************************
6577 Rename an open file - given an fsp.
6578****************************************************************************/
6579
6580NTSTATUS rename_internals_fsp(connection_struct *conn,
6581 files_struct *fsp,
6582 const struct smb_filename *smb_fname_dst_in,
6583 uint32_t attrs,
6584 bool replace_if_exists)
6585{
6586 TALLOC_CTX *ctx = talloc_tos();
6587 struct smb_filename *smb_fname_dst = NULL;
6588 NTSTATUS status = NT_STATUS_OK;
6589 struct share_mode_lock *lck = NULL;
6590 bool dst_exists, old_is_stream, new_is_stream;
6591
6592 status = check_name(conn, smb_fname_dst_in->base_name);
6593 if (!NT_STATUS_IS_OK(status)) {
6594 return status;
6595 }
6596
6597 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 return status;
6600 }
6601
6602 /* Make a copy of the dst smb_fname structs */
6603
6604 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6605 if (smb_fname_dst == NULL) {
6606 status = NT_STATUS_NO_MEMORY;
6607 goto out;
6608 }
6609
6610 /*
6611 * Check for special case with case preserving and not
6612 * case sensitive. If the new last component differs from the original
6613 * last component only by case, then we should allow
6614 * the rename (user is trying to change the case of the
6615 * filename).
6616 */
6617 if (!conn->case_sensitive && conn->case_preserve &&
6618 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6619 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6620 char *last_slash;
6621 char *fname_dst_lcomp_base_mod = NULL;
6622 struct smb_filename *smb_fname_orig_lcomp = NULL;
6623
6624 /*
6625 * Get the last component of the destination name.
6626 */
6627 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6628 if (last_slash) {
6629 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6630 } else {
6631 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6632 }
6633 if (!fname_dst_lcomp_base_mod) {
6634 status = NT_STATUS_NO_MEMORY;
6635 goto out;
6636 }
6637
6638 /*
6639 * Create an smb_filename struct using the original last
6640 * component of the destination.
6641 */
6642 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6643 ctx, smb_fname_dst->original_lcomp, NULL);
6644 if (smb_fname_orig_lcomp == NULL) {
6645 status = NT_STATUS_NO_MEMORY;
6646 TALLOC_FREE(fname_dst_lcomp_base_mod);
6647 goto out;
6648 }
6649
6650 /* If the base names only differ by case, use original. */
6651 if(!strcsequal(fname_dst_lcomp_base_mod,
6652 smb_fname_orig_lcomp->base_name)) {
6653 char *tmp;
6654 /*
6655 * Replace the modified last component with the
6656 * original.
6657 */
6658 if (last_slash) {
6659 *last_slash = '\0'; /* Truncate at the '/' */
6660 tmp = talloc_asprintf(smb_fname_dst,
6661 "%s/%s",
6662 smb_fname_dst->base_name,
6663 smb_fname_orig_lcomp->base_name);
6664 } else {
6665 tmp = talloc_asprintf(smb_fname_dst,
6666 "%s",
6667 smb_fname_orig_lcomp->base_name);
6668 }
6669 if (tmp == NULL) {
6670 status = NT_STATUS_NO_MEMORY;
6671 TALLOC_FREE(fname_dst_lcomp_base_mod);
6672 TALLOC_FREE(smb_fname_orig_lcomp);
6673 goto out;
6674 }
6675 TALLOC_FREE(smb_fname_dst->base_name);
6676 smb_fname_dst->base_name = tmp;
6677 }
6678
6679 /* If the stream_names only differ by case, use original. */
6680 if(!strcsequal(smb_fname_dst->stream_name,
6681 smb_fname_orig_lcomp->stream_name)) {
6682 char *tmp = NULL;
6683 /* Use the original stream. */
6684 tmp = talloc_strdup(smb_fname_dst,
6685 smb_fname_orig_lcomp->stream_name);
6686 if (tmp == NULL) {
6687 status = NT_STATUS_NO_MEMORY;
6688 TALLOC_FREE(fname_dst_lcomp_base_mod);
6689 TALLOC_FREE(smb_fname_orig_lcomp);
6690 goto out;
6691 }
6692 TALLOC_FREE(smb_fname_dst->stream_name);
6693 smb_fname_dst->stream_name = tmp;
6694 }
6695 TALLOC_FREE(fname_dst_lcomp_base_mod);
6696 TALLOC_FREE(smb_fname_orig_lcomp);
6697 }
6698
6699 /*
6700 * If the src and dest names are identical - including case,
6701 * don't do the rename, just return success.
6702 */
6703
6704 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6705 strcsequal(fsp->fsp_name->stream_name,
6706 smb_fname_dst->stream_name)) {
6707 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6708 "- returning success\n",
6709 smb_fname_str_dbg(smb_fname_dst)));
6710 status = NT_STATUS_OK;
6711 goto out;
6712 }
6713
6714 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6715 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6716
6717 /* Return the correct error code if both names aren't streams. */
6718 if (!old_is_stream && new_is_stream) {
6719 status = NT_STATUS_OBJECT_NAME_INVALID;
6720 goto out;
6721 }
6722
6723 if (old_is_stream && !new_is_stream) {
6724 status = NT_STATUS_INVALID_PARAMETER;
6725 goto out;
6726 }
6727
6728 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6729
6730 if(!replace_if_exists && dst_exists) {
6731 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6732 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6733 smb_fname_str_dbg(smb_fname_dst)));
6734 status = NT_STATUS_OBJECT_NAME_COLLISION;
6735 goto out;
6736 }
6737
6738 if (dst_exists) {
6739 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6740 &smb_fname_dst->st);
6741 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6742 fileid);
6743 /* The file can be open when renaming a stream */
6744 if (dst_fsp && !new_is_stream) {
6745 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6746 status = NT_STATUS_ACCESS_DENIED;
6747 goto out;
6748 }
6749 }
6750
6751 /* Ensure we have a valid stat struct for the source. */
6752 status = vfs_stat_fsp(fsp);
6753 if (!NT_STATUS_IS_OK(status)) {
6754 goto out;
6755 }
6756
6757 status = can_rename(conn, fsp, attrs);
6758
6759 if (!NT_STATUS_IS_OK(status)) {
6760 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6761 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6762 smb_fname_str_dbg(smb_fname_dst)));
6763 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6764 status = NT_STATUS_ACCESS_DENIED;
6765 goto out;
6766 }
6767
6768 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6769 status = NT_STATUS_ACCESS_DENIED;
6770 }
6771
6772 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6773
6774 /*
6775 * We have the file open ourselves, so not being able to get the
6776 * corresponding share mode lock is a fatal error.
6777 */
6778
6779 SMB_ASSERT(lck != NULL);
6780
6781 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6782 uint32_t create_options = fsp->fh->private_options;
6783
6784 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6785 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6786 smb_fname_str_dbg(smb_fname_dst)));
6787
6788 if (!fsp->is_directory &&
6789 !lp_posix_pathnames() &&
6790 (lp_map_archive(SNUM(conn)) ||
6791 lp_store_dos_attributes(SNUM(conn)))) {
6792 /* We must set the archive bit on the newly
6793 renamed file. */
6794 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6795 uint32_t old_dosmode = dos_mode(conn,
6796 smb_fname_dst);
6797 file_set_dosmode(conn,
6798 smb_fname_dst,
6799 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6800 NULL,
6801 true);
6802 }
6803 }
6804
6805 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6806 smb_fname_dst);
6807
6808 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6809 smb_fname_dst);
6810
6811 /*
6812 * A rename acts as a new file create w.r.t. allowing an initial delete
6813 * on close, probably because in Windows there is a new handle to the
6814 * new file. If initial delete on close was requested but not
6815 * originally set, we need to set it here. This is probably not 100% correct,
6816 * but will work for the CIFSFS client which in non-posix mode
6817 * depends on these semantics. JRA.
6818 */
6819
6820 if (create_options & FILE_DELETE_ON_CLOSE) {
6821 status = can_set_delete_on_close(fsp, 0);
6822
6823 if (NT_STATUS_IS_OK(status)) {
6824 /* Note that here we set the *inital* delete on close flag,
6825 * not the regular one. The magic gets handled in close. */
6826 fsp->initial_delete_on_close = True;
6827 }
6828 }
6829 TALLOC_FREE(lck);
6830 status = NT_STATUS_OK;
6831 goto out;
6832 }
6833
6834 TALLOC_FREE(lck);
6835
6836 if (errno == ENOTDIR || errno == EISDIR) {
6837 status = NT_STATUS_OBJECT_NAME_COLLISION;
6838 } else {
6839 status = map_nt_error_from_unix(errno);
6840 }
6841
6842 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6843 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6844 smb_fname_str_dbg(smb_fname_dst)));
6845
6846 out:
6847 TALLOC_FREE(smb_fname_dst);
6848
6849 return status;
6850}
6851
6852/****************************************************************************
6853 The guts of the rename command, split out so it may be called by the NT SMB
6854 code.
6855****************************************************************************/
6856
6857NTSTATUS rename_internals(TALLOC_CTX *ctx,
6858 connection_struct *conn,
6859 struct smb_request *req,
6860 struct smb_filename *smb_fname_src,
6861 struct smb_filename *smb_fname_dst,
6862 uint32_t attrs,
6863 bool replace_if_exists,
6864 bool src_has_wild,
6865 bool dest_has_wild,
6866 uint32_t access_mask)
6867{
6868 char *fname_src_dir = NULL;
6869 char *fname_src_mask = NULL;
6870 int count=0;
6871 NTSTATUS status = NT_STATUS_OK;
6872 struct smb_Dir *dir_hnd = NULL;
6873 const char *dname = NULL;
6874 char *talloced = NULL;
6875 long offset = 0;
6876 int create_options = 0;
6877 bool posix_pathnames = (req != NULL && req->posix_pathnames);
6878 int rc;
6879
6880 /*
6881 * Split the old name into directory and last component
6882 * strings. Note that unix_convert may have stripped off a
6883 * leading ./ from both name and newname if the rename is
6884 * at the root of the share. We need to make sure either both
6885 * name and newname contain a / character or neither of them do
6886 * as this is checked in resolve_wildcards().
6887 */
6888
6889 /* Split up the directory from the filename/mask. */
6890 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6891 &fname_src_dir, &fname_src_mask);
6892 if (!NT_STATUS_IS_OK(status)) {
6893 status = NT_STATUS_NO_MEMORY;
6894 goto out;
6895 }
6896
6897 /*
6898 * We should only check the mangled cache
6899 * here if unix_convert failed. This means
6900 * that the path in 'mask' doesn't exist
6901 * on the file system and so we need to look
6902 * for a possible mangle. This patch from
6903 * Tine Smukavec <valentin.smukavec@hermes.si>.
6904 */
6905
6906 if (!VALID_STAT(smb_fname_src->st) &&
6907 mangle_is_mangled(fname_src_mask, conn->params)) {
6908 char *new_mask = NULL;
6909 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6910 conn->params);
6911 if (new_mask) {
6912 TALLOC_FREE(fname_src_mask);
6913 fname_src_mask = new_mask;
6914 }
6915 }
6916
6917 if (!src_has_wild) {
6918 files_struct *fsp;
6919
6920 /*
6921 * Only one file needs to be renamed. Append the mask back
6922 * onto the directory.
6923 */
6924 TALLOC_FREE(smb_fname_src->base_name);
6925 if (ISDOT(fname_src_dir)) {
6926 /* Ensure we use canonical names on open. */
6927 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6928 "%s",
6929 fname_src_mask);
6930 } else {
6931 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6932 "%s/%s",
6933 fname_src_dir,
6934 fname_src_mask);
6935 }
6936 if (!smb_fname_src->base_name) {
6937 status = NT_STATUS_NO_MEMORY;
6938 goto out;
6939 }
6940
6941 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6942 "case_preserve = %d, short case preserve = %d, "
6943 "directory = %s, newname = %s, "
6944 "last_component_dest = %s\n",
6945 conn->case_sensitive, conn->case_preserve,
6946 conn->short_case_preserve,
6947 smb_fname_str_dbg(smb_fname_src),
6948 smb_fname_str_dbg(smb_fname_dst),
6949 smb_fname_dst->original_lcomp));
6950
6951 /* The dest name still may have wildcards. */
6952 if (dest_has_wild) {
6953 char *fname_dst_mod = NULL;
6954 if (!resolve_wildcards(smb_fname_dst,
6955 smb_fname_src->base_name,
6956 smb_fname_dst->base_name,
6957 &fname_dst_mod)) {
6958 DEBUG(6, ("rename_internals: resolve_wildcards "
6959 "%s %s failed\n",
6960 smb_fname_src->base_name,
6961 smb_fname_dst->base_name));
6962 status = NT_STATUS_NO_MEMORY;
6963 goto out;
6964 }
6965 TALLOC_FREE(smb_fname_dst->base_name);
6966 smb_fname_dst->base_name = fname_dst_mod;
6967 }
6968
6969 ZERO_STRUCT(smb_fname_src->st);
6970 if (posix_pathnames) {
6971 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6972 } else {
6973 rc = SMB_VFS_STAT(conn, smb_fname_src);
6974 }
6975 if (rc == -1) {
6976 status = map_nt_error_from_unix_common(errno);
6977 goto out;
6978 }
6979
6980 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6981 create_options |= FILE_DIRECTORY_FILE;
6982 }
6983
6984 status = SMB_VFS_CREATE_FILE(
6985 conn, /* conn */
6986 req, /* req */
6987 0, /* root_dir_fid */
6988 smb_fname_src, /* fname */
6989 access_mask, /* access_mask */
6990 (FILE_SHARE_READ | /* share_access */
6991 FILE_SHARE_WRITE),
6992 FILE_OPEN, /* create_disposition*/
6993 create_options, /* create_options */
6994 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6995 0, /* oplock_request */
6996 NULL, /* lease */
6997 0, /* allocation_size */
6998 0, /* private_flags */
6999 NULL, /* sd */
7000 NULL, /* ea_list */
7001 &fsp, /* result */
7002 NULL, /* pinfo */
7003 NULL, NULL); /* create context */
7004
7005 if (!NT_STATUS_IS_OK(status)) {
7006 DEBUG(3, ("Could not open rename source %s: %s\n",
7007 smb_fname_str_dbg(smb_fname_src),
7008 nt_errstr(status)));
7009 goto out;
7010 }
7011
7012 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7013 attrs, replace_if_exists);
7014
7015 close_file(req, fsp, NORMAL_CLOSE);
7016
7017 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7018 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7019 smb_fname_str_dbg(smb_fname_dst)));
7020
7021 goto out;
7022 }
7023
7024 /*
7025 * Wildcards - process each file that matches.
7026 */
7027 if (strequal(fname_src_mask, "????????.???")) {
7028 TALLOC_FREE(fname_src_mask);
7029 fname_src_mask = talloc_strdup(ctx, "*");
7030 if (!fname_src_mask) {
7031 status = NT_STATUS_NO_MEMORY;
7032 goto out;
7033 }
7034 }
7035
7036 status = check_name(conn, fname_src_dir);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 goto out;
7039 }
7040
7041 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
7042 attrs);
7043 if (dir_hnd == NULL) {
7044 status = map_nt_error_from_unix(errno);
7045 goto out;
7046 }
7047
7048 status = NT_STATUS_NO_SUCH_FILE;
7049 /*
7050 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
7051 * - gentest fix. JRA
7052 */
7053
7054 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
7055 &talloced))) {
7056 files_struct *fsp = NULL;
7057 char *destname = NULL;
7058 bool sysdir_entry = False;
7059
7060 /* Quick check for "." and ".." */
7061 if (ISDOT(dname) || ISDOTDOT(dname)) {
7062 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
7063 sysdir_entry = True;
7064 } else {
7065 TALLOC_FREE(talloced);
7066 continue;
7067 }
7068 }
7069
7070 if (!is_visible_file(conn, fname_src_dir, dname,
7071 &smb_fname_src->st, false)) {
7072 TALLOC_FREE(talloced);
7073 continue;
7074 }
7075
7076 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
7077 TALLOC_FREE(talloced);
7078 continue;
7079 }
7080
7081 if (sysdir_entry) {
7082 status = NT_STATUS_OBJECT_NAME_INVALID;
7083 break;
7084 }
7085
7086 TALLOC_FREE(smb_fname_src->base_name);
7087 if (ISDOT(fname_src_dir)) {
7088 /* Ensure we use canonical names on open. */
7089 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7090 "%s",
7091 dname);
7092 } else {
7093 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7094 "%s/%s",
7095 fname_src_dir,
7096 dname);
7097 }
7098 if (!smb_fname_src->base_name) {
7099 status = NT_STATUS_NO_MEMORY;
7100 goto out;
7101 }
7102
7103 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7104 smb_fname_dst->base_name,
7105 &destname)) {
7106 DEBUG(6, ("resolve_wildcards %s %s failed\n",
7107 smb_fname_src->base_name, destname));
7108 TALLOC_FREE(talloced);
7109 continue;
7110 }
7111 if (!destname) {
7112 status = NT_STATUS_NO_MEMORY;
7113 goto out;
7114 }
7115
7116 TALLOC_FREE(smb_fname_dst->base_name);
7117 smb_fname_dst->base_name = destname;
7118
7119 ZERO_STRUCT(smb_fname_src->st);
7120 if (posix_pathnames) {
7121 SMB_VFS_LSTAT(conn, smb_fname_src);
7122 } else {
7123 SMB_VFS_STAT(conn, smb_fname_src);
7124 }
7125
7126 create_options = 0;
7127
7128 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7129 create_options |= FILE_DIRECTORY_FILE;
7130 }
7131
7132 status = SMB_VFS_CREATE_FILE(
7133 conn, /* conn */
7134 req, /* req */
7135 0, /* root_dir_fid */
7136 smb_fname_src, /* fname */
7137 access_mask, /* access_mask */
7138 (FILE_SHARE_READ | /* share_access */
7139 FILE_SHARE_WRITE),
7140 FILE_OPEN, /* create_disposition*/
7141 create_options, /* create_options */
7142 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7143 0, /* oplock_request */
7144 NULL, /* lease */
7145 0, /* allocation_size */
7146 0, /* private_flags */
7147 NULL, /* sd */
7148 NULL, /* ea_list */
7149 &fsp, /* result */
7150 NULL, /* pinfo */
7151 NULL, NULL); /* create context */
7152
7153 if (!NT_STATUS_IS_OK(status)) {
7154 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
7155 "returned %s rename %s -> %s\n",
7156 nt_errstr(status),
7157 smb_fname_str_dbg(smb_fname_src),
7158 smb_fname_str_dbg(smb_fname_dst)));
7159 break;
7160 }
7161
7162 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7163 dname);
7164 if (!smb_fname_dst->original_lcomp) {
7165 status = NT_STATUS_NO_MEMORY;
7166 goto out;
7167 }
7168
7169 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7170 attrs, replace_if_exists);
7171
7172 close_file(req, fsp, NORMAL_CLOSE);
7173
7174 if (!NT_STATUS_IS_OK(status)) {
7175 DEBUG(3, ("rename_internals_fsp returned %s for "
7176 "rename %s -> %s\n", nt_errstr(status),
7177 smb_fname_str_dbg(smb_fname_src),
7178 smb_fname_str_dbg(smb_fname_dst)));
7179 break;
7180 }
7181
7182 count++;
7183
7184 DEBUG(3,("rename_internals: doing rename on %s -> "
7185 "%s\n", smb_fname_str_dbg(smb_fname_src),
7186 smb_fname_str_dbg(smb_fname_src)));
7187 TALLOC_FREE(talloced);
7188 }
7189 TALLOC_FREE(dir_hnd);
7190
7191 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7192 status = map_nt_error_from_unix(errno);
7193 }
7194
7195 out:
7196 TALLOC_FREE(talloced);
7197 TALLOC_FREE(fname_src_dir);
7198 TALLOC_FREE(fname_src_mask);
7199 return status;
7200}
7201
7202/****************************************************************************
7203 Reply to a mv.
7204****************************************************************************/
7205
7206void reply_mv(struct smb_request *req)
7207{
7208 connection_struct *conn = req->conn;
7209 char *name = NULL;
7210 char *newname = NULL;
7211 const char *p;
7212 uint32_t attrs;
7213 NTSTATUS status;
7214 bool src_has_wcard = False;
7215 bool dest_has_wcard = False;
7216 TALLOC_CTX *ctx = talloc_tos();
7217 struct smb_filename *smb_fname_src = NULL;
7218 struct smb_filename *smb_fname_dst = NULL;
7219 uint32_t src_ucf_flags = (req->posix_pathnames ?
7220 (UCF_UNIX_NAME_LOOKUP|UCF_POSIX_PATHNAMES) :
7221 UCF_COND_ALLOW_WCARD_LCOMP);
7222 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP |
7223 (req->posix_pathnames ? UCF_POSIX_PATHNAMES :
7224 UCF_COND_ALLOW_WCARD_LCOMP);
7225 bool stream_rename = false;
7226
7227 START_PROFILE(SMBmv);
7228
7229 if (req->wct < 1) {
7230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7231 goto out;
7232 }
7233
7234 attrs = SVAL(req->vwv+0, 0);
7235
7236 p = (const char *)req->buf + 1;
7237 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7238 &status, &src_has_wcard);
7239 if (!NT_STATUS_IS_OK(status)) {
7240 reply_nterror(req, status);
7241 goto out;
7242 }
7243 p++;
7244 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7245 &status, &dest_has_wcard);
7246 if (!NT_STATUS_IS_OK(status)) {
7247 reply_nterror(req, status);
7248 goto out;
7249 }
7250
7251 if (!req->posix_pathnames) {
7252 /* The newname must begin with a ':' if the
7253 name contains a ':'. */
7254 if (strchr_m(name, ':')) {
7255 if (newname[0] != ':') {
7256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7257 goto out;
7258 }
7259 stream_rename = true;
7260 }
7261 }
7262
7263 status = filename_convert(ctx,
7264 conn,
7265 req->flags2 & FLAGS2_DFS_PATHNAMES,
7266 name,
7267 src_ucf_flags,
7268 &src_has_wcard,
7269 &smb_fname_src);
7270
7271 if (!NT_STATUS_IS_OK(status)) {
7272 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7273 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7274 ERRSRV, ERRbadpath);
7275 goto out;
7276 }
7277 reply_nterror(req, status);
7278 goto out;
7279 }
7280
7281 status = filename_convert(ctx,
7282 conn,
7283 req->flags2 & FLAGS2_DFS_PATHNAMES,
7284 newname,
7285 dst_ucf_flags,
7286 &dest_has_wcard,
7287 &smb_fname_dst);
7288
7289 if (!NT_STATUS_IS_OK(status)) {
7290 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7291 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7292 ERRSRV, ERRbadpath);
7293 goto out;
7294 }
7295 reply_nterror(req, status);
7296 goto out;
7297 }
7298
7299 if (stream_rename) {
7300 /* smb_fname_dst->base_name must be the same as
7301 smb_fname_src->base_name. */
7302 TALLOC_FREE(smb_fname_dst->base_name);
7303 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7304 smb_fname_src->base_name);
7305 if (!smb_fname_dst->base_name) {
7306 reply_nterror(req, NT_STATUS_NO_MEMORY);
7307 goto out;
7308 }
7309 }
7310
7311 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7312 smb_fname_str_dbg(smb_fname_dst)));
7313
7314 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7315 attrs, False, src_has_wcard, dest_has_wcard,
7316 DELETE_ACCESS);
7317 if (!NT_STATUS_IS_OK(status)) {
7318 if (open_was_deferred(req->xconn, req->mid)) {
7319 /* We have re-scheduled this call. */
7320 goto out;
7321 }
7322 reply_nterror(req, status);
7323 goto out;
7324 }
7325
7326 reply_outbuf(req, 0, 0);
7327 out:
7328 TALLOC_FREE(smb_fname_src);
7329 TALLOC_FREE(smb_fname_dst);
7330 END_PROFILE(SMBmv);
7331 return;
7332}
7333
7334/*******************************************************************
7335 Copy a file as part of a reply_copy.
7336******************************************************************/
7337
7338/*
7339 * TODO: check error codes on all callers
7340 */
7341
7342NTSTATUS copy_file(TALLOC_CTX *ctx,
7343 connection_struct *conn,
7344 struct smb_filename *smb_fname_src,
7345 struct smb_filename *smb_fname_dst,
7346 int ofun,
7347 int count,
7348 bool target_is_directory)
7349{
7350 struct smb_filename *smb_fname_dst_tmp = NULL;
7351 off_t ret=-1;
7352 files_struct *fsp1,*fsp2;
7353 uint32_t dosattrs;
7354 uint32_t new_create_disposition;
7355 NTSTATUS status;
7356
7357
7358 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7359 if (smb_fname_dst_tmp == NULL) {
7360 return NT_STATUS_NO_MEMORY;
7361 }
7362
7363 /*
7364 * If the target is a directory, extract the last component from the
7365 * src filename and append it to the dst filename
7366 */
7367 if (target_is_directory) {
7368 const char *p;
7369
7370 /* dest/target can't be a stream if it's a directory. */
7371 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7372
7373 p = strrchr_m(smb_fname_src->base_name,'/');
7374 if (p) {
7375 p++;
7376 } else {
7377 p = smb_fname_src->base_name;
7378 }
7379 smb_fname_dst_tmp->base_name =
7380 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7381 p);
7382 if (!smb_fname_dst_tmp->base_name) {
7383 status = NT_STATUS_NO_MEMORY;
7384 goto out;
7385 }
7386 }
7387
7388 status = vfs_file_exist(conn, smb_fname_src);
7389 if (!NT_STATUS_IS_OK(status)) {
7390 goto out;
7391 }
7392
7393 if (!target_is_directory && count) {
7394 new_create_disposition = FILE_OPEN;
7395 } else {
7396 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7397 0, ofun,
7398 NULL, NULL,
7399 &new_create_disposition,
7400 NULL,
7401 NULL)) {
7402 status = NT_STATUS_INVALID_PARAMETER;
7403 goto out;
7404 }
7405 }
7406
7407 /* Open the src file for reading. */
7408 status = SMB_VFS_CREATE_FILE(
7409 conn, /* conn */
7410 NULL, /* req */
7411 0, /* root_dir_fid */
7412 smb_fname_src, /* fname */
7413 FILE_GENERIC_READ, /* access_mask */
7414 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7415 FILE_OPEN, /* create_disposition*/
7416 0, /* create_options */
7417 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7418 INTERNAL_OPEN_ONLY, /* oplock_request */
7419 NULL, /* lease */
7420 0, /* allocation_size */
7421 0, /* private_flags */
7422 NULL, /* sd */
7423 NULL, /* ea_list */
7424 &fsp1, /* result */
7425 NULL, /* psbuf */
7426 NULL, NULL); /* create context */
7427
7428 if (!NT_STATUS_IS_OK(status)) {
7429 goto out;
7430 }
7431
7432 dosattrs = dos_mode(conn, smb_fname_src);
7433
7434 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7435 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7436 }
7437
7438 /* Open the dst file for writing. */
7439 status = SMB_VFS_CREATE_FILE(
7440 conn, /* conn */
7441 NULL, /* req */
7442 0, /* root_dir_fid */
7443 smb_fname_dst, /* fname */
7444 FILE_GENERIC_WRITE, /* access_mask */
7445 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7446 new_create_disposition, /* create_disposition*/
7447 0, /* create_options */
7448 dosattrs, /* file_attributes */
7449 INTERNAL_OPEN_ONLY, /* oplock_request */
7450 NULL, /* lease */
7451 0, /* allocation_size */
7452 0, /* private_flags */
7453 NULL, /* sd */
7454 NULL, /* ea_list */
7455 &fsp2, /* result */
7456 NULL, /* psbuf */
7457 NULL, NULL); /* create context */
7458
7459 if (!NT_STATUS_IS_OK(status)) {
7460 close_file(NULL, fsp1, ERROR_CLOSE);
7461 goto out;
7462 }
7463
7464 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7465 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7466 if (ret == -1) {
7467 DEBUG(0, ("error - vfs lseek returned error %s\n",
7468 strerror(errno)));
7469 status = map_nt_error_from_unix(errno);
7470 close_file(NULL, fsp1, ERROR_CLOSE);
7471 close_file(NULL, fsp2, ERROR_CLOSE);
7472 goto out;
7473 }
7474 }
7475
7476 /* Do the actual copy. */
7477 if (smb_fname_src->st.st_ex_size) {
7478 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7479 } else {
7480 ret = 0;
7481 }
7482
7483 close_file(NULL, fsp1, NORMAL_CLOSE);
7484
7485 /* Ensure the modtime is set correctly on the destination file. */
7486 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7487
7488 /*
7489 * As we are opening fsp1 read-only we only expect
7490 * an error on close on fsp2 if we are out of space.
7491 * Thus we don't look at the error return from the
7492 * close of fsp1.
7493 */
7494 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7495
7496 if (!NT_STATUS_IS_OK(status)) {
7497 goto out;
7498 }
7499
7500 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7501 status = NT_STATUS_DISK_FULL;
7502 goto out;
7503 }
7504
7505 status = NT_STATUS_OK;
7506
7507 out:
7508 TALLOC_FREE(smb_fname_dst_tmp);
7509 return status;
7510}
7511
7512/****************************************************************************
7513 Reply to a file copy.
7514****************************************************************************/
7515
7516void reply_copy(struct smb_request *req)
7517{
7518 connection_struct *conn = req->conn;
7519 struct smb_filename *smb_fname_src = NULL;
7520 struct smb_filename *smb_fname_dst = NULL;
7521 char *fname_src = NULL;
7522 char *fname_dst = NULL;
7523 char *fname_src_mask = NULL;
7524 char *fname_src_dir = NULL;
7525 const char *p;
7526 int count=0;
7527 int error = ERRnoaccess;
7528 int tid2;
7529 int ofun;
7530 int flags;
7531 bool target_is_directory=False;
7532 bool source_has_wild = False;
7533 bool dest_has_wild = False;
7534 NTSTATUS status;
7535 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
7536 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7537 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
7538 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
7539 TALLOC_CTX *ctx = talloc_tos();
7540
7541 START_PROFILE(SMBcopy);
7542
7543 if (req->wct < 3) {
7544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7545 goto out;
7546 }
7547
7548 tid2 = SVAL(req->vwv+0, 0);
7549 ofun = SVAL(req->vwv+1, 0);
7550 flags = SVAL(req->vwv+2, 0);
7551
7552 p = (const char *)req->buf;
7553 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7554 &status, &source_has_wild);
7555 if (!NT_STATUS_IS_OK(status)) {
7556 reply_nterror(req, status);
7557 goto out;
7558 }
7559 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7560 &status, &dest_has_wild);
7561 if (!NT_STATUS_IS_OK(status)) {
7562 reply_nterror(req, status);
7563 goto out;
7564 }
7565
7566 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7567
7568 if (tid2 != conn->cnum) {
7569 /* can't currently handle inter share copies XXXX */
7570 DEBUG(3,("Rejecting inter-share copy\n"));
7571 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7572 goto out;
7573 }
7574
7575 status = filename_convert(ctx, conn,
7576 req->flags2 & FLAGS2_DFS_PATHNAMES,
7577 fname_src,
7578 ucf_flags_src,
7579 &source_has_wild,
7580 &smb_fname_src);
7581 if (!NT_STATUS_IS_OK(status)) {
7582 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7583 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7584 ERRSRV, ERRbadpath);
7585 goto out;
7586 }
7587 reply_nterror(req, status);
7588 goto out;
7589 }
7590
7591 status = filename_convert(ctx, conn,
7592 req->flags2 & FLAGS2_DFS_PATHNAMES,
7593 fname_dst,
7594 ucf_flags_dst,
7595 &dest_has_wild,
7596 &smb_fname_dst);
7597 if (!NT_STATUS_IS_OK(status)) {
7598 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7599 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7600 ERRSRV, ERRbadpath);
7601 goto out;
7602 }
7603 reply_nterror(req, status);
7604 goto out;
7605 }
7606
7607 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7608
7609 if ((flags&1) && target_is_directory) {
7610 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7611 goto out;
7612 }
7613
7614 if ((flags&2) && !target_is_directory) {
7615 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7616 goto out;
7617 }
7618
7619 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7620 /* wants a tree copy! XXXX */
7621 DEBUG(3,("Rejecting tree copy\n"));
7622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7623 goto out;
7624 }
7625
7626 /* Split up the directory from the filename/mask. */
7627 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7628 &fname_src_dir, &fname_src_mask);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 reply_nterror(req, NT_STATUS_NO_MEMORY);
7631 goto out;
7632 }
7633
7634 /*
7635 * We should only check the mangled cache
7636 * here if unix_convert failed. This means
7637 * that the path in 'mask' doesn't exist
7638 * on the file system and so we need to look
7639 * for a possible mangle. This patch from
7640 * Tine Smukavec <valentin.smukavec@hermes.si>.
7641 */
7642 if (!VALID_STAT(smb_fname_src->st) &&
7643 mangle_is_mangled(fname_src_mask, conn->params)) {
7644 char *new_mask = NULL;
7645 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7646 &new_mask, conn->params);
7647
7648 /* Use demangled name if one was successfully found. */
7649 if (new_mask) {
7650 TALLOC_FREE(fname_src_mask);
7651 fname_src_mask = new_mask;
7652 }
7653 }
7654
7655 if (!source_has_wild) {
7656
7657 /*
7658 * Only one file needs to be copied. Append the mask back onto
7659 * the directory.
7660 */
7661 TALLOC_FREE(smb_fname_src->base_name);
7662 if (ISDOT(fname_src_dir)) {
7663 /* Ensure we use canonical names on open. */
7664 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7665 "%s",
7666 fname_src_mask);
7667 } else {
7668 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7669 "%s/%s",
7670 fname_src_dir,
7671 fname_src_mask);
7672 }
7673 if (!smb_fname_src->base_name) {
7674 reply_nterror(req, NT_STATUS_NO_MEMORY);
7675 goto out;
7676 }
7677
7678 if (dest_has_wild) {
7679 char *fname_dst_mod = NULL;
7680 if (!resolve_wildcards(smb_fname_dst,
7681 smb_fname_src->base_name,
7682 smb_fname_dst->base_name,
7683 &fname_dst_mod)) {
7684 reply_nterror(req, NT_STATUS_NO_MEMORY);
7685 goto out;
7686 }
7687 TALLOC_FREE(smb_fname_dst->base_name);
7688 smb_fname_dst->base_name = fname_dst_mod;
7689 }
7690
7691 status = check_name(conn, smb_fname_src->base_name);
7692 if (!NT_STATUS_IS_OK(status)) {
7693 reply_nterror(req, status);
7694 goto out;
7695 }
7696
7697 status = check_name(conn, smb_fname_dst->base_name);
7698 if (!NT_STATUS_IS_OK(status)) {
7699 reply_nterror(req, status);
7700 goto out;
7701 }
7702
7703 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7704 ofun, count, target_is_directory);
7705
7706 if(!NT_STATUS_IS_OK(status)) {
7707 reply_nterror(req, status);
7708 goto out;
7709 } else {
7710 count++;
7711 }
7712 } else {
7713 struct smb_Dir *dir_hnd = NULL;
7714 const char *dname = NULL;
7715 char *talloced = NULL;
7716 long offset = 0;
7717
7718 /*
7719 * There is a wildcard that requires us to actually read the
7720 * src dir and copy each file matching the mask to the dst.
7721 * Right now streams won't be copied, but this could
7722 * presumably be added with a nested loop for reach dir entry.
7723 */
7724 SMB_ASSERT(!smb_fname_src->stream_name);
7725 SMB_ASSERT(!smb_fname_dst->stream_name);
7726
7727 smb_fname_src->stream_name = NULL;
7728 smb_fname_dst->stream_name = NULL;
7729
7730 if (strequal(fname_src_mask,"????????.???")) {
7731 TALLOC_FREE(fname_src_mask);
7732 fname_src_mask = talloc_strdup(ctx, "*");
7733 if (!fname_src_mask) {
7734 reply_nterror(req, NT_STATUS_NO_MEMORY);
7735 goto out;
7736 }
7737 }
7738
7739 status = check_name(conn, fname_src_dir);
7740 if (!NT_STATUS_IS_OK(status)) {
7741 reply_nterror(req, status);
7742 goto out;
7743 }
7744
7745 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7746 if (dir_hnd == NULL) {
7747 status = map_nt_error_from_unix(errno);
7748 reply_nterror(req, status);
7749 goto out;
7750 }
7751
7752 error = ERRbadfile;
7753
7754 /* Iterate over the src dir copying each entry to the dst. */
7755 while ((dname = ReadDirName(dir_hnd, &offset,
7756 &smb_fname_src->st, &talloced))) {
7757 char *destname = NULL;
7758
7759 if (ISDOT(dname) || ISDOTDOT(dname)) {
7760 TALLOC_FREE(talloced);
7761 continue;
7762 }
7763
7764 if (!is_visible_file(conn, fname_src_dir, dname,
7765 &smb_fname_src->st, false)) {
7766 TALLOC_FREE(talloced);
7767 continue;
7768 }
7769
7770 if(!mask_match(dname, fname_src_mask,
7771 conn->case_sensitive)) {
7772 TALLOC_FREE(talloced);
7773 continue;
7774 }
7775
7776 error = ERRnoaccess;
7777
7778 /* Get the src smb_fname struct setup. */
7779 TALLOC_FREE(smb_fname_src->base_name);
7780 if (ISDOT(fname_src_dir)) {
7781 /* Ensure we use canonical names on open. */
7782 smb_fname_src->base_name =
7783 talloc_asprintf(smb_fname_src, "%s",
7784 dname);
7785 } else {
7786 smb_fname_src->base_name =
7787 talloc_asprintf(smb_fname_src, "%s/%s",
7788 fname_src_dir, dname);
7789 }
7790
7791 if (!smb_fname_src->base_name) {
7792 TALLOC_FREE(dir_hnd);
7793 TALLOC_FREE(talloced);
7794 reply_nterror(req, NT_STATUS_NO_MEMORY);
7795 goto out;
7796 }
7797
7798 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7799 smb_fname_dst->base_name,
7800 &destname)) {
7801 TALLOC_FREE(talloced);
7802 continue;
7803 }
7804 if (!destname) {
7805 TALLOC_FREE(dir_hnd);
7806 TALLOC_FREE(talloced);
7807 reply_nterror(req, NT_STATUS_NO_MEMORY);
7808 goto out;
7809 }
7810
7811 TALLOC_FREE(smb_fname_dst->base_name);
7812 smb_fname_dst->base_name = destname;
7813
7814 status = check_name(conn, smb_fname_src->base_name);
7815 if (!NT_STATUS_IS_OK(status)) {
7816 TALLOC_FREE(dir_hnd);
7817 TALLOC_FREE(talloced);
7818 reply_nterror(req, status);
7819 goto out;
7820 }
7821
7822 status = check_name(conn, smb_fname_dst->base_name);
7823 if (!NT_STATUS_IS_OK(status)) {
7824 TALLOC_FREE(dir_hnd);
7825 TALLOC_FREE(talloced);
7826 reply_nterror(req, status);
7827 goto out;
7828 }
7829
7830 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7831 smb_fname_src->base_name,
7832 smb_fname_dst->base_name));
7833
7834 status = copy_file(ctx, conn, smb_fname_src,
7835 smb_fname_dst, ofun, count,
7836 target_is_directory);
7837 if (NT_STATUS_IS_OK(status)) {
7838 count++;
7839 }
7840
7841 TALLOC_FREE(talloced);
7842 }
7843 TALLOC_FREE(dir_hnd);
7844 }
7845
7846 if (count == 0) {
7847 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7848 goto out;
7849 }
7850
7851 reply_outbuf(req, 1, 0);
7852 SSVAL(req->outbuf,smb_vwv0,count);
7853 out:
7854 TALLOC_FREE(smb_fname_src);
7855 TALLOC_FREE(smb_fname_dst);
7856 TALLOC_FREE(fname_src);
7857 TALLOC_FREE(fname_dst);
7858 TALLOC_FREE(fname_src_mask);
7859 TALLOC_FREE(fname_src_dir);
7860
7861 END_PROFILE(SMBcopy);
7862 return;
7863}
7864
7865#undef DBGC_CLASS
7866#define DBGC_CLASS DBGC_LOCKING
7867
7868/****************************************************************************
7869 Get a lock pid, dealing with large count requests.
7870****************************************************************************/
7871
7872uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7873 bool large_file_format)
7874{
7875 if(!large_file_format)
7876 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7877 else
7878 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7879}
7880
7881/****************************************************************************
7882 Get a lock count, dealing with large count requests.
7883****************************************************************************/
7884
7885uint64_t get_lock_count(const uint8_t *data, int data_offset,
7886 bool large_file_format)
7887{
7888 uint64_t count = 0;
7889
7890 if(!large_file_format) {
7891 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7892 } else {
7893 /*
7894 * No BVAL, this is reversed!
7895 */
7896 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7897 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7898 }
7899
7900 return count;
7901}
7902
7903/****************************************************************************
7904 Get a lock offset, dealing with large offset requests.
7905****************************************************************************/
7906
7907uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7908 bool large_file_format)
7909{
7910 uint64_t offset = 0;
7911
7912 if(!large_file_format) {
7913 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7914 } else {
7915 /*
7916 * No BVAL, this is reversed!
7917 */
7918 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7919 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7920 }
7921
7922 return offset;
7923}
7924
7925NTSTATUS smbd_do_locking(struct smb_request *req,
7926 files_struct *fsp,
7927 uint8_t type,
7928 int32_t timeout,
7929 uint16_t num_locks,
7930 struct smbd_lock_element *locks,
7931 bool *async)
7932{
7933 connection_struct *conn = req->conn;
7934 int i;
7935 NTSTATUS status = NT_STATUS_OK;
7936
7937 *async = false;
7938
7939 /* Setup the timeout in seconds. */
7940
7941 if (!lp_blocking_locks(SNUM(conn))) {
7942 timeout = 0;
7943 }
7944
7945 for(i = 0; i < (int)num_locks; i++) {
7946 struct smbd_lock_element *e = &locks[i];
7947
7948 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7949 "%llu, file %s timeout = %d\n",
7950 (double)e->offset,
7951 (double)e->count,
7952 (unsigned long long)e->smblctx,
7953 fsp_str_dbg(fsp),
7954 (int)timeout));
7955
7956 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7957 struct blocking_lock_record *blr = NULL;
7958
7959 if (num_locks > 1) {
7960 /*
7961 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7962 * if the lock vector contains one entry. When given multiple cancel
7963 * requests in a single PDU we expect the server to return an
7964 * error. Windows servers seem to accept the request but only
7965 * cancel the first lock.
7966 * JRA - Do what Windows does (tm) :-).
7967 */
7968
7969#if 0
7970 /* MS-CIFS (2.2.4.32.1) behavior. */
7971 return NT_STATUS_DOS(ERRDOS,
7972 ERRcancelviolation);
7973#else
7974 /* Windows behavior. */
7975 if (i != 0) {
7976 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7977 "cancel request\n"));
7978 continue;
7979 }
7980#endif
7981 }
7982
7983 if (lp_blocking_locks(SNUM(conn))) {
7984
7985 /* Schedule a message to ourselves to
7986 remove the blocking lock record and
7987 return the right error. */
7988
7989 blr = blocking_lock_cancel_smb1(fsp,
7990 e->smblctx,
7991 e->offset,
7992 e->count,
7993 WINDOWS_LOCK,
7994 type,
7995 NT_STATUS_FILE_LOCK_CONFLICT);
7996 if (blr == NULL) {
7997 return NT_STATUS_DOS(
7998 ERRDOS,
7999 ERRcancelviolation);
8000 }
8001 }
8002 /* Remove a matching pending lock. */
8003 status = do_lock_cancel(fsp,
8004 e->smblctx,
8005 e->count,
8006 e->offset,
8007 WINDOWS_LOCK);
8008 } else {
8009 bool blocking_lock = timeout ? true : false;
8010 bool defer_lock = false;
8011 struct byte_range_lock *br_lck;
8012 uint64_t block_smblctx;
8013
8014 br_lck = do_lock(req->sconn->msg_ctx,
8015 fsp,
8016 e->smblctx,
8017 e->count,
8018 e->offset,
8019 e->brltype,
8020 WINDOWS_LOCK,
8021 blocking_lock,
8022 &status,
8023 &block_smblctx);
8024
8025 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
8026 /* Windows internal resolution for blocking locks seems
8027 to be about 200ms... Don't wait for less than that. JRA. */
8028 if (timeout != -1 && timeout < lp_lock_spin_time()) {
8029 timeout = lp_lock_spin_time();
8030 }
8031 defer_lock = true;
8032 }
8033
8034 /* If a lock sent with timeout of zero would fail, and
8035 * this lock has been requested multiple times,
8036 * according to brl_lock_failed() we convert this
8037 * request to a blocking lock with a timeout of between
8038 * 150 - 300 milliseconds.
8039 *
8040 * If lp_lock_spin_time() has been set to 0, we skip
8041 * this blocking retry and fail immediately.
8042 *
8043 * Replacement for do_lock_spin(). JRA. */
8044
8045 if (!req->sconn->using_smb2 &&
8046 br_lck && lp_blocking_locks(SNUM(conn)) &&
8047 lp_lock_spin_time() && !blocking_lock &&
8048 NT_STATUS_EQUAL((status),
8049 NT_STATUS_FILE_LOCK_CONFLICT))
8050 {
8051 defer_lock = true;
8052 timeout = lp_lock_spin_time();
8053 }
8054
8055 if (br_lck && defer_lock) {
8056 /*
8057 * A blocking lock was requested. Package up
8058 * this smb into a queued request and push it
8059 * onto the blocking lock queue.
8060 */
8061 if(push_blocking_lock_request(br_lck,
8062 req,
8063 fsp,
8064 timeout,
8065 i,
8066 e->smblctx,
8067 e->brltype,
8068 WINDOWS_LOCK,
8069 e->offset,
8070 e->count,
8071 block_smblctx)) {
8072 TALLOC_FREE(br_lck);
8073 *async = true;
8074 return NT_STATUS_OK;
8075 }
8076 }
8077
8078 TALLOC_FREE(br_lck);
8079 }
8080
8081 if (!NT_STATUS_IS_OK(status)) {
8082 break;
8083 }
8084 }
8085
8086 /* If any of the above locks failed, then we must unlock
8087 all of the previous locks (X/Open spec). */
8088
8089 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
8090
8091 if (type & LOCKING_ANDX_CANCEL_LOCK) {
8092 i = -1; /* we want to skip the for loop */
8093 }
8094
8095 /*
8096 * Ensure we don't do a remove on the lock that just failed,
8097 * as under POSIX rules, if we have a lock already there, we
8098 * will delete it (and we shouldn't) .....
8099 */
8100 for(i--; i >= 0; i--) {
8101 struct smbd_lock_element *e = &locks[i];
8102
8103 do_unlock(req->sconn->msg_ctx,
8104 fsp,
8105 e->smblctx,
8106 e->count,
8107 e->offset,
8108 WINDOWS_LOCK);
8109 }
8110 return status;
8111 }
8112
8113 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
8114 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
8115
8116 return NT_STATUS_OK;
8117}
8118
8119NTSTATUS smbd_do_unlocking(struct smb_request *req,
8120 files_struct *fsp,
8121 uint16_t num_ulocks,
8122 struct smbd_lock_element *ulocks)
8123{
8124 int i;
8125
8126 for(i = 0; i < (int)num_ulocks; i++) {
8127 struct smbd_lock_element *e = &ulocks[i];
8128 NTSTATUS status;
8129
8130 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
8131 "pid %u, file %s\n", __func__,
8132 (double)e->offset,
8133 (double)e->count,
8134 (unsigned int)e->smblctx,
8135 fsp_str_dbg(fsp)));
8136
8137 if (e->brltype != UNLOCK_LOCK) {
8138 /* this can only happen with SMB2 */
8139 return NT_STATUS_INVALID_PARAMETER;
8140 }
8141
8142 status = do_unlock(req->sconn->msg_ctx,
8143 fsp,
8144 e->smblctx,
8145 e->count,
8146 e->offset,
8147 WINDOWS_LOCK);
8148
8149 DEBUG(10, ("%s: unlock returned %s\n", __func__,
8150 nt_errstr(status)));
8151
8152 if (!NT_STATUS_IS_OK(status)) {
8153 return status;
8154 }
8155 }
8156
8157 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
8158 num_ulocks));
8159
8160 return NT_STATUS_OK;
8161}
8162
8163/****************************************************************************
8164 Reply to a lockingX request.
8165****************************************************************************/
8166
8167void reply_lockingX(struct smb_request *req)
8168{
8169 connection_struct *conn = req->conn;
8170 files_struct *fsp;
8171 unsigned char locktype;
8172 unsigned char oplocklevel;
8173 uint16_t num_ulocks;
8174 uint16_t num_locks;
8175 int32_t lock_timeout;
8176 int i;
8177 const uint8_t *data;
8178 bool large_file_format;
8179 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8180 struct smbd_lock_element *ulocks;
8181 struct smbd_lock_element *locks;
8182 bool async = false;
8183
8184 START_PROFILE(SMBlockingX);
8185
8186 if (req->wct < 8) {
8187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8188 END_PROFILE(SMBlockingX);
8189 return;
8190 }
8191
8192 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8193 locktype = CVAL(req->vwv+3, 0);
8194 oplocklevel = CVAL(req->vwv+3, 1);
8195 num_ulocks = SVAL(req->vwv+6, 0);
8196 num_locks = SVAL(req->vwv+7, 0);
8197 lock_timeout = IVAL(req->vwv+4, 0);
8198 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8199
8200 if (!check_fsp(conn, req, fsp)) {
8201 END_PROFILE(SMBlockingX);
8202 return;
8203 }
8204
8205 data = req->buf;
8206
8207 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8208 /* we don't support these - and CANCEL_LOCK makes w2k
8209 and XP reboot so I don't really want to be
8210 compatible! (tridge) */
8211 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8212 END_PROFILE(SMBlockingX);
8213 return;
8214 }
8215
8216 /* Check if this is an oplock break on a file
8217 we have granted an oplock on.
8218 */
8219 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8220 /* Client can insist on breaking to none. */
8221 bool break_to_none = (oplocklevel == 0);
8222 bool result;
8223
8224 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8225 "for %s\n", (unsigned int)oplocklevel,
8226 fsp_fnum_dbg(fsp)));
8227
8228 /*
8229 * Make sure we have granted an exclusive or batch oplock on
8230 * this file.
8231 */
8232
8233 if (fsp->oplock_type == 0) {
8234
8235 /* The Samba4 nbench simulator doesn't understand
8236 the difference between break to level2 and break
8237 to none from level2 - it sends oplock break
8238 replies in both cases. Don't keep logging an error
8239 message here - just ignore it. JRA. */
8240
8241 DEBUG(5,("reply_lockingX: Error : oplock break from "
8242 "client for %s (oplock=%d) and no "
8243 "oplock granted on this file (%s).\n",
8244 fsp_fnum_dbg(fsp), fsp->oplock_type,
8245 fsp_str_dbg(fsp)));
8246
8247 /* if this is a pure oplock break request then don't
8248 * send a reply */
8249 if (num_locks == 0 && num_ulocks == 0) {
8250 END_PROFILE(SMBlockingX);
8251 return;
8252 } else {
8253 END_PROFILE(SMBlockingX);
8254 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8255 return;
8256 }
8257 }
8258
8259 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8260 (break_to_none)) {
8261 result = remove_oplock(fsp);
8262 } else {
8263 result = downgrade_oplock(fsp);
8264 }
8265
8266 if (!result) {
8267 DEBUG(0, ("reply_lockingX: error in removing "
8268 "oplock on file %s\n", fsp_str_dbg(fsp)));
8269 /* Hmmm. Is this panic justified? */
8270 smb_panic("internal tdb error");
8271 }
8272
8273 /* if this is a pure oplock break request then don't send a
8274 * reply */
8275 if (num_locks == 0 && num_ulocks == 0) {
8276 /* Sanity check - ensure a pure oplock break is not a
8277 chained request. */
8278 if (CVAL(req->vwv+0, 0) != 0xff) {
8279 DEBUG(0,("reply_lockingX: Error : pure oplock "
8280 "break is a chained %d request !\n",
8281 (unsigned int)CVAL(req->vwv+0, 0)));
8282 }
8283 END_PROFILE(SMBlockingX);
8284 return;
8285 }
8286 }
8287
8288 if (req->buflen <
8289 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8291 END_PROFILE(SMBlockingX);
8292 return;
8293 }
8294
8295 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8296 if (ulocks == NULL) {
8297 reply_nterror(req, NT_STATUS_NO_MEMORY);
8298 END_PROFILE(SMBlockingX);
8299 return;
8300 }
8301
8302 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8303 if (locks == NULL) {
8304 reply_nterror(req, NT_STATUS_NO_MEMORY);
8305 END_PROFILE(SMBlockingX);
8306 return;
8307 }
8308
8309 /* Data now points at the beginning of the list
8310 of smb_unlkrng structs */
8311 for(i = 0; i < (int)num_ulocks; i++) {
8312 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8313 ulocks[i].count = get_lock_count(data, i, large_file_format);
8314 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8315 ulocks[i].brltype = UNLOCK_LOCK;
8316 }
8317
8318 /* Now do any requested locks */
8319 data += ((large_file_format ? 20 : 10)*num_ulocks);
8320
8321 /* Data now points at the beginning of the list
8322 of smb_lkrng structs */
8323
8324 for(i = 0; i < (int)num_locks; i++) {
8325 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8326 locks[i].count = get_lock_count(data, i, large_file_format);
8327 locks[i].offset = get_lock_offset(data, i, large_file_format);
8328
8329 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8330 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8331 locks[i].brltype = PENDING_READ_LOCK;
8332 } else {
8333 locks[i].brltype = READ_LOCK;
8334 }
8335 } else {
8336 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8337 locks[i].brltype = PENDING_WRITE_LOCK;
8338 } else {
8339 locks[i].brltype = WRITE_LOCK;
8340 }
8341 }
8342 }
8343
8344 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8345 if (!NT_STATUS_IS_OK(status)) {
8346 END_PROFILE(SMBlockingX);
8347 reply_nterror(req, status);
8348 return;
8349 }
8350
8351 status = smbd_do_locking(req, fsp,
8352 locktype, lock_timeout,
8353 num_locks, locks,
8354 &async);
8355 if (!NT_STATUS_IS_OK(status)) {
8356 END_PROFILE(SMBlockingX);
8357 reply_nterror(req, status);
8358 return;
8359 }
8360 if (async) {
8361 END_PROFILE(SMBlockingX);
8362 return;
8363 }
8364
8365 reply_outbuf(req, 2, 0);
8366 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8367 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8368
8369 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8370 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8371
8372 END_PROFILE(SMBlockingX);
8373}
8374
8375#undef DBGC_CLASS
8376#define DBGC_CLASS DBGC_ALL
8377
8378/****************************************************************************
8379 Reply to a SMBreadbmpx (read block multiplex) request.
8380 Always reply with an error, if someone has a platform really needs this,
8381 please contact vl@samba.org
8382****************************************************************************/
8383
8384void reply_readbmpx(struct smb_request *req)
8385{
8386 START_PROFILE(SMBreadBmpx);
8387 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8388 END_PROFILE(SMBreadBmpx);
8389 return;
8390}
8391
8392/****************************************************************************
8393 Reply to a SMBreadbs (read block multiplex secondary) request.
8394 Always reply with an error, if someone has a platform really needs this,
8395 please contact vl@samba.org
8396****************************************************************************/
8397
8398void reply_readbs(struct smb_request *req)
8399{
8400 START_PROFILE(SMBreadBs);
8401 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8402 END_PROFILE(SMBreadBs);
8403 return;
8404}
8405
8406/****************************************************************************
8407 Reply to a SMBsetattrE.
8408****************************************************************************/
8409
8410void reply_setattrE(struct smb_request *req)
8411{
8412 connection_struct *conn = req->conn;
8413 struct smb_file_time ft;
8414 files_struct *fsp;
8415 NTSTATUS status;
8416
8417 START_PROFILE(SMBsetattrE);
8418 ZERO_STRUCT(ft);
8419
8420 if (req->wct < 7) {
8421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8422 goto out;
8423 }
8424
8425 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8426
8427 if(!fsp || (fsp->conn != conn)) {
8428 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8429 goto out;
8430 }
8431
8432 /*
8433 * Convert the DOS times into unix times.
8434 */
8435
8436 ft.atime = convert_time_t_to_timespec(
8437 srv_make_unix_date2(req->vwv+3));
8438 ft.mtime = convert_time_t_to_timespec(
8439 srv_make_unix_date2(req->vwv+5));
8440 ft.create_time = convert_time_t_to_timespec(
8441 srv_make_unix_date2(req->vwv+1));
8442
8443 reply_outbuf(req, 0, 0);
8444
8445 /*
8446 * Patch from Ray Frush <frush@engr.colostate.edu>
8447 * Sometimes times are sent as zero - ignore them.
8448 */
8449
8450 /* Ensure we have a valid stat struct for the source. */
8451 status = vfs_stat_fsp(fsp);
8452 if (!NT_STATUS_IS_OK(status)) {
8453 reply_nterror(req, status);
8454 goto out;
8455 }
8456
8457 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8458 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8459 goto out;
8460 }
8461
8462 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8463 if (!NT_STATUS_IS_OK(status)) {
8464 reply_nterror(req, status);
8465 goto out;
8466 }
8467
8468 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8469 " createtime=%u\n",
8470 fsp_fnum_dbg(fsp),
8471 (unsigned int)ft.atime.tv_sec,
8472 (unsigned int)ft.mtime.tv_sec,
8473 (unsigned int)ft.create_time.tv_sec
8474 ));
8475 out:
8476 END_PROFILE(SMBsetattrE);
8477 return;
8478}
8479
8480
8481/* Back from the dead for OS/2..... JRA. */
8482
8483/****************************************************************************
8484 Reply to a SMBwritebmpx (write block multiplex primary) request.
8485 Always reply with an error, if someone has a platform really needs this,
8486 please contact vl@samba.org
8487****************************************************************************/
8488
8489void reply_writebmpx(struct smb_request *req)
8490{
8491 START_PROFILE(SMBwriteBmpx);
8492 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8493 END_PROFILE(SMBwriteBmpx);
8494 return;
8495}
8496
8497/****************************************************************************
8498 Reply to a SMBwritebs (write block multiplex secondary) request.
8499 Always reply with an error, if someone has a platform really needs this,
8500 please contact vl@samba.org
8501****************************************************************************/
8502
8503void reply_writebs(struct smb_request *req)
8504{
8505 START_PROFILE(SMBwriteBs);
8506 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8507 END_PROFILE(SMBwriteBs);
8508 return;
8509}
8510
8511/****************************************************************************
8512 Reply to a SMBgetattrE.
8513****************************************************************************/
8514
8515void reply_getattrE(struct smb_request *req)
8516{
8517 connection_struct *conn = req->conn;
8518 int mode;
8519 files_struct *fsp;
8520 struct timespec create_ts;
8521
8522 START_PROFILE(SMBgetattrE);
8523
8524 if (req->wct < 1) {
8525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8526 END_PROFILE(SMBgetattrE);
8527 return;
8528 }
8529
8530 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8531
8532 if(!fsp || (fsp->conn != conn)) {
8533 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8534 END_PROFILE(SMBgetattrE);
8535 return;
8536 }
8537
8538 /* Do an fstat on this file */
8539 if(fsp_stat(fsp)) {
8540 reply_nterror(req, map_nt_error_from_unix(errno));
8541 END_PROFILE(SMBgetattrE);
8542 return;
8543 }
8544
8545 mode = dos_mode(conn, fsp->fsp_name);
8546
8547 /*
8548 * Convert the times into dos times. Set create
8549 * date to be last modify date as UNIX doesn't save
8550 * this.
8551 */
8552
8553 reply_outbuf(req, 11, 0);
8554
8555 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8556 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8557 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8558 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8559 /* Should we check pending modtime here ? JRA */
8560 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8561 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8562
8563 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8564 SIVAL(req->outbuf, smb_vwv6, 0);
8565 SIVAL(req->outbuf, smb_vwv8, 0);
8566 } else {
8567 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8568 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8569 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8570 }
8571 SSVAL(req->outbuf,smb_vwv10, mode);
8572
8573 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8574
8575 END_PROFILE(SMBgetattrE);
8576 return;
8577}
Note: See TracBrowser for help on using the repository browser.