s3:smbd: move sconn->smb1.negprot.* to xconn->smb1.negprot.*
[Samba.git] / source3 / smbd / reply.c
blob72f493194a022c230057d0f03b44b33c53caa8da
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
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.
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.
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/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
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"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
52 set.
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS check_path_syntax_internal(char *path,
59 bool posix_path,
60 bool *p_last_component_contains_wcard)
62 char *d = path;
63 const char *s = path;
64 NTSTATUS ret = NT_STATUS_OK;
65 bool start_of_name_component = True;
66 bool stream_started = false;
68 *p_last_component_contains_wcard = False;
70 while (*s) {
71 if (stream_started) {
72 switch (*s) {
73 case '/':
74 case '\\':
75 return NT_STATUS_OBJECT_NAME_INVALID;
76 case ':':
77 if (s[1] == '\0') {
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 if (strchr_m(&s[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 break;
87 if ((*s == ':') && !posix_path && !stream_started) {
88 if (*p_last_component_contains_wcard) {
89 return NT_STATUS_OBJECT_NAME_INVALID;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
95 JRA.
97 stream_started = true;
98 start_of_name_component = false;
99 posix_path = true;
101 if (s[1] == '\0') {
102 return NT_STATUS_OBJECT_NAME_INVALID;
106 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s,posix_path)) {
113 s++;
115 if ((d != path) && (*s != '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
117 *d++ = '/';
120 start_of_name_component = True;
121 /* New component. */
122 *p_last_component_contains_wcard = False;
123 continue;
126 if (start_of_name_component) {
127 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d > path) && (*(d-1) == '/')) {
136 *(d-1) = '\0';
137 d--;
140 /* Are we at the start ? Can't go back further if so. */
141 if (d <= path) {
142 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
143 break;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d--; d > path; d--) {
150 if (*d == '/')
151 break;
153 s += 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
155 continue;
157 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
158 if (posix_path) {
159 /* Eat the '.' */
160 s++;
161 continue;
167 if (!(*s & 0x80)) {
168 if (!posix_path) {
169 if (*s <= 0x1f || *s == '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID;
172 switch (*s) {
173 case '*':
174 case '?':
175 case '<':
176 case '>':
177 case '"':
178 *p_last_component_contains_wcard = True;
179 break;
180 default:
181 break;
184 *d++ = *s++;
185 } else {
186 size_t siz;
187 /* Get the size of the next MB character. */
188 next_codepoint(s,&siz);
189 switch(siz) {
190 case 5:
191 *d++ = *s++;
192 /*fall through*/
193 case 4:
194 *d++ = *s++;
195 /*fall through*/
196 case 3:
197 *d++ = *s++;
198 /*fall through*/
199 case 2:
200 *d++ = *s++;
201 /*fall through*/
202 case 1:
203 *d++ = *s++;
204 break;
205 default:
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
207 *d = '\0';
208 return NT_STATUS_INVALID_PARAMETER;
211 start_of_name_component = False;
214 *d = '\0';
216 return ret;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax(char *path)
226 bool ignore;
227 return check_path_syntax_internal(path, False, &ignore);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
233 a wildcard.
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238 return check_path_syntax_internal(path, False, p_contains_wcard);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS check_path_syntax_posix(char *path)
249 bool ignore;
250 return check_path_syntax_internal(path, True, &ignore);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
258 const char *base_ptr,
259 uint16 smb_flags2,
260 char **pp_dest,
261 const char *src,
262 size_t src_len,
263 int flags,
264 NTSTATUS *err,
265 bool *contains_wcard)
267 size_t ret;
269 *pp_dest = NULL;
271 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
272 src_len, flags);
274 if (!*pp_dest) {
275 *err = NT_STATUS_INVALID_PARAMETER;
276 return ret;
279 *contains_wcard = False;
281 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
286 *err = NT_STATUS_OK;
287 return ret;
290 if (lp_posix_pathnames()) {
291 *err = check_path_syntax_posix(*pp_dest);
292 } else {
293 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
296 return ret;
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX *ctx,
304 const char *base_ptr,
305 uint16 smb_flags2,
306 char **pp_dest,
307 const char *src,
308 size_t src_len,
309 int flags,
310 NTSTATUS *err)
312 bool ignore;
313 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
314 src_len, flags, err, &ignore);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
318 char **pp_dest, const char *src, int flags,
319 NTSTATUS *err, bool *contains_wcard)
321 ssize_t bufrem = smbreq_bufrem(req, src);
323 if (bufrem < 0) {
324 *err = NT_STATUS_INVALID_PARAMETER;
325 return 0;
328 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf,
329 req->flags2, pp_dest, src, bufrem, flags,
330 err, contains_wcard);
333 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
334 char **pp_dest, const char *src, int flags,
335 NTSTATUS *err)
337 bool ignore;
338 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
339 flags, err, &ignore);
343 * pull a string from the smb_buf part of a packet. In this case the
344 * string can either be null terminated or it can be terminated by the
345 * end of the smbbuf area
347 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
348 char **dest, const uint8_t *src, int flags)
350 ssize_t bufrem = smbreq_bufrem(req, src);
352 if (bufrem < 0) {
353 return 0;
356 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
357 bufrem, flags);
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
362 ****************************************************************************/
364 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
365 files_struct *fsp)
367 if ((fsp == NULL) || (conn == NULL)) {
368 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
369 return False;
371 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
372 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
373 return False;
375 return True;
378 /****************************************************************************
379 Check if we have a correct fsp pointing to a file.
380 ****************************************************************************/
382 bool check_fsp(connection_struct *conn, struct smb_request *req,
383 files_struct *fsp)
385 if (!check_fsp_open(conn, req, fsp)) {
386 return False;
388 if (fsp->is_directory) {
389 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
390 return False;
392 if (fsp->fh->fd == -1) {
393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
394 return False;
396 fsp->num_smb_operations++;
397 return True;
400 /****************************************************************************
401 Check if we have a correct fsp pointing to a quota fake file. Replacement for
402 the CHECK_NTQUOTA_HANDLE_OK macro.
403 ****************************************************************************/
405 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
406 files_struct *fsp)
408 if (!check_fsp_open(conn, req, fsp)) {
409 return false;
412 if (fsp->is_directory) {
413 return false;
416 if (fsp->fake_file_handle == NULL) {
417 return false;
420 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
421 return false;
424 if (fsp->fake_file_handle->private_data == NULL) {
425 return false;
428 return true;
431 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
432 const char *name, int name_type)
434 struct smbXsrv_connection *xconn = sconn->conn;
435 char *trim_name;
436 char *trim_name_type;
437 const char *retarget_parm;
438 char *retarget;
439 char *p;
440 int retarget_type = 0x20;
441 int retarget_port = NBT_SMB_PORT;
442 struct sockaddr_storage retarget_addr;
443 struct sockaddr_in *in_addr;
444 bool ret = false;
445 uint8_t outbuf[10];
447 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
448 return false;
451 trim_name = talloc_strdup(talloc_tos(), name);
452 if (trim_name == NULL) {
453 goto fail;
455 trim_char(trim_name, ' ', ' ');
457 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
458 name_type);
459 if (trim_name_type == NULL) {
460 goto fail;
463 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
464 trim_name_type, NULL);
465 if (retarget_parm == NULL) {
466 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
467 trim_name, NULL);
469 if (retarget_parm == NULL) {
470 goto fail;
473 retarget = talloc_strdup(trim_name, retarget_parm);
474 if (retarget == NULL) {
475 goto fail;
478 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
480 p = strchr(retarget, ':');
481 if (p != NULL) {
482 *p++ = '\0';
483 retarget_port = atoi(p);
486 p = strchr_m(retarget, '#');
487 if (p != NULL) {
488 *p++ = '\0';
489 if (sscanf(p, "%x", &retarget_type) != 1) {
490 goto fail;
494 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
495 if (!ret) {
496 DEBUG(10, ("could not resolve %s\n", retarget));
497 goto fail;
500 if (retarget_addr.ss_family != AF_INET) {
501 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
502 goto fail;
505 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
507 _smb_setlen(outbuf, 6);
508 SCVAL(outbuf, 0, 0x84);
509 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
510 *(uint16_t *)(outbuf+8) = htons(retarget_port);
512 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
513 NULL)) {
514 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
515 "failed.");
518 ret = true;
519 fail:
520 TALLOC_FREE(trim_name);
521 return ret;
524 static void reply_called_name_not_present(char *outbuf)
526 smb_setlen(outbuf, 1);
527 SCVAL(outbuf, 0, 0x83);
528 SCVAL(outbuf, 4, 0x82);
531 /****************************************************************************
532 Reply to a (netbios-level) special message.
533 ****************************************************************************/
535 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
537 struct smbXsrv_connection *xconn = sconn->conn;
538 int msg_type = CVAL(inbuf,0);
539 int msg_flags = CVAL(inbuf,1);
541 * We only really use 4 bytes of the outbuf, but for the smb_setlen
542 * calculation & friends (srv_send_smb uses that) we need the full smb
543 * header.
545 char outbuf[smb_size];
547 memset(outbuf, '\0', sizeof(outbuf));
549 smb_setlen(outbuf,0);
551 switch (msg_type) {
552 case NBSSrequest: /* session request */
554 /* inbuf_size is guarenteed to be at least 4. */
555 fstring name1,name2;
556 int name_type1, name_type2;
557 int name_len1, name_len2;
559 *name1 = *name2 = 0;
561 if (xconn->transport.nbt.got_session) {
562 exit_server_cleanly("multiple session request not permitted");
565 SCVAL(outbuf,0,NBSSpositive);
566 SCVAL(outbuf,3,0);
568 /* inbuf_size is guaranteed to be at least 4. */
569 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
570 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
571 DEBUG(0,("Invalid name length in session request\n"));
572 reply_called_name_not_present(outbuf);
573 break;
575 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
576 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
577 DEBUG(0,("Invalid name length in session request\n"));
578 reply_called_name_not_present(outbuf);
579 break;
582 name_type1 = name_extract((unsigned char *)inbuf,
583 inbuf_size,(unsigned int)4,name1);
584 name_type2 = name_extract((unsigned char *)inbuf,
585 inbuf_size,(unsigned int)(4 + name_len1),name2);
587 if (name_type1 == -1 || name_type2 == -1) {
588 DEBUG(0,("Invalid name type in session request\n"));
589 reply_called_name_not_present(outbuf);
590 break;
593 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
594 name1, name_type1, name2, name_type2));
596 if (netbios_session_retarget(sconn, name1, name_type1)) {
597 exit_server_cleanly("retargeted client");
601 * Windows NT/2k uses "*SMBSERVER" and XP uses
602 * "*SMBSERV" arrggg!!!
604 if (strequal(name1, "*SMBSERVER ")
605 || strequal(name1, "*SMBSERV ")) {
606 char *raddr;
608 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
609 talloc_tos());
610 if (raddr == NULL) {
611 exit_server_cleanly("could not allocate raddr");
614 fstrcpy(name1, raddr);
617 set_local_machine_name(name1, True);
618 set_remote_machine_name(name2, True);
620 if (is_ipaddress(sconn->remote_hostname)) {
621 char *p = discard_const_p(char, sconn->remote_hostname);
623 talloc_free(p);
625 sconn->remote_hostname = talloc_strdup(sconn,
626 get_remote_machine_name());
627 if (sconn->remote_hostname == NULL) {
628 exit_server_cleanly("could not copy remote name");
630 sconn->conn->remote_hostname = sconn->remote_hostname;
633 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
634 get_local_machine_name(), get_remote_machine_name(),
635 name_type2));
637 if (name_type2 == 'R') {
638 /* We are being asked for a pathworks session ---
639 no thanks! */
640 reply_called_name_not_present(outbuf);
641 break;
644 reload_services(sconn, conn_snum_used, true);
645 reopen_logs();
647 xconn->transport.nbt.got_session = true;
648 break;
651 case 0x89: /* session keepalive request
652 (some old clients produce this?) */
653 SCVAL(outbuf,0,NBSSkeepalive);
654 SCVAL(outbuf,3,0);
655 break;
657 case NBSSpositive: /* positive session response */
658 case NBSSnegative: /* negative session response */
659 case NBSSretarget: /* retarget session response */
660 DEBUG(0,("Unexpected session response\n"));
661 break;
663 case NBSSkeepalive: /* session keepalive */
664 default:
665 return;
668 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
669 msg_type, msg_flags));
671 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
673 if (CVAL(outbuf, 0) != 0x82) {
674 exit_server_cleanly("invalid netbios session");
676 return;
679 /****************************************************************************
680 Reply to a tcon.
681 conn POINTER CAN BE NULL HERE !
682 ****************************************************************************/
684 void reply_tcon(struct smb_request *req)
686 connection_struct *conn = req->conn;
687 const char *service;
688 char *service_buf = NULL;
689 char *password = NULL;
690 char *dev = NULL;
691 int pwlen=0;
692 NTSTATUS nt_status;
693 const uint8_t *p;
694 const char *p2;
695 TALLOC_CTX *ctx = talloc_tos();
696 struct smbd_server_connection *sconn = req->sconn;
697 struct smbXsrv_connection *xconn = sconn->conn;
698 NTTIME now = timeval_to_nttime(&req->request_time);
700 START_PROFILE(SMBtcon);
702 if (req->buflen < 4) {
703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
704 END_PROFILE(SMBtcon);
705 return;
708 p = req->buf + 1;
709 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
710 p += 1;
711 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
712 p += pwlen+1;
713 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
714 p += 1;
716 if (service_buf == NULL || password == NULL || dev == NULL) {
717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
718 END_PROFILE(SMBtcon);
719 return;
721 p2 = strrchr_m(service_buf,'\\');
722 if (p2) {
723 service = p2+1;
724 } else {
725 service = service_buf;
728 conn = make_connection(sconn, now, service, dev,
729 req->vuid,&nt_status);
730 req->conn = conn;
732 if (!conn) {
733 reply_nterror(req, nt_status);
734 END_PROFILE(SMBtcon);
735 return;
738 reply_outbuf(req, 2, 0);
739 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
740 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
741 SSVAL(req->outbuf,smb_tid,conn->cnum);
743 DEBUG(3,("tcon service=%s cnum=%d\n",
744 service, conn->cnum));
746 END_PROFILE(SMBtcon);
747 return;
750 /****************************************************************************
751 Reply to a tcon and X.
752 conn POINTER CAN BE NULL HERE !
753 ****************************************************************************/
755 void reply_tcon_and_X(struct smb_request *req)
757 connection_struct *conn = req->conn;
758 const char *service = NULL;
759 TALLOC_CTX *ctx = talloc_tos();
760 /* what the cleint thinks the device is */
761 char *client_devicetype = NULL;
762 /* what the server tells the client the share represents */
763 const char *server_devicetype;
764 NTSTATUS nt_status;
765 int passlen;
766 char *path = NULL;
767 const uint8_t *p;
768 const char *q;
769 uint16_t tcon_flags;
770 struct smbXsrv_session *session = NULL;
771 NTTIME now = timeval_to_nttime(&req->request_time);
772 bool session_key_updated = false;
773 uint16_t optional_support = 0;
774 struct smbd_server_connection *sconn = req->sconn;
775 struct smbXsrv_connection *xconn = sconn->conn;
777 START_PROFILE(SMBtconX);
779 if (req->wct < 4) {
780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
781 END_PROFILE(SMBtconX);
782 return;
785 passlen = SVAL(req->vwv+3, 0);
786 tcon_flags = SVAL(req->vwv+2, 0);
788 /* we might have to close an old one */
789 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
790 struct smbXsrv_tcon *tcon;
791 NTSTATUS status;
793 tcon = conn->tcon;
794 req->conn = NULL;
795 conn = NULL;
798 * TODO: cancel all outstanding requests on the tcon
800 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
801 if (!NT_STATUS_IS_OK(status)) {
802 DEBUG(0, ("reply_tcon_and_X: "
803 "smbXsrv_tcon_disconnect() failed: %s\n",
804 nt_errstr(status)));
806 * If we hit this case, there is something completely
807 * wrong, so we better disconnect the transport connection.
809 END_PROFILE(SMBtconX);
810 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
811 return;
814 TALLOC_FREE(tcon);
817 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
818 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
819 END_PROFILE(SMBtconX);
820 return;
823 if (xconn->smb1.negprot.encrypted_passwords) {
824 p = req->buf + passlen;
825 } else {
826 p = req->buf + passlen + 1;
829 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
831 if (path == NULL) {
832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833 END_PROFILE(SMBtconX);
834 return;
838 * the service name can be either: \\server\share
839 * or share directly like on the DELL PowerVault 705
841 if (*path=='\\') {
842 q = strchr_m(path+2,'\\');
843 if (!q) {
844 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
845 END_PROFILE(SMBtconX);
846 return;
848 service = q+1;
849 } else {
850 service = path;
853 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
854 &client_devicetype, p,
855 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
857 if (client_devicetype == NULL) {
858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
859 END_PROFILE(SMBtconX);
860 return;
863 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
865 nt_status = smb1srv_session_lookup(req->sconn->conn,
866 req->vuid, now, &session);
867 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
868 reply_force_doserror(req, ERRSRV, ERRbaduid);
869 END_PROFILE(SMBtconX);
870 return;
872 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
873 reply_nterror(req, nt_status);
874 END_PROFILE(SMBtconX);
875 return;
877 if (!NT_STATUS_IS_OK(nt_status)) {
878 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
879 END_PROFILE(SMBtconX);
880 return;
883 if (session->global->auth_session_info == NULL) {
884 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
885 END_PROFILE(SMBtconX);
886 return;
890 * If there is no application key defined yet
891 * we create one.
893 * This means we setup the application key on the
894 * first tcon that happens via the given session.
896 * Once the application key is defined, it does not
897 * change any more.
899 if (session->global->application_key.length == 0 &&
900 session->global->signing_key.length > 0)
902 struct smbXsrv_session *x = session;
903 struct auth_session_info *session_info =
904 session->global->auth_session_info;
905 uint8_t session_key[16];
907 ZERO_STRUCT(session_key);
908 memcpy(session_key, x->global->signing_key.data,
909 MIN(x->global->signing_key.length, sizeof(session_key)));
912 * The application key is truncated/padded to 16 bytes
914 x->global->application_key = data_blob_talloc(x->global,
915 session_key,
916 sizeof(session_key));
917 ZERO_STRUCT(session_key);
918 if (x->global->application_key.data == NULL) {
919 reply_nterror(req, NT_STATUS_NO_MEMORY);
920 END_PROFILE(SMBtconX);
921 return;
924 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
925 smb_key_derivation(x->global->application_key.data,
926 x->global->application_key.length,
927 x->global->application_key.data);
928 optional_support |= SMB_EXTENDED_SIGNATURES;
932 * Place the application key into the session_info
934 data_blob_clear_free(&session_info->session_key);
935 session_info->session_key = data_blob_dup_talloc(session_info,
936 x->global->application_key);
937 if (session_info->session_key.data == NULL) {
938 data_blob_clear_free(&x->global->application_key);
939 reply_nterror(req, NT_STATUS_NO_MEMORY);
940 END_PROFILE(SMBtconX);
941 return;
943 session_key_updated = true;
946 conn = make_connection(sconn, now, service, client_devicetype,
947 req->vuid, &nt_status);
948 req->conn =conn;
950 if (!conn) {
951 if (session_key_updated) {
952 struct smbXsrv_session *x = session;
953 struct auth_session_info *session_info =
954 session->global->auth_session_info;
955 data_blob_clear_free(&x->global->application_key);
956 data_blob_clear_free(&session_info->session_key);
958 reply_nterror(req, nt_status);
959 END_PROFILE(SMBtconX);
960 return;
963 if ( IS_IPC(conn) )
964 server_devicetype = "IPC";
965 else if ( IS_PRINT(conn) )
966 server_devicetype = "LPT1:";
967 else
968 server_devicetype = "A:";
970 if (get_Protocol() < PROTOCOL_NT1) {
971 reply_outbuf(req, 2, 0);
972 if (message_push_string(&req->outbuf, server_devicetype,
973 STR_TERMINATE|STR_ASCII) == -1) {
974 reply_nterror(req, NT_STATUS_NO_MEMORY);
975 END_PROFILE(SMBtconX);
976 return;
978 } else {
979 /* NT sets the fstype of IPC$ to the null string */
980 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
982 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
983 /* Return permissions. */
984 uint32 perm1 = 0;
985 uint32 perm2 = 0;
987 reply_outbuf(req, 7, 0);
989 if (IS_IPC(conn)) {
990 perm1 = FILE_ALL_ACCESS;
991 perm2 = FILE_ALL_ACCESS;
992 } else {
993 perm1 = conn->share_access;
996 SIVAL(req->outbuf, smb_vwv3, perm1);
997 SIVAL(req->outbuf, smb_vwv5, perm2);
998 } else {
999 reply_outbuf(req, 3, 0);
1002 if ((message_push_string(&req->outbuf, server_devicetype,
1003 STR_TERMINATE|STR_ASCII) == -1)
1004 || (message_push_string(&req->outbuf, fstype,
1005 STR_TERMINATE) == -1)) {
1006 reply_nterror(req, NT_STATUS_NO_MEMORY);
1007 END_PROFILE(SMBtconX);
1008 return;
1011 /* what does setting this bit do? It is set by NT4 and
1012 may affect the ability to autorun mounted cdroms */
1013 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1014 optional_support |=
1015 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1017 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1018 DEBUG(2,("Serving %s as a Dfs root\n",
1019 lp_servicename(ctx, SNUM(conn)) ));
1020 optional_support |= SMB_SHARE_IN_DFS;
1023 SSVAL(req->outbuf, smb_vwv2, optional_support);
1026 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1027 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1029 DEBUG(3,("tconX service=%s \n",
1030 service));
1032 /* set the incoming and outgoing tid to the just created one */
1033 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1034 SSVAL(req->outbuf,smb_tid,conn->cnum);
1036 END_PROFILE(SMBtconX);
1038 req->tid = conn->cnum;
1041 /****************************************************************************
1042 Reply to an unknown type.
1043 ****************************************************************************/
1045 void reply_unknown_new(struct smb_request *req, uint8 type)
1047 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1048 smb_fn_name(type), type, type));
1049 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1050 return;
1053 /****************************************************************************
1054 Reply to an ioctl.
1055 conn POINTER CAN BE NULL HERE !
1056 ****************************************************************************/
1058 void reply_ioctl(struct smb_request *req)
1060 connection_struct *conn = req->conn;
1061 uint16 device;
1062 uint16 function;
1063 uint32 ioctl_code;
1064 int replysize;
1065 char *p;
1067 START_PROFILE(SMBioctl);
1069 if (req->wct < 3) {
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1071 END_PROFILE(SMBioctl);
1072 return;
1075 device = SVAL(req->vwv+1, 0);
1076 function = SVAL(req->vwv+2, 0);
1077 ioctl_code = (device << 16) + function;
1079 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1081 switch (ioctl_code) {
1082 case IOCTL_QUERY_JOB_INFO:
1083 replysize = 32;
1084 break;
1085 default:
1086 reply_force_doserror(req, ERRSRV, ERRnosupport);
1087 END_PROFILE(SMBioctl);
1088 return;
1091 reply_outbuf(req, 8, replysize+1);
1092 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1093 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1094 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1095 p = smb_buf(req->outbuf);
1096 memset(p, '\0', replysize+1); /* valgrind-safe. */
1097 p += 1; /* Allow for alignment */
1099 switch (ioctl_code) {
1100 case IOCTL_QUERY_JOB_INFO:
1102 files_struct *fsp = file_fsp(
1103 req, SVAL(req->vwv+0, 0));
1104 if (!fsp) {
1105 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1106 END_PROFILE(SMBioctl);
1107 return;
1109 /* Job number */
1110 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1112 srvstr_push((char *)req->outbuf, req->flags2, p+2,
1113 lp_netbios_name(), 15,
1114 STR_TERMINATE|STR_ASCII);
1115 if (conn) {
1116 srvstr_push((char *)req->outbuf, req->flags2,
1117 p+18,
1118 lp_servicename(talloc_tos(),
1119 SNUM(conn)),
1120 13, STR_TERMINATE|STR_ASCII);
1121 } else {
1122 memset(p+18, 0, 13);
1124 break;
1128 END_PROFILE(SMBioctl);
1129 return;
1132 /****************************************************************************
1133 Strange checkpath NTSTATUS mapping.
1134 ****************************************************************************/
1136 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1138 /* Strange DOS error code semantics only for checkpath... */
1139 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1140 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1141 /* We need to map to ERRbadpath */
1142 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1145 return status;
1148 /****************************************************************************
1149 Reply to a checkpath.
1150 ****************************************************************************/
1152 void reply_checkpath(struct smb_request *req)
1154 connection_struct *conn = req->conn;
1155 struct smb_filename *smb_fname = NULL;
1156 char *name = NULL;
1157 NTSTATUS status;
1158 TALLOC_CTX *ctx = talloc_tos();
1160 START_PROFILE(SMBcheckpath);
1162 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1163 STR_TERMINATE, &status);
1165 if (!NT_STATUS_IS_OK(status)) {
1166 status = map_checkpath_error(req->flags2, status);
1167 reply_nterror(req, status);
1168 END_PROFILE(SMBcheckpath);
1169 return;
1172 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1174 status = filename_convert(ctx,
1175 conn,
1176 req->flags2 & FLAGS2_DFS_PATHNAMES,
1177 name,
1179 NULL,
1180 &smb_fname);
1182 if (!NT_STATUS_IS_OK(status)) {
1183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1184 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1185 ERRSRV, ERRbadpath);
1186 END_PROFILE(SMBcheckpath);
1187 return;
1189 goto path_err;
1192 if (!VALID_STAT(smb_fname->st) &&
1193 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1194 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1195 smb_fname_str_dbg(smb_fname), strerror(errno)));
1196 status = map_nt_error_from_unix(errno);
1197 goto path_err;
1200 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1201 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1202 ERRDOS, ERRbadpath);
1203 goto out;
1206 reply_outbuf(req, 0, 0);
1208 path_err:
1209 /* We special case this - as when a Windows machine
1210 is parsing a path is steps through the components
1211 one at a time - if a component fails it expects
1212 ERRbadpath, not ERRbadfile.
1214 status = map_checkpath_error(req->flags2, status);
1215 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1217 * Windows returns different error codes if
1218 * the parent directory is valid but not the
1219 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1220 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1221 * if the path is invalid.
1223 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1224 ERRDOS, ERRbadpath);
1225 goto out;
1228 reply_nterror(req, status);
1230 out:
1231 TALLOC_FREE(smb_fname);
1232 END_PROFILE(SMBcheckpath);
1233 return;
1236 /****************************************************************************
1237 Reply to a getatr.
1238 ****************************************************************************/
1240 void reply_getatr(struct smb_request *req)
1242 connection_struct *conn = req->conn;
1243 struct smb_filename *smb_fname = NULL;
1244 char *fname = NULL;
1245 int mode=0;
1246 off_t size=0;
1247 time_t mtime=0;
1248 const char *p;
1249 NTSTATUS status;
1250 TALLOC_CTX *ctx = talloc_tos();
1251 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1253 START_PROFILE(SMBgetatr);
1255 p = (const char *)req->buf + 1;
1256 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 reply_nterror(req, status);
1259 goto out;
1262 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1263 under WfWg - weird! */
1264 if (*fname == '\0') {
1265 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1266 if (!CAN_WRITE(conn)) {
1267 mode |= FILE_ATTRIBUTE_READONLY;
1269 size = 0;
1270 mtime = 0;
1271 } else {
1272 status = filename_convert(ctx,
1273 conn,
1274 req->flags2 & FLAGS2_DFS_PATHNAMES,
1275 fname,
1277 NULL,
1278 &smb_fname);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1281 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1282 ERRSRV, ERRbadpath);
1283 goto out;
1285 reply_nterror(req, status);
1286 goto out;
1288 if (!VALID_STAT(smb_fname->st) &&
1289 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1290 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1291 smb_fname_str_dbg(smb_fname),
1292 strerror(errno)));
1293 reply_nterror(req, map_nt_error_from_unix(errno));
1294 goto out;
1297 mode = dos_mode(conn, smb_fname);
1298 size = smb_fname->st.st_ex_size;
1300 if (ask_sharemode) {
1301 struct timespec write_time_ts;
1302 struct file_id fileid;
1304 ZERO_STRUCT(write_time_ts);
1305 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1306 get_file_infos(fileid, 0, NULL, &write_time_ts);
1307 if (!null_timespec(write_time_ts)) {
1308 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1312 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1313 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1314 size = 0;
1318 reply_outbuf(req, 10, 0);
1320 SSVAL(req->outbuf,smb_vwv0,mode);
1321 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1322 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1323 } else {
1324 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1326 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1328 if (get_Protocol() >= PROTOCOL_NT1) {
1329 SSVAL(req->outbuf, smb_flg2,
1330 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1333 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1334 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1336 out:
1337 TALLOC_FREE(smb_fname);
1338 TALLOC_FREE(fname);
1339 END_PROFILE(SMBgetatr);
1340 return;
1343 /****************************************************************************
1344 Reply to a setatr.
1345 ****************************************************************************/
1347 void reply_setatr(struct smb_request *req)
1349 struct smb_file_time ft;
1350 connection_struct *conn = req->conn;
1351 struct smb_filename *smb_fname = NULL;
1352 char *fname = NULL;
1353 int mode;
1354 time_t mtime;
1355 const char *p;
1356 NTSTATUS status;
1357 TALLOC_CTX *ctx = talloc_tos();
1359 START_PROFILE(SMBsetatr);
1361 ZERO_STRUCT(ft);
1363 if (req->wct < 2) {
1364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1365 goto out;
1368 p = (const char *)req->buf + 1;
1369 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1370 if (!NT_STATUS_IS_OK(status)) {
1371 reply_nterror(req, status);
1372 goto out;
1375 status = filename_convert(ctx,
1376 conn,
1377 req->flags2 & FLAGS2_DFS_PATHNAMES,
1378 fname,
1380 NULL,
1381 &smb_fname);
1382 if (!NT_STATUS_IS_OK(status)) {
1383 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1384 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1385 ERRSRV, ERRbadpath);
1386 goto out;
1388 reply_nterror(req, status);
1389 goto out;
1392 if (smb_fname->base_name[0] == '.' &&
1393 smb_fname->base_name[1] == '\0') {
1395 * Not sure here is the right place to catch this
1396 * condition. Might be moved to somewhere else later -- vl
1398 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1399 goto out;
1402 mode = SVAL(req->vwv+0, 0);
1403 mtime = srv_make_unix_date3(req->vwv+1);
1405 if (mode != FILE_ATTRIBUTE_NORMAL) {
1406 if (VALID_STAT_OF_DIR(smb_fname->st))
1407 mode |= FILE_ATTRIBUTE_DIRECTORY;
1408 else
1409 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1411 status = check_access(conn, NULL, smb_fname,
1412 FILE_WRITE_ATTRIBUTES);
1413 if (!NT_STATUS_IS_OK(status)) {
1414 reply_nterror(req, status);
1415 goto out;
1418 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1419 false) != 0) {
1420 reply_nterror(req, map_nt_error_from_unix(errno));
1421 goto out;
1425 ft.mtime = convert_time_t_to_timespec(mtime);
1426 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1427 if (!NT_STATUS_IS_OK(status)) {
1428 reply_nterror(req, status);
1429 goto out;
1432 reply_outbuf(req, 0, 0);
1434 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1435 mode));
1436 out:
1437 TALLOC_FREE(smb_fname);
1438 END_PROFILE(SMBsetatr);
1439 return;
1442 /****************************************************************************
1443 Reply to a dskattr.
1444 ****************************************************************************/
1446 void reply_dskattr(struct smb_request *req)
1448 connection_struct *conn = req->conn;
1449 uint64_t dfree,dsize,bsize;
1450 START_PROFILE(SMBdskattr);
1452 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1453 reply_nterror(req, map_nt_error_from_unix(errno));
1454 END_PROFILE(SMBdskattr);
1455 return;
1458 reply_outbuf(req, 5, 0);
1460 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1461 double total_space, free_space;
1462 /* we need to scale this to a number that DOS6 can handle. We
1463 use floating point so we can handle large drives on systems
1464 that don't have 64 bit integers
1466 we end up displaying a maximum of 2G to DOS systems
1468 total_space = dsize * (double)bsize;
1469 free_space = dfree * (double)bsize;
1471 dsize = (uint64_t)((total_space+63*512) / (64*512));
1472 dfree = (uint64_t)((free_space+63*512) / (64*512));
1474 if (dsize > 0xFFFF) dsize = 0xFFFF;
1475 if (dfree > 0xFFFF) dfree = 0xFFFF;
1477 SSVAL(req->outbuf,smb_vwv0,dsize);
1478 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1479 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1480 SSVAL(req->outbuf,smb_vwv3,dfree);
1481 } else {
1482 SSVAL(req->outbuf,smb_vwv0,dsize);
1483 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1484 SSVAL(req->outbuf,smb_vwv2,512);
1485 SSVAL(req->outbuf,smb_vwv3,dfree);
1488 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1490 END_PROFILE(SMBdskattr);
1491 return;
1495 * Utility function to split the filename from the directory.
1497 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1498 char **fname_dir_out,
1499 char **fname_mask_out)
1501 const char *p = NULL;
1502 char *fname_dir = NULL;
1503 char *fname_mask = NULL;
1505 p = strrchr_m(fname_in, '/');
1506 if (!p) {
1507 fname_dir = talloc_strdup(ctx, ".");
1508 fname_mask = talloc_strdup(ctx, fname_in);
1509 } else {
1510 fname_dir = talloc_strndup(ctx, fname_in,
1511 PTR_DIFF(p, fname_in));
1512 fname_mask = talloc_strdup(ctx, p+1);
1515 if (!fname_dir || !fname_mask) {
1516 TALLOC_FREE(fname_dir);
1517 TALLOC_FREE(fname_mask);
1518 return NT_STATUS_NO_MEMORY;
1521 *fname_dir_out = fname_dir;
1522 *fname_mask_out = fname_mask;
1523 return NT_STATUS_OK;
1526 /****************************************************************************
1527 Reply to a search.
1528 Can be called from SMBsearch, SMBffirst or SMBfunique.
1529 ****************************************************************************/
1531 void reply_search(struct smb_request *req)
1533 connection_struct *conn = req->conn;
1534 char *path = NULL;
1535 const char *mask = NULL;
1536 char *directory = NULL;
1537 struct smb_filename *smb_fname = NULL;
1538 char *fname = NULL;
1539 off_t size;
1540 uint32 mode;
1541 struct timespec date;
1542 uint32 dirtype;
1543 unsigned int numentries = 0;
1544 unsigned int maxentries = 0;
1545 bool finished = False;
1546 const char *p;
1547 int status_len;
1548 char status[21];
1549 int dptr_num= -1;
1550 bool check_descend = False;
1551 bool expect_close = False;
1552 NTSTATUS nt_status;
1553 bool mask_contains_wcard = False;
1554 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1555 TALLOC_CTX *ctx = talloc_tos();
1556 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1557 struct dptr_struct *dirptr = NULL;
1558 struct smbd_server_connection *sconn = req->sconn;
1560 START_PROFILE(SMBsearch);
1562 if (req->wct < 2) {
1563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1564 goto out;
1567 if (lp_posix_pathnames()) {
1568 reply_unknown_new(req, req->cmd);
1569 goto out;
1572 /* If we were called as SMBffirst then we must expect close. */
1573 if(req->cmd == SMBffirst) {
1574 expect_close = True;
1577 reply_outbuf(req, 1, 3);
1578 maxentries = SVAL(req->vwv+0, 0);
1579 dirtype = SVAL(req->vwv+1, 0);
1580 p = (const char *)req->buf + 1;
1581 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1582 &nt_status, &mask_contains_wcard);
1583 if (!NT_STATUS_IS_OK(nt_status)) {
1584 reply_nterror(req, nt_status);
1585 goto out;
1588 p++;
1589 status_len = SVAL(p, 0);
1590 p += 2;
1592 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1594 if (status_len == 0) {
1595 nt_status = filename_convert(ctx, conn,
1596 req->flags2 & FLAGS2_DFS_PATHNAMES,
1597 path,
1598 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1599 &mask_contains_wcard,
1600 &smb_fname);
1601 if (!NT_STATUS_IS_OK(nt_status)) {
1602 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1603 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1604 ERRSRV, ERRbadpath);
1605 goto out;
1607 reply_nterror(req, nt_status);
1608 goto out;
1611 directory = smb_fname->base_name;
1613 p = strrchr_m(directory,'/');
1614 if ((p != NULL) && (*directory != '/')) {
1615 mask = p + 1;
1616 directory = talloc_strndup(ctx, directory,
1617 PTR_DIFF(p, directory));
1618 } else {
1619 mask = directory;
1620 directory = talloc_strdup(ctx,".");
1623 if (!directory) {
1624 reply_nterror(req, NT_STATUS_NO_MEMORY);
1625 goto out;
1628 memset((char *)status,'\0',21);
1629 SCVAL(status,0,(dirtype & 0x1F));
1631 nt_status = dptr_create(conn,
1632 NULL, /* req */
1633 NULL, /* fsp */
1634 directory,
1635 True,
1636 expect_close,
1637 req->smbpid,
1638 mask,
1639 mask_contains_wcard,
1640 dirtype,
1641 &dirptr);
1642 if (!NT_STATUS_IS_OK(nt_status)) {
1643 reply_nterror(req, nt_status);
1644 goto out;
1646 dptr_num = dptr_dnum(dirptr);
1647 } else {
1648 int status_dirtype;
1649 const char *dirpath;
1651 memcpy(status,p,21);
1652 status_dirtype = CVAL(status,0) & 0x1F;
1653 if (status_dirtype != (dirtype & 0x1F)) {
1654 dirtype = status_dirtype;
1657 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1658 if (!dirptr) {
1659 goto SearchEmpty;
1661 dirpath = dptr_path(sconn, dptr_num);
1662 directory = talloc_strdup(ctx, dirpath);
1663 if (!directory) {
1664 reply_nterror(req, NT_STATUS_NO_MEMORY);
1665 goto out;
1668 mask = dptr_wcard(sconn, dptr_num);
1669 if (!mask) {
1670 goto SearchEmpty;
1673 * For a 'continue' search we have no string. So
1674 * check from the initial saved string.
1676 mask_contains_wcard = ms_has_wild(mask);
1677 dirtype = dptr_attr(sconn, dptr_num);
1680 DEBUG(4,("dptr_num is %d\n",dptr_num));
1682 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1683 dptr_init_search_op(dirptr);
1685 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1686 char buf[DIR_STRUCT_SIZE];
1687 memcpy(buf,status,21);
1688 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1689 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1690 reply_nterror(req, NT_STATUS_NO_MEMORY);
1691 goto out;
1693 dptr_fill(sconn, buf+12,dptr_num);
1694 if (dptr_zero(buf+12) && (status_len==0)) {
1695 numentries = 1;
1696 } else {
1697 numentries = 0;
1699 if (message_push_blob(&req->outbuf,
1700 data_blob_const(buf, sizeof(buf)))
1701 == -1) {
1702 reply_nterror(req, NT_STATUS_NO_MEMORY);
1703 goto out;
1705 } else {
1706 unsigned int i;
1707 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1708 size_t available_space = sconn->smb1.sessions.max_send - hdr_size;
1710 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1712 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1713 directory,lp_dont_descend(ctx, SNUM(conn))));
1714 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1715 check_descend = True;
1718 for (i=numentries;(i<maxentries) && !finished;i++) {
1719 finished = !get_dir_entry(ctx,
1720 dirptr,
1721 mask,
1722 dirtype,
1723 &fname,
1724 &size,
1725 &mode,
1726 &date,
1727 check_descend,
1728 ask_sharemode);
1729 if (!finished) {
1730 char buf[DIR_STRUCT_SIZE];
1731 memcpy(buf,status,21);
1732 if (!make_dir_struct(ctx,
1733 buf,
1734 mask,
1735 fname,
1736 size,
1737 mode,
1738 convert_timespec_to_time_t(date),
1739 !allow_long_path_components)) {
1740 reply_nterror(req, NT_STATUS_NO_MEMORY);
1741 goto out;
1743 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1744 break;
1746 if (message_push_blob(&req->outbuf,
1747 data_blob_const(buf, sizeof(buf)))
1748 == -1) {
1749 reply_nterror(req, NT_STATUS_NO_MEMORY);
1750 goto out;
1752 numentries++;
1757 SearchEmpty:
1759 /* If we were called as SMBffirst with smb_search_id == NULL
1760 and no entries were found then return error and close dirptr
1761 (X/Open spec) */
1763 if (numentries == 0) {
1764 dptr_close(sconn, &dptr_num);
1765 } else if(expect_close && status_len == 0) {
1766 /* Close the dptr - we know it's gone */
1767 dptr_close(sconn, &dptr_num);
1770 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1771 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1772 dptr_close(sconn, &dptr_num);
1775 if ((numentries == 0) && !mask_contains_wcard) {
1776 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1777 goto out;
1780 SSVAL(req->outbuf,smb_vwv0,numentries);
1781 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1782 SCVAL(smb_buf(req->outbuf),0,5);
1783 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1785 /* The replies here are never long name. */
1786 SSVAL(req->outbuf, smb_flg2,
1787 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1788 if (!allow_long_path_components) {
1789 SSVAL(req->outbuf, smb_flg2,
1790 SVAL(req->outbuf, smb_flg2)
1791 & (~FLAGS2_LONG_PATH_COMPONENTS));
1794 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1795 SSVAL(req->outbuf, smb_flg2,
1796 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1798 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1799 smb_fn_name(req->cmd),
1800 mask,
1801 directory,
1802 dirtype,
1803 numentries,
1804 maxentries ));
1805 out:
1806 TALLOC_FREE(directory);
1807 TALLOC_FREE(smb_fname);
1808 END_PROFILE(SMBsearch);
1809 return;
1812 /****************************************************************************
1813 Reply to a fclose (stop directory search).
1814 ****************************************************************************/
1816 void reply_fclose(struct smb_request *req)
1818 int status_len;
1819 char status[21];
1820 int dptr_num= -2;
1821 const char *p;
1822 char *path = NULL;
1823 NTSTATUS err;
1824 bool path_contains_wcard = False;
1825 TALLOC_CTX *ctx = talloc_tos();
1826 struct smbd_server_connection *sconn = req->sconn;
1828 START_PROFILE(SMBfclose);
1830 if (lp_posix_pathnames()) {
1831 reply_unknown_new(req, req->cmd);
1832 END_PROFILE(SMBfclose);
1833 return;
1836 p = (const char *)req->buf + 1;
1837 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1838 &err, &path_contains_wcard);
1839 if (!NT_STATUS_IS_OK(err)) {
1840 reply_nterror(req, err);
1841 END_PROFILE(SMBfclose);
1842 return;
1844 p++;
1845 status_len = SVAL(p,0);
1846 p += 2;
1848 if (status_len == 0) {
1849 reply_force_doserror(req, ERRSRV, ERRsrverror);
1850 END_PROFILE(SMBfclose);
1851 return;
1854 memcpy(status,p,21);
1856 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1857 /* Close the dptr - we know it's gone */
1858 dptr_close(sconn, &dptr_num);
1861 reply_outbuf(req, 1, 0);
1862 SSVAL(req->outbuf,smb_vwv0,0);
1864 DEBUG(3,("search close\n"));
1866 END_PROFILE(SMBfclose);
1867 return;
1870 /****************************************************************************
1871 Reply to an open.
1872 ****************************************************************************/
1874 void reply_open(struct smb_request *req)
1876 connection_struct *conn = req->conn;
1877 struct smb_filename *smb_fname = NULL;
1878 char *fname = NULL;
1879 uint32 fattr=0;
1880 off_t size = 0;
1881 time_t mtime=0;
1882 int info;
1883 files_struct *fsp;
1884 int oplock_request;
1885 int deny_mode;
1886 uint32 dos_attr;
1887 uint32 access_mask;
1888 uint32 share_mode;
1889 uint32 create_disposition;
1890 uint32 create_options = 0;
1891 uint32_t private_flags = 0;
1892 NTSTATUS status;
1893 TALLOC_CTX *ctx = talloc_tos();
1895 START_PROFILE(SMBopen);
1897 if (req->wct < 2) {
1898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1899 goto out;
1902 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1903 deny_mode = SVAL(req->vwv+0, 0);
1904 dos_attr = SVAL(req->vwv+1, 0);
1906 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1907 STR_TERMINATE, &status);
1908 if (!NT_STATUS_IS_OK(status)) {
1909 reply_nterror(req, status);
1910 goto out;
1913 if (!map_open_params_to_ntcreate(fname, deny_mode,
1914 OPENX_FILE_EXISTS_OPEN, &access_mask,
1915 &share_mode, &create_disposition,
1916 &create_options, &private_flags)) {
1917 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1918 goto out;
1921 status = filename_convert(ctx,
1922 conn,
1923 req->flags2 & FLAGS2_DFS_PATHNAMES,
1924 fname,
1925 UCF_PREP_CREATEFILE,
1926 NULL,
1927 &smb_fname);
1928 if (!NT_STATUS_IS_OK(status)) {
1929 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1930 reply_botherror(req,
1931 NT_STATUS_PATH_NOT_COVERED,
1932 ERRSRV, ERRbadpath);
1933 goto out;
1935 reply_nterror(req, status);
1936 goto out;
1939 status = SMB_VFS_CREATE_FILE(
1940 conn, /* conn */
1941 req, /* req */
1942 0, /* root_dir_fid */
1943 smb_fname, /* fname */
1944 access_mask, /* access_mask */
1945 share_mode, /* share_access */
1946 create_disposition, /* create_disposition*/
1947 create_options, /* create_options */
1948 dos_attr, /* file_attributes */
1949 oplock_request, /* oplock_request */
1950 0, /* allocation_size */
1951 private_flags,
1952 NULL, /* sd */
1953 NULL, /* ea_list */
1954 &fsp, /* result */
1955 &info); /* pinfo */
1957 if (!NT_STATUS_IS_OK(status)) {
1958 if (open_was_deferred(req->sconn, req->mid)) {
1959 /* We have re-scheduled this call. */
1960 goto out;
1962 reply_openerror(req, status);
1963 goto out;
1966 /* Ensure we're pointing at the correct stat struct. */
1967 TALLOC_FREE(smb_fname);
1968 smb_fname = fsp->fsp_name;
1970 size = smb_fname->st.st_ex_size;
1971 fattr = dos_mode(conn, smb_fname);
1973 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1975 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1976 DEBUG(3,("attempt to open a directory %s\n",
1977 fsp_str_dbg(fsp)));
1978 close_file(req, fsp, ERROR_CLOSE);
1979 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1980 ERRDOS, ERRnoaccess);
1981 goto out;
1984 reply_outbuf(req, 7, 0);
1985 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1986 SSVAL(req->outbuf,smb_vwv1,fattr);
1987 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1988 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1989 } else {
1990 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1992 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1993 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1995 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1996 SCVAL(req->outbuf,smb_flg,
1997 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2000 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2001 SCVAL(req->outbuf,smb_flg,
2002 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2004 out:
2005 END_PROFILE(SMBopen);
2006 return;
2009 /****************************************************************************
2010 Reply to an open and X.
2011 ****************************************************************************/
2013 void reply_open_and_X(struct smb_request *req)
2015 connection_struct *conn = req->conn;
2016 struct smb_filename *smb_fname = NULL;
2017 char *fname = NULL;
2018 uint16 open_flags;
2019 int deny_mode;
2020 uint32 smb_attr;
2021 /* Breakout the oplock request bits so we can set the
2022 reply bits separately. */
2023 int ex_oplock_request;
2024 int core_oplock_request;
2025 int oplock_request;
2026 #if 0
2027 int smb_sattr = SVAL(req->vwv+4, 0);
2028 uint32 smb_time = make_unix_date3(req->vwv+6);
2029 #endif
2030 int smb_ofun;
2031 uint32 fattr=0;
2032 int mtime=0;
2033 int smb_action = 0;
2034 files_struct *fsp;
2035 NTSTATUS status;
2036 uint64_t allocation_size;
2037 ssize_t retval = -1;
2038 uint32 access_mask;
2039 uint32 share_mode;
2040 uint32 create_disposition;
2041 uint32 create_options = 0;
2042 uint32_t private_flags = 0;
2043 TALLOC_CTX *ctx = talloc_tos();
2045 START_PROFILE(SMBopenX);
2047 if (req->wct < 15) {
2048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2049 goto out;
2052 open_flags = SVAL(req->vwv+2, 0);
2053 deny_mode = SVAL(req->vwv+3, 0);
2054 smb_attr = SVAL(req->vwv+5, 0);
2055 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2056 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2057 oplock_request = ex_oplock_request | core_oplock_request;
2058 smb_ofun = SVAL(req->vwv+8, 0);
2059 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2061 /* If it's an IPC, pass off the pipe handler. */
2062 if (IS_IPC(conn)) {
2063 if (lp_nt_pipe_support()) {
2064 reply_open_pipe_and_X(conn, req);
2065 } else {
2066 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2068 goto out;
2071 /* XXXX we need to handle passed times, sattr and flags */
2072 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2073 STR_TERMINATE, &status);
2074 if (!NT_STATUS_IS_OK(status)) {
2075 reply_nterror(req, status);
2076 goto out;
2079 if (!map_open_params_to_ntcreate(fname, deny_mode,
2080 smb_ofun,
2081 &access_mask, &share_mode,
2082 &create_disposition,
2083 &create_options,
2084 &private_flags)) {
2085 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2086 goto out;
2089 status = filename_convert(ctx,
2090 conn,
2091 req->flags2 & FLAGS2_DFS_PATHNAMES,
2092 fname,
2093 UCF_PREP_CREATEFILE,
2094 NULL,
2095 &smb_fname);
2096 if (!NT_STATUS_IS_OK(status)) {
2097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2098 reply_botherror(req,
2099 NT_STATUS_PATH_NOT_COVERED,
2100 ERRSRV, ERRbadpath);
2101 goto out;
2103 reply_nterror(req, status);
2104 goto out;
2107 status = SMB_VFS_CREATE_FILE(
2108 conn, /* conn */
2109 req, /* req */
2110 0, /* root_dir_fid */
2111 smb_fname, /* fname */
2112 access_mask, /* access_mask */
2113 share_mode, /* share_access */
2114 create_disposition, /* create_disposition*/
2115 create_options, /* create_options */
2116 smb_attr, /* file_attributes */
2117 oplock_request, /* oplock_request */
2118 0, /* allocation_size */
2119 private_flags,
2120 NULL, /* sd */
2121 NULL, /* ea_list */
2122 &fsp, /* result */
2123 &smb_action); /* pinfo */
2125 if (!NT_STATUS_IS_OK(status)) {
2126 if (open_was_deferred(req->sconn, req->mid)) {
2127 /* We have re-scheduled this call. */
2128 goto out;
2130 reply_openerror(req, status);
2131 goto out;
2134 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2135 if the file is truncated or created. */
2136 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2137 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2138 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2139 close_file(req, fsp, ERROR_CLOSE);
2140 reply_nterror(req, NT_STATUS_DISK_FULL);
2141 goto out;
2143 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2144 if (retval < 0) {
2145 close_file(req, fsp, ERROR_CLOSE);
2146 reply_nterror(req, NT_STATUS_DISK_FULL);
2147 goto out;
2149 status = vfs_stat_fsp(fsp);
2150 if (!NT_STATUS_IS_OK(status)) {
2151 close_file(req, fsp, ERROR_CLOSE);
2152 reply_nterror(req, status);
2153 goto out;
2157 fattr = dos_mode(conn, fsp->fsp_name);
2158 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2159 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2160 close_file(req, fsp, ERROR_CLOSE);
2161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2162 goto out;
2165 /* If the caller set the extended oplock request bit
2166 and we granted one (by whatever means) - set the
2167 correct bit for extended oplock reply.
2170 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2171 smb_action |= EXTENDED_OPLOCK_GRANTED;
2174 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2175 smb_action |= EXTENDED_OPLOCK_GRANTED;
2178 /* If the caller set the core oplock request bit
2179 and we granted one (by whatever means) - set the
2180 correct bit for core oplock reply.
2183 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2184 reply_outbuf(req, 19, 0);
2185 } else {
2186 reply_outbuf(req, 15, 0);
2189 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2190 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2192 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2193 SCVAL(req->outbuf, smb_flg,
2194 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2197 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2198 SCVAL(req->outbuf, smb_flg,
2199 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2202 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2203 SSVAL(req->outbuf,smb_vwv3,fattr);
2204 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2205 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2206 } else {
2207 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2209 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2210 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2211 SSVAL(req->outbuf,smb_vwv11,smb_action);
2213 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2214 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2217 out:
2218 TALLOC_FREE(smb_fname);
2219 END_PROFILE(SMBopenX);
2220 return;
2223 /****************************************************************************
2224 Reply to a SMBulogoffX.
2225 ****************************************************************************/
2227 void reply_ulogoffX(struct smb_request *req)
2229 struct smbd_server_connection *sconn = req->sconn;
2230 struct user_struct *vuser;
2231 struct smbXsrv_session *session = NULL;
2232 NTSTATUS status;
2234 START_PROFILE(SMBulogoffX);
2236 vuser = get_valid_user_struct(sconn, req->vuid);
2238 if(vuser == NULL) {
2239 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2240 (unsigned long long)req->vuid));
2242 req->vuid = UID_FIELD_INVALID;
2243 reply_force_doserror(req, ERRSRV, ERRbaduid);
2244 END_PROFILE(SMBulogoffX);
2245 return;
2248 session = vuser->session;
2249 vuser = NULL;
2252 * TODO: cancel all outstanding requests on the session
2254 status = smbXsrv_session_logoff(session);
2255 if (!NT_STATUS_IS_OK(status)) {
2256 DEBUG(0, ("reply_ulogoff: "
2257 "smbXsrv_session_logoff() failed: %s\n",
2258 nt_errstr(status)));
2260 * If we hit this case, there is something completely
2261 * wrong, so we better disconnect the transport connection.
2263 END_PROFILE(SMBulogoffX);
2264 exit_server(__location__ ": smbXsrv_session_logoff failed");
2265 return;
2268 TALLOC_FREE(session);
2270 reply_outbuf(req, 2, 0);
2271 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2272 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2274 DEBUG(3, ("ulogoffX vuid=%llu\n",
2275 (unsigned long long)req->vuid));
2277 END_PROFILE(SMBulogoffX);
2278 req->vuid = UID_FIELD_INVALID;
2281 /****************************************************************************
2282 Reply to a mknew or a create.
2283 ****************************************************************************/
2285 void reply_mknew(struct smb_request *req)
2287 connection_struct *conn = req->conn;
2288 struct smb_filename *smb_fname = NULL;
2289 char *fname = NULL;
2290 uint32 fattr = 0;
2291 struct smb_file_time ft;
2292 files_struct *fsp;
2293 int oplock_request = 0;
2294 NTSTATUS status;
2295 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2296 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2297 uint32 create_disposition;
2298 uint32 create_options = 0;
2299 TALLOC_CTX *ctx = talloc_tos();
2301 START_PROFILE(SMBcreate);
2302 ZERO_STRUCT(ft);
2304 if (req->wct < 3) {
2305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2306 goto out;
2309 fattr = SVAL(req->vwv+0, 0);
2310 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2312 /* mtime. */
2313 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2315 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2316 STR_TERMINATE, &status);
2317 if (!NT_STATUS_IS_OK(status)) {
2318 reply_nterror(req, status);
2319 goto out;
2322 status = filename_convert(ctx,
2323 conn,
2324 req->flags2 & FLAGS2_DFS_PATHNAMES,
2325 fname,
2326 UCF_PREP_CREATEFILE,
2327 NULL,
2328 &smb_fname);
2329 if (!NT_STATUS_IS_OK(status)) {
2330 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2331 reply_botherror(req,
2332 NT_STATUS_PATH_NOT_COVERED,
2333 ERRSRV, ERRbadpath);
2334 goto out;
2336 reply_nterror(req, status);
2337 goto out;
2340 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2341 DEBUG(0,("Attempt to create file (%s) with volid set - "
2342 "please report this\n",
2343 smb_fname_str_dbg(smb_fname)));
2346 if(req->cmd == SMBmknew) {
2347 /* We should fail if file exists. */
2348 create_disposition = FILE_CREATE;
2349 } else {
2350 /* Create if file doesn't exist, truncate if it does. */
2351 create_disposition = FILE_OVERWRITE_IF;
2354 status = SMB_VFS_CREATE_FILE(
2355 conn, /* conn */
2356 req, /* req */
2357 0, /* root_dir_fid */
2358 smb_fname, /* fname */
2359 access_mask, /* access_mask */
2360 share_mode, /* share_access */
2361 create_disposition, /* create_disposition*/
2362 create_options, /* create_options */
2363 fattr, /* file_attributes */
2364 oplock_request, /* oplock_request */
2365 0, /* allocation_size */
2366 0, /* private_flags */
2367 NULL, /* sd */
2368 NULL, /* ea_list */
2369 &fsp, /* result */
2370 NULL); /* pinfo */
2372 if (!NT_STATUS_IS_OK(status)) {
2373 if (open_was_deferred(req->sconn, req->mid)) {
2374 /* We have re-scheduled this call. */
2375 goto out;
2377 reply_openerror(req, status);
2378 goto out;
2381 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2382 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 END_PROFILE(SMBcreate);
2385 goto out;
2388 reply_outbuf(req, 1, 0);
2389 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2391 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2392 SCVAL(req->outbuf,smb_flg,
2393 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2396 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2397 SCVAL(req->outbuf,smb_flg,
2398 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2401 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2402 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2403 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2404 (unsigned int)fattr));
2406 out:
2407 TALLOC_FREE(smb_fname);
2408 END_PROFILE(SMBcreate);
2409 return;
2412 /****************************************************************************
2413 Reply to a create temporary file.
2414 ****************************************************************************/
2416 void reply_ctemp(struct smb_request *req)
2418 connection_struct *conn = req->conn;
2419 struct smb_filename *smb_fname = NULL;
2420 char *wire_name = NULL;
2421 char *fname = NULL;
2422 uint32 fattr;
2423 files_struct *fsp;
2424 int oplock_request;
2425 char *s;
2426 NTSTATUS status;
2427 int i;
2428 TALLOC_CTX *ctx = talloc_tos();
2430 START_PROFILE(SMBctemp);
2432 if (req->wct < 3) {
2433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2434 goto out;
2437 fattr = SVAL(req->vwv+0, 0);
2438 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2440 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2441 STR_TERMINATE, &status);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 reply_nterror(req, status);
2444 goto out;
2447 for (i = 0; i < 10; i++) {
2448 if (*wire_name) {
2449 fname = talloc_asprintf(ctx,
2450 "%s/TMP%s",
2451 wire_name,
2452 generate_random_str_list(ctx, 5, "0123456789"));
2453 } else {
2454 fname = talloc_asprintf(ctx,
2455 "TMP%s",
2456 generate_random_str_list(ctx, 5, "0123456789"));
2459 if (!fname) {
2460 reply_nterror(req, NT_STATUS_NO_MEMORY);
2461 goto out;
2464 status = filename_convert(ctx, conn,
2465 req->flags2 & FLAGS2_DFS_PATHNAMES,
2466 fname,
2467 UCF_PREP_CREATEFILE,
2468 NULL,
2469 &smb_fname);
2470 if (!NT_STATUS_IS_OK(status)) {
2471 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2472 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2473 ERRSRV, ERRbadpath);
2474 goto out;
2476 reply_nterror(req, status);
2477 goto out;
2480 /* Create the file. */
2481 status = SMB_VFS_CREATE_FILE(
2482 conn, /* conn */
2483 req, /* req */
2484 0, /* root_dir_fid */
2485 smb_fname, /* fname */
2486 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2487 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2488 FILE_CREATE, /* create_disposition*/
2489 0, /* create_options */
2490 fattr, /* file_attributes */
2491 oplock_request, /* oplock_request */
2492 0, /* allocation_size */
2493 0, /* private_flags */
2494 NULL, /* sd */
2495 NULL, /* ea_list */
2496 &fsp, /* result */
2497 NULL); /* pinfo */
2499 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2500 TALLOC_FREE(fname);
2501 TALLOC_FREE(smb_fname);
2502 continue;
2505 if (!NT_STATUS_IS_OK(status)) {
2506 if (open_was_deferred(req->sconn, req->mid)) {
2507 /* We have re-scheduled this call. */
2508 goto out;
2510 reply_openerror(req, status);
2511 goto out;
2514 break;
2517 if (i == 10) {
2518 /* Collision after 10 times... */
2519 reply_nterror(req, status);
2520 goto out;
2523 reply_outbuf(req, 1, 0);
2524 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2526 /* the returned filename is relative to the directory */
2527 s = strrchr_m(fsp->fsp_name->base_name, '/');
2528 if (!s) {
2529 s = fsp->fsp_name->base_name;
2530 } else {
2531 s++;
2534 #if 0
2535 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2536 thing in the byte section. JRA */
2537 SSVALS(p, 0, -1); /* what is this? not in spec */
2538 #endif
2539 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2540 == -1) {
2541 reply_nterror(req, NT_STATUS_NO_MEMORY);
2542 goto out;
2545 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2546 SCVAL(req->outbuf, smb_flg,
2547 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2550 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2551 SCVAL(req->outbuf, smb_flg,
2552 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2555 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2556 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2557 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2558 out:
2559 TALLOC_FREE(smb_fname);
2560 TALLOC_FREE(wire_name);
2561 END_PROFILE(SMBctemp);
2562 return;
2565 /*******************************************************************
2566 Check if a user is allowed to rename a file.
2567 ********************************************************************/
2569 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2570 uint16 dirtype)
2572 if (!CAN_WRITE(conn)) {
2573 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2576 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2577 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2578 /* Only bother to read the DOS attribute if we might deny the
2579 rename on the grounds of attribute missmatch. */
2580 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2581 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2582 return NT_STATUS_NO_SUCH_FILE;
2586 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2587 if (fsp->posix_open) {
2588 return NT_STATUS_OK;
2591 /* If no pathnames are open below this
2592 directory, allow the rename. */
2594 if (file_find_subpath(fsp)) {
2595 return NT_STATUS_ACCESS_DENIED;
2597 return NT_STATUS_OK;
2600 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2601 return NT_STATUS_OK;
2604 return NT_STATUS_ACCESS_DENIED;
2607 /*******************************************************************
2608 * unlink a file with all relevant access checks
2609 *******************************************************************/
2611 static NTSTATUS do_unlink(connection_struct *conn,
2612 struct smb_request *req,
2613 struct smb_filename *smb_fname,
2614 uint32 dirtype)
2616 uint32 fattr;
2617 files_struct *fsp;
2618 uint32 dirtype_orig = dirtype;
2619 NTSTATUS status;
2620 int ret;
2621 bool posix_paths = lp_posix_pathnames();
2623 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2624 smb_fname_str_dbg(smb_fname),
2625 dirtype));
2627 if (!CAN_WRITE(conn)) {
2628 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2631 if (posix_paths) {
2632 ret = SMB_VFS_LSTAT(conn, smb_fname);
2633 } else {
2634 ret = SMB_VFS_STAT(conn, smb_fname);
2636 if (ret != 0) {
2637 return map_nt_error_from_unix(errno);
2640 fattr = dos_mode(conn, smb_fname);
2642 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2643 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2646 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2647 if (!dirtype) {
2648 return NT_STATUS_NO_SUCH_FILE;
2651 if (!dir_check_ftype(fattr, dirtype)) {
2652 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2653 return NT_STATUS_FILE_IS_A_DIRECTORY;
2655 return NT_STATUS_NO_SUCH_FILE;
2658 if (dirtype_orig & 0x8000) {
2659 /* These will never be set for POSIX. */
2660 return NT_STATUS_NO_SUCH_FILE;
2663 #if 0
2664 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2665 return NT_STATUS_FILE_IS_A_DIRECTORY;
2668 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2669 return NT_STATUS_NO_SUCH_FILE;
2672 if (dirtype & 0xFF00) {
2673 /* These will never be set for POSIX. */
2674 return NT_STATUS_NO_SUCH_FILE;
2677 dirtype &= 0xFF;
2678 if (!dirtype) {
2679 return NT_STATUS_NO_SUCH_FILE;
2682 /* Can't delete a directory. */
2683 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2684 return NT_STATUS_FILE_IS_A_DIRECTORY;
2686 #endif
2688 #if 0 /* JRATEST */
2689 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2690 return NT_STATUS_OBJECT_NAME_INVALID;
2691 #endif /* JRATEST */
2693 /* On open checks the open itself will check the share mode, so
2694 don't do it here as we'll get it wrong. */
2696 status = SMB_VFS_CREATE_FILE
2697 (conn, /* conn */
2698 req, /* req */
2699 0, /* root_dir_fid */
2700 smb_fname, /* fname */
2701 DELETE_ACCESS, /* access_mask */
2702 FILE_SHARE_NONE, /* share_access */
2703 FILE_OPEN, /* create_disposition*/
2704 FILE_NON_DIRECTORY_FILE, /* create_options */
2705 /* file_attributes */
2706 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2707 FILE_ATTRIBUTE_NORMAL,
2708 0, /* oplock_request */
2709 0, /* allocation_size */
2710 0, /* private_flags */
2711 NULL, /* sd */
2712 NULL, /* ea_list */
2713 &fsp, /* result */
2714 NULL); /* pinfo */
2716 if (!NT_STATUS_IS_OK(status)) {
2717 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2718 nt_errstr(status)));
2719 return status;
2722 status = can_set_delete_on_close(fsp, fattr);
2723 if (!NT_STATUS_IS_OK(status)) {
2724 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2725 "(%s)\n",
2726 smb_fname_str_dbg(smb_fname),
2727 nt_errstr(status)));
2728 close_file(req, fsp, NORMAL_CLOSE);
2729 return status;
2732 /* The set is across all open files on this dev/inode pair. */
2733 if (!set_delete_on_close(fsp, True,
2734 conn->session_info->security_token,
2735 conn->session_info->unix_token)) {
2736 close_file(req, fsp, NORMAL_CLOSE);
2737 return NT_STATUS_ACCESS_DENIED;
2740 return close_file(req, fsp, NORMAL_CLOSE);
2743 /****************************************************************************
2744 The guts of the unlink command, split out so it may be called by the NT SMB
2745 code.
2746 ****************************************************************************/
2748 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2749 uint32 dirtype, struct smb_filename *smb_fname,
2750 bool has_wild)
2752 char *fname_dir = NULL;
2753 char *fname_mask = NULL;
2754 int count=0;
2755 NTSTATUS status = NT_STATUS_OK;
2756 TALLOC_CTX *ctx = talloc_tos();
2758 /* Split up the directory from the filename/mask. */
2759 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2760 &fname_dir, &fname_mask);
2761 if (!NT_STATUS_IS_OK(status)) {
2762 goto out;
2766 * We should only check the mangled cache
2767 * here if unix_convert failed. This means
2768 * that the path in 'mask' doesn't exist
2769 * on the file system and so we need to look
2770 * for a possible mangle. This patch from
2771 * Tine Smukavec <valentin.smukavec@hermes.si>.
2774 if (!VALID_STAT(smb_fname->st) &&
2775 mangle_is_mangled(fname_mask, conn->params)) {
2776 char *new_mask = NULL;
2777 mangle_lookup_name_from_8_3(ctx, fname_mask,
2778 &new_mask, conn->params);
2779 if (new_mask) {
2780 TALLOC_FREE(fname_mask);
2781 fname_mask = new_mask;
2785 if (!has_wild) {
2788 * Only one file needs to be unlinked. Append the mask back
2789 * onto the directory.
2791 TALLOC_FREE(smb_fname->base_name);
2792 if (ISDOT(fname_dir)) {
2793 /* Ensure we use canonical names on open. */
2794 smb_fname->base_name = talloc_asprintf(smb_fname,
2795 "%s",
2796 fname_mask);
2797 } else {
2798 smb_fname->base_name = talloc_asprintf(smb_fname,
2799 "%s/%s",
2800 fname_dir,
2801 fname_mask);
2803 if (!smb_fname->base_name) {
2804 status = NT_STATUS_NO_MEMORY;
2805 goto out;
2807 if (dirtype == 0) {
2808 dirtype = FILE_ATTRIBUTE_NORMAL;
2811 status = check_name(conn, smb_fname->base_name);
2812 if (!NT_STATUS_IS_OK(status)) {
2813 goto out;
2816 status = do_unlink(conn, req, smb_fname, dirtype);
2817 if (!NT_STATUS_IS_OK(status)) {
2818 goto out;
2821 count++;
2822 } else {
2823 struct smb_Dir *dir_hnd = NULL;
2824 long offset = 0;
2825 const char *dname = NULL;
2826 char *talloced = NULL;
2828 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2829 status = NT_STATUS_OBJECT_NAME_INVALID;
2830 goto out;
2833 if (strequal(fname_mask,"????????.???")) {
2834 TALLOC_FREE(fname_mask);
2835 fname_mask = talloc_strdup(ctx, "*");
2836 if (!fname_mask) {
2837 status = NT_STATUS_NO_MEMORY;
2838 goto out;
2842 status = check_name(conn, fname_dir);
2843 if (!NT_STATUS_IS_OK(status)) {
2844 goto out;
2847 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2848 dirtype);
2849 if (dir_hnd == NULL) {
2850 status = map_nt_error_from_unix(errno);
2851 goto out;
2854 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2855 the pattern matches against the long name, otherwise the short name
2856 We don't implement this yet XXXX
2859 status = NT_STATUS_NO_SUCH_FILE;
2861 while ((dname = ReadDirName(dir_hnd, &offset,
2862 &smb_fname->st, &talloced))) {
2863 TALLOC_CTX *frame = talloc_stackframe();
2865 if (!is_visible_file(conn, fname_dir, dname,
2866 &smb_fname->st, true)) {
2867 TALLOC_FREE(frame);
2868 TALLOC_FREE(talloced);
2869 continue;
2872 /* Quick check for "." and ".." */
2873 if (ISDOT(dname) || ISDOTDOT(dname)) {
2874 TALLOC_FREE(frame);
2875 TALLOC_FREE(talloced);
2876 continue;
2879 if(!mask_match(dname, fname_mask,
2880 conn->case_sensitive)) {
2881 TALLOC_FREE(frame);
2882 TALLOC_FREE(talloced);
2883 continue;
2886 TALLOC_FREE(smb_fname->base_name);
2887 if (ISDOT(fname_dir)) {
2888 /* Ensure we use canonical names on open. */
2889 smb_fname->base_name =
2890 talloc_asprintf(smb_fname, "%s",
2891 dname);
2892 } else {
2893 smb_fname->base_name =
2894 talloc_asprintf(smb_fname, "%s/%s",
2895 fname_dir, dname);
2898 if (!smb_fname->base_name) {
2899 TALLOC_FREE(dir_hnd);
2900 status = NT_STATUS_NO_MEMORY;
2901 TALLOC_FREE(frame);
2902 TALLOC_FREE(talloced);
2903 goto out;
2906 status = check_name(conn, smb_fname->base_name);
2907 if (!NT_STATUS_IS_OK(status)) {
2908 TALLOC_FREE(dir_hnd);
2909 TALLOC_FREE(frame);
2910 TALLOC_FREE(talloced);
2911 goto out;
2914 status = do_unlink(conn, req, smb_fname, dirtype);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 TALLOC_FREE(dir_hnd);
2917 TALLOC_FREE(frame);
2918 TALLOC_FREE(talloced);
2919 goto out;
2922 count++;
2923 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2924 smb_fname->base_name));
2926 TALLOC_FREE(frame);
2927 TALLOC_FREE(talloced);
2929 TALLOC_FREE(dir_hnd);
2932 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2933 status = map_nt_error_from_unix(errno);
2936 out:
2937 TALLOC_FREE(fname_dir);
2938 TALLOC_FREE(fname_mask);
2939 return status;
2942 /****************************************************************************
2943 Reply to a unlink
2944 ****************************************************************************/
2946 void reply_unlink(struct smb_request *req)
2948 connection_struct *conn = req->conn;
2949 char *name = NULL;
2950 struct smb_filename *smb_fname = NULL;
2951 uint32 dirtype;
2952 NTSTATUS status;
2953 bool path_contains_wcard = False;
2954 TALLOC_CTX *ctx = talloc_tos();
2956 START_PROFILE(SMBunlink);
2958 if (req->wct < 1) {
2959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2960 goto out;
2963 dirtype = SVAL(req->vwv+0, 0);
2965 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2966 STR_TERMINATE, &status,
2967 &path_contains_wcard);
2968 if (!NT_STATUS_IS_OK(status)) {
2969 reply_nterror(req, status);
2970 goto out;
2973 status = filename_convert(ctx, conn,
2974 req->flags2 & FLAGS2_DFS_PATHNAMES,
2975 name,
2976 UCF_COND_ALLOW_WCARD_LCOMP,
2977 &path_contains_wcard,
2978 &smb_fname);
2979 if (!NT_STATUS_IS_OK(status)) {
2980 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2981 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2982 ERRSRV, ERRbadpath);
2983 goto out;
2985 reply_nterror(req, status);
2986 goto out;
2989 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2991 status = unlink_internals(conn, req, dirtype, smb_fname,
2992 path_contains_wcard);
2993 if (!NT_STATUS_IS_OK(status)) {
2994 if (open_was_deferred(req->sconn, req->mid)) {
2995 /* We have re-scheduled this call. */
2996 goto out;
2998 reply_nterror(req, status);
2999 goto out;
3002 reply_outbuf(req, 0, 0);
3003 out:
3004 TALLOC_FREE(smb_fname);
3005 END_PROFILE(SMBunlink);
3006 return;
3009 /****************************************************************************
3010 Fail for readbraw.
3011 ****************************************************************************/
3013 static void fail_readraw(void)
3015 const char *errstr = talloc_asprintf(talloc_tos(),
3016 "FAIL ! reply_readbraw: socket write fail (%s)",
3017 strerror(errno));
3018 if (!errstr) {
3019 errstr = "";
3021 exit_server_cleanly(errstr);
3024 /****************************************************************************
3025 Fake (read/write) sendfile. Returns -1 on read or write fail.
3026 ****************************************************************************/
3028 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
3030 struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
3031 size_t bufsize;
3032 size_t tosend = nread;
3033 char *buf;
3035 if (nread == 0) {
3036 return 0;
3039 bufsize = MIN(nread, 65536);
3041 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3042 return -1;
3045 while (tosend > 0) {
3046 ssize_t ret;
3047 size_t cur_read;
3049 if (tosend > bufsize) {
3050 cur_read = bufsize;
3051 } else {
3052 cur_read = tosend;
3054 ret = read_file(fsp,buf,startpos,cur_read);
3055 if (ret == -1) {
3056 SAFE_FREE(buf);
3057 return -1;
3060 /* If we had a short read, fill with zeros. */
3061 if (ret < cur_read) {
3062 memset(buf + ret, '\0', cur_read - ret);
3065 ret = write_data(xconn->transport.sock, buf, cur_read);
3066 if (ret != cur_read) {
3067 int saved_errno = errno;
3069 * Try and give an error message saying what
3070 * client failed.
3072 DEBUG(0, ("write_data failed for client %s. "
3073 "Error %s\n",
3074 smbXsrv_connection_dbg(xconn),
3075 strerror(saved_errno)));
3076 SAFE_FREE(buf);
3077 errno = saved_errno;
3078 return -1;
3080 tosend -= cur_read;
3081 startpos += cur_read;
3084 SAFE_FREE(buf);
3085 return (ssize_t)nread;
3088 /****************************************************************************
3089 Deal with the case of sendfile reading less bytes from the file than
3090 requested. Fill with zeros (all we can do).
3091 ****************************************************************************/
3093 void sendfile_short_send(files_struct *fsp,
3094 ssize_t nread,
3095 size_t headersize,
3096 size_t smb_maxcnt)
3098 struct smbXsrv_connection *xconn = fsp->conn->sconn->conn;
3100 #define SHORT_SEND_BUFSIZE 1024
3101 if (nread < headersize) {
3102 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3103 "header for file %s (%s). Terminating\n",
3104 fsp_str_dbg(fsp), strerror(errno)));
3105 exit_server_cleanly("sendfile_short_send failed");
3108 nread -= headersize;
3110 if (nread < smb_maxcnt) {
3111 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3112 if (!buf) {
3113 exit_server_cleanly("sendfile_short_send: "
3114 "malloc failed");
3117 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3118 "with zeros !\n", fsp_str_dbg(fsp)));
3120 while (nread < smb_maxcnt) {
3122 * We asked for the real file size and told sendfile
3123 * to not go beyond the end of the file. But it can
3124 * happen that in between our fstat call and the
3125 * sendfile call the file was truncated. This is very
3126 * bad because we have already announced the larger
3127 * number of bytes to the client.
3129 * The best we can do now is to send 0-bytes, just as
3130 * a read from a hole in a sparse file would do.
3132 * This should happen rarely enough that I don't care
3133 * about efficiency here :-)
3135 size_t to_write;
3136 ssize_t ret;
3138 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3139 ret = write_data(xconn->transport.sock, buf, to_write);
3140 if (ret != to_write) {
3141 int saved_errno = errno;
3143 * Try and give an error message saying what
3144 * client failed.
3146 DEBUG(0, ("write_data failed for client %s. "
3147 "Error %s\n",
3148 smbXsrv_connection_dbg(xconn),
3149 strerror(saved_errno)));
3150 errno = saved_errno;
3151 exit_server_cleanly("sendfile_short_send: "
3152 "write_data failed");
3154 nread += to_write;
3156 SAFE_FREE(buf);
3160 /****************************************************************************
3161 Return a readbraw error (4 bytes of zero).
3162 ****************************************************************************/
3164 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3166 struct smbXsrv_connection *xconn = sconn->conn;
3167 char header[4];
3169 SIVAL(header,0,0);
3171 smbd_lock_socket(sconn);
3172 if (write_data(xconn->transport.sock,header,4) != 4) {
3173 int saved_errno = errno;
3175 * Try and give an error message saying what
3176 * client failed.
3178 DEBUG(0, ("write_data failed for client %s. "
3179 "Error %s\n",
3180 smbXsrv_connection_dbg(xconn),
3181 strerror(saved_errno)));
3182 errno = saved_errno;
3184 fail_readraw();
3186 smbd_unlock_socket(sconn);
3189 /****************************************************************************
3190 Use sendfile in readbraw.
3191 ****************************************************************************/
3193 static void send_file_readbraw(connection_struct *conn,
3194 struct smb_request *req,
3195 files_struct *fsp,
3196 off_t startpos,
3197 size_t nread,
3198 ssize_t mincount)
3200 struct smbd_server_connection *sconn = req->sconn;
3201 struct smbXsrv_connection *xconn = sconn->conn;
3202 char *outbuf = NULL;
3203 ssize_t ret=0;
3206 * We can only use sendfile on a non-chained packet
3207 * but we can use on a non-oplocked file. tridge proved this
3208 * on a train in Germany :-). JRA.
3209 * reply_readbraw has already checked the length.
3212 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3213 (fsp->wcp == NULL) &&
3214 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3215 ssize_t sendfile_read = -1;
3216 char header[4];
3217 DATA_BLOB header_blob;
3219 _smb_setlen(header,nread);
3220 header_blob = data_blob_const(header, 4);
3222 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3223 &header_blob, startpos,
3224 nread);
3225 if (sendfile_read == -1) {
3226 /* Returning ENOSYS means no data at all was sent.
3227 * Do this as a normal read. */
3228 if (errno == ENOSYS) {
3229 goto normal_readbraw;
3233 * Special hack for broken Linux with no working sendfile. If we
3234 * return EINTR we sent the header but not the rest of the data.
3235 * Fake this up by doing read/write calls.
3237 if (errno == EINTR) {
3238 /* Ensure we don't do this again. */
3239 set_use_sendfile(SNUM(conn), False);
3240 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3242 if (fake_sendfile(fsp, startpos, nread) == -1) {
3243 DEBUG(0,("send_file_readbraw: "
3244 "fake_sendfile failed for "
3245 "file %s (%s).\n",
3246 fsp_str_dbg(fsp),
3247 strerror(errno)));
3248 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3250 return;
3253 DEBUG(0,("send_file_readbraw: sendfile failed for "
3254 "file %s (%s). Terminating\n",
3255 fsp_str_dbg(fsp), strerror(errno)));
3256 exit_server_cleanly("send_file_readbraw sendfile failed");
3257 } else if (sendfile_read == 0) {
3259 * Some sendfile implementations return 0 to indicate
3260 * that there was a short read, but nothing was
3261 * actually written to the socket. In this case,
3262 * fallback to the normal read path so the header gets
3263 * the correct byte count.
3265 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3266 "bytes falling back to the normal read: "
3267 "%s\n", fsp_str_dbg(fsp)));
3268 goto normal_readbraw;
3271 /* Deal with possible short send. */
3272 if (sendfile_read != 4+nread) {
3273 sendfile_short_send(fsp, sendfile_read, 4, nread);
3275 return;
3278 normal_readbraw:
3280 outbuf = talloc_array(NULL, char, nread+4);
3281 if (!outbuf) {
3282 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3283 (unsigned)(nread+4)));
3284 reply_readbraw_error(sconn);
3285 return;
3288 if (nread > 0) {
3289 ret = read_file(fsp,outbuf+4,startpos,nread);
3290 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3291 if (ret < mincount)
3292 ret = 0;
3293 #else
3294 if (ret < nread)
3295 ret = 0;
3296 #endif
3299 _smb_setlen(outbuf,ret);
3300 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3301 int saved_errno = errno;
3303 * Try and give an error message saying what
3304 * client failed.
3306 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3307 smbXsrv_connection_dbg(xconn),
3308 strerror(saved_errno)));
3309 errno = saved_errno;
3311 fail_readraw();
3314 TALLOC_FREE(outbuf);
3317 /****************************************************************************
3318 Reply to a readbraw (core+ protocol).
3319 ****************************************************************************/
3321 void reply_readbraw(struct smb_request *req)
3323 connection_struct *conn = req->conn;
3324 struct smbd_server_connection *sconn = req->sconn;
3325 ssize_t maxcount,mincount;
3326 size_t nread = 0;
3327 off_t startpos;
3328 files_struct *fsp;
3329 struct lock_struct lock;
3330 off_t size = 0;
3332 START_PROFILE(SMBreadbraw);
3334 if (srv_is_signing_active(sconn) || req->encrypted) {
3335 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3336 "raw reads/writes are disallowed.");
3339 if (req->wct < 8) {
3340 reply_readbraw_error(sconn);
3341 END_PROFILE(SMBreadbraw);
3342 return;
3345 if (sconn->smb1.echo_handler.trusted_fde) {
3346 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3347 "'async smb echo handler = yes'\n"));
3348 reply_readbraw_error(sconn);
3349 END_PROFILE(SMBreadbraw);
3350 return;
3354 * Special check if an oplock break has been issued
3355 * and the readraw request croses on the wire, we must
3356 * return a zero length response here.
3359 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3362 * We have to do a check_fsp by hand here, as
3363 * we must always return 4 zero bytes on error,
3364 * not a NTSTATUS.
3367 if (!fsp || !conn || conn != fsp->conn ||
3368 req->vuid != fsp->vuid ||
3369 fsp->is_directory || fsp->fh->fd == -1) {
3371 * fsp could be NULL here so use the value from the packet. JRA.
3373 DEBUG(3,("reply_readbraw: fnum %d not valid "
3374 "- cache prime?\n",
3375 (int)SVAL(req->vwv+0, 0)));
3376 reply_readbraw_error(sconn);
3377 END_PROFILE(SMBreadbraw);
3378 return;
3381 /* Do a "by hand" version of CHECK_READ. */
3382 if (!(fsp->can_read ||
3383 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3384 (fsp->access_mask & FILE_EXECUTE)))) {
3385 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3386 (int)SVAL(req->vwv+0, 0)));
3387 reply_readbraw_error(sconn);
3388 END_PROFILE(SMBreadbraw);
3389 return;
3392 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3394 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3395 if(req->wct == 10) {
3397 * This is a large offset (64 bit) read.
3400 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3402 if(startpos < 0) {
3403 DEBUG(0,("reply_readbraw: negative 64 bit "
3404 "readraw offset (%.0f) !\n",
3405 (double)startpos ));
3406 reply_readbraw_error(sconn);
3407 END_PROFILE(SMBreadbraw);
3408 return;
3412 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3413 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3415 /* ensure we don't overrun the packet size */
3416 maxcount = MIN(65535,maxcount);
3418 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3419 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3420 &lock);
3422 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3423 reply_readbraw_error(sconn);
3424 END_PROFILE(SMBreadbraw);
3425 return;
3428 if (fsp_stat(fsp) == 0) {
3429 size = fsp->fsp_name->st.st_ex_size;
3432 if (startpos >= size) {
3433 nread = 0;
3434 } else {
3435 nread = MIN(maxcount,(size - startpos));
3438 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3439 if (nread < mincount)
3440 nread = 0;
3441 #endif
3443 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3444 "min=%lu nread=%lu\n",
3445 fsp_fnum_dbg(fsp), (double)startpos,
3446 (unsigned long)maxcount,
3447 (unsigned long)mincount,
3448 (unsigned long)nread ) );
3450 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3452 DEBUG(5,("reply_readbraw finished\n"));
3454 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3456 END_PROFILE(SMBreadbraw);
3457 return;
3460 #undef DBGC_CLASS
3461 #define DBGC_CLASS DBGC_LOCKING
3463 /****************************************************************************
3464 Reply to a lockread (core+ protocol).
3465 ****************************************************************************/
3467 void reply_lockread(struct smb_request *req)
3469 connection_struct *conn = req->conn;
3470 ssize_t nread = -1;
3471 char *data;
3472 off_t startpos;
3473 size_t numtoread;
3474 size_t maxtoread;
3475 NTSTATUS status;
3476 files_struct *fsp;
3477 struct byte_range_lock *br_lck = NULL;
3478 char *p = NULL;
3479 struct smbd_server_connection *sconn = req->sconn;
3481 START_PROFILE(SMBlockread);
3483 if (req->wct < 5) {
3484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3485 END_PROFILE(SMBlockread);
3486 return;
3489 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3491 if (!check_fsp(conn, req, fsp)) {
3492 END_PROFILE(SMBlockread);
3493 return;
3496 if (!CHECK_READ(fsp,req)) {
3497 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3498 END_PROFILE(SMBlockread);
3499 return;
3502 numtoread = SVAL(req->vwv+1, 0);
3503 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3506 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3507 * protocol request that predates the read/write lock concept.
3508 * Thus instead of asking for a read lock here we need to ask
3509 * for a write lock. JRA.
3510 * Note that the requested lock size is unaffected by max_send.
3513 br_lck = do_lock(req->sconn->msg_ctx,
3514 fsp,
3515 (uint64_t)req->smbpid,
3516 (uint64_t)numtoread,
3517 (uint64_t)startpos,
3518 WRITE_LOCK,
3519 WINDOWS_LOCK,
3520 False, /* Non-blocking lock. */
3521 &status,
3522 NULL);
3523 TALLOC_FREE(br_lck);
3525 if (NT_STATUS_V(status)) {
3526 reply_nterror(req, status);
3527 END_PROFILE(SMBlockread);
3528 return;
3532 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3534 maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3536 if (numtoread > maxtoread) {
3537 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3538 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3539 (unsigned int)numtoread, (unsigned int)maxtoread,
3540 (unsigned int)sconn->smb1.sessions.max_send));
3541 numtoread = maxtoread;
3544 reply_outbuf(req, 5, numtoread + 3);
3546 data = smb_buf(req->outbuf) + 3;
3548 nread = read_file(fsp,data,startpos,numtoread);
3550 if (nread < 0) {
3551 reply_nterror(req, map_nt_error_from_unix(errno));
3552 END_PROFILE(SMBlockread);
3553 return;
3556 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3558 SSVAL(req->outbuf,smb_vwv0,nread);
3559 SSVAL(req->outbuf,smb_vwv5,nread+3);
3560 p = smb_buf(req->outbuf);
3561 SCVAL(p,0,0); /* pad byte. */
3562 SSVAL(p,1,nread);
3564 DEBUG(3,("lockread %s num=%d nread=%d\n",
3565 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3567 END_PROFILE(SMBlockread);
3568 return;
3571 #undef DBGC_CLASS
3572 #define DBGC_CLASS DBGC_ALL
3574 /****************************************************************************
3575 Reply to a read.
3576 ****************************************************************************/
3578 void reply_read(struct smb_request *req)
3580 connection_struct *conn = req->conn;
3581 size_t numtoread;
3582 size_t maxtoread;
3583 ssize_t nread = 0;
3584 char *data;
3585 off_t startpos;
3586 files_struct *fsp;
3587 struct lock_struct lock;
3588 struct smbd_server_connection *sconn = req->sconn;
3590 START_PROFILE(SMBread);
3592 if (req->wct < 3) {
3593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3594 END_PROFILE(SMBread);
3595 return;
3598 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3600 if (!check_fsp(conn, req, fsp)) {
3601 END_PROFILE(SMBread);
3602 return;
3605 if (!CHECK_READ(fsp,req)) {
3606 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3607 END_PROFILE(SMBread);
3608 return;
3611 numtoread = SVAL(req->vwv+1, 0);
3612 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3615 * The requested read size cannot be greater than max_send. JRA.
3617 maxtoread = sconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3619 if (numtoread > maxtoread) {
3620 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3621 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3622 (unsigned int)numtoread, (unsigned int)maxtoread,
3623 (unsigned int)sconn->smb1.sessions.max_send));
3624 numtoread = maxtoread;
3627 reply_outbuf(req, 5, numtoread+3);
3629 data = smb_buf(req->outbuf) + 3;
3631 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3632 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3633 &lock);
3635 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3636 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3637 END_PROFILE(SMBread);
3638 return;
3641 if (numtoread > 0)
3642 nread = read_file(fsp,data,startpos,numtoread);
3644 if (nread < 0) {
3645 reply_nterror(req, map_nt_error_from_unix(errno));
3646 goto strict_unlock;
3649 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3651 SSVAL(req->outbuf,smb_vwv0,nread);
3652 SSVAL(req->outbuf,smb_vwv5,nread+3);
3653 SCVAL(smb_buf(req->outbuf),0,1);
3654 SSVAL(smb_buf(req->outbuf),1,nread);
3656 DEBUG(3, ("read %s num=%d nread=%d\n",
3657 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3659 strict_unlock:
3660 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3662 END_PROFILE(SMBread);
3663 return;
3666 /****************************************************************************
3667 Setup readX header.
3668 ****************************************************************************/
3670 static int setup_readX_header(struct smb_request *req, char *outbuf,
3671 size_t smb_maxcnt)
3673 int outsize;
3675 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3677 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3679 SCVAL(outbuf,smb_vwv0,0xFF);
3680 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3681 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3682 SSVAL(outbuf,smb_vwv6,
3683 (smb_wct - 4) /* offset from smb header to wct */
3684 + 1 /* the wct field */
3685 + 12 * sizeof(uint16_t) /* vwv */
3686 + 2); /* the buflen field */
3687 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3688 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3689 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3690 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3691 return outsize;
3694 /****************************************************************************
3695 Reply to a read and X - possibly using sendfile.
3696 ****************************************************************************/
3698 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3699 files_struct *fsp, off_t startpos,
3700 size_t smb_maxcnt)
3702 struct smbXsrv_connection *xconn = req->sconn->conn;
3703 ssize_t nread = -1;
3704 struct lock_struct lock;
3705 int saved_errno = 0;
3707 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3708 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3709 &lock);
3711 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3712 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3713 return;
3717 * We can only use sendfile on a non-chained packet
3718 * but we can use on a non-oplocked file. tridge proved this
3719 * on a train in Germany :-). JRA.
3722 if (!req_is_in_chain(req) &&
3723 !req->encrypted &&
3724 (fsp->base_fsp == NULL) &&
3725 (fsp->wcp == NULL) &&
3726 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3727 uint8 headerbuf[smb_size + 12 * 2];
3728 DATA_BLOB header;
3730 if(fsp_stat(fsp) == -1) {
3731 reply_nterror(req, map_nt_error_from_unix(errno));
3732 goto strict_unlock;
3735 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3736 (startpos > fsp->fsp_name->st.st_ex_size) ||
3737 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3739 * We already know that we would do a short read, so don't
3740 * try the sendfile() path.
3742 goto nosendfile_read;
3746 * Set up the packet header before send. We
3747 * assume here the sendfile will work (get the
3748 * correct amount of data).
3751 header = data_blob_const(headerbuf, sizeof(headerbuf));
3753 construct_reply_common_req(req, (char *)headerbuf);
3754 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3756 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3757 startpos, smb_maxcnt);
3758 if (nread == -1) {
3759 saved_errno = errno;
3761 /* Returning ENOSYS means no data at all was sent.
3762 Do this as a normal read. */
3763 if (errno == ENOSYS) {
3764 goto normal_read;
3768 * Special hack for broken Linux with no working sendfile. If we
3769 * return EINTR we sent the header but not the rest of the data.
3770 * Fake this up by doing read/write calls.
3773 if (errno == EINTR) {
3774 /* Ensure we don't do this again. */
3775 set_use_sendfile(SNUM(conn), False);
3776 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3777 nread = fake_sendfile(fsp, startpos,
3778 smb_maxcnt);
3779 if (nread == -1) {
3780 saved_errno = errno;
3781 DEBUG(0,("send_file_readX: "
3782 "fake_sendfile failed for "
3783 "file %s (%s) for client %s. "
3784 "Terminating\n",
3785 fsp_str_dbg(fsp),
3786 smbXsrv_connection_dbg(xconn),
3787 strerror(saved_errno)));
3788 errno = saved_errno;
3789 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3791 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3792 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3793 /* No outbuf here means successful sendfile. */
3794 goto strict_unlock;
3797 DEBUG(0,("send_file_readX: sendfile failed for file "
3798 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3799 strerror(errno)));
3800 exit_server_cleanly("send_file_readX sendfile failed");
3801 } else if (nread == 0) {
3803 * Some sendfile implementations return 0 to indicate
3804 * that there was a short read, but nothing was
3805 * actually written to the socket. In this case,
3806 * fallback to the normal read path so the header gets
3807 * the correct byte count.
3809 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3810 "falling back to the normal read: %s\n",
3811 fsp_str_dbg(fsp)));
3812 goto normal_read;
3815 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3816 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3818 /* Deal with possible short send. */
3819 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3820 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3822 /* No outbuf here means successful sendfile. */
3823 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3824 SMB_PERFCOUNT_END(&req->pcd);
3825 goto strict_unlock;
3828 normal_read:
3830 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3831 uint8 headerbuf[smb_size + 2*12];
3832 ssize_t ret;
3834 construct_reply_common_req(req, (char *)headerbuf);
3835 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3837 /* Send out the header. */
3838 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3839 sizeof(headerbuf));
3840 if (ret != sizeof(headerbuf)) {
3841 saved_errno = errno;
3843 * Try and give an error message saying what
3844 * client failed.
3846 DEBUG(0,("send_file_readX: write_data failed for file "
3847 "%s (%s) for client %s. Terminating\n",
3848 fsp_str_dbg(fsp),
3849 smbXsrv_connection_dbg(xconn),
3850 strerror(saved_errno)));
3851 errno = saved_errno;
3852 exit_server_cleanly("send_file_readX sendfile failed");
3854 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3855 if (nread == -1) {
3856 saved_errno = errno;
3857 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3858 "%s (%s) for client %s. Terminating\n",
3859 fsp_str_dbg(fsp),
3860 smbXsrv_connection_dbg(xconn),
3861 strerror(saved_errno)));
3862 errno = saved_errno;
3863 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3865 goto strict_unlock;
3868 nosendfile_read:
3870 reply_outbuf(req, 12, smb_maxcnt);
3871 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3872 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3874 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3875 saved_errno = errno;
3877 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3879 if (nread < 0) {
3880 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3881 return;
3884 setup_readX_header(req, (char *)req->outbuf, nread);
3886 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3887 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3888 return;
3890 strict_unlock:
3891 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3892 TALLOC_FREE(req->outbuf);
3893 return;
3896 /****************************************************************************
3897 Work out how much space we have for a read return.
3898 ****************************************************************************/
3900 static size_t calc_max_read_pdu(const struct smb_request *req)
3902 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3903 return req->sconn->smb1.sessions.max_send;
3906 if (!lp_large_readwrite()) {
3907 return req->sconn->smb1.sessions.max_send;
3910 if (req_is_in_chain(req)) {
3911 return req->sconn->smb1.sessions.max_send;
3914 if (req->encrypted) {
3916 * Don't take encrypted traffic up to the
3917 * limit. There are padding considerations
3918 * that make that tricky.
3920 return req->sconn->smb1.sessions.max_send;
3923 if (srv_is_signing_active(req->sconn)) {
3924 return 0x1FFFF;
3927 if (!lp_unix_extensions()) {
3928 return 0x1FFFF;
3932 * We can do ultra-large POSIX reads.
3934 return 0xFFFFFF;
3937 /****************************************************************************
3938 Calculate how big a read can be. Copes with all clients. It's always
3939 safe to return a short read - Windows does this.
3940 ****************************************************************************/
3942 static size_t calc_read_size(const struct smb_request *req,
3943 size_t upper_size,
3944 size_t lower_size)
3946 size_t max_pdu = calc_max_read_pdu(req);
3947 size_t total_size = 0;
3948 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3949 size_t max_len = max_pdu - hdr_len;
3952 * Windows explicitly ignores upper size of 0xFFFF.
3953 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3954 * We must do the same as these will never fit even in
3955 * an extended size NetBIOS packet.
3957 if (upper_size == 0xFFFF) {
3958 upper_size = 0;
3961 if (req->sconn->conn->protocol < PROTOCOL_NT1) {
3962 upper_size = 0;
3965 total_size = ((upper_size<<16) | lower_size);
3968 * LARGE_READX test shows it's always safe to return
3969 * a short read. Windows does so.
3971 return MIN(total_size, max_len);
3974 /****************************************************************************
3975 Reply to a read and X.
3976 ****************************************************************************/
3978 void reply_read_and_X(struct smb_request *req)
3980 connection_struct *conn = req->conn;
3981 files_struct *fsp;
3982 off_t startpos;
3983 size_t smb_maxcnt;
3984 size_t upper_size;
3985 bool big_readX = False;
3986 #if 0
3987 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3988 #endif
3990 START_PROFILE(SMBreadX);
3992 if ((req->wct != 10) && (req->wct != 12)) {
3993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3994 return;
3997 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3998 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3999 smb_maxcnt = SVAL(req->vwv+5, 0);
4001 /* If it's an IPC, pass off the pipe handler. */
4002 if (IS_IPC(conn)) {
4003 reply_pipe_read_and_X(req);
4004 END_PROFILE(SMBreadX);
4005 return;
4008 if (!check_fsp(conn, req, fsp)) {
4009 END_PROFILE(SMBreadX);
4010 return;
4013 if (!CHECK_READ(fsp,req)) {
4014 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4015 END_PROFILE(SMBreadX);
4016 return;
4019 upper_size = SVAL(req->vwv+7, 0);
4020 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4021 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4023 * This is a heuristic to avoid keeping large
4024 * outgoing buffers around over long-lived aio
4025 * requests.
4027 big_readX = True;
4030 if (req->wct == 12) {
4032 * This is a large offset (64 bit) read.
4034 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4038 if (!big_readX) {
4039 NTSTATUS status = schedule_aio_read_and_X(conn,
4040 req,
4041 fsp,
4042 startpos,
4043 smb_maxcnt);
4044 if (NT_STATUS_IS_OK(status)) {
4045 /* Read scheduled - we're done. */
4046 goto out;
4048 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4049 /* Real error - report to client. */
4050 END_PROFILE(SMBreadX);
4051 reply_nterror(req, status);
4052 return;
4054 /* NT_STATUS_RETRY - fall back to sync read. */
4057 smbd_lock_socket(req->sconn);
4058 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4059 smbd_unlock_socket(req->sconn);
4061 out:
4062 END_PROFILE(SMBreadX);
4063 return;
4066 /****************************************************************************
4067 Error replies to writebraw must have smb_wct == 1. Fix this up.
4068 ****************************************************************************/
4070 void error_to_writebrawerr(struct smb_request *req)
4072 uint8 *old_outbuf = req->outbuf;
4074 reply_outbuf(req, 1, 0);
4076 memcpy(req->outbuf, old_outbuf, smb_size);
4077 TALLOC_FREE(old_outbuf);
4080 /****************************************************************************
4081 Read 4 bytes of a smb packet and return the smb length of the packet.
4082 Store the result in the buffer. This version of the function will
4083 never return a session keepalive (length of zero).
4084 Timeout is in milliseconds.
4085 ****************************************************************************/
4087 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4088 size_t *len)
4090 uint8_t msgtype = NBSSkeepalive;
4092 while (msgtype == NBSSkeepalive) {
4093 NTSTATUS status;
4095 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4096 len);
4097 if (!NT_STATUS_IS_OK(status)) {
4098 char addr[INET6_ADDRSTRLEN];
4099 /* Try and give an error message
4100 * saying what client failed. */
4101 DEBUG(0, ("read_fd_with_timeout failed for "
4102 "client %s read error = %s.\n",
4103 get_peer_addr(fd,addr,sizeof(addr)),
4104 nt_errstr(status)));
4105 return status;
4108 msgtype = CVAL(inbuf, 0);
4111 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4112 (unsigned long)len));
4114 return NT_STATUS_OK;
4117 /****************************************************************************
4118 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4119 ****************************************************************************/
4121 void reply_writebraw(struct smb_request *req)
4123 connection_struct *conn = req->conn;
4124 struct smbXsrv_connection *xconn = req->sconn->conn;
4125 char *buf = NULL;
4126 ssize_t nwritten=0;
4127 ssize_t total_written=0;
4128 size_t numtowrite=0;
4129 size_t tcount;
4130 off_t startpos;
4131 const char *data=NULL;
4132 bool write_through;
4133 files_struct *fsp;
4134 struct lock_struct lock;
4135 NTSTATUS status;
4137 START_PROFILE(SMBwritebraw);
4140 * If we ever reply with an error, it must have the SMB command
4141 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4142 * we're finished.
4144 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4146 if (srv_is_signing_active(req->sconn)) {
4147 END_PROFILE(SMBwritebraw);
4148 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4149 "raw reads/writes are disallowed.");
4152 if (req->wct < 12) {
4153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4154 error_to_writebrawerr(req);
4155 END_PROFILE(SMBwritebraw);
4156 return;
4159 if (req->sconn->smb1.echo_handler.trusted_fde) {
4160 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4161 "'async smb echo handler = yes'\n"));
4162 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4163 error_to_writebrawerr(req);
4164 END_PROFILE(SMBwritebraw);
4165 return;
4168 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4169 if (!check_fsp(conn, req, fsp)) {
4170 error_to_writebrawerr(req);
4171 END_PROFILE(SMBwritebraw);
4172 return;
4175 if (!CHECK_WRITE(fsp)) {
4176 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4177 error_to_writebrawerr(req);
4178 END_PROFILE(SMBwritebraw);
4179 return;
4182 tcount = IVAL(req->vwv+1, 0);
4183 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4184 write_through = BITSETW(req->vwv+7,0);
4186 /* We have to deal with slightly different formats depending
4187 on whether we are using the core+ or lanman1.0 protocol */
4189 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4190 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4191 data = smb_buf_const(req->inbuf);
4192 } else {
4193 numtowrite = SVAL(req->vwv+10, 0);
4194 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4197 /* Ensure we don't write bytes past the end of this packet. */
4198 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4200 error_to_writebrawerr(req);
4201 END_PROFILE(SMBwritebraw);
4202 return;
4205 if (!fsp->print_file) {
4206 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4207 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4208 &lock);
4210 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4211 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4212 error_to_writebrawerr(req);
4213 END_PROFILE(SMBwritebraw);
4214 return;
4218 if (numtowrite>0) {
4219 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4222 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4223 "wrote=%d sync=%d\n",
4224 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4225 (int)nwritten, (int)write_through));
4227 if (nwritten < (ssize_t)numtowrite) {
4228 reply_nterror(req, NT_STATUS_DISK_FULL);
4229 error_to_writebrawerr(req);
4230 goto strict_unlock;
4233 total_written = nwritten;
4235 /* Allocate a buffer of 64k + length. */
4236 buf = talloc_array(NULL, char, 65540);
4237 if (!buf) {
4238 reply_nterror(req, NT_STATUS_NO_MEMORY);
4239 error_to_writebrawerr(req);
4240 goto strict_unlock;
4243 /* Return a SMBwritebraw message to the redirector to tell
4244 * it to send more bytes */
4246 memcpy(buf, req->inbuf, smb_size);
4247 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4248 SCVAL(buf,smb_com,SMBwritebraw);
4249 SSVALS(buf,smb_vwv0,0xFFFF);
4250 show_msg(buf);
4251 if (!srv_send_smb(req->sconn,
4252 buf,
4253 false, 0, /* no signing */
4254 IS_CONN_ENCRYPTED(conn),
4255 &req->pcd)) {
4256 exit_server_cleanly("reply_writebraw: srv_send_smb "
4257 "failed.");
4260 /* Now read the raw data into the buffer and write it */
4261 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4262 &numtowrite);
4263 if (!NT_STATUS_IS_OK(status)) {
4264 exit_server_cleanly("secondary writebraw failed");
4267 /* Set up outbuf to return the correct size */
4268 reply_outbuf(req, 1, 0);
4270 if (numtowrite != 0) {
4272 if (numtowrite > 0xFFFF) {
4273 DEBUG(0,("reply_writebraw: Oversize secondary write "
4274 "raw requested (%u). Terminating\n",
4275 (unsigned int)numtowrite ));
4276 exit_server_cleanly("secondary writebraw failed");
4279 if (tcount > nwritten+numtowrite) {
4280 DEBUG(3,("reply_writebraw: Client overestimated the "
4281 "write %d %d %d\n",
4282 (int)tcount,(int)nwritten,(int)numtowrite));
4285 status = read_data(xconn->transport.sock, buf+4, numtowrite);
4287 if (!NT_STATUS_IS_OK(status)) {
4288 /* Try and give an error message
4289 * saying what client failed. */
4290 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4291 "raw read failed (%s) for client %s. "
4292 "Terminating\n", nt_errstr(status),
4293 smbXsrv_connection_dbg(xconn)));
4294 exit_server_cleanly("secondary writebraw failed");
4297 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4298 if (nwritten == -1) {
4299 TALLOC_FREE(buf);
4300 reply_nterror(req, map_nt_error_from_unix(errno));
4301 error_to_writebrawerr(req);
4302 goto strict_unlock;
4305 if (nwritten < (ssize_t)numtowrite) {
4306 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4307 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4310 if (nwritten > 0) {
4311 total_written += nwritten;
4315 TALLOC_FREE(buf);
4316 SSVAL(req->outbuf,smb_vwv0,total_written);
4318 status = sync_file(conn, fsp, write_through);
4319 if (!NT_STATUS_IS_OK(status)) {
4320 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4321 fsp_str_dbg(fsp), nt_errstr(status)));
4322 reply_nterror(req, status);
4323 error_to_writebrawerr(req);
4324 goto strict_unlock;
4327 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4328 "wrote=%d\n",
4329 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4330 (int)total_written));
4332 if (!fsp->print_file) {
4333 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4336 /* We won't return a status if write through is not selected - this
4337 * follows what WfWg does */
4338 END_PROFILE(SMBwritebraw);
4340 if (!write_through && total_written==tcount) {
4342 #if RABBIT_PELLET_FIX
4344 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4345 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4346 * JRA.
4348 if (!send_keepalive(xconn->transport.sock)) {
4349 exit_server_cleanly("reply_writebraw: send of "
4350 "keepalive failed");
4352 #endif
4353 TALLOC_FREE(req->outbuf);
4355 return;
4357 strict_unlock:
4358 if (!fsp->print_file) {
4359 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4362 END_PROFILE(SMBwritebraw);
4363 return;
4366 #undef DBGC_CLASS
4367 #define DBGC_CLASS DBGC_LOCKING
4369 /****************************************************************************
4370 Reply to a writeunlock (core+).
4371 ****************************************************************************/
4373 void reply_writeunlock(struct smb_request *req)
4375 connection_struct *conn = req->conn;
4376 ssize_t nwritten = -1;
4377 size_t numtowrite;
4378 off_t startpos;
4379 const char *data;
4380 NTSTATUS status = NT_STATUS_OK;
4381 files_struct *fsp;
4382 struct lock_struct lock;
4383 int saved_errno = 0;
4385 START_PROFILE(SMBwriteunlock);
4387 if (req->wct < 5) {
4388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4389 END_PROFILE(SMBwriteunlock);
4390 return;
4393 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4395 if (!check_fsp(conn, req, fsp)) {
4396 END_PROFILE(SMBwriteunlock);
4397 return;
4400 if (!CHECK_WRITE(fsp)) {
4401 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4402 END_PROFILE(SMBwriteunlock);
4403 return;
4406 numtowrite = SVAL(req->vwv+1, 0);
4407 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4408 data = (const char *)req->buf + 3;
4410 if (!fsp->print_file && numtowrite > 0) {
4411 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4412 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4413 &lock);
4415 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4416 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4417 END_PROFILE(SMBwriteunlock);
4418 return;
4422 /* The special X/Open SMB protocol handling of
4423 zero length writes is *NOT* done for
4424 this call */
4425 if(numtowrite == 0) {
4426 nwritten = 0;
4427 } else {
4428 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4429 saved_errno = errno;
4432 status = sync_file(conn, fsp, False /* write through */);
4433 if (!NT_STATUS_IS_OK(status)) {
4434 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4435 fsp_str_dbg(fsp), nt_errstr(status)));
4436 reply_nterror(req, status);
4437 goto strict_unlock;
4440 if(nwritten < 0) {
4441 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4442 goto strict_unlock;
4445 if((nwritten < numtowrite) && (numtowrite != 0)) {
4446 reply_nterror(req, NT_STATUS_DISK_FULL);
4447 goto strict_unlock;
4450 if (numtowrite && !fsp->print_file) {
4451 status = do_unlock(req->sconn->msg_ctx,
4452 fsp,
4453 (uint64_t)req->smbpid,
4454 (uint64_t)numtowrite,
4455 (uint64_t)startpos,
4456 WINDOWS_LOCK);
4458 if (NT_STATUS_V(status)) {
4459 reply_nterror(req, status);
4460 goto strict_unlock;
4464 reply_outbuf(req, 1, 0);
4466 SSVAL(req->outbuf,smb_vwv0,nwritten);
4468 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4469 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4471 strict_unlock:
4472 if (numtowrite && !fsp->print_file) {
4473 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4476 END_PROFILE(SMBwriteunlock);
4477 return;
4480 #undef DBGC_CLASS
4481 #define DBGC_CLASS DBGC_ALL
4483 /****************************************************************************
4484 Reply to a write.
4485 ****************************************************************************/
4487 void reply_write(struct smb_request *req)
4489 connection_struct *conn = req->conn;
4490 size_t numtowrite;
4491 ssize_t nwritten = -1;
4492 off_t startpos;
4493 const char *data;
4494 files_struct *fsp;
4495 struct lock_struct lock;
4496 NTSTATUS status;
4497 int saved_errno = 0;
4499 START_PROFILE(SMBwrite);
4501 if (req->wct < 5) {
4502 END_PROFILE(SMBwrite);
4503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4504 return;
4507 /* If it's an IPC, pass off the pipe handler. */
4508 if (IS_IPC(conn)) {
4509 reply_pipe_write(req);
4510 END_PROFILE(SMBwrite);
4511 return;
4514 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4516 if (!check_fsp(conn, req, fsp)) {
4517 END_PROFILE(SMBwrite);
4518 return;
4521 if (!CHECK_WRITE(fsp)) {
4522 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4523 END_PROFILE(SMBwrite);
4524 return;
4527 numtowrite = SVAL(req->vwv+1, 0);
4528 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4529 data = (const char *)req->buf + 3;
4531 if (!fsp->print_file) {
4532 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4533 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4534 &lock);
4536 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4537 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4538 END_PROFILE(SMBwrite);
4539 return;
4544 * X/Open SMB protocol says that if smb_vwv1 is
4545 * zero then the file size should be extended or
4546 * truncated to the size given in smb_vwv[2-3].
4549 if(numtowrite == 0) {
4551 * This is actually an allocate call, and set EOF. JRA.
4553 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4554 if (nwritten < 0) {
4555 reply_nterror(req, NT_STATUS_DISK_FULL);
4556 goto strict_unlock;
4558 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4559 if (nwritten < 0) {
4560 reply_nterror(req, NT_STATUS_DISK_FULL);
4561 goto strict_unlock;
4563 trigger_write_time_update_immediate(fsp);
4564 } else {
4565 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4568 status = sync_file(conn, fsp, False);
4569 if (!NT_STATUS_IS_OK(status)) {
4570 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4571 fsp_str_dbg(fsp), nt_errstr(status)));
4572 reply_nterror(req, status);
4573 goto strict_unlock;
4576 if(nwritten < 0) {
4577 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4578 goto strict_unlock;
4581 if((nwritten == 0) && (numtowrite != 0)) {
4582 reply_nterror(req, NT_STATUS_DISK_FULL);
4583 goto strict_unlock;
4586 reply_outbuf(req, 1, 0);
4588 SSVAL(req->outbuf,smb_vwv0,nwritten);
4590 if (nwritten < (ssize_t)numtowrite) {
4591 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4592 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4595 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4597 strict_unlock:
4598 if (!fsp->print_file) {
4599 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4602 END_PROFILE(SMBwrite);
4603 return;
4606 /****************************************************************************
4607 Ensure a buffer is a valid writeX for recvfile purposes.
4608 ****************************************************************************/
4610 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4611 (2*14) + /* word count (including bcc) */ \
4612 1 /* pad byte */)
4614 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4615 const uint8_t *inbuf)
4617 size_t numtowrite;
4618 unsigned int doff = 0;
4619 size_t len = smb_len_large(inbuf);
4620 uint16_t fnum;
4621 struct smbXsrv_open *op = NULL;
4622 struct files_struct *fsp = NULL;
4623 NTSTATUS status;
4625 if (is_encrypted_packet(sconn, inbuf)) {
4626 /* Can't do this on encrypted
4627 * connections. */
4628 return false;
4631 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4632 return false;
4635 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4636 CVAL(inbuf,smb_wct) != 14) {
4637 DEBUG(10,("is_valid_writeX_buffer: chained or "
4638 "invalid word length.\n"));
4639 return false;
4642 fnum = SVAL(inbuf, smb_vwv2);
4643 status = smb1srv_open_lookup(sconn->conn,
4644 fnum,
4645 0, /* now */
4646 &op);
4647 if (!NT_STATUS_IS_OK(status)) {
4648 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4649 return false;
4651 fsp = op->compat;
4652 if (fsp == NULL) {
4653 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4654 return false;
4656 if (fsp->conn == NULL) {
4657 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4658 return false;
4661 if (IS_IPC(fsp->conn)) {
4662 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4663 return false;
4665 if (IS_PRINT(fsp->conn)) {
4666 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4667 return false;
4669 doff = SVAL(inbuf,smb_vwv11);
4671 numtowrite = SVAL(inbuf,smb_vwv10);
4673 if (len > doff && len - doff > 0xFFFF) {
4674 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4677 if (numtowrite == 0) {
4678 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4679 return false;
4682 /* Ensure the sizes match up. */
4683 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4684 /* no pad byte...old smbclient :-( */
4685 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4686 (unsigned int)doff,
4687 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4688 return false;
4691 if (len - doff != numtowrite) {
4692 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4693 "len = %u, doff = %u, numtowrite = %u\n",
4694 (unsigned int)len,
4695 (unsigned int)doff,
4696 (unsigned int)numtowrite ));
4697 return false;
4700 DEBUG(10,("is_valid_writeX_buffer: true "
4701 "len = %u, doff = %u, numtowrite = %u\n",
4702 (unsigned int)len,
4703 (unsigned int)doff,
4704 (unsigned int)numtowrite ));
4706 return true;
4709 /****************************************************************************
4710 Reply to a write and X.
4711 ****************************************************************************/
4713 void reply_write_and_X(struct smb_request *req)
4715 connection_struct *conn = req->conn;
4716 struct smbXsrv_connection *xconn = req->sconn->conn;
4717 files_struct *fsp;
4718 struct lock_struct lock;
4719 off_t startpos;
4720 size_t numtowrite;
4721 bool write_through;
4722 ssize_t nwritten;
4723 unsigned int smb_doff;
4724 unsigned int smblen;
4725 const char *data;
4726 NTSTATUS status;
4727 int saved_errno = 0;
4729 START_PROFILE(SMBwriteX);
4731 if ((req->wct != 12) && (req->wct != 14)) {
4732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4733 goto out;
4736 numtowrite = SVAL(req->vwv+10, 0);
4737 smb_doff = SVAL(req->vwv+11, 0);
4738 smblen = smb_len(req->inbuf);
4740 if (req->unread_bytes > 0xFFFF ||
4741 (smblen > smb_doff &&
4742 smblen - smb_doff > 0xFFFF)) {
4743 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4746 if (req->unread_bytes) {
4747 /* Can't do a recvfile write on IPC$ */
4748 if (IS_IPC(conn)) {
4749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4750 goto out;
4752 if (numtowrite != req->unread_bytes) {
4753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4754 goto out;
4756 } else {
4757 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4758 smb_doff + numtowrite > smblen) {
4759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4760 goto out;
4764 /* If it's an IPC, pass off the pipe handler. */
4765 if (IS_IPC(conn)) {
4766 if (req->unread_bytes) {
4767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4768 goto out;
4770 reply_pipe_write_and_X(req);
4771 goto out;
4774 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4775 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4776 write_through = BITSETW(req->vwv+7,0);
4778 if (!check_fsp(conn, req, fsp)) {
4779 goto out;
4782 if (!CHECK_WRITE(fsp)) {
4783 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4784 goto out;
4787 data = smb_base(req->inbuf) + smb_doff;
4789 if(req->wct == 14) {
4791 * This is a large offset (64 bit) write.
4793 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4797 /* X/Open SMB protocol says that, unlike SMBwrite
4798 if the length is zero then NO truncation is
4799 done, just a write of zero. To truncate a file,
4800 use SMBwrite. */
4802 if(numtowrite == 0) {
4803 nwritten = 0;
4804 } else {
4805 if (req->unread_bytes == 0) {
4806 status = schedule_aio_write_and_X(conn,
4807 req,
4808 fsp,
4809 data,
4810 startpos,
4811 numtowrite);
4813 if (NT_STATUS_IS_OK(status)) {
4814 /* write scheduled - we're done. */
4815 goto out;
4817 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4818 /* Real error - report to client. */
4819 reply_nterror(req, status);
4820 goto out;
4822 /* NT_STATUS_RETRY - fall through to sync write. */
4825 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4826 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4827 &lock);
4829 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4830 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4831 goto out;
4834 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4835 saved_errno = errno;
4837 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4840 if(nwritten < 0) {
4841 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4842 goto out;
4845 if((nwritten == 0) && (numtowrite != 0)) {
4846 reply_nterror(req, NT_STATUS_DISK_FULL);
4847 goto out;
4850 reply_outbuf(req, 6, 0);
4851 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4852 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4853 SSVAL(req->outbuf,smb_vwv2,nwritten);
4854 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4856 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4857 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4859 status = sync_file(conn, fsp, write_through);
4860 if (!NT_STATUS_IS_OK(status)) {
4861 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4862 fsp_str_dbg(fsp), nt_errstr(status)));
4863 reply_nterror(req, status);
4864 goto out;
4867 END_PROFILE(SMBwriteX);
4868 return;
4870 out:
4871 if (req->unread_bytes) {
4872 /* writeX failed. drain socket. */
4873 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4874 req->unread_bytes) {
4875 smb_panic("failed to drain pending bytes");
4877 req->unread_bytes = 0;
4880 END_PROFILE(SMBwriteX);
4881 return;
4884 /****************************************************************************
4885 Reply to a lseek.
4886 ****************************************************************************/
4888 void reply_lseek(struct smb_request *req)
4890 connection_struct *conn = req->conn;
4891 off_t startpos;
4892 off_t res= -1;
4893 int mode,umode;
4894 files_struct *fsp;
4896 START_PROFILE(SMBlseek);
4898 if (req->wct < 4) {
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 END_PROFILE(SMBlseek);
4901 return;
4904 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4906 if (!check_fsp(conn, req, fsp)) {
4907 return;
4910 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4912 mode = SVAL(req->vwv+1, 0) & 3;
4913 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4914 startpos = (off_t)IVALS(req->vwv+2, 0);
4916 switch (mode) {
4917 case 0:
4918 umode = SEEK_SET;
4919 res = startpos;
4920 break;
4921 case 1:
4922 umode = SEEK_CUR;
4923 res = fsp->fh->pos + startpos;
4924 break;
4925 case 2:
4926 umode = SEEK_END;
4927 break;
4928 default:
4929 umode = SEEK_SET;
4930 res = startpos;
4931 break;
4934 if (umode == SEEK_END) {
4935 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4936 if(errno == EINVAL) {
4937 off_t current_pos = startpos;
4939 if(fsp_stat(fsp) == -1) {
4940 reply_nterror(req,
4941 map_nt_error_from_unix(errno));
4942 END_PROFILE(SMBlseek);
4943 return;
4946 current_pos += fsp->fsp_name->st.st_ex_size;
4947 if(current_pos < 0)
4948 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4952 if(res == -1) {
4953 reply_nterror(req, map_nt_error_from_unix(errno));
4954 END_PROFILE(SMBlseek);
4955 return;
4959 fsp->fh->pos = res;
4961 reply_outbuf(req, 2, 0);
4962 SIVAL(req->outbuf,smb_vwv0,res);
4964 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4965 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4967 END_PROFILE(SMBlseek);
4968 return;
4971 /****************************************************************************
4972 Reply to a flush.
4973 ****************************************************************************/
4975 void reply_flush(struct smb_request *req)
4977 connection_struct *conn = req->conn;
4978 uint16 fnum;
4979 files_struct *fsp;
4981 START_PROFILE(SMBflush);
4983 if (req->wct < 1) {
4984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985 return;
4988 fnum = SVAL(req->vwv+0, 0);
4989 fsp = file_fsp(req, fnum);
4991 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4992 return;
4995 if (!fsp) {
4996 file_sync_all(conn);
4997 } else {
4998 NTSTATUS status = sync_file(conn, fsp, True);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5001 fsp_str_dbg(fsp), nt_errstr(status)));
5002 reply_nterror(req, status);
5003 END_PROFILE(SMBflush);
5004 return;
5008 reply_outbuf(req, 0, 0);
5010 DEBUG(3,("flush\n"));
5011 END_PROFILE(SMBflush);
5012 return;
5015 /****************************************************************************
5016 Reply to a exit.
5017 conn POINTER CAN BE NULL HERE !
5018 ****************************************************************************/
5020 void reply_exit(struct smb_request *req)
5022 START_PROFILE(SMBexit);
5024 file_close_pid(req->sconn, req->smbpid, req->vuid);
5026 reply_outbuf(req, 0, 0);
5028 DEBUG(3,("exit\n"));
5030 END_PROFILE(SMBexit);
5031 return;
5034 struct reply_close_state {
5035 files_struct *fsp;
5036 struct smb_request *smbreq;
5039 static void do_smb1_close(struct tevent_req *req);
5041 void reply_close(struct smb_request *req)
5043 connection_struct *conn = req->conn;
5044 NTSTATUS status = NT_STATUS_OK;
5045 files_struct *fsp = NULL;
5046 START_PROFILE(SMBclose);
5048 if (req->wct < 3) {
5049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5050 END_PROFILE(SMBclose);
5051 return;
5054 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5057 * We can only use check_fsp if we know it's not a directory.
5060 if (!check_fsp_open(conn, req, fsp)) {
5061 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5062 END_PROFILE(SMBclose);
5063 return;
5066 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5067 fsp->is_directory ? "directory" : "file",
5068 fsp->fh->fd, fsp_fnum_dbg(fsp),
5069 conn->num_files_open));
5071 if (!fsp->is_directory) {
5072 time_t t;
5075 * Take care of any time sent in the close.
5078 t = srv_make_unix_date3(req->vwv+1);
5079 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5082 if (fsp->num_aio_requests != 0) {
5084 struct reply_close_state *state;
5086 DEBUG(10, ("closing with aio %u requests pending\n",
5087 fsp->num_aio_requests));
5090 * We depend on the aio_extra destructor to take care of this
5091 * close request once fsp->num_aio_request drops to 0.
5094 fsp->deferred_close = tevent_wait_send(
5095 fsp, fsp->conn->sconn->ev_ctx);
5096 if (fsp->deferred_close == NULL) {
5097 status = NT_STATUS_NO_MEMORY;
5098 goto done;
5101 state = talloc(fsp, struct reply_close_state);
5102 if (state == NULL) {
5103 TALLOC_FREE(fsp->deferred_close);
5104 status = NT_STATUS_NO_MEMORY;
5105 goto done;
5107 state->fsp = fsp;
5108 state->smbreq = talloc_move(fsp, &req);
5109 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5110 state);
5111 END_PROFILE(SMBclose);
5112 return;
5116 * close_file() returns the unix errno if an error was detected on
5117 * close - normally this is due to a disk full error. If not then it
5118 * was probably an I/O error.
5121 status = close_file(req, fsp, NORMAL_CLOSE);
5122 done:
5123 if (!NT_STATUS_IS_OK(status)) {
5124 reply_nterror(req, status);
5125 END_PROFILE(SMBclose);
5126 return;
5129 reply_outbuf(req, 0, 0);
5130 END_PROFILE(SMBclose);
5131 return;
5134 static void do_smb1_close(struct tevent_req *req)
5136 struct reply_close_state *state = tevent_req_callback_data(
5137 req, struct reply_close_state);
5138 struct smb_request *smbreq;
5139 NTSTATUS status;
5140 int ret;
5142 ret = tevent_wait_recv(req);
5143 TALLOC_FREE(req);
5144 if (ret != 0) {
5145 DEBUG(10, ("tevent_wait_recv returned %s\n",
5146 strerror(ret)));
5148 * Continue anyway, this should never happen
5153 * fsp->smb2_close_request right now is a talloc grandchild of
5154 * fsp. When we close_file(fsp), it would go with it. No chance to
5155 * reply...
5157 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5159 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5160 if (NT_STATUS_IS_OK(status)) {
5161 reply_outbuf(smbreq, 0, 0);
5162 } else {
5163 reply_nterror(smbreq, status);
5165 if (!srv_send_smb(smbreq->sconn,
5166 (char *)smbreq->outbuf,
5167 true,
5168 smbreq->seqnum+1,
5169 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5170 NULL)) {
5171 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5172 "failed.");
5174 TALLOC_FREE(smbreq);
5177 /****************************************************************************
5178 Reply to a writeclose (Core+ protocol).
5179 ****************************************************************************/
5181 void reply_writeclose(struct smb_request *req)
5183 connection_struct *conn = req->conn;
5184 size_t numtowrite;
5185 ssize_t nwritten = -1;
5186 NTSTATUS close_status = NT_STATUS_OK;
5187 off_t startpos;
5188 const char *data;
5189 struct timespec mtime;
5190 files_struct *fsp;
5191 struct lock_struct lock;
5193 START_PROFILE(SMBwriteclose);
5195 if (req->wct < 6) {
5196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5197 END_PROFILE(SMBwriteclose);
5198 return;
5201 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5203 if (!check_fsp(conn, req, fsp)) {
5204 END_PROFILE(SMBwriteclose);
5205 return;
5207 if (!CHECK_WRITE(fsp)) {
5208 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5209 END_PROFILE(SMBwriteclose);
5210 return;
5213 numtowrite = SVAL(req->vwv+1, 0);
5214 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5215 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5216 data = (const char *)req->buf + 1;
5218 if (fsp->print_file == NULL) {
5219 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5220 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5221 &lock);
5223 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5224 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5225 END_PROFILE(SMBwriteclose);
5226 return;
5230 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5232 if (fsp->print_file == NULL) {
5233 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5236 set_close_write_time(fsp, mtime);
5239 * More insanity. W2K only closes the file if writelen > 0.
5240 * JRA.
5243 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5244 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5245 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5247 if (numtowrite) {
5248 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5249 "file %s\n", fsp_str_dbg(fsp)));
5250 close_status = close_file(req, fsp, NORMAL_CLOSE);
5251 fsp = NULL;
5254 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5255 reply_nterror(req, NT_STATUS_DISK_FULL);
5256 goto out;
5259 if(!NT_STATUS_IS_OK(close_status)) {
5260 reply_nterror(req, close_status);
5261 goto out;
5264 reply_outbuf(req, 1, 0);
5266 SSVAL(req->outbuf,smb_vwv0,nwritten);
5268 out:
5270 END_PROFILE(SMBwriteclose);
5271 return;
5274 #undef DBGC_CLASS
5275 #define DBGC_CLASS DBGC_LOCKING
5277 /****************************************************************************
5278 Reply to a lock.
5279 ****************************************************************************/
5281 void reply_lock(struct smb_request *req)
5283 connection_struct *conn = req->conn;
5284 uint64_t count,offset;
5285 NTSTATUS status;
5286 files_struct *fsp;
5287 struct byte_range_lock *br_lck = NULL;
5289 START_PROFILE(SMBlock);
5291 if (req->wct < 5) {
5292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5293 END_PROFILE(SMBlock);
5294 return;
5297 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5299 if (!check_fsp(conn, req, fsp)) {
5300 END_PROFILE(SMBlock);
5301 return;
5304 count = (uint64_t)IVAL(req->vwv+1, 0);
5305 offset = (uint64_t)IVAL(req->vwv+3, 0);
5307 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5308 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5310 br_lck = do_lock(req->sconn->msg_ctx,
5311 fsp,
5312 (uint64_t)req->smbpid,
5313 count,
5314 offset,
5315 WRITE_LOCK,
5316 WINDOWS_LOCK,
5317 False, /* Non-blocking lock. */
5318 &status,
5319 NULL);
5321 TALLOC_FREE(br_lck);
5323 if (NT_STATUS_V(status)) {
5324 reply_nterror(req, status);
5325 END_PROFILE(SMBlock);
5326 return;
5329 reply_outbuf(req, 0, 0);
5331 END_PROFILE(SMBlock);
5332 return;
5335 /****************************************************************************
5336 Reply to a unlock.
5337 ****************************************************************************/
5339 void reply_unlock(struct smb_request *req)
5341 connection_struct *conn = req->conn;
5342 uint64_t count,offset;
5343 NTSTATUS status;
5344 files_struct *fsp;
5346 START_PROFILE(SMBunlock);
5348 if (req->wct < 5) {
5349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5350 END_PROFILE(SMBunlock);
5351 return;
5354 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5356 if (!check_fsp(conn, req, fsp)) {
5357 END_PROFILE(SMBunlock);
5358 return;
5361 count = (uint64_t)IVAL(req->vwv+1, 0);
5362 offset = (uint64_t)IVAL(req->vwv+3, 0);
5364 status = do_unlock(req->sconn->msg_ctx,
5365 fsp,
5366 (uint64_t)req->smbpid,
5367 count,
5368 offset,
5369 WINDOWS_LOCK);
5371 if (NT_STATUS_V(status)) {
5372 reply_nterror(req, status);
5373 END_PROFILE(SMBunlock);
5374 return;
5377 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5378 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5380 reply_outbuf(req, 0, 0);
5382 END_PROFILE(SMBunlock);
5383 return;
5386 #undef DBGC_CLASS
5387 #define DBGC_CLASS DBGC_ALL
5389 /****************************************************************************
5390 Reply to a tdis.
5391 conn POINTER CAN BE NULL HERE !
5392 ****************************************************************************/
5394 void reply_tdis(struct smb_request *req)
5396 NTSTATUS status;
5397 connection_struct *conn = req->conn;
5398 struct smbXsrv_tcon *tcon;
5400 START_PROFILE(SMBtdis);
5402 if (!conn) {
5403 DEBUG(4,("Invalid connection in tdis\n"));
5404 reply_force_doserror(req, ERRSRV, ERRinvnid);
5405 END_PROFILE(SMBtdis);
5406 return;
5409 tcon = conn->tcon;
5410 req->conn = NULL;
5413 * TODO: cancel all outstanding requests on the tcon
5415 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5416 if (!NT_STATUS_IS_OK(status)) {
5417 DEBUG(0, ("reply_tdis: "
5418 "smbXsrv_tcon_disconnect() failed: %s\n",
5419 nt_errstr(status)));
5421 * If we hit this case, there is something completely
5422 * wrong, so we better disconnect the transport connection.
5424 END_PROFILE(SMBtdis);
5425 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5426 return;
5429 TALLOC_FREE(tcon);
5431 reply_outbuf(req, 0, 0);
5432 END_PROFILE(SMBtdis);
5433 return;
5436 /****************************************************************************
5437 Reply to a echo.
5438 conn POINTER CAN BE NULL HERE !
5439 ****************************************************************************/
5441 void reply_echo(struct smb_request *req)
5443 connection_struct *conn = req->conn;
5444 struct smb_perfcount_data local_pcd;
5445 struct smb_perfcount_data *cur_pcd;
5446 int smb_reverb;
5447 int seq_num;
5449 START_PROFILE(SMBecho);
5451 smb_init_perfcount_data(&local_pcd);
5453 if (req->wct < 1) {
5454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5455 END_PROFILE(SMBecho);
5456 return;
5459 smb_reverb = SVAL(req->vwv+0, 0);
5461 reply_outbuf(req, 1, req->buflen);
5463 /* copy any incoming data back out */
5464 if (req->buflen > 0) {
5465 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5468 if (smb_reverb > 100) {
5469 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5470 smb_reverb = 100;
5473 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5475 /* this makes sure we catch the request pcd */
5476 if (seq_num == smb_reverb) {
5477 cur_pcd = &req->pcd;
5478 } else {
5479 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5480 cur_pcd = &local_pcd;
5483 SSVAL(req->outbuf,smb_vwv0,seq_num);
5485 show_msg((char *)req->outbuf);
5486 if (!srv_send_smb(req->sconn,
5487 (char *)req->outbuf,
5488 true, req->seqnum+1,
5489 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5490 cur_pcd))
5491 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5494 DEBUG(3,("echo %d times\n", smb_reverb));
5496 TALLOC_FREE(req->outbuf);
5498 END_PROFILE(SMBecho);
5499 return;
5502 /****************************************************************************
5503 Reply to a printopen.
5504 ****************************************************************************/
5506 void reply_printopen(struct smb_request *req)
5508 connection_struct *conn = req->conn;
5509 files_struct *fsp;
5510 NTSTATUS status;
5512 START_PROFILE(SMBsplopen);
5514 if (req->wct < 2) {
5515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5516 END_PROFILE(SMBsplopen);
5517 return;
5520 if (!CAN_PRINT(conn)) {
5521 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5522 END_PROFILE(SMBsplopen);
5523 return;
5526 status = file_new(req, conn, &fsp);
5527 if(!NT_STATUS_IS_OK(status)) {
5528 reply_nterror(req, status);
5529 END_PROFILE(SMBsplopen);
5530 return;
5533 /* Open for exclusive use, write only. */
5534 status = print_spool_open(fsp, NULL, req->vuid);
5536 if (!NT_STATUS_IS_OK(status)) {
5537 file_free(req, fsp);
5538 reply_nterror(req, status);
5539 END_PROFILE(SMBsplopen);
5540 return;
5543 reply_outbuf(req, 1, 0);
5544 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5546 DEBUG(3,("openprint fd=%d %s\n",
5547 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5549 END_PROFILE(SMBsplopen);
5550 return;
5553 /****************************************************************************
5554 Reply to a printclose.
5555 ****************************************************************************/
5557 void reply_printclose(struct smb_request *req)
5559 connection_struct *conn = req->conn;
5560 files_struct *fsp;
5561 NTSTATUS status;
5563 START_PROFILE(SMBsplclose);
5565 if (req->wct < 1) {
5566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5567 END_PROFILE(SMBsplclose);
5568 return;
5571 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5573 if (!check_fsp(conn, req, fsp)) {
5574 END_PROFILE(SMBsplclose);
5575 return;
5578 if (!CAN_PRINT(conn)) {
5579 reply_force_doserror(req, ERRSRV, ERRerror);
5580 END_PROFILE(SMBsplclose);
5581 return;
5584 DEBUG(3,("printclose fd=%d %s\n",
5585 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5587 status = close_file(req, fsp, NORMAL_CLOSE);
5589 if(!NT_STATUS_IS_OK(status)) {
5590 reply_nterror(req, status);
5591 END_PROFILE(SMBsplclose);
5592 return;
5595 reply_outbuf(req, 0, 0);
5597 END_PROFILE(SMBsplclose);
5598 return;
5601 /****************************************************************************
5602 Reply to a printqueue.
5603 ****************************************************************************/
5605 void reply_printqueue(struct smb_request *req)
5607 connection_struct *conn = req->conn;
5608 int max_count;
5609 int start_index;
5611 START_PROFILE(SMBsplretq);
5613 if (req->wct < 2) {
5614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5615 END_PROFILE(SMBsplretq);
5616 return;
5619 max_count = SVAL(req->vwv+0, 0);
5620 start_index = SVAL(req->vwv+1, 0);
5622 /* we used to allow the client to get the cnum wrong, but that
5623 is really quite gross and only worked when there was only
5624 one printer - I think we should now only accept it if they
5625 get it right (tridge) */
5626 if (!CAN_PRINT(conn)) {
5627 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5628 END_PROFILE(SMBsplretq);
5629 return;
5632 reply_outbuf(req, 2, 3);
5633 SSVAL(req->outbuf,smb_vwv0,0);
5634 SSVAL(req->outbuf,smb_vwv1,0);
5635 SCVAL(smb_buf(req->outbuf),0,1);
5636 SSVAL(smb_buf(req->outbuf),1,0);
5638 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5639 start_index, max_count));
5642 TALLOC_CTX *mem_ctx = talloc_tos();
5643 NTSTATUS status;
5644 WERROR werr;
5645 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5646 struct rpc_pipe_client *cli = NULL;
5647 struct dcerpc_binding_handle *b = NULL;
5648 struct policy_handle handle;
5649 struct spoolss_DevmodeContainer devmode_ctr;
5650 union spoolss_JobInfo *info;
5651 uint32_t count;
5652 uint32_t num_to_get;
5653 uint32_t first;
5654 uint32_t i;
5656 ZERO_STRUCT(handle);
5658 status = rpc_pipe_open_interface(conn,
5659 &ndr_table_spoolss,
5660 conn->session_info,
5661 conn->sconn->remote_address,
5662 conn->sconn->msg_ctx,
5663 &cli);
5664 if (!NT_STATUS_IS_OK(status)) {
5665 DEBUG(0, ("reply_printqueue: "
5666 "could not connect to spoolss: %s\n",
5667 nt_errstr(status)));
5668 reply_nterror(req, status);
5669 goto out;
5671 b = cli->binding_handle;
5673 ZERO_STRUCT(devmode_ctr);
5675 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5676 sharename,
5677 NULL, devmode_ctr,
5678 SEC_FLAG_MAXIMUM_ALLOWED,
5679 &handle,
5680 &werr);
5681 if (!NT_STATUS_IS_OK(status)) {
5682 reply_nterror(req, status);
5683 goto out;
5685 if (!W_ERROR_IS_OK(werr)) {
5686 reply_nterror(req, werror_to_ntstatus(werr));
5687 goto out;
5690 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5691 &handle,
5692 0, /* firstjob */
5693 0xff, /* numjobs */
5694 2, /* level */
5695 0, /* offered */
5696 &count,
5697 &info);
5698 if (!W_ERROR_IS_OK(werr)) {
5699 reply_nterror(req, werror_to_ntstatus(werr));
5700 goto out;
5703 if (max_count > 0) {
5704 first = start_index;
5705 } else {
5706 first = start_index + max_count + 1;
5709 if (first >= count) {
5710 num_to_get = first;
5711 } else {
5712 num_to_get = first + MIN(ABS(max_count), count - first);
5715 for (i = first; i < num_to_get; i++) {
5716 char blob[28];
5717 char *p = blob;
5718 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5719 int qstatus;
5720 uint16_t qrapjobid = pjobid_to_rap(sharename,
5721 info[i].info2.job_id);
5723 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5724 qstatus = 2;
5725 } else {
5726 qstatus = 3;
5729 srv_put_dos_date2(p, 0, qtime);
5730 SCVAL(p, 4, qstatus);
5731 SSVAL(p, 5, qrapjobid);
5732 SIVAL(p, 7, info[i].info2.size);
5733 SCVAL(p, 11, 0);
5734 srvstr_push(blob, req->flags2, p+12,
5735 info[i].info2.notify_name, 16, STR_ASCII);
5737 if (message_push_blob(
5738 &req->outbuf,
5739 data_blob_const(
5740 blob, sizeof(blob))) == -1) {
5741 reply_nterror(req, NT_STATUS_NO_MEMORY);
5742 goto out;
5746 if (count > 0) {
5747 SSVAL(req->outbuf,smb_vwv0,count);
5748 SSVAL(req->outbuf,smb_vwv1,
5749 (max_count>0?first+count:first-1));
5750 SCVAL(smb_buf(req->outbuf),0,1);
5751 SSVAL(smb_buf(req->outbuf),1,28*count);
5755 DEBUG(3, ("%u entries returned in queue\n",
5756 (unsigned)count));
5758 out:
5759 if (b && is_valid_policy_hnd(&handle)) {
5760 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5765 END_PROFILE(SMBsplretq);
5766 return;
5769 /****************************************************************************
5770 Reply to a printwrite.
5771 ****************************************************************************/
5773 void reply_printwrite(struct smb_request *req)
5775 connection_struct *conn = req->conn;
5776 int numtowrite;
5777 const char *data;
5778 files_struct *fsp;
5780 START_PROFILE(SMBsplwr);
5782 if (req->wct < 1) {
5783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5784 END_PROFILE(SMBsplwr);
5785 return;
5788 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5790 if (!check_fsp(conn, req, fsp)) {
5791 END_PROFILE(SMBsplwr);
5792 return;
5795 if (!fsp->print_file) {
5796 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5797 END_PROFILE(SMBsplwr);
5798 return;
5801 if (!CHECK_WRITE(fsp)) {
5802 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5803 END_PROFILE(SMBsplwr);
5804 return;
5807 numtowrite = SVAL(req->buf, 1);
5809 if (req->buflen < numtowrite + 3) {
5810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5811 END_PROFILE(SMBsplwr);
5812 return;
5815 data = (const char *)req->buf + 3;
5817 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5818 reply_nterror(req, map_nt_error_from_unix(errno));
5819 END_PROFILE(SMBsplwr);
5820 return;
5823 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5825 END_PROFILE(SMBsplwr);
5826 return;
5829 /****************************************************************************
5830 Reply to a mkdir.
5831 ****************************************************************************/
5833 void reply_mkdir(struct smb_request *req)
5835 connection_struct *conn = req->conn;
5836 struct smb_filename *smb_dname = NULL;
5837 char *directory = NULL;
5838 NTSTATUS status;
5839 TALLOC_CTX *ctx = talloc_tos();
5841 START_PROFILE(SMBmkdir);
5843 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5844 STR_TERMINATE, &status);
5845 if (!NT_STATUS_IS_OK(status)) {
5846 reply_nterror(req, status);
5847 goto out;
5850 status = filename_convert(ctx, conn,
5851 req->flags2 & FLAGS2_DFS_PATHNAMES,
5852 directory,
5853 UCF_PREP_CREATEFILE,
5854 NULL,
5855 &smb_dname);
5856 if (!NT_STATUS_IS_OK(status)) {
5857 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5858 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5859 ERRSRV, ERRbadpath);
5860 goto out;
5862 reply_nterror(req, status);
5863 goto out;
5866 status = create_directory(conn, req, smb_dname);
5868 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5870 if (!NT_STATUS_IS_OK(status)) {
5872 if (!use_nt_status()
5873 && NT_STATUS_EQUAL(status,
5874 NT_STATUS_OBJECT_NAME_COLLISION)) {
5876 * Yes, in the DOS error code case we get a
5877 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5878 * samba4 torture test.
5880 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5883 reply_nterror(req, status);
5884 goto out;
5887 reply_outbuf(req, 0, 0);
5889 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5890 out:
5891 TALLOC_FREE(smb_dname);
5892 END_PROFILE(SMBmkdir);
5893 return;
5896 /****************************************************************************
5897 Reply to a rmdir.
5898 ****************************************************************************/
5900 void reply_rmdir(struct smb_request *req)
5902 connection_struct *conn = req->conn;
5903 struct smb_filename *smb_dname = NULL;
5904 char *directory = NULL;
5905 NTSTATUS status;
5906 TALLOC_CTX *ctx = talloc_tos();
5907 files_struct *fsp = NULL;
5908 int info = 0;
5909 struct smbd_server_connection *sconn = req->sconn;
5911 START_PROFILE(SMBrmdir);
5913 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5914 STR_TERMINATE, &status);
5915 if (!NT_STATUS_IS_OK(status)) {
5916 reply_nterror(req, status);
5917 goto out;
5920 status = filename_convert(ctx, conn,
5921 req->flags2 & FLAGS2_DFS_PATHNAMES,
5922 directory,
5924 NULL,
5925 &smb_dname);
5926 if (!NT_STATUS_IS_OK(status)) {
5927 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5928 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5929 ERRSRV, ERRbadpath);
5930 goto out;
5932 reply_nterror(req, status);
5933 goto out;
5936 if (is_ntfs_stream_smb_fname(smb_dname)) {
5937 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5938 goto out;
5941 status = SMB_VFS_CREATE_FILE(
5942 conn, /* conn */
5943 req, /* req */
5944 0, /* root_dir_fid */
5945 smb_dname, /* fname */
5946 DELETE_ACCESS, /* access_mask */
5947 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5948 FILE_SHARE_DELETE),
5949 FILE_OPEN, /* create_disposition*/
5950 FILE_DIRECTORY_FILE, /* create_options */
5951 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5952 0, /* oplock_request */
5953 0, /* allocation_size */
5954 0, /* private_flags */
5955 NULL, /* sd */
5956 NULL, /* ea_list */
5957 &fsp, /* result */
5958 &info); /* pinfo */
5960 if (!NT_STATUS_IS_OK(status)) {
5961 if (open_was_deferred(req->sconn, req->mid)) {
5962 /* We have re-scheduled this call. */
5963 goto out;
5965 reply_nterror(req, status);
5966 goto out;
5969 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5970 if (!NT_STATUS_IS_OK(status)) {
5971 close_file(req, fsp, ERROR_CLOSE);
5972 reply_nterror(req, status);
5973 goto out;
5976 if (!set_delete_on_close(fsp, true,
5977 conn->session_info->security_token,
5978 conn->session_info->unix_token)) {
5979 close_file(req, fsp, ERROR_CLOSE);
5980 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5981 goto out;
5984 status = close_file(req, fsp, NORMAL_CLOSE);
5985 if (!NT_STATUS_IS_OK(status)) {
5986 reply_nterror(req, status);
5987 } else {
5988 reply_outbuf(req, 0, 0);
5991 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5993 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5994 out:
5995 TALLOC_FREE(smb_dname);
5996 END_PROFILE(SMBrmdir);
5997 return;
6000 /*******************************************************************
6001 Resolve wildcards in a filename rename.
6002 ********************************************************************/
6004 static bool resolve_wildcards(TALLOC_CTX *ctx,
6005 const char *name1,
6006 const char *name2,
6007 char **pp_newname)
6009 char *name2_copy = NULL;
6010 char *root1 = NULL;
6011 char *root2 = NULL;
6012 char *ext1 = NULL;
6013 char *ext2 = NULL;
6014 char *p,*p2, *pname1, *pname2;
6016 name2_copy = talloc_strdup(ctx, name2);
6017 if (!name2_copy) {
6018 return False;
6021 pname1 = strrchr_m(name1,'/');
6022 pname2 = strrchr_m(name2_copy,'/');
6024 if (!pname1 || !pname2) {
6025 return False;
6028 /* Truncate the copy of name2 at the last '/' */
6029 *pname2 = '\0';
6031 /* Now go past the '/' */
6032 pname1++;
6033 pname2++;
6035 root1 = talloc_strdup(ctx, pname1);
6036 root2 = talloc_strdup(ctx, pname2);
6038 if (!root1 || !root2) {
6039 return False;
6042 p = strrchr_m(root1,'.');
6043 if (p) {
6044 *p = 0;
6045 ext1 = talloc_strdup(ctx, p+1);
6046 } else {
6047 ext1 = talloc_strdup(ctx, "");
6049 p = strrchr_m(root2,'.');
6050 if (p) {
6051 *p = 0;
6052 ext2 = talloc_strdup(ctx, p+1);
6053 } else {
6054 ext2 = talloc_strdup(ctx, "");
6057 if (!ext1 || !ext2) {
6058 return False;
6061 p = root1;
6062 p2 = root2;
6063 while (*p2) {
6064 if (*p2 == '?') {
6065 /* Hmmm. Should this be mb-aware ? */
6066 *p2 = *p;
6067 p2++;
6068 } else if (*p2 == '*') {
6069 *p2 = '\0';
6070 root2 = talloc_asprintf(ctx, "%s%s",
6071 root2,
6073 if (!root2) {
6074 return False;
6076 break;
6077 } else {
6078 p2++;
6080 if (*p) {
6081 p++;
6085 p = ext1;
6086 p2 = ext2;
6087 while (*p2) {
6088 if (*p2 == '?') {
6089 /* Hmmm. Should this be mb-aware ? */
6090 *p2 = *p;
6091 p2++;
6092 } else if (*p2 == '*') {
6093 *p2 = '\0';
6094 ext2 = talloc_asprintf(ctx, "%s%s",
6095 ext2,
6097 if (!ext2) {
6098 return False;
6100 break;
6101 } else {
6102 p2++;
6104 if (*p) {
6105 p++;
6109 if (*ext2) {
6110 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6111 name2_copy,
6112 root2,
6113 ext2);
6114 } else {
6115 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6116 name2_copy,
6117 root2);
6120 if (!*pp_newname) {
6121 return False;
6124 return True;
6127 /****************************************************************************
6128 Ensure open files have their names updated. Updated to notify other smbd's
6129 asynchronously.
6130 ****************************************************************************/
6132 static void rename_open_files(connection_struct *conn,
6133 struct share_mode_lock *lck,
6134 struct file_id id,
6135 uint32_t orig_name_hash,
6136 const struct smb_filename *smb_fname_dst)
6138 files_struct *fsp;
6139 bool did_rename = False;
6140 NTSTATUS status;
6141 uint32_t new_name_hash = 0;
6143 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6144 fsp = file_find_di_next(fsp)) {
6145 /* fsp_name is a relative path under the fsp. To change this for other
6146 sharepaths we need to manipulate relative paths. */
6147 /* TODO - create the absolute path and manipulate the newname
6148 relative to the sharepath. */
6149 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6150 continue;
6152 if (fsp->name_hash != orig_name_hash) {
6153 continue;
6155 DEBUG(10, ("rename_open_files: renaming file %s "
6156 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6157 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6158 smb_fname_str_dbg(smb_fname_dst)));
6160 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6161 if (NT_STATUS_IS_OK(status)) {
6162 did_rename = True;
6163 new_name_hash = fsp->name_hash;
6167 if (!did_rename) {
6168 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6169 "for %s\n", file_id_string_tos(&id),
6170 smb_fname_str_dbg(smb_fname_dst)));
6173 /* Send messages to all smbd's (not ourself) that the name has changed. */
6174 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6175 orig_name_hash, new_name_hash,
6176 smb_fname_dst);
6180 /****************************************************************************
6181 We need to check if the source path is a parent directory of the destination
6182 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6183 refuse the rename with a sharing violation. Under UNIX the above call can
6184 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6185 probably need to check that the client is a Windows one before disallowing
6186 this as a UNIX client (one with UNIX extensions) can know the source is a
6187 symlink and make this decision intelligently. Found by an excellent bug
6188 report from <AndyLiebman@aol.com>.
6189 ****************************************************************************/
6191 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6192 const struct smb_filename *smb_fname_dst)
6194 const char *psrc = smb_fname_src->base_name;
6195 const char *pdst = smb_fname_dst->base_name;
6196 size_t slen;
6198 if (psrc[0] == '.' && psrc[1] == '/') {
6199 psrc += 2;
6201 if (pdst[0] == '.' && pdst[1] == '/') {
6202 pdst += 2;
6204 if ((slen = strlen(psrc)) > strlen(pdst)) {
6205 return False;
6207 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6211 * Do the notify calls from a rename
6214 static void notify_rename(connection_struct *conn, bool is_dir,
6215 const struct smb_filename *smb_fname_src,
6216 const struct smb_filename *smb_fname_dst)
6218 char *parent_dir_src = NULL;
6219 char *parent_dir_dst = NULL;
6220 uint32 mask;
6222 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6223 : FILE_NOTIFY_CHANGE_FILE_NAME;
6225 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6226 &parent_dir_src, NULL) ||
6227 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6228 &parent_dir_dst, NULL)) {
6229 goto out;
6232 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6233 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6234 smb_fname_src->base_name);
6235 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6236 smb_fname_dst->base_name);
6238 else {
6239 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6240 smb_fname_src->base_name);
6241 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6242 smb_fname_dst->base_name);
6245 /* this is a strange one. w2k3 gives an additional event for
6246 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6247 files, but not directories */
6248 if (!is_dir) {
6249 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6250 FILE_NOTIFY_CHANGE_ATTRIBUTES
6251 |FILE_NOTIFY_CHANGE_CREATION,
6252 smb_fname_dst->base_name);
6254 out:
6255 TALLOC_FREE(parent_dir_src);
6256 TALLOC_FREE(parent_dir_dst);
6259 /****************************************************************************
6260 Returns an error if the parent directory for a filename is open in an
6261 incompatible way.
6262 ****************************************************************************/
6264 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6265 const struct smb_filename *smb_fname_dst_in)
6267 char *parent_dir = NULL;
6268 struct smb_filename smb_fname_parent;
6269 struct file_id id;
6270 files_struct *fsp = NULL;
6271 int ret;
6273 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6274 &parent_dir, NULL)) {
6275 return NT_STATUS_NO_MEMORY;
6277 ZERO_STRUCT(smb_fname_parent);
6278 smb_fname_parent.base_name = parent_dir;
6280 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6281 if (ret == -1) {
6282 return map_nt_error_from_unix(errno);
6286 * We're only checking on this smbd here, mostly good
6287 * enough.. and will pass tests.
6290 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6291 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6292 fsp = file_find_di_next(fsp)) {
6293 if (fsp->access_mask & DELETE_ACCESS) {
6294 return NT_STATUS_SHARING_VIOLATION;
6297 return NT_STATUS_OK;
6300 /****************************************************************************
6301 Rename an open file - given an fsp.
6302 ****************************************************************************/
6304 NTSTATUS rename_internals_fsp(connection_struct *conn,
6305 files_struct *fsp,
6306 const struct smb_filename *smb_fname_dst_in,
6307 uint32 attrs,
6308 bool replace_if_exists)
6310 TALLOC_CTX *ctx = talloc_tos();
6311 struct smb_filename *smb_fname_dst = NULL;
6312 NTSTATUS status = NT_STATUS_OK;
6313 struct share_mode_lock *lck = NULL;
6314 bool dst_exists, old_is_stream, new_is_stream;
6316 status = check_name(conn, smb_fname_dst_in->base_name);
6317 if (!NT_STATUS_IS_OK(status)) {
6318 return status;
6321 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 return status;
6326 /* Make a copy of the dst smb_fname structs */
6328 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6329 if (smb_fname_dst == NULL) {
6330 status = NT_STATUS_NO_MEMORY;
6331 goto out;
6335 * Check for special case with case preserving and not
6336 * case sensitive. If the old last component differs from the original
6337 * last component only by case, then we should allow
6338 * the rename (user is trying to change the case of the
6339 * filename).
6341 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6342 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6343 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6344 char *last_slash;
6345 char *fname_dst_lcomp_base_mod = NULL;
6346 struct smb_filename *smb_fname_orig_lcomp = NULL;
6349 * Get the last component of the destination name.
6351 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6352 if (last_slash) {
6353 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6354 } else {
6355 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6357 if (!fname_dst_lcomp_base_mod) {
6358 status = NT_STATUS_NO_MEMORY;
6359 goto out;
6363 * Create an smb_filename struct using the original last
6364 * component of the destination.
6366 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6367 ctx, smb_fname_dst->original_lcomp, NULL);
6368 if (smb_fname_orig_lcomp == NULL) {
6369 status = NT_STATUS_NO_MEMORY;
6370 TALLOC_FREE(fname_dst_lcomp_base_mod);
6371 goto out;
6374 /* If the base names only differ by case, use original. */
6375 if(!strcsequal(fname_dst_lcomp_base_mod,
6376 smb_fname_orig_lcomp->base_name)) {
6377 char *tmp;
6379 * Replace the modified last component with the
6380 * original.
6382 if (last_slash) {
6383 *last_slash = '\0'; /* Truncate at the '/' */
6384 tmp = talloc_asprintf(smb_fname_dst,
6385 "%s/%s",
6386 smb_fname_dst->base_name,
6387 smb_fname_orig_lcomp->base_name);
6388 } else {
6389 tmp = talloc_asprintf(smb_fname_dst,
6390 "%s",
6391 smb_fname_orig_lcomp->base_name);
6393 if (tmp == NULL) {
6394 status = NT_STATUS_NO_MEMORY;
6395 TALLOC_FREE(fname_dst_lcomp_base_mod);
6396 TALLOC_FREE(smb_fname_orig_lcomp);
6397 goto out;
6399 TALLOC_FREE(smb_fname_dst->base_name);
6400 smb_fname_dst->base_name = tmp;
6403 /* If the stream_names only differ by case, use original. */
6404 if(!strcsequal(smb_fname_dst->stream_name,
6405 smb_fname_orig_lcomp->stream_name)) {
6406 char *tmp = NULL;
6407 /* Use the original stream. */
6408 tmp = talloc_strdup(smb_fname_dst,
6409 smb_fname_orig_lcomp->stream_name);
6410 if (tmp == NULL) {
6411 status = NT_STATUS_NO_MEMORY;
6412 TALLOC_FREE(fname_dst_lcomp_base_mod);
6413 TALLOC_FREE(smb_fname_orig_lcomp);
6414 goto out;
6416 TALLOC_FREE(smb_fname_dst->stream_name);
6417 smb_fname_dst->stream_name = tmp;
6419 TALLOC_FREE(fname_dst_lcomp_base_mod);
6420 TALLOC_FREE(smb_fname_orig_lcomp);
6424 * If the src and dest names are identical - including case,
6425 * don't do the rename, just return success.
6428 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6429 strcsequal(fsp->fsp_name->stream_name,
6430 smb_fname_dst->stream_name)) {
6431 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6432 "- returning success\n",
6433 smb_fname_str_dbg(smb_fname_dst)));
6434 status = NT_STATUS_OK;
6435 goto out;
6438 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6439 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6441 /* Return the correct error code if both names aren't streams. */
6442 if (!old_is_stream && new_is_stream) {
6443 status = NT_STATUS_OBJECT_NAME_INVALID;
6444 goto out;
6447 if (old_is_stream && !new_is_stream) {
6448 status = NT_STATUS_INVALID_PARAMETER;
6449 goto out;
6452 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6454 if(!replace_if_exists && dst_exists) {
6455 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6456 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6457 smb_fname_str_dbg(smb_fname_dst)));
6458 status = NT_STATUS_OBJECT_NAME_COLLISION;
6459 goto out;
6462 if (dst_exists) {
6463 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6464 &smb_fname_dst->st);
6465 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6466 fileid);
6467 /* The file can be open when renaming a stream */
6468 if (dst_fsp && !new_is_stream) {
6469 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6470 status = NT_STATUS_ACCESS_DENIED;
6471 goto out;
6475 /* Ensure we have a valid stat struct for the source. */
6476 status = vfs_stat_fsp(fsp);
6477 if (!NT_STATUS_IS_OK(status)) {
6478 goto out;
6481 status = can_rename(conn, fsp, attrs);
6483 if (!NT_STATUS_IS_OK(status)) {
6484 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6485 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6486 smb_fname_str_dbg(smb_fname_dst)));
6487 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6488 status = NT_STATUS_ACCESS_DENIED;
6489 goto out;
6492 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6493 status = NT_STATUS_ACCESS_DENIED;
6496 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6499 * We have the file open ourselves, so not being able to get the
6500 * corresponding share mode lock is a fatal error.
6503 SMB_ASSERT(lck != NULL);
6505 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6506 uint32 create_options = fsp->fh->private_options;
6508 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6509 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6510 smb_fname_str_dbg(smb_fname_dst)));
6512 if (!fsp->is_directory &&
6513 !lp_posix_pathnames() &&
6514 (lp_map_archive(SNUM(conn)) ||
6515 lp_store_dos_attributes(SNUM(conn)))) {
6516 /* We must set the archive bit on the newly
6517 renamed file. */
6518 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6519 uint32_t old_dosmode = dos_mode(conn,
6520 smb_fname_dst);
6521 file_set_dosmode(conn,
6522 smb_fname_dst,
6523 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6524 NULL,
6525 true);
6529 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6530 smb_fname_dst);
6532 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6533 smb_fname_dst);
6536 * A rename acts as a new file create w.r.t. allowing an initial delete
6537 * on close, probably because in Windows there is a new handle to the
6538 * new file. If initial delete on close was requested but not
6539 * originally set, we need to set it here. This is probably not 100% correct,
6540 * but will work for the CIFSFS client which in non-posix mode
6541 * depends on these semantics. JRA.
6544 if (create_options & FILE_DELETE_ON_CLOSE) {
6545 status = can_set_delete_on_close(fsp, 0);
6547 if (NT_STATUS_IS_OK(status)) {
6548 /* Note that here we set the *inital* delete on close flag,
6549 * not the regular one. The magic gets handled in close. */
6550 fsp->initial_delete_on_close = True;
6553 TALLOC_FREE(lck);
6554 status = NT_STATUS_OK;
6555 goto out;
6558 TALLOC_FREE(lck);
6560 if (errno == ENOTDIR || errno == EISDIR) {
6561 status = NT_STATUS_OBJECT_NAME_COLLISION;
6562 } else {
6563 status = map_nt_error_from_unix(errno);
6566 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6567 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6568 smb_fname_str_dbg(smb_fname_dst)));
6570 out:
6571 TALLOC_FREE(smb_fname_dst);
6573 return status;
6576 /****************************************************************************
6577 The guts of the rename command, split out so it may be called by the NT SMB
6578 code.
6579 ****************************************************************************/
6581 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6582 connection_struct *conn,
6583 struct smb_request *req,
6584 struct smb_filename *smb_fname_src,
6585 struct smb_filename *smb_fname_dst,
6586 uint32 attrs,
6587 bool replace_if_exists,
6588 bool src_has_wild,
6589 bool dest_has_wild,
6590 uint32_t access_mask)
6592 char *fname_src_dir = NULL;
6593 char *fname_src_mask = NULL;
6594 int count=0;
6595 NTSTATUS status = NT_STATUS_OK;
6596 struct smb_Dir *dir_hnd = NULL;
6597 const char *dname = NULL;
6598 char *talloced = NULL;
6599 long offset = 0;
6600 int create_options = 0;
6601 bool posix_pathnames = lp_posix_pathnames();
6602 int rc;
6605 * Split the old name into directory and last component
6606 * strings. Note that unix_convert may have stripped off a
6607 * leading ./ from both name and newname if the rename is
6608 * at the root of the share. We need to make sure either both
6609 * name and newname contain a / character or neither of them do
6610 * as this is checked in resolve_wildcards().
6613 /* Split up the directory from the filename/mask. */
6614 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6615 &fname_src_dir, &fname_src_mask);
6616 if (!NT_STATUS_IS_OK(status)) {
6617 status = NT_STATUS_NO_MEMORY;
6618 goto out;
6622 * We should only check the mangled cache
6623 * here if unix_convert failed. This means
6624 * that the path in 'mask' doesn't exist
6625 * on the file system and so we need to look
6626 * for a possible mangle. This patch from
6627 * Tine Smukavec <valentin.smukavec@hermes.si>.
6630 if (!VALID_STAT(smb_fname_src->st) &&
6631 mangle_is_mangled(fname_src_mask, conn->params)) {
6632 char *new_mask = NULL;
6633 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6634 conn->params);
6635 if (new_mask) {
6636 TALLOC_FREE(fname_src_mask);
6637 fname_src_mask = new_mask;
6641 if (!src_has_wild) {
6642 files_struct *fsp;
6645 * Only one file needs to be renamed. Append the mask back
6646 * onto the directory.
6648 TALLOC_FREE(smb_fname_src->base_name);
6649 if (ISDOT(fname_src_dir)) {
6650 /* Ensure we use canonical names on open. */
6651 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6652 "%s",
6653 fname_src_mask);
6654 } else {
6655 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6656 "%s/%s",
6657 fname_src_dir,
6658 fname_src_mask);
6660 if (!smb_fname_src->base_name) {
6661 status = NT_STATUS_NO_MEMORY;
6662 goto out;
6665 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6666 "case_preserve = %d, short case preserve = %d, "
6667 "directory = %s, newname = %s, "
6668 "last_component_dest = %s\n",
6669 conn->case_sensitive, conn->case_preserve,
6670 conn->short_case_preserve,
6671 smb_fname_str_dbg(smb_fname_src),
6672 smb_fname_str_dbg(smb_fname_dst),
6673 smb_fname_dst->original_lcomp));
6675 /* The dest name still may have wildcards. */
6676 if (dest_has_wild) {
6677 char *fname_dst_mod = NULL;
6678 if (!resolve_wildcards(smb_fname_dst,
6679 smb_fname_src->base_name,
6680 smb_fname_dst->base_name,
6681 &fname_dst_mod)) {
6682 DEBUG(6, ("rename_internals: resolve_wildcards "
6683 "%s %s failed\n",
6684 smb_fname_src->base_name,
6685 smb_fname_dst->base_name));
6686 status = NT_STATUS_NO_MEMORY;
6687 goto out;
6689 TALLOC_FREE(smb_fname_dst->base_name);
6690 smb_fname_dst->base_name = fname_dst_mod;
6693 ZERO_STRUCT(smb_fname_src->st);
6694 if (posix_pathnames) {
6695 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6696 } else {
6697 rc = SMB_VFS_STAT(conn, smb_fname_src);
6699 if (rc == -1) {
6700 status = map_nt_error_from_unix_common(errno);
6701 goto out;
6704 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6705 create_options |= FILE_DIRECTORY_FILE;
6708 status = SMB_VFS_CREATE_FILE(
6709 conn, /* conn */
6710 req, /* req */
6711 0, /* root_dir_fid */
6712 smb_fname_src, /* fname */
6713 access_mask, /* access_mask */
6714 (FILE_SHARE_READ | /* share_access */
6715 FILE_SHARE_WRITE),
6716 FILE_OPEN, /* create_disposition*/
6717 create_options, /* create_options */
6718 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6719 0, /* oplock_request */
6720 0, /* allocation_size */
6721 0, /* private_flags */
6722 NULL, /* sd */
6723 NULL, /* ea_list */
6724 &fsp, /* result */
6725 NULL); /* pinfo */
6727 if (!NT_STATUS_IS_OK(status)) {
6728 DEBUG(3, ("Could not open rename source %s: %s\n",
6729 smb_fname_str_dbg(smb_fname_src),
6730 nt_errstr(status)));
6731 goto out;
6734 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6735 attrs, replace_if_exists);
6737 close_file(req, fsp, NORMAL_CLOSE);
6739 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6740 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6741 smb_fname_str_dbg(smb_fname_dst)));
6743 goto out;
6747 * Wildcards - process each file that matches.
6749 if (strequal(fname_src_mask, "????????.???")) {
6750 TALLOC_FREE(fname_src_mask);
6751 fname_src_mask = talloc_strdup(ctx, "*");
6752 if (!fname_src_mask) {
6753 status = NT_STATUS_NO_MEMORY;
6754 goto out;
6758 status = check_name(conn, fname_src_dir);
6759 if (!NT_STATUS_IS_OK(status)) {
6760 goto out;
6763 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6764 attrs);
6765 if (dir_hnd == NULL) {
6766 status = map_nt_error_from_unix(errno);
6767 goto out;
6770 status = NT_STATUS_NO_SUCH_FILE;
6772 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6773 * - gentest fix. JRA
6776 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6777 &talloced))) {
6778 files_struct *fsp = NULL;
6779 char *destname = NULL;
6780 bool sysdir_entry = False;
6782 /* Quick check for "." and ".." */
6783 if (ISDOT(dname) || ISDOTDOT(dname)) {
6784 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6785 sysdir_entry = True;
6786 } else {
6787 TALLOC_FREE(talloced);
6788 continue;
6792 if (!is_visible_file(conn, fname_src_dir, dname,
6793 &smb_fname_src->st, false)) {
6794 TALLOC_FREE(talloced);
6795 continue;
6798 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6799 TALLOC_FREE(talloced);
6800 continue;
6803 if (sysdir_entry) {
6804 status = NT_STATUS_OBJECT_NAME_INVALID;
6805 break;
6808 TALLOC_FREE(smb_fname_src->base_name);
6809 if (ISDOT(fname_src_dir)) {
6810 /* Ensure we use canonical names on open. */
6811 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6812 "%s",
6813 dname);
6814 } else {
6815 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6816 "%s/%s",
6817 fname_src_dir,
6818 dname);
6820 if (!smb_fname_src->base_name) {
6821 status = NT_STATUS_NO_MEMORY;
6822 goto out;
6825 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6826 smb_fname_dst->base_name,
6827 &destname)) {
6828 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6829 smb_fname_src->base_name, destname));
6830 TALLOC_FREE(talloced);
6831 continue;
6833 if (!destname) {
6834 status = NT_STATUS_NO_MEMORY;
6835 goto out;
6838 TALLOC_FREE(smb_fname_dst->base_name);
6839 smb_fname_dst->base_name = destname;
6841 ZERO_STRUCT(smb_fname_src->st);
6842 if (posix_pathnames) {
6843 SMB_VFS_LSTAT(conn, smb_fname_src);
6844 } else {
6845 SMB_VFS_STAT(conn, smb_fname_src);
6848 create_options = 0;
6850 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6851 create_options |= FILE_DIRECTORY_FILE;
6854 status = SMB_VFS_CREATE_FILE(
6855 conn, /* conn */
6856 req, /* req */
6857 0, /* root_dir_fid */
6858 smb_fname_src, /* fname */
6859 access_mask, /* access_mask */
6860 (FILE_SHARE_READ | /* share_access */
6861 FILE_SHARE_WRITE),
6862 FILE_OPEN, /* create_disposition*/
6863 create_options, /* create_options */
6864 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6865 0, /* oplock_request */
6866 0, /* allocation_size */
6867 0, /* private_flags */
6868 NULL, /* sd */
6869 NULL, /* ea_list */
6870 &fsp, /* result */
6871 NULL); /* pinfo */
6873 if (!NT_STATUS_IS_OK(status)) {
6874 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6875 "returned %s rename %s -> %s\n",
6876 nt_errstr(status),
6877 smb_fname_str_dbg(smb_fname_src),
6878 smb_fname_str_dbg(smb_fname_dst)));
6879 break;
6882 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6883 dname);
6884 if (!smb_fname_dst->original_lcomp) {
6885 status = NT_STATUS_NO_MEMORY;
6886 goto out;
6889 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6890 attrs, replace_if_exists);
6892 close_file(req, fsp, NORMAL_CLOSE);
6894 if (!NT_STATUS_IS_OK(status)) {
6895 DEBUG(3, ("rename_internals_fsp returned %s for "
6896 "rename %s -> %s\n", nt_errstr(status),
6897 smb_fname_str_dbg(smb_fname_src),
6898 smb_fname_str_dbg(smb_fname_dst)));
6899 break;
6902 count++;
6904 DEBUG(3,("rename_internals: doing rename on %s -> "
6905 "%s\n", smb_fname_str_dbg(smb_fname_src),
6906 smb_fname_str_dbg(smb_fname_src)));
6907 TALLOC_FREE(talloced);
6909 TALLOC_FREE(dir_hnd);
6911 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6912 status = map_nt_error_from_unix(errno);
6915 out:
6916 TALLOC_FREE(talloced);
6917 TALLOC_FREE(fname_src_dir);
6918 TALLOC_FREE(fname_src_mask);
6919 return status;
6922 /****************************************************************************
6923 Reply to a mv.
6924 ****************************************************************************/
6926 void reply_mv(struct smb_request *req)
6928 connection_struct *conn = req->conn;
6929 char *name = NULL;
6930 char *newname = NULL;
6931 const char *p;
6932 uint32 attrs;
6933 NTSTATUS status;
6934 bool src_has_wcard = False;
6935 bool dest_has_wcard = False;
6936 TALLOC_CTX *ctx = talloc_tos();
6937 struct smb_filename *smb_fname_src = NULL;
6938 struct smb_filename *smb_fname_dst = NULL;
6939 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6940 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6941 bool stream_rename = false;
6943 START_PROFILE(SMBmv);
6945 if (req->wct < 1) {
6946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6947 goto out;
6950 attrs = SVAL(req->vwv+0, 0);
6952 p = (const char *)req->buf + 1;
6953 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6954 &status, &src_has_wcard);
6955 if (!NT_STATUS_IS_OK(status)) {
6956 reply_nterror(req, status);
6957 goto out;
6959 p++;
6960 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6961 &status, &dest_has_wcard);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 reply_nterror(req, status);
6964 goto out;
6967 if (!lp_posix_pathnames()) {
6968 /* The newname must begin with a ':' if the
6969 name contains a ':'. */
6970 if (strchr_m(name, ':')) {
6971 if (newname[0] != ':') {
6972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6973 goto out;
6975 stream_rename = true;
6979 status = filename_convert(ctx,
6980 conn,
6981 req->flags2 & FLAGS2_DFS_PATHNAMES,
6982 name,
6983 src_ucf_flags,
6984 &src_has_wcard,
6985 &smb_fname_src);
6987 if (!NT_STATUS_IS_OK(status)) {
6988 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6989 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6990 ERRSRV, ERRbadpath);
6991 goto out;
6993 reply_nterror(req, status);
6994 goto out;
6997 status = filename_convert(ctx,
6998 conn,
6999 req->flags2 & FLAGS2_DFS_PATHNAMES,
7000 newname,
7001 dst_ucf_flags,
7002 &dest_has_wcard,
7003 &smb_fname_dst);
7005 if (!NT_STATUS_IS_OK(status)) {
7006 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7007 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7008 ERRSRV, ERRbadpath);
7009 goto out;
7011 reply_nterror(req, status);
7012 goto out;
7015 if (stream_rename) {
7016 /* smb_fname_dst->base_name must be the same as
7017 smb_fname_src->base_name. */
7018 TALLOC_FREE(smb_fname_dst->base_name);
7019 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7020 smb_fname_src->base_name);
7021 if (!smb_fname_dst->base_name) {
7022 reply_nterror(req, NT_STATUS_NO_MEMORY);
7023 goto out;
7027 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7028 smb_fname_str_dbg(smb_fname_dst)));
7030 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7031 attrs, False, src_has_wcard, dest_has_wcard,
7032 DELETE_ACCESS);
7033 if (!NT_STATUS_IS_OK(status)) {
7034 if (open_was_deferred(req->sconn, req->mid)) {
7035 /* We have re-scheduled this call. */
7036 goto out;
7038 reply_nterror(req, status);
7039 goto out;
7042 reply_outbuf(req, 0, 0);
7043 out:
7044 TALLOC_FREE(smb_fname_src);
7045 TALLOC_FREE(smb_fname_dst);
7046 END_PROFILE(SMBmv);
7047 return;
7050 /*******************************************************************
7051 Copy a file as part of a reply_copy.
7052 ******************************************************************/
7055 * TODO: check error codes on all callers
7058 NTSTATUS copy_file(TALLOC_CTX *ctx,
7059 connection_struct *conn,
7060 struct smb_filename *smb_fname_src,
7061 struct smb_filename *smb_fname_dst,
7062 int ofun,
7063 int count,
7064 bool target_is_directory)
7066 struct smb_filename *smb_fname_dst_tmp = NULL;
7067 off_t ret=-1;
7068 files_struct *fsp1,*fsp2;
7069 uint32 dosattrs;
7070 uint32 new_create_disposition;
7071 NTSTATUS status;
7074 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7075 if (smb_fname_dst_tmp == NULL) {
7076 return NT_STATUS_NO_MEMORY;
7080 * If the target is a directory, extract the last component from the
7081 * src filename and append it to the dst filename
7083 if (target_is_directory) {
7084 const char *p;
7086 /* dest/target can't be a stream if it's a directory. */
7087 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7089 p = strrchr_m(smb_fname_src->base_name,'/');
7090 if (p) {
7091 p++;
7092 } else {
7093 p = smb_fname_src->base_name;
7095 smb_fname_dst_tmp->base_name =
7096 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7098 if (!smb_fname_dst_tmp->base_name) {
7099 status = NT_STATUS_NO_MEMORY;
7100 goto out;
7104 status = vfs_file_exist(conn, smb_fname_src);
7105 if (!NT_STATUS_IS_OK(status)) {
7106 goto out;
7109 if (!target_is_directory && count) {
7110 new_create_disposition = FILE_OPEN;
7111 } else {
7112 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7113 0, ofun,
7114 NULL, NULL,
7115 &new_create_disposition,
7116 NULL,
7117 NULL)) {
7118 status = NT_STATUS_INVALID_PARAMETER;
7119 goto out;
7123 /* Open the src file for reading. */
7124 status = SMB_VFS_CREATE_FILE(
7125 conn, /* conn */
7126 NULL, /* req */
7127 0, /* root_dir_fid */
7128 smb_fname_src, /* fname */
7129 FILE_GENERIC_READ, /* access_mask */
7130 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7131 FILE_OPEN, /* create_disposition*/
7132 0, /* create_options */
7133 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7134 INTERNAL_OPEN_ONLY, /* oplock_request */
7135 0, /* allocation_size */
7136 0, /* private_flags */
7137 NULL, /* sd */
7138 NULL, /* ea_list */
7139 &fsp1, /* result */
7140 NULL); /* psbuf */
7142 if (!NT_STATUS_IS_OK(status)) {
7143 goto out;
7146 dosattrs = dos_mode(conn, smb_fname_src);
7148 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7149 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7152 /* Open the dst file for writing. */
7153 status = SMB_VFS_CREATE_FILE(
7154 conn, /* conn */
7155 NULL, /* req */
7156 0, /* root_dir_fid */
7157 smb_fname_dst, /* fname */
7158 FILE_GENERIC_WRITE, /* access_mask */
7159 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7160 new_create_disposition, /* create_disposition*/
7161 0, /* create_options */
7162 dosattrs, /* file_attributes */
7163 INTERNAL_OPEN_ONLY, /* oplock_request */
7164 0, /* allocation_size */
7165 0, /* private_flags */
7166 NULL, /* sd */
7167 NULL, /* ea_list */
7168 &fsp2, /* result */
7169 NULL); /* psbuf */
7171 if (!NT_STATUS_IS_OK(status)) {
7172 close_file(NULL, fsp1, ERROR_CLOSE);
7173 goto out;
7176 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7177 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7178 if (ret == -1) {
7179 DEBUG(0, ("error - vfs lseek returned error %s\n",
7180 strerror(errno)));
7181 status = map_nt_error_from_unix(errno);
7182 close_file(NULL, fsp1, ERROR_CLOSE);
7183 close_file(NULL, fsp2, ERROR_CLOSE);
7184 goto out;
7188 /* Do the actual copy. */
7189 if (smb_fname_src->st.st_ex_size) {
7190 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7191 } else {
7192 ret = 0;
7195 close_file(NULL, fsp1, NORMAL_CLOSE);
7197 /* Ensure the modtime is set correctly on the destination file. */
7198 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7201 * As we are opening fsp1 read-only we only expect
7202 * an error on close on fsp2 if we are out of space.
7203 * Thus we don't look at the error return from the
7204 * close of fsp1.
7206 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7208 if (!NT_STATUS_IS_OK(status)) {
7209 goto out;
7212 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7213 status = NT_STATUS_DISK_FULL;
7214 goto out;
7217 status = NT_STATUS_OK;
7219 out:
7220 TALLOC_FREE(smb_fname_dst_tmp);
7221 return status;
7224 /****************************************************************************
7225 Reply to a file copy.
7226 ****************************************************************************/
7228 void reply_copy(struct smb_request *req)
7230 connection_struct *conn = req->conn;
7231 struct smb_filename *smb_fname_src = NULL;
7232 struct smb_filename *smb_fname_dst = NULL;
7233 char *fname_src = NULL;
7234 char *fname_dst = NULL;
7235 char *fname_src_mask = NULL;
7236 char *fname_src_dir = NULL;
7237 const char *p;
7238 int count=0;
7239 int error = ERRnoaccess;
7240 int tid2;
7241 int ofun;
7242 int flags;
7243 bool target_is_directory=False;
7244 bool source_has_wild = False;
7245 bool dest_has_wild = False;
7246 NTSTATUS status;
7247 TALLOC_CTX *ctx = talloc_tos();
7249 START_PROFILE(SMBcopy);
7251 if (req->wct < 3) {
7252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7253 goto out;
7256 tid2 = SVAL(req->vwv+0, 0);
7257 ofun = SVAL(req->vwv+1, 0);
7258 flags = SVAL(req->vwv+2, 0);
7260 p = (const char *)req->buf;
7261 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7262 &status, &source_has_wild);
7263 if (!NT_STATUS_IS_OK(status)) {
7264 reply_nterror(req, status);
7265 goto out;
7267 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7268 &status, &dest_has_wild);
7269 if (!NT_STATUS_IS_OK(status)) {
7270 reply_nterror(req, status);
7271 goto out;
7274 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7276 if (tid2 != conn->cnum) {
7277 /* can't currently handle inter share copies XXXX */
7278 DEBUG(3,("Rejecting inter-share copy\n"));
7279 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7280 goto out;
7283 status = filename_convert(ctx, conn,
7284 req->flags2 & FLAGS2_DFS_PATHNAMES,
7285 fname_src,
7286 UCF_COND_ALLOW_WCARD_LCOMP,
7287 &source_has_wild,
7288 &smb_fname_src);
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;
7295 reply_nterror(req, status);
7296 goto out;
7299 status = filename_convert(ctx, conn,
7300 req->flags2 & FLAGS2_DFS_PATHNAMES,
7301 fname_dst,
7302 UCF_COND_ALLOW_WCARD_LCOMP,
7303 &dest_has_wild,
7304 &smb_fname_dst);
7305 if (!NT_STATUS_IS_OK(status)) {
7306 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7307 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7308 ERRSRV, ERRbadpath);
7309 goto out;
7311 reply_nterror(req, status);
7312 goto out;
7315 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7317 if ((flags&1) && target_is_directory) {
7318 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7319 goto out;
7322 if ((flags&2) && !target_is_directory) {
7323 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7324 goto out;
7327 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7328 /* wants a tree copy! XXXX */
7329 DEBUG(3,("Rejecting tree copy\n"));
7330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7331 goto out;
7334 /* Split up the directory from the filename/mask. */
7335 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7336 &fname_src_dir, &fname_src_mask);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 reply_nterror(req, NT_STATUS_NO_MEMORY);
7339 goto out;
7343 * We should only check the mangled cache
7344 * here if unix_convert failed. This means
7345 * that the path in 'mask' doesn't exist
7346 * on the file system and so we need to look
7347 * for a possible mangle. This patch from
7348 * Tine Smukavec <valentin.smukavec@hermes.si>.
7350 if (!VALID_STAT(smb_fname_src->st) &&
7351 mangle_is_mangled(fname_src_mask, conn->params)) {
7352 char *new_mask = NULL;
7353 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7354 &new_mask, conn->params);
7356 /* Use demangled name if one was successfully found. */
7357 if (new_mask) {
7358 TALLOC_FREE(fname_src_mask);
7359 fname_src_mask = new_mask;
7363 if (!source_has_wild) {
7366 * Only one file needs to be copied. Append the mask back onto
7367 * the directory.
7369 TALLOC_FREE(smb_fname_src->base_name);
7370 if (ISDOT(fname_src_dir)) {
7371 /* Ensure we use canonical names on open. */
7372 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7373 "%s",
7374 fname_src_mask);
7375 } else {
7376 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7377 "%s/%s",
7378 fname_src_dir,
7379 fname_src_mask);
7381 if (!smb_fname_src->base_name) {
7382 reply_nterror(req, NT_STATUS_NO_MEMORY);
7383 goto out;
7386 if (dest_has_wild) {
7387 char *fname_dst_mod = NULL;
7388 if (!resolve_wildcards(smb_fname_dst,
7389 smb_fname_src->base_name,
7390 smb_fname_dst->base_name,
7391 &fname_dst_mod)) {
7392 reply_nterror(req, NT_STATUS_NO_MEMORY);
7393 goto out;
7395 TALLOC_FREE(smb_fname_dst->base_name);
7396 smb_fname_dst->base_name = fname_dst_mod;
7399 status = check_name(conn, smb_fname_src->base_name);
7400 if (!NT_STATUS_IS_OK(status)) {
7401 reply_nterror(req, status);
7402 goto out;
7405 status = check_name(conn, smb_fname_dst->base_name);
7406 if (!NT_STATUS_IS_OK(status)) {
7407 reply_nterror(req, status);
7408 goto out;
7411 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7412 ofun, count, target_is_directory);
7414 if(!NT_STATUS_IS_OK(status)) {
7415 reply_nterror(req, status);
7416 goto out;
7417 } else {
7418 count++;
7420 } else {
7421 struct smb_Dir *dir_hnd = NULL;
7422 const char *dname = NULL;
7423 char *talloced = NULL;
7424 long offset = 0;
7427 * There is a wildcard that requires us to actually read the
7428 * src dir and copy each file matching the mask to the dst.
7429 * Right now streams won't be copied, but this could
7430 * presumably be added with a nested loop for reach dir entry.
7432 SMB_ASSERT(!smb_fname_src->stream_name);
7433 SMB_ASSERT(!smb_fname_dst->stream_name);
7435 smb_fname_src->stream_name = NULL;
7436 smb_fname_dst->stream_name = NULL;
7438 if (strequal(fname_src_mask,"????????.???")) {
7439 TALLOC_FREE(fname_src_mask);
7440 fname_src_mask = talloc_strdup(ctx, "*");
7441 if (!fname_src_mask) {
7442 reply_nterror(req, NT_STATUS_NO_MEMORY);
7443 goto out;
7447 status = check_name(conn, fname_src_dir);
7448 if (!NT_STATUS_IS_OK(status)) {
7449 reply_nterror(req, status);
7450 goto out;
7453 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7454 if (dir_hnd == NULL) {
7455 status = map_nt_error_from_unix(errno);
7456 reply_nterror(req, status);
7457 goto out;
7460 error = ERRbadfile;
7462 /* Iterate over the src dir copying each entry to the dst. */
7463 while ((dname = ReadDirName(dir_hnd, &offset,
7464 &smb_fname_src->st, &talloced))) {
7465 char *destname = NULL;
7467 if (ISDOT(dname) || ISDOTDOT(dname)) {
7468 TALLOC_FREE(talloced);
7469 continue;
7472 if (!is_visible_file(conn, fname_src_dir, dname,
7473 &smb_fname_src->st, false)) {
7474 TALLOC_FREE(talloced);
7475 continue;
7478 if(!mask_match(dname, fname_src_mask,
7479 conn->case_sensitive)) {
7480 TALLOC_FREE(talloced);
7481 continue;
7484 error = ERRnoaccess;
7486 /* Get the src smb_fname struct setup. */
7487 TALLOC_FREE(smb_fname_src->base_name);
7488 if (ISDOT(fname_src_dir)) {
7489 /* Ensure we use canonical names on open. */
7490 smb_fname_src->base_name =
7491 talloc_asprintf(smb_fname_src, "%s",
7492 dname);
7493 } else {
7494 smb_fname_src->base_name =
7495 talloc_asprintf(smb_fname_src, "%s/%s",
7496 fname_src_dir, dname);
7499 if (!smb_fname_src->base_name) {
7500 TALLOC_FREE(dir_hnd);
7501 TALLOC_FREE(talloced);
7502 reply_nterror(req, NT_STATUS_NO_MEMORY);
7503 goto out;
7506 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7507 smb_fname_dst->base_name,
7508 &destname)) {
7509 TALLOC_FREE(talloced);
7510 continue;
7512 if (!destname) {
7513 TALLOC_FREE(dir_hnd);
7514 TALLOC_FREE(talloced);
7515 reply_nterror(req, NT_STATUS_NO_MEMORY);
7516 goto out;
7519 TALLOC_FREE(smb_fname_dst->base_name);
7520 smb_fname_dst->base_name = destname;
7522 status = check_name(conn, smb_fname_src->base_name);
7523 if (!NT_STATUS_IS_OK(status)) {
7524 TALLOC_FREE(dir_hnd);
7525 TALLOC_FREE(talloced);
7526 reply_nterror(req, status);
7527 goto out;
7530 status = check_name(conn, smb_fname_dst->base_name);
7531 if (!NT_STATUS_IS_OK(status)) {
7532 TALLOC_FREE(dir_hnd);
7533 TALLOC_FREE(talloced);
7534 reply_nterror(req, status);
7535 goto out;
7538 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7539 smb_fname_src->base_name,
7540 smb_fname_dst->base_name));
7542 status = copy_file(ctx, conn, smb_fname_src,
7543 smb_fname_dst, ofun, count,
7544 target_is_directory);
7545 if (NT_STATUS_IS_OK(status)) {
7546 count++;
7549 TALLOC_FREE(talloced);
7551 TALLOC_FREE(dir_hnd);
7554 if (count == 0) {
7555 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7556 goto out;
7559 reply_outbuf(req, 1, 0);
7560 SSVAL(req->outbuf,smb_vwv0,count);
7561 out:
7562 TALLOC_FREE(smb_fname_src);
7563 TALLOC_FREE(smb_fname_dst);
7564 TALLOC_FREE(fname_src);
7565 TALLOC_FREE(fname_dst);
7566 TALLOC_FREE(fname_src_mask);
7567 TALLOC_FREE(fname_src_dir);
7569 END_PROFILE(SMBcopy);
7570 return;
7573 #undef DBGC_CLASS
7574 #define DBGC_CLASS DBGC_LOCKING
7576 /****************************************************************************
7577 Get a lock pid, dealing with large count requests.
7578 ****************************************************************************/
7580 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7581 bool large_file_format)
7583 if(!large_file_format)
7584 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7585 else
7586 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7589 /****************************************************************************
7590 Get a lock count, dealing with large count requests.
7591 ****************************************************************************/
7593 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7594 bool large_file_format)
7596 uint64_t count = 0;
7598 if(!large_file_format) {
7599 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7600 } else {
7602 * No BVAL, this is reversed!
7604 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7605 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7608 return count;
7611 /****************************************************************************
7612 Get a lock offset, dealing with large offset requests.
7613 ****************************************************************************/
7615 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7616 bool large_file_format)
7618 uint64_t offset = 0;
7620 if(!large_file_format) {
7621 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7622 } else {
7624 * No BVAL, this is reversed!
7626 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7627 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7630 return offset;
7633 NTSTATUS smbd_do_locking(struct smb_request *req,
7634 files_struct *fsp,
7635 uint8_t type,
7636 int32_t timeout,
7637 uint16_t num_locks,
7638 struct smbd_lock_element *locks,
7639 bool *async)
7641 connection_struct *conn = req->conn;
7642 int i;
7643 NTSTATUS status = NT_STATUS_OK;
7645 *async = false;
7647 /* Setup the timeout in seconds. */
7649 if (!lp_blocking_locks(SNUM(conn))) {
7650 timeout = 0;
7653 for(i = 0; i < (int)num_locks; i++) {
7654 struct smbd_lock_element *e = &locks[i];
7656 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7657 "%llu, file %s timeout = %d\n",
7658 (double)e->offset,
7659 (double)e->count,
7660 (unsigned long long)e->smblctx,
7661 fsp_str_dbg(fsp),
7662 (int)timeout));
7664 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7665 struct blocking_lock_record *blr = NULL;
7667 if (num_locks > 1) {
7669 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7670 * if the lock vector contains one entry. When given multiple cancel
7671 * requests in a single PDU we expect the server to return an
7672 * error. Windows servers seem to accept the request but only
7673 * cancel the first lock.
7674 * JRA - Do what Windows does (tm) :-).
7677 #if 0
7678 /* MS-CIFS (2.2.4.32.1) behavior. */
7679 return NT_STATUS_DOS(ERRDOS,
7680 ERRcancelviolation);
7681 #else
7682 /* Windows behavior. */
7683 if (i != 0) {
7684 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7685 "cancel request\n"));
7686 continue;
7688 #endif
7691 if (lp_blocking_locks(SNUM(conn))) {
7693 /* Schedule a message to ourselves to
7694 remove the blocking lock record and
7695 return the right error. */
7697 blr = blocking_lock_cancel_smb1(fsp,
7698 e->smblctx,
7699 e->offset,
7700 e->count,
7701 WINDOWS_LOCK,
7702 type,
7703 NT_STATUS_FILE_LOCK_CONFLICT);
7704 if (blr == NULL) {
7705 return NT_STATUS_DOS(
7706 ERRDOS,
7707 ERRcancelviolation);
7710 /* Remove a matching pending lock. */
7711 status = do_lock_cancel(fsp,
7712 e->smblctx,
7713 e->count,
7714 e->offset,
7715 WINDOWS_LOCK);
7716 } else {
7717 bool blocking_lock = timeout ? true : false;
7718 bool defer_lock = false;
7719 struct byte_range_lock *br_lck;
7720 uint64_t block_smblctx;
7722 br_lck = do_lock(req->sconn->msg_ctx,
7723 fsp,
7724 e->smblctx,
7725 e->count,
7726 e->offset,
7727 e->brltype,
7728 WINDOWS_LOCK,
7729 blocking_lock,
7730 &status,
7731 &block_smblctx);
7733 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7734 /* Windows internal resolution for blocking locks seems
7735 to be about 200ms... Don't wait for less than that. JRA. */
7736 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7737 timeout = lp_lock_spin_time();
7739 defer_lock = true;
7742 /* If a lock sent with timeout of zero would fail, and
7743 * this lock has been requested multiple times,
7744 * according to brl_lock_failed() we convert this
7745 * request to a blocking lock with a timeout of between
7746 * 150 - 300 milliseconds.
7748 * If lp_lock_spin_time() has been set to 0, we skip
7749 * this blocking retry and fail immediately.
7751 * Replacement for do_lock_spin(). JRA. */
7753 if (!req->sconn->using_smb2 &&
7754 br_lck && lp_blocking_locks(SNUM(conn)) &&
7755 lp_lock_spin_time() && !blocking_lock &&
7756 NT_STATUS_EQUAL((status),
7757 NT_STATUS_FILE_LOCK_CONFLICT))
7759 defer_lock = true;
7760 timeout = lp_lock_spin_time();
7763 if (br_lck && defer_lock) {
7765 * A blocking lock was requested. Package up
7766 * this smb into a queued request and push it
7767 * onto the blocking lock queue.
7769 if(push_blocking_lock_request(br_lck,
7770 req,
7771 fsp,
7772 timeout,
7774 e->smblctx,
7775 e->brltype,
7776 WINDOWS_LOCK,
7777 e->offset,
7778 e->count,
7779 block_smblctx)) {
7780 TALLOC_FREE(br_lck);
7781 *async = true;
7782 return NT_STATUS_OK;
7786 TALLOC_FREE(br_lck);
7789 if (!NT_STATUS_IS_OK(status)) {
7790 break;
7794 /* If any of the above locks failed, then we must unlock
7795 all of the previous locks (X/Open spec). */
7797 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7799 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7800 i = -1; /* we want to skip the for loop */
7804 * Ensure we don't do a remove on the lock that just failed,
7805 * as under POSIX rules, if we have a lock already there, we
7806 * will delete it (and we shouldn't) .....
7808 for(i--; i >= 0; i--) {
7809 struct smbd_lock_element *e = &locks[i];
7811 do_unlock(req->sconn->msg_ctx,
7812 fsp,
7813 e->smblctx,
7814 e->count,
7815 e->offset,
7816 WINDOWS_LOCK);
7818 return status;
7821 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7822 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7824 return NT_STATUS_OK;
7827 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7828 files_struct *fsp,
7829 uint16_t num_ulocks,
7830 struct smbd_lock_element *ulocks)
7832 int i;
7834 for(i = 0; i < (int)num_ulocks; i++) {
7835 struct smbd_lock_element *e = &ulocks[i];
7836 NTSTATUS status;
7838 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7839 "pid %u, file %s\n", __func__,
7840 (double)e->offset,
7841 (double)e->count,
7842 (unsigned int)e->smblctx,
7843 fsp_str_dbg(fsp)));
7845 if (e->brltype != UNLOCK_LOCK) {
7846 /* this can only happen with SMB2 */
7847 return NT_STATUS_INVALID_PARAMETER;
7850 status = do_unlock(req->sconn->msg_ctx,
7851 fsp,
7852 e->smblctx,
7853 e->count,
7854 e->offset,
7855 WINDOWS_LOCK);
7857 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7858 nt_errstr(status)));
7860 if (!NT_STATUS_IS_OK(status)) {
7861 return status;
7865 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7866 num_ulocks));
7868 return NT_STATUS_OK;
7871 /****************************************************************************
7872 Reply to a lockingX request.
7873 ****************************************************************************/
7875 void reply_lockingX(struct smb_request *req)
7877 connection_struct *conn = req->conn;
7878 files_struct *fsp;
7879 unsigned char locktype;
7880 unsigned char oplocklevel;
7881 uint16 num_ulocks;
7882 uint16 num_locks;
7883 int32 lock_timeout;
7884 int i;
7885 const uint8_t *data;
7886 bool large_file_format;
7887 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7888 struct smbd_lock_element *ulocks;
7889 struct smbd_lock_element *locks;
7890 bool async = false;
7892 START_PROFILE(SMBlockingX);
7894 if (req->wct < 8) {
7895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7896 END_PROFILE(SMBlockingX);
7897 return;
7900 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7901 locktype = CVAL(req->vwv+3, 0);
7902 oplocklevel = CVAL(req->vwv+3, 1);
7903 num_ulocks = SVAL(req->vwv+6, 0);
7904 num_locks = SVAL(req->vwv+7, 0);
7905 lock_timeout = IVAL(req->vwv+4, 0);
7906 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7908 if (!check_fsp(conn, req, fsp)) {
7909 END_PROFILE(SMBlockingX);
7910 return;
7913 data = req->buf;
7915 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7916 /* we don't support these - and CANCEL_LOCK makes w2k
7917 and XP reboot so I don't really want to be
7918 compatible! (tridge) */
7919 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7920 END_PROFILE(SMBlockingX);
7921 return;
7924 /* Check if this is an oplock break on a file
7925 we have granted an oplock on.
7927 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7928 /* Client can insist on breaking to none. */
7929 bool break_to_none = (oplocklevel == 0);
7930 bool result;
7932 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7933 "for %s\n", (unsigned int)oplocklevel,
7934 fsp_fnum_dbg(fsp)));
7937 * Make sure we have granted an exclusive or batch oplock on
7938 * this file.
7941 if (fsp->oplock_type == 0) {
7943 /* The Samba4 nbench simulator doesn't understand
7944 the difference between break to level2 and break
7945 to none from level2 - it sends oplock break
7946 replies in both cases. Don't keep logging an error
7947 message here - just ignore it. JRA. */
7949 DEBUG(5,("reply_lockingX: Error : oplock break from "
7950 "client for %s (oplock=%d) and no "
7951 "oplock granted on this file (%s).\n",
7952 fsp_fnum_dbg(fsp), fsp->oplock_type,
7953 fsp_str_dbg(fsp)));
7955 /* if this is a pure oplock break request then don't
7956 * send a reply */
7957 if (num_locks == 0 && num_ulocks == 0) {
7958 END_PROFILE(SMBlockingX);
7959 return;
7960 } else {
7961 END_PROFILE(SMBlockingX);
7962 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7963 return;
7967 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7968 (break_to_none)) {
7969 result = remove_oplock(fsp);
7970 } else {
7971 result = downgrade_oplock(fsp);
7974 if (!result) {
7975 DEBUG(0, ("reply_lockingX: error in removing "
7976 "oplock on file %s\n", fsp_str_dbg(fsp)));
7977 /* Hmmm. Is this panic justified? */
7978 smb_panic("internal tdb error");
7981 /* if this is a pure oplock break request then don't send a
7982 * reply */
7983 if (num_locks == 0 && num_ulocks == 0) {
7984 /* Sanity check - ensure a pure oplock break is not a
7985 chained request. */
7986 if (CVAL(req->vwv+0, 0) != 0xff) {
7987 DEBUG(0,("reply_lockingX: Error : pure oplock "
7988 "break is a chained %d request !\n",
7989 (unsigned int)CVAL(req->vwv+0, 0)));
7991 END_PROFILE(SMBlockingX);
7992 return;
7996 if (req->buflen <
7997 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7999 END_PROFILE(SMBlockingX);
8000 return;
8003 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8004 if (ulocks == NULL) {
8005 reply_nterror(req, NT_STATUS_NO_MEMORY);
8006 END_PROFILE(SMBlockingX);
8007 return;
8010 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8011 if (locks == NULL) {
8012 reply_nterror(req, NT_STATUS_NO_MEMORY);
8013 END_PROFILE(SMBlockingX);
8014 return;
8017 /* Data now points at the beginning of the list
8018 of smb_unlkrng structs */
8019 for(i = 0; i < (int)num_ulocks; i++) {
8020 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8021 ulocks[i].count = get_lock_count(data, i, large_file_format);
8022 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8023 ulocks[i].brltype = UNLOCK_LOCK;
8026 /* Now do any requested locks */
8027 data += ((large_file_format ? 20 : 10)*num_ulocks);
8029 /* Data now points at the beginning of the list
8030 of smb_lkrng structs */
8032 for(i = 0; i < (int)num_locks; i++) {
8033 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8034 locks[i].count = get_lock_count(data, i, large_file_format);
8035 locks[i].offset = get_lock_offset(data, i, large_file_format);
8037 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8038 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8039 locks[i].brltype = PENDING_READ_LOCK;
8040 } else {
8041 locks[i].brltype = READ_LOCK;
8043 } else {
8044 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8045 locks[i].brltype = PENDING_WRITE_LOCK;
8046 } else {
8047 locks[i].brltype = WRITE_LOCK;
8052 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8053 if (!NT_STATUS_IS_OK(status)) {
8054 END_PROFILE(SMBlockingX);
8055 reply_nterror(req, status);
8056 return;
8059 status = smbd_do_locking(req, fsp,
8060 locktype, lock_timeout,
8061 num_locks, locks,
8062 &async);
8063 if (!NT_STATUS_IS_OK(status)) {
8064 END_PROFILE(SMBlockingX);
8065 reply_nterror(req, status);
8066 return;
8068 if (async) {
8069 END_PROFILE(SMBlockingX);
8070 return;
8073 reply_outbuf(req, 2, 0);
8074 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8075 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8077 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8078 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8080 END_PROFILE(SMBlockingX);
8083 #undef DBGC_CLASS
8084 #define DBGC_CLASS DBGC_ALL
8086 /****************************************************************************
8087 Reply to a SMBreadbmpx (read block multiplex) request.
8088 Always reply with an error, if someone has a platform really needs this,
8089 please contact vl@samba.org
8090 ****************************************************************************/
8092 void reply_readbmpx(struct smb_request *req)
8094 START_PROFILE(SMBreadBmpx);
8095 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8096 END_PROFILE(SMBreadBmpx);
8097 return;
8100 /****************************************************************************
8101 Reply to a SMBreadbs (read block multiplex secondary) request.
8102 Always reply with an error, if someone has a platform really needs this,
8103 please contact vl@samba.org
8104 ****************************************************************************/
8106 void reply_readbs(struct smb_request *req)
8108 START_PROFILE(SMBreadBs);
8109 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8110 END_PROFILE(SMBreadBs);
8111 return;
8114 /****************************************************************************
8115 Reply to a SMBsetattrE.
8116 ****************************************************************************/
8118 void reply_setattrE(struct smb_request *req)
8120 connection_struct *conn = req->conn;
8121 struct smb_file_time ft;
8122 files_struct *fsp;
8123 NTSTATUS status;
8125 START_PROFILE(SMBsetattrE);
8126 ZERO_STRUCT(ft);
8128 if (req->wct < 7) {
8129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8130 goto out;
8133 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8135 if(!fsp || (fsp->conn != conn)) {
8136 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8137 goto out;
8141 * Convert the DOS times into unix times.
8144 ft.atime = convert_time_t_to_timespec(
8145 srv_make_unix_date2(req->vwv+3));
8146 ft.mtime = convert_time_t_to_timespec(
8147 srv_make_unix_date2(req->vwv+5));
8148 ft.create_time = convert_time_t_to_timespec(
8149 srv_make_unix_date2(req->vwv+1));
8151 reply_outbuf(req, 0, 0);
8154 * Patch from Ray Frush <frush@engr.colostate.edu>
8155 * Sometimes times are sent as zero - ignore them.
8158 /* Ensure we have a valid stat struct for the source. */
8159 status = vfs_stat_fsp(fsp);
8160 if (!NT_STATUS_IS_OK(status)) {
8161 reply_nterror(req, status);
8162 goto out;
8165 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8167 goto out;
8170 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8171 if (!NT_STATUS_IS_OK(status)) {
8172 reply_nterror(req, status);
8173 goto out;
8176 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8177 " createtime=%u\n",
8178 fsp_fnum_dbg(fsp),
8179 (unsigned int)ft.atime.tv_sec,
8180 (unsigned int)ft.mtime.tv_sec,
8181 (unsigned int)ft.create_time.tv_sec
8183 out:
8184 END_PROFILE(SMBsetattrE);
8185 return;
8189 /* Back from the dead for OS/2..... JRA. */
8191 /****************************************************************************
8192 Reply to a SMBwritebmpx (write block multiplex primary) request.
8193 Always reply with an error, if someone has a platform really needs this,
8194 please contact vl@samba.org
8195 ****************************************************************************/
8197 void reply_writebmpx(struct smb_request *req)
8199 START_PROFILE(SMBwriteBmpx);
8200 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8201 END_PROFILE(SMBwriteBmpx);
8202 return;
8205 /****************************************************************************
8206 Reply to a SMBwritebs (write block multiplex secondary) request.
8207 Always reply with an error, if someone has a platform really needs this,
8208 please contact vl@samba.org
8209 ****************************************************************************/
8211 void reply_writebs(struct smb_request *req)
8213 START_PROFILE(SMBwriteBs);
8214 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8215 END_PROFILE(SMBwriteBs);
8216 return;
8219 /****************************************************************************
8220 Reply to a SMBgetattrE.
8221 ****************************************************************************/
8223 void reply_getattrE(struct smb_request *req)
8225 connection_struct *conn = req->conn;
8226 int mode;
8227 files_struct *fsp;
8228 struct timespec create_ts;
8230 START_PROFILE(SMBgetattrE);
8232 if (req->wct < 1) {
8233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8234 END_PROFILE(SMBgetattrE);
8235 return;
8238 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8240 if(!fsp || (fsp->conn != conn)) {
8241 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8242 END_PROFILE(SMBgetattrE);
8243 return;
8246 /* Do an fstat on this file */
8247 if(fsp_stat(fsp)) {
8248 reply_nterror(req, map_nt_error_from_unix(errno));
8249 END_PROFILE(SMBgetattrE);
8250 return;
8253 mode = dos_mode(conn, fsp->fsp_name);
8256 * Convert the times into dos times. Set create
8257 * date to be last modify date as UNIX doesn't save
8258 * this.
8261 reply_outbuf(req, 11, 0);
8263 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8264 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8265 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8266 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8267 /* Should we check pending modtime here ? JRA */
8268 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8269 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8271 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8272 SIVAL(req->outbuf, smb_vwv6, 0);
8273 SIVAL(req->outbuf, smb_vwv8, 0);
8274 } else {
8275 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8276 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8277 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8279 SSVAL(req->outbuf,smb_vwv10, mode);
8281 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8283 END_PROFILE(SMBgetattrE);
8284 return;