ctdb-logging: Separate out syslog and file logging backends
[Samba.git] / source3 / smbd / reply.c
blob9b3ed65447377bceee1ef14e50eec7a273d7ac0c
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 smbXsrv_connection *xconn,
432 const char *name, int name_type)
434 char *trim_name;
435 char *trim_name_type;
436 const char *retarget_parm;
437 char *retarget;
438 char *p;
439 int retarget_type = 0x20;
440 int retarget_port = NBT_SMB_PORT;
441 struct sockaddr_storage retarget_addr;
442 struct sockaddr_in *in_addr;
443 bool ret = false;
444 uint8_t outbuf[10];
446 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
447 return false;
450 trim_name = talloc_strdup(talloc_tos(), name);
451 if (trim_name == NULL) {
452 goto fail;
454 trim_char(trim_name, ' ', ' ');
456 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
457 name_type);
458 if (trim_name_type == NULL) {
459 goto fail;
462 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
463 trim_name_type, NULL);
464 if (retarget_parm == NULL) {
465 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
466 trim_name, NULL);
468 if (retarget_parm == NULL) {
469 goto fail;
472 retarget = talloc_strdup(trim_name, retarget_parm);
473 if (retarget == NULL) {
474 goto fail;
477 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
479 p = strchr(retarget, ':');
480 if (p != NULL) {
481 *p++ = '\0';
482 retarget_port = atoi(p);
485 p = strchr_m(retarget, '#');
486 if (p != NULL) {
487 *p++ = '\0';
488 if (sscanf(p, "%x", &retarget_type) != 1) {
489 goto fail;
493 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
494 if (!ret) {
495 DEBUG(10, ("could not resolve %s\n", retarget));
496 goto fail;
499 if (retarget_addr.ss_family != AF_INET) {
500 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
501 goto fail;
504 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
506 _smb_setlen(outbuf, 6);
507 SCVAL(outbuf, 0, 0x84);
508 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
509 *(uint16_t *)(outbuf+8) = htons(retarget_port);
511 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
512 NULL)) {
513 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
514 "failed.");
517 ret = true;
518 fail:
519 TALLOC_FREE(trim_name);
520 return ret;
523 static void reply_called_name_not_present(char *outbuf)
525 smb_setlen(outbuf, 1);
526 SCVAL(outbuf, 0, 0x83);
527 SCVAL(outbuf, 4, 0x82);
530 /****************************************************************************
531 Reply to a (netbios-level) special message.
532 ****************************************************************************/
534 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
536 struct smbd_server_connection *sconn = xconn->client->sconn;
537 int msg_type = CVAL(inbuf,0);
538 int msg_flags = CVAL(inbuf,1);
540 * We only really use 4 bytes of the outbuf, but for the smb_setlen
541 * calculation & friends (srv_send_smb uses that) we need the full smb
542 * header.
544 char outbuf[smb_size];
546 memset(outbuf, '\0', sizeof(outbuf));
548 smb_setlen(outbuf,0);
550 switch (msg_type) {
551 case NBSSrequest: /* session request */
553 /* inbuf_size is guarenteed to be at least 4. */
554 fstring name1,name2;
555 int name_type1, name_type2;
556 int name_len1, name_len2;
558 *name1 = *name2 = 0;
560 if (xconn->transport.nbt.got_session) {
561 exit_server_cleanly("multiple session request not permitted");
564 SCVAL(outbuf,0,NBSSpositive);
565 SCVAL(outbuf,3,0);
567 /* inbuf_size is guaranteed to be at least 4. */
568 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
569 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
570 DEBUG(0,("Invalid name length in session request\n"));
571 reply_called_name_not_present(outbuf);
572 break;
574 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
575 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
576 DEBUG(0,("Invalid name length in session request\n"));
577 reply_called_name_not_present(outbuf);
578 break;
581 name_type1 = name_extract((unsigned char *)inbuf,
582 inbuf_size,(unsigned int)4,name1);
583 name_type2 = name_extract((unsigned char *)inbuf,
584 inbuf_size,(unsigned int)(4 + name_len1),name2);
586 if (name_type1 == -1 || name_type2 == -1) {
587 DEBUG(0,("Invalid name type in session request\n"));
588 reply_called_name_not_present(outbuf);
589 break;
592 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
593 name1, name_type1, name2, name_type2));
595 if (netbios_session_retarget(xconn, name1, name_type1)) {
596 exit_server_cleanly("retargeted client");
600 * Windows NT/2k uses "*SMBSERVER" and XP uses
601 * "*SMBSERV" arrggg!!!
603 if (strequal(name1, "*SMBSERVER ")
604 || strequal(name1, "*SMBSERV ")) {
605 char *raddr;
607 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
608 talloc_tos());
609 if (raddr == NULL) {
610 exit_server_cleanly("could not allocate raddr");
613 fstrcpy(name1, raddr);
616 set_local_machine_name(name1, True);
617 set_remote_machine_name(name2, True);
619 if (is_ipaddress(sconn->remote_hostname)) {
620 char *p = discard_const_p(char, sconn->remote_hostname);
622 talloc_free(p);
624 sconn->remote_hostname = talloc_strdup(sconn,
625 get_remote_machine_name());
626 if (sconn->remote_hostname == NULL) {
627 exit_server_cleanly("could not copy remote name");
629 xconn->remote_hostname = sconn->remote_hostname;
632 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
633 get_local_machine_name(), get_remote_machine_name(),
634 name_type2));
636 if (name_type2 == 'R') {
637 /* We are being asked for a pathworks session ---
638 no thanks! */
639 reply_called_name_not_present(outbuf);
640 break;
643 reload_services(sconn, conn_snum_used, true);
644 reopen_logs();
646 xconn->transport.nbt.got_session = true;
647 break;
650 case 0x89: /* session keepalive request
651 (some old clients produce this?) */
652 SCVAL(outbuf,0,NBSSkeepalive);
653 SCVAL(outbuf,3,0);
654 break;
656 case NBSSpositive: /* positive session response */
657 case NBSSnegative: /* negative session response */
658 case NBSSretarget: /* retarget session response */
659 DEBUG(0,("Unexpected session response\n"));
660 break;
662 case NBSSkeepalive: /* session keepalive */
663 default:
664 return;
667 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
668 msg_type, msg_flags));
670 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
672 if (CVAL(outbuf, 0) != 0x82) {
673 exit_server_cleanly("invalid netbios session");
675 return;
678 /****************************************************************************
679 Reply to a tcon.
680 conn POINTER CAN BE NULL HERE !
681 ****************************************************************************/
683 void reply_tcon(struct smb_request *req)
685 connection_struct *conn = req->conn;
686 const char *service;
687 char *service_buf = NULL;
688 char *password = NULL;
689 char *dev = NULL;
690 int pwlen=0;
691 NTSTATUS nt_status;
692 const uint8_t *p;
693 const char *p2;
694 TALLOC_CTX *ctx = talloc_tos();
695 struct smbXsrv_connection *xconn = req->xconn;
696 NTTIME now = timeval_to_nttime(&req->request_time);
698 START_PROFILE(SMBtcon);
700 if (req->buflen < 4) {
701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
702 END_PROFILE(SMBtcon);
703 return;
706 p = req->buf + 1;
707 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
708 p += 1;
709 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
710 p += pwlen+1;
711 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
712 p += 1;
714 if (service_buf == NULL || password == NULL || dev == NULL) {
715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
716 END_PROFILE(SMBtcon);
717 return;
719 p2 = strrchr_m(service_buf,'\\');
720 if (p2) {
721 service = p2+1;
722 } else {
723 service = service_buf;
726 conn = make_connection(req, now, service, dev,
727 req->vuid,&nt_status);
728 req->conn = conn;
730 if (!conn) {
731 reply_nterror(req, nt_status);
732 END_PROFILE(SMBtcon);
733 return;
736 reply_outbuf(req, 2, 0);
737 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
738 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
739 SSVAL(req->outbuf,smb_tid,conn->cnum);
741 DEBUG(3,("tcon service=%s cnum=%d\n",
742 service, conn->cnum));
744 END_PROFILE(SMBtcon);
745 return;
748 /****************************************************************************
749 Reply to a tcon and X.
750 conn POINTER CAN BE NULL HERE !
751 ****************************************************************************/
753 void reply_tcon_and_X(struct smb_request *req)
755 connection_struct *conn = req->conn;
756 const char *service = NULL;
757 TALLOC_CTX *ctx = talloc_tos();
758 /* what the cleint thinks the device is */
759 char *client_devicetype = NULL;
760 /* what the server tells the client the share represents */
761 const char *server_devicetype;
762 NTSTATUS nt_status;
763 int passlen;
764 char *path = NULL;
765 const uint8_t *p;
766 const char *q;
767 uint16_t tcon_flags;
768 struct smbXsrv_session *session = NULL;
769 NTTIME now = timeval_to_nttime(&req->request_time);
770 bool session_key_updated = false;
771 uint16_t optional_support = 0;
772 struct smbXsrv_connection *xconn = req->xconn;
774 START_PROFILE(SMBtconX);
776 if (req->wct < 4) {
777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
778 END_PROFILE(SMBtconX);
779 return;
782 passlen = SVAL(req->vwv+3, 0);
783 tcon_flags = SVAL(req->vwv+2, 0);
785 /* we might have to close an old one */
786 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
787 struct smbXsrv_tcon *tcon;
788 NTSTATUS status;
790 tcon = conn->tcon;
791 req->conn = NULL;
792 conn = NULL;
795 * TODO: cancel all outstanding requests on the tcon
797 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
798 if (!NT_STATUS_IS_OK(status)) {
799 DEBUG(0, ("reply_tcon_and_X: "
800 "smbXsrv_tcon_disconnect() failed: %s\n",
801 nt_errstr(status)));
803 * If we hit this case, there is something completely
804 * wrong, so we better disconnect the transport connection.
806 END_PROFILE(SMBtconX);
807 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
808 return;
811 TALLOC_FREE(tcon);
814 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
815 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
816 END_PROFILE(SMBtconX);
817 return;
820 if (xconn->smb1.negprot.encrypted_passwords) {
821 p = req->buf + passlen;
822 } else {
823 p = req->buf + passlen + 1;
826 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
828 if (path == NULL) {
829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
830 END_PROFILE(SMBtconX);
831 return;
835 * the service name can be either: \\server\share
836 * or share directly like on the DELL PowerVault 705
838 if (*path=='\\') {
839 q = strchr_m(path+2,'\\');
840 if (!q) {
841 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
842 END_PROFILE(SMBtconX);
843 return;
845 service = q+1;
846 } else {
847 service = path;
850 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
851 &client_devicetype, p,
852 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
854 if (client_devicetype == NULL) {
855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
856 END_PROFILE(SMBtconX);
857 return;
860 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
862 nt_status = smb1srv_session_lookup(xconn,
863 req->vuid, now, &session);
864 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
865 reply_force_doserror(req, ERRSRV, ERRbaduid);
866 END_PROFILE(SMBtconX);
867 return;
869 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
870 reply_nterror(req, nt_status);
871 END_PROFILE(SMBtconX);
872 return;
874 if (!NT_STATUS_IS_OK(nt_status)) {
875 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
876 END_PROFILE(SMBtconX);
877 return;
880 if (session->global->auth_session_info == NULL) {
881 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
882 END_PROFILE(SMBtconX);
883 return;
887 * If there is no application key defined yet
888 * we create one.
890 * This means we setup the application key on the
891 * first tcon that happens via the given session.
893 * Once the application key is defined, it does not
894 * change any more.
896 if (session->global->application_key.length == 0 &&
897 session->global->signing_key.length > 0)
899 struct smbXsrv_session *x = session;
900 struct auth_session_info *session_info =
901 session->global->auth_session_info;
902 uint8_t session_key[16];
904 ZERO_STRUCT(session_key);
905 memcpy(session_key, x->global->signing_key.data,
906 MIN(x->global->signing_key.length, sizeof(session_key)));
909 * The application key is truncated/padded to 16 bytes
911 x->global->application_key = data_blob_talloc(x->global,
912 session_key,
913 sizeof(session_key));
914 ZERO_STRUCT(session_key);
915 if (x->global->application_key.data == NULL) {
916 reply_nterror(req, NT_STATUS_NO_MEMORY);
917 END_PROFILE(SMBtconX);
918 return;
921 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
922 smb_key_derivation(x->global->application_key.data,
923 x->global->application_key.length,
924 x->global->application_key.data);
925 optional_support |= SMB_EXTENDED_SIGNATURES;
929 * Place the application key into the session_info
931 data_blob_clear_free(&session_info->session_key);
932 session_info->session_key = data_blob_dup_talloc(session_info,
933 x->global->application_key);
934 if (session_info->session_key.data == NULL) {
935 data_blob_clear_free(&x->global->application_key);
936 reply_nterror(req, NT_STATUS_NO_MEMORY);
937 END_PROFILE(SMBtconX);
938 return;
940 session_key_updated = true;
943 conn = make_connection(req, now, service, client_devicetype,
944 req->vuid, &nt_status);
945 req->conn =conn;
947 if (!conn) {
948 if (session_key_updated) {
949 struct smbXsrv_session *x = session;
950 struct auth_session_info *session_info =
951 session->global->auth_session_info;
952 data_blob_clear_free(&x->global->application_key);
953 data_blob_clear_free(&session_info->session_key);
955 reply_nterror(req, nt_status);
956 END_PROFILE(SMBtconX);
957 return;
960 if ( IS_IPC(conn) )
961 server_devicetype = "IPC";
962 else if ( IS_PRINT(conn) )
963 server_devicetype = "LPT1:";
964 else
965 server_devicetype = "A:";
967 if (get_Protocol() < PROTOCOL_NT1) {
968 reply_outbuf(req, 2, 0);
969 if (message_push_string(&req->outbuf, server_devicetype,
970 STR_TERMINATE|STR_ASCII) == -1) {
971 reply_nterror(req, NT_STATUS_NO_MEMORY);
972 END_PROFILE(SMBtconX);
973 return;
975 } else {
976 /* NT sets the fstype of IPC$ to the null string */
977 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
979 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
980 /* Return permissions. */
981 uint32 perm1 = 0;
982 uint32 perm2 = 0;
984 reply_outbuf(req, 7, 0);
986 if (IS_IPC(conn)) {
987 perm1 = FILE_ALL_ACCESS;
988 perm2 = FILE_ALL_ACCESS;
989 } else {
990 perm1 = conn->share_access;
993 SIVAL(req->outbuf, smb_vwv3, perm1);
994 SIVAL(req->outbuf, smb_vwv5, perm2);
995 } else {
996 reply_outbuf(req, 3, 0);
999 if ((message_push_string(&req->outbuf, server_devicetype,
1000 STR_TERMINATE|STR_ASCII) == -1)
1001 || (message_push_string(&req->outbuf, fstype,
1002 STR_TERMINATE) == -1)) {
1003 reply_nterror(req, NT_STATUS_NO_MEMORY);
1004 END_PROFILE(SMBtconX);
1005 return;
1008 /* what does setting this bit do? It is set by NT4 and
1009 may affect the ability to autorun mounted cdroms */
1010 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1011 optional_support |=
1012 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1014 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1015 DEBUG(2,("Serving %s as a Dfs root\n",
1016 lp_servicename(ctx, SNUM(conn)) ));
1017 optional_support |= SMB_SHARE_IN_DFS;
1020 SSVAL(req->outbuf, smb_vwv2, optional_support);
1023 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1024 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1026 DEBUG(3,("tconX service=%s \n",
1027 service));
1029 /* set the incoming and outgoing tid to the just created one */
1030 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1031 SSVAL(req->outbuf,smb_tid,conn->cnum);
1033 END_PROFILE(SMBtconX);
1035 req->tid = conn->cnum;
1038 /****************************************************************************
1039 Reply to an unknown type.
1040 ****************************************************************************/
1042 void reply_unknown_new(struct smb_request *req, uint8 type)
1044 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1045 smb_fn_name(type), type, type));
1046 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1047 return;
1050 /****************************************************************************
1051 Reply to an ioctl.
1052 conn POINTER CAN BE NULL HERE !
1053 ****************************************************************************/
1055 void reply_ioctl(struct smb_request *req)
1057 connection_struct *conn = req->conn;
1058 uint16 device;
1059 uint16 function;
1060 uint32 ioctl_code;
1061 int replysize;
1062 char *p;
1064 START_PROFILE(SMBioctl);
1066 if (req->wct < 3) {
1067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1068 END_PROFILE(SMBioctl);
1069 return;
1072 device = SVAL(req->vwv+1, 0);
1073 function = SVAL(req->vwv+2, 0);
1074 ioctl_code = (device << 16) + function;
1076 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1078 switch (ioctl_code) {
1079 case IOCTL_QUERY_JOB_INFO:
1080 replysize = 32;
1081 break;
1082 default:
1083 reply_force_doserror(req, ERRSRV, ERRnosupport);
1084 END_PROFILE(SMBioctl);
1085 return;
1088 reply_outbuf(req, 8, replysize+1);
1089 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1090 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1091 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1092 p = smb_buf(req->outbuf);
1093 memset(p, '\0', replysize+1); /* valgrind-safe. */
1094 p += 1; /* Allow for alignment */
1096 switch (ioctl_code) {
1097 case IOCTL_QUERY_JOB_INFO:
1099 NTSTATUS status;
1100 size_t len = 0;
1101 files_struct *fsp = file_fsp(
1102 req, SVAL(req->vwv+0, 0));
1103 if (!fsp) {
1104 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1105 END_PROFILE(SMBioctl);
1106 return;
1108 /* Job number */
1109 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1111 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1112 lp_netbios_name(), 15,
1113 STR_TERMINATE|STR_ASCII, &len);
1114 if (!NT_STATUS_IS_OK(status)) {
1115 reply_nterror(req, status);
1116 END_PROFILE(SMBioctl);
1117 return;
1119 if (conn) {
1120 status = srvstr_push((char *)req->outbuf, req->flags2,
1121 p+18,
1122 lp_servicename(talloc_tos(),
1123 SNUM(conn)),
1124 13, STR_TERMINATE|STR_ASCII, &len);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 reply_nterror(req, status);
1127 END_PROFILE(SMBioctl);
1128 return;
1130 } else {
1131 memset(p+18, 0, 13);
1133 break;
1137 END_PROFILE(SMBioctl);
1138 return;
1141 /****************************************************************************
1142 Strange checkpath NTSTATUS mapping.
1143 ****************************************************************************/
1145 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1147 /* Strange DOS error code semantics only for checkpath... */
1148 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1149 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1150 /* We need to map to ERRbadpath */
1151 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1154 return status;
1157 /****************************************************************************
1158 Reply to a checkpath.
1159 ****************************************************************************/
1161 void reply_checkpath(struct smb_request *req)
1163 connection_struct *conn = req->conn;
1164 struct smb_filename *smb_fname = NULL;
1165 char *name = NULL;
1166 NTSTATUS status;
1167 TALLOC_CTX *ctx = talloc_tos();
1169 START_PROFILE(SMBcheckpath);
1171 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1172 STR_TERMINATE, &status);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 status = map_checkpath_error(req->flags2, status);
1176 reply_nterror(req, status);
1177 END_PROFILE(SMBcheckpath);
1178 return;
1181 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1183 status = filename_convert(ctx,
1184 conn,
1185 req->flags2 & FLAGS2_DFS_PATHNAMES,
1186 name,
1188 NULL,
1189 &smb_fname);
1191 if (!NT_STATUS_IS_OK(status)) {
1192 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1193 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1194 ERRSRV, ERRbadpath);
1195 END_PROFILE(SMBcheckpath);
1196 return;
1198 goto path_err;
1201 if (!VALID_STAT(smb_fname->st) &&
1202 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1203 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1204 smb_fname_str_dbg(smb_fname), strerror(errno)));
1205 status = map_nt_error_from_unix(errno);
1206 goto path_err;
1209 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1210 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1211 ERRDOS, ERRbadpath);
1212 goto out;
1215 reply_outbuf(req, 0, 0);
1217 path_err:
1218 /* We special case this - as when a Windows machine
1219 is parsing a path is steps through the components
1220 one at a time - if a component fails it expects
1221 ERRbadpath, not ERRbadfile.
1223 status = map_checkpath_error(req->flags2, status);
1224 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1226 * Windows returns different error codes if
1227 * the parent directory is valid but not the
1228 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1229 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1230 * if the path is invalid.
1232 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1233 ERRDOS, ERRbadpath);
1234 goto out;
1237 reply_nterror(req, status);
1239 out:
1240 TALLOC_FREE(smb_fname);
1241 END_PROFILE(SMBcheckpath);
1242 return;
1245 /****************************************************************************
1246 Reply to a getatr.
1247 ****************************************************************************/
1249 void reply_getatr(struct smb_request *req)
1251 connection_struct *conn = req->conn;
1252 struct smb_filename *smb_fname = NULL;
1253 char *fname = NULL;
1254 int mode=0;
1255 off_t size=0;
1256 time_t mtime=0;
1257 const char *p;
1258 NTSTATUS status;
1259 TALLOC_CTX *ctx = talloc_tos();
1260 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1262 START_PROFILE(SMBgetatr);
1264 p = (const char *)req->buf + 1;
1265 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1266 if (!NT_STATUS_IS_OK(status)) {
1267 reply_nterror(req, status);
1268 goto out;
1271 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1272 under WfWg - weird! */
1273 if (*fname == '\0') {
1274 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1275 if (!CAN_WRITE(conn)) {
1276 mode |= FILE_ATTRIBUTE_READONLY;
1278 size = 0;
1279 mtime = 0;
1280 } else {
1281 status = filename_convert(ctx,
1282 conn,
1283 req->flags2 & FLAGS2_DFS_PATHNAMES,
1284 fname,
1286 NULL,
1287 &smb_fname);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1290 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1291 ERRSRV, ERRbadpath);
1292 goto out;
1294 reply_nterror(req, status);
1295 goto out;
1297 if (!VALID_STAT(smb_fname->st) &&
1298 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1299 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1300 smb_fname_str_dbg(smb_fname),
1301 strerror(errno)));
1302 reply_nterror(req, map_nt_error_from_unix(errno));
1303 goto out;
1306 mode = dos_mode(conn, smb_fname);
1307 size = smb_fname->st.st_ex_size;
1309 if (ask_sharemode) {
1310 struct timespec write_time_ts;
1311 struct file_id fileid;
1313 ZERO_STRUCT(write_time_ts);
1314 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1315 get_file_infos(fileid, 0, NULL, &write_time_ts);
1316 if (!null_timespec(write_time_ts)) {
1317 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1321 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1322 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1323 size = 0;
1327 reply_outbuf(req, 10, 0);
1329 SSVAL(req->outbuf,smb_vwv0,mode);
1330 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1331 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1332 } else {
1333 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1335 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1337 if (get_Protocol() >= PROTOCOL_NT1) {
1338 SSVAL(req->outbuf, smb_flg2,
1339 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1342 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1343 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1345 out:
1346 TALLOC_FREE(smb_fname);
1347 TALLOC_FREE(fname);
1348 END_PROFILE(SMBgetatr);
1349 return;
1352 /****************************************************************************
1353 Reply to a setatr.
1354 ****************************************************************************/
1356 void reply_setatr(struct smb_request *req)
1358 struct smb_file_time ft;
1359 connection_struct *conn = req->conn;
1360 struct smb_filename *smb_fname = NULL;
1361 char *fname = NULL;
1362 int mode;
1363 time_t mtime;
1364 const char *p;
1365 NTSTATUS status;
1366 TALLOC_CTX *ctx = talloc_tos();
1368 START_PROFILE(SMBsetatr);
1370 ZERO_STRUCT(ft);
1372 if (req->wct < 2) {
1373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1374 goto out;
1377 p = (const char *)req->buf + 1;
1378 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1379 if (!NT_STATUS_IS_OK(status)) {
1380 reply_nterror(req, status);
1381 goto out;
1384 status = filename_convert(ctx,
1385 conn,
1386 req->flags2 & FLAGS2_DFS_PATHNAMES,
1387 fname,
1389 NULL,
1390 &smb_fname);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1393 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1394 ERRSRV, ERRbadpath);
1395 goto out;
1397 reply_nterror(req, status);
1398 goto out;
1401 if (smb_fname->base_name[0] == '.' &&
1402 smb_fname->base_name[1] == '\0') {
1404 * Not sure here is the right place to catch this
1405 * condition. Might be moved to somewhere else later -- vl
1407 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1408 goto out;
1411 mode = SVAL(req->vwv+0, 0);
1412 mtime = srv_make_unix_date3(req->vwv+1);
1414 if (mode != FILE_ATTRIBUTE_NORMAL) {
1415 if (VALID_STAT_OF_DIR(smb_fname->st))
1416 mode |= FILE_ATTRIBUTE_DIRECTORY;
1417 else
1418 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1420 status = check_access(conn, NULL, smb_fname,
1421 FILE_WRITE_ATTRIBUTES);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 reply_nterror(req, status);
1424 goto out;
1427 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1428 false) != 0) {
1429 reply_nterror(req, map_nt_error_from_unix(errno));
1430 goto out;
1434 ft.mtime = convert_time_t_to_timespec(mtime);
1435 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 reply_nterror(req, status);
1438 goto out;
1441 reply_outbuf(req, 0, 0);
1443 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1444 mode));
1445 out:
1446 TALLOC_FREE(smb_fname);
1447 END_PROFILE(SMBsetatr);
1448 return;
1451 /****************************************************************************
1452 Reply to a dskattr.
1453 ****************************************************************************/
1455 void reply_dskattr(struct smb_request *req)
1457 connection_struct *conn = req->conn;
1458 uint64_t dfree,dsize,bsize;
1459 START_PROFILE(SMBdskattr);
1461 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1462 reply_nterror(req, map_nt_error_from_unix(errno));
1463 END_PROFILE(SMBdskattr);
1464 return;
1467 reply_outbuf(req, 5, 0);
1469 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1470 double total_space, free_space;
1471 /* we need to scale this to a number that DOS6 can handle. We
1472 use floating point so we can handle large drives on systems
1473 that don't have 64 bit integers
1475 we end up displaying a maximum of 2G to DOS systems
1477 total_space = dsize * (double)bsize;
1478 free_space = dfree * (double)bsize;
1480 dsize = (uint64_t)((total_space+63*512) / (64*512));
1481 dfree = (uint64_t)((free_space+63*512) / (64*512));
1483 if (dsize > 0xFFFF) dsize = 0xFFFF;
1484 if (dfree > 0xFFFF) dfree = 0xFFFF;
1486 SSVAL(req->outbuf,smb_vwv0,dsize);
1487 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1488 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1489 SSVAL(req->outbuf,smb_vwv3,dfree);
1490 } else {
1491 SSVAL(req->outbuf,smb_vwv0,dsize);
1492 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1493 SSVAL(req->outbuf,smb_vwv2,512);
1494 SSVAL(req->outbuf,smb_vwv3,dfree);
1497 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1499 END_PROFILE(SMBdskattr);
1500 return;
1504 * Utility function to split the filename from the directory.
1506 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1507 char **fname_dir_out,
1508 char **fname_mask_out)
1510 const char *p = NULL;
1511 char *fname_dir = NULL;
1512 char *fname_mask = NULL;
1514 p = strrchr_m(fname_in, '/');
1515 if (!p) {
1516 fname_dir = talloc_strdup(ctx, ".");
1517 fname_mask = talloc_strdup(ctx, fname_in);
1518 } else {
1519 fname_dir = talloc_strndup(ctx, fname_in,
1520 PTR_DIFF(p, fname_in));
1521 fname_mask = talloc_strdup(ctx, p+1);
1524 if (!fname_dir || !fname_mask) {
1525 TALLOC_FREE(fname_dir);
1526 TALLOC_FREE(fname_mask);
1527 return NT_STATUS_NO_MEMORY;
1530 *fname_dir_out = fname_dir;
1531 *fname_mask_out = fname_mask;
1532 return NT_STATUS_OK;
1535 /****************************************************************************
1536 Make a dir struct.
1537 ****************************************************************************/
1539 static bool make_dir_struct(TALLOC_CTX *ctx,
1540 char *buf,
1541 const char *mask,
1542 const char *fname,
1543 off_t size,
1544 uint32 mode,
1545 time_t date,
1546 bool uc)
1548 char *p;
1549 char *mask2 = talloc_strdup(ctx, mask);
1551 if (!mask2) {
1552 return False;
1555 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1556 size = 0;
1559 memset(buf+1,' ',11);
1560 if ((p = strchr_m(mask2,'.')) != NULL) {
1561 *p = 0;
1562 push_ascii(buf+1,mask2,8, 0);
1563 push_ascii(buf+9,p+1,3, 0);
1564 *p = '.';
1565 } else {
1566 push_ascii(buf+1,mask2,11, 0);
1569 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1570 SCVAL(buf,21,mode);
1571 srv_put_dos_date(buf,22,date);
1572 SSVAL(buf,26,size & 0xFFFF);
1573 SSVAL(buf,28,(size >> 16)&0xFFFF);
1574 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1575 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1576 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1577 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1578 return True;
1581 /****************************************************************************
1582 Reply to a search.
1583 Can be called from SMBsearch, SMBffirst or SMBfunique.
1584 ****************************************************************************/
1586 void reply_search(struct smb_request *req)
1588 connection_struct *conn = req->conn;
1589 char *path = NULL;
1590 const char *mask = NULL;
1591 char *directory = NULL;
1592 struct smb_filename *smb_fname = NULL;
1593 char *fname = NULL;
1594 off_t size;
1595 uint32 mode;
1596 struct timespec date;
1597 uint32 dirtype;
1598 unsigned int numentries = 0;
1599 unsigned int maxentries = 0;
1600 bool finished = False;
1601 const char *p;
1602 int status_len;
1603 char status[21];
1604 int dptr_num= -1;
1605 bool check_descend = False;
1606 bool expect_close = False;
1607 NTSTATUS nt_status;
1608 bool mask_contains_wcard = False;
1609 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1610 TALLOC_CTX *ctx = talloc_tos();
1611 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1612 struct dptr_struct *dirptr = NULL;
1613 struct smbXsrv_connection *xconn = req->xconn;
1614 struct smbd_server_connection *sconn = req->sconn;
1616 START_PROFILE(SMBsearch);
1618 if (req->wct < 2) {
1619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1620 goto out;
1623 if (lp_posix_pathnames()) {
1624 reply_unknown_new(req, req->cmd);
1625 goto out;
1628 /* If we were called as SMBffirst then we must expect close. */
1629 if(req->cmd == SMBffirst) {
1630 expect_close = True;
1633 reply_outbuf(req, 1, 3);
1634 maxentries = SVAL(req->vwv+0, 0);
1635 dirtype = SVAL(req->vwv+1, 0);
1636 p = (const char *)req->buf + 1;
1637 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1638 &nt_status, &mask_contains_wcard);
1639 if (!NT_STATUS_IS_OK(nt_status)) {
1640 reply_nterror(req, nt_status);
1641 goto out;
1644 p++;
1645 status_len = SVAL(p, 0);
1646 p += 2;
1648 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1650 if (status_len == 0) {
1651 nt_status = filename_convert(ctx, conn,
1652 req->flags2 & FLAGS2_DFS_PATHNAMES,
1653 path,
1654 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1655 &mask_contains_wcard,
1656 &smb_fname);
1657 if (!NT_STATUS_IS_OK(nt_status)) {
1658 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1659 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1660 ERRSRV, ERRbadpath);
1661 goto out;
1663 reply_nterror(req, nt_status);
1664 goto out;
1667 directory = smb_fname->base_name;
1669 p = strrchr_m(directory,'/');
1670 if ((p != NULL) && (*directory != '/')) {
1671 mask = p + 1;
1672 directory = talloc_strndup(ctx, directory,
1673 PTR_DIFF(p, directory));
1674 } else {
1675 mask = directory;
1676 directory = talloc_strdup(ctx,".");
1679 if (!directory) {
1680 reply_nterror(req, NT_STATUS_NO_MEMORY);
1681 goto out;
1684 memset((char *)status,'\0',21);
1685 SCVAL(status,0,(dirtype & 0x1F));
1687 nt_status = dptr_create(conn,
1688 NULL, /* req */
1689 NULL, /* fsp */
1690 directory,
1691 True,
1692 expect_close,
1693 req->smbpid,
1694 mask,
1695 mask_contains_wcard,
1696 dirtype,
1697 &dirptr);
1698 if (!NT_STATUS_IS_OK(nt_status)) {
1699 reply_nterror(req, nt_status);
1700 goto out;
1702 dptr_num = dptr_dnum(dirptr);
1703 } else {
1704 int status_dirtype;
1705 const char *dirpath;
1707 memcpy(status,p,21);
1708 status_dirtype = CVAL(status,0) & 0x1F;
1709 if (status_dirtype != (dirtype & 0x1F)) {
1710 dirtype = status_dirtype;
1713 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1714 if (!dirptr) {
1715 goto SearchEmpty;
1717 dirpath = dptr_path(sconn, dptr_num);
1718 directory = talloc_strdup(ctx, dirpath);
1719 if (!directory) {
1720 reply_nterror(req, NT_STATUS_NO_MEMORY);
1721 goto out;
1724 mask = dptr_wcard(sconn, dptr_num);
1725 if (!mask) {
1726 goto SearchEmpty;
1729 * For a 'continue' search we have no string. So
1730 * check from the initial saved string.
1732 mask_contains_wcard = ms_has_wild(mask);
1733 dirtype = dptr_attr(sconn, dptr_num);
1736 DEBUG(4,("dptr_num is %d\n",dptr_num));
1738 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1739 dptr_init_search_op(dirptr);
1741 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1742 char buf[DIR_STRUCT_SIZE];
1743 memcpy(buf,status,21);
1744 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1745 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1746 reply_nterror(req, NT_STATUS_NO_MEMORY);
1747 goto out;
1749 dptr_fill(sconn, buf+12,dptr_num);
1750 if (dptr_zero(buf+12) && (status_len==0)) {
1751 numentries = 1;
1752 } else {
1753 numentries = 0;
1755 if (message_push_blob(&req->outbuf,
1756 data_blob_const(buf, sizeof(buf)))
1757 == -1) {
1758 reply_nterror(req, NT_STATUS_NO_MEMORY);
1759 goto out;
1761 } else {
1762 unsigned int i;
1763 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1764 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1766 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1768 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1769 directory,lp_dont_descend(ctx, SNUM(conn))));
1770 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1771 check_descend = True;
1774 for (i=numentries;(i<maxentries) && !finished;i++) {
1775 finished = !get_dir_entry(ctx,
1776 dirptr,
1777 mask,
1778 dirtype,
1779 &fname,
1780 &size,
1781 &mode,
1782 &date,
1783 check_descend,
1784 ask_sharemode);
1785 if (!finished) {
1786 char buf[DIR_STRUCT_SIZE];
1787 memcpy(buf,status,21);
1788 if (!make_dir_struct(ctx,
1789 buf,
1790 mask,
1791 fname,
1792 size,
1793 mode,
1794 convert_timespec_to_time_t(date),
1795 !allow_long_path_components)) {
1796 reply_nterror(req, NT_STATUS_NO_MEMORY);
1797 goto out;
1799 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1800 break;
1802 if (message_push_blob(&req->outbuf,
1803 data_blob_const(buf, sizeof(buf)))
1804 == -1) {
1805 reply_nterror(req, NT_STATUS_NO_MEMORY);
1806 goto out;
1808 numentries++;
1813 SearchEmpty:
1815 /* If we were called as SMBffirst with smb_search_id == NULL
1816 and no entries were found then return error and close dirptr
1817 (X/Open spec) */
1819 if (numentries == 0) {
1820 dptr_close(sconn, &dptr_num);
1821 } else if(expect_close && status_len == 0) {
1822 /* Close the dptr - we know it's gone */
1823 dptr_close(sconn, &dptr_num);
1826 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1827 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1828 dptr_close(sconn, &dptr_num);
1831 if ((numentries == 0) && !mask_contains_wcard) {
1832 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1833 goto out;
1836 SSVAL(req->outbuf,smb_vwv0,numentries);
1837 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1838 SCVAL(smb_buf(req->outbuf),0,5);
1839 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1841 /* The replies here are never long name. */
1842 SSVAL(req->outbuf, smb_flg2,
1843 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1844 if (!allow_long_path_components) {
1845 SSVAL(req->outbuf, smb_flg2,
1846 SVAL(req->outbuf, smb_flg2)
1847 & (~FLAGS2_LONG_PATH_COMPONENTS));
1850 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1851 SSVAL(req->outbuf, smb_flg2,
1852 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1854 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1855 smb_fn_name(req->cmd),
1856 mask,
1857 directory,
1858 dirtype,
1859 numentries,
1860 maxentries ));
1861 out:
1862 TALLOC_FREE(directory);
1863 TALLOC_FREE(smb_fname);
1864 END_PROFILE(SMBsearch);
1865 return;
1868 /****************************************************************************
1869 Reply to a fclose (stop directory search).
1870 ****************************************************************************/
1872 void reply_fclose(struct smb_request *req)
1874 int status_len;
1875 char status[21];
1876 int dptr_num= -2;
1877 const char *p;
1878 char *path = NULL;
1879 NTSTATUS err;
1880 bool path_contains_wcard = False;
1881 TALLOC_CTX *ctx = talloc_tos();
1882 struct smbd_server_connection *sconn = req->sconn;
1884 START_PROFILE(SMBfclose);
1886 if (lp_posix_pathnames()) {
1887 reply_unknown_new(req, req->cmd);
1888 END_PROFILE(SMBfclose);
1889 return;
1892 p = (const char *)req->buf + 1;
1893 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1894 &err, &path_contains_wcard);
1895 if (!NT_STATUS_IS_OK(err)) {
1896 reply_nterror(req, err);
1897 END_PROFILE(SMBfclose);
1898 return;
1900 p++;
1901 status_len = SVAL(p,0);
1902 p += 2;
1904 if (status_len == 0) {
1905 reply_force_doserror(req, ERRSRV, ERRsrverror);
1906 END_PROFILE(SMBfclose);
1907 return;
1910 memcpy(status,p,21);
1912 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1913 /* Close the dptr - we know it's gone */
1914 dptr_close(sconn, &dptr_num);
1917 reply_outbuf(req, 1, 0);
1918 SSVAL(req->outbuf,smb_vwv0,0);
1920 DEBUG(3,("search close\n"));
1922 END_PROFILE(SMBfclose);
1923 return;
1926 /****************************************************************************
1927 Reply to an open.
1928 ****************************************************************************/
1930 void reply_open(struct smb_request *req)
1932 connection_struct *conn = req->conn;
1933 struct smb_filename *smb_fname = NULL;
1934 char *fname = NULL;
1935 uint32 fattr=0;
1936 off_t size = 0;
1937 time_t mtime=0;
1938 int info;
1939 files_struct *fsp;
1940 int oplock_request;
1941 int deny_mode;
1942 uint32 dos_attr;
1943 uint32 access_mask;
1944 uint32 share_mode;
1945 uint32 create_disposition;
1946 uint32 create_options = 0;
1947 uint32_t private_flags = 0;
1948 NTSTATUS status;
1949 TALLOC_CTX *ctx = talloc_tos();
1951 START_PROFILE(SMBopen);
1953 if (req->wct < 2) {
1954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1955 goto out;
1958 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1959 deny_mode = SVAL(req->vwv+0, 0);
1960 dos_attr = SVAL(req->vwv+1, 0);
1962 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1963 STR_TERMINATE, &status);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 reply_nterror(req, status);
1966 goto out;
1969 if (!map_open_params_to_ntcreate(fname, deny_mode,
1970 OPENX_FILE_EXISTS_OPEN, &access_mask,
1971 &share_mode, &create_disposition,
1972 &create_options, &private_flags)) {
1973 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1974 goto out;
1977 status = filename_convert(ctx,
1978 conn,
1979 req->flags2 & FLAGS2_DFS_PATHNAMES,
1980 fname,
1981 UCF_PREP_CREATEFILE,
1982 NULL,
1983 &smb_fname);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1986 reply_botherror(req,
1987 NT_STATUS_PATH_NOT_COVERED,
1988 ERRSRV, ERRbadpath);
1989 goto out;
1991 reply_nterror(req, status);
1992 goto out;
1995 status = SMB_VFS_CREATE_FILE(
1996 conn, /* conn */
1997 req, /* req */
1998 0, /* root_dir_fid */
1999 smb_fname, /* fname */
2000 access_mask, /* access_mask */
2001 share_mode, /* share_access */
2002 create_disposition, /* create_disposition*/
2003 create_options, /* create_options */
2004 dos_attr, /* file_attributes */
2005 oplock_request, /* oplock_request */
2006 NULL, /* lease */
2007 0, /* allocation_size */
2008 private_flags,
2009 NULL, /* sd */
2010 NULL, /* ea_list */
2011 &fsp, /* result */
2012 &info); /* pinfo */
2014 if (!NT_STATUS_IS_OK(status)) {
2015 if (open_was_deferred(req->xconn, req->mid)) {
2016 /* We have re-scheduled this call. */
2017 goto out;
2019 reply_openerror(req, status);
2020 goto out;
2023 /* Ensure we're pointing at the correct stat struct. */
2024 TALLOC_FREE(smb_fname);
2025 smb_fname = fsp->fsp_name;
2027 size = smb_fname->st.st_ex_size;
2028 fattr = dos_mode(conn, smb_fname);
2030 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2032 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2033 DEBUG(3,("attempt to open a directory %s\n",
2034 fsp_str_dbg(fsp)));
2035 close_file(req, fsp, ERROR_CLOSE);
2036 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2037 ERRDOS, ERRnoaccess);
2038 goto out;
2041 reply_outbuf(req, 7, 0);
2042 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2043 SSVAL(req->outbuf,smb_vwv1,fattr);
2044 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2045 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2046 } else {
2047 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2049 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
2050 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2052 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2053 SCVAL(req->outbuf,smb_flg,
2054 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2057 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2058 SCVAL(req->outbuf,smb_flg,
2059 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2061 out:
2062 END_PROFILE(SMBopen);
2063 return;
2066 /****************************************************************************
2067 Reply to an open and X.
2068 ****************************************************************************/
2070 void reply_open_and_X(struct smb_request *req)
2072 connection_struct *conn = req->conn;
2073 struct smb_filename *smb_fname = NULL;
2074 char *fname = NULL;
2075 uint16 open_flags;
2076 int deny_mode;
2077 uint32 smb_attr;
2078 /* Breakout the oplock request bits so we can set the
2079 reply bits separately. */
2080 int ex_oplock_request;
2081 int core_oplock_request;
2082 int oplock_request;
2083 #if 0
2084 int smb_sattr = SVAL(req->vwv+4, 0);
2085 uint32 smb_time = make_unix_date3(req->vwv+6);
2086 #endif
2087 int smb_ofun;
2088 uint32 fattr=0;
2089 int mtime=0;
2090 int smb_action = 0;
2091 files_struct *fsp;
2092 NTSTATUS status;
2093 uint64_t allocation_size;
2094 ssize_t retval = -1;
2095 uint32 access_mask;
2096 uint32 share_mode;
2097 uint32 create_disposition;
2098 uint32 create_options = 0;
2099 uint32_t private_flags = 0;
2100 TALLOC_CTX *ctx = talloc_tos();
2102 START_PROFILE(SMBopenX);
2104 if (req->wct < 15) {
2105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2106 goto out;
2109 open_flags = SVAL(req->vwv+2, 0);
2110 deny_mode = SVAL(req->vwv+3, 0);
2111 smb_attr = SVAL(req->vwv+5, 0);
2112 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2113 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2114 oplock_request = ex_oplock_request | core_oplock_request;
2115 smb_ofun = SVAL(req->vwv+8, 0);
2116 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2118 /* If it's an IPC, pass off the pipe handler. */
2119 if (IS_IPC(conn)) {
2120 if (lp_nt_pipe_support()) {
2121 reply_open_pipe_and_X(conn, req);
2122 } else {
2123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2125 goto out;
2128 /* XXXX we need to handle passed times, sattr and flags */
2129 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2130 STR_TERMINATE, &status);
2131 if (!NT_STATUS_IS_OK(status)) {
2132 reply_nterror(req, status);
2133 goto out;
2136 if (!map_open_params_to_ntcreate(fname, deny_mode,
2137 smb_ofun,
2138 &access_mask, &share_mode,
2139 &create_disposition,
2140 &create_options,
2141 &private_flags)) {
2142 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2143 goto out;
2146 status = filename_convert(ctx,
2147 conn,
2148 req->flags2 & FLAGS2_DFS_PATHNAMES,
2149 fname,
2150 UCF_PREP_CREATEFILE,
2151 NULL,
2152 &smb_fname);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2155 reply_botherror(req,
2156 NT_STATUS_PATH_NOT_COVERED,
2157 ERRSRV, ERRbadpath);
2158 goto out;
2160 reply_nterror(req, status);
2161 goto out;
2164 status = SMB_VFS_CREATE_FILE(
2165 conn, /* conn */
2166 req, /* req */
2167 0, /* root_dir_fid */
2168 smb_fname, /* fname */
2169 access_mask, /* access_mask */
2170 share_mode, /* share_access */
2171 create_disposition, /* create_disposition*/
2172 create_options, /* create_options */
2173 smb_attr, /* file_attributes */
2174 oplock_request, /* oplock_request */
2175 NULL, /* lease */
2176 0, /* allocation_size */
2177 private_flags,
2178 NULL, /* sd */
2179 NULL, /* ea_list */
2180 &fsp, /* result */
2181 &smb_action); /* pinfo */
2183 if (!NT_STATUS_IS_OK(status)) {
2184 if (open_was_deferred(req->xconn, req->mid)) {
2185 /* We have re-scheduled this call. */
2186 goto out;
2188 reply_openerror(req, status);
2189 goto out;
2192 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2193 if the file is truncated or created. */
2194 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2195 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2196 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2197 close_file(req, fsp, ERROR_CLOSE);
2198 reply_nterror(req, NT_STATUS_DISK_FULL);
2199 goto out;
2201 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2202 if (retval < 0) {
2203 close_file(req, fsp, ERROR_CLOSE);
2204 reply_nterror(req, NT_STATUS_DISK_FULL);
2205 goto out;
2207 status = vfs_stat_fsp(fsp);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 close_file(req, fsp, ERROR_CLOSE);
2210 reply_nterror(req, status);
2211 goto out;
2215 fattr = dos_mode(conn, fsp->fsp_name);
2216 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2217 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2218 close_file(req, fsp, ERROR_CLOSE);
2219 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2220 goto out;
2223 /* If the caller set the extended oplock request bit
2224 and we granted one (by whatever means) - set the
2225 correct bit for extended oplock reply.
2228 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2229 smb_action |= EXTENDED_OPLOCK_GRANTED;
2232 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2233 smb_action |= EXTENDED_OPLOCK_GRANTED;
2236 /* If the caller set the core oplock request bit
2237 and we granted one (by whatever means) - set the
2238 correct bit for core oplock reply.
2241 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2242 reply_outbuf(req, 19, 0);
2243 } else {
2244 reply_outbuf(req, 15, 0);
2247 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2248 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2250 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2251 SCVAL(req->outbuf, smb_flg,
2252 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2255 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2256 SCVAL(req->outbuf, smb_flg,
2257 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2260 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2261 SSVAL(req->outbuf,smb_vwv3,fattr);
2262 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2263 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2264 } else {
2265 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2267 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2268 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2269 SSVAL(req->outbuf,smb_vwv11,smb_action);
2271 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2272 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2275 out:
2276 TALLOC_FREE(smb_fname);
2277 END_PROFILE(SMBopenX);
2278 return;
2281 /****************************************************************************
2282 Reply to a SMBulogoffX.
2283 ****************************************************************************/
2285 void reply_ulogoffX(struct smb_request *req)
2287 struct smbd_server_connection *sconn = req->sconn;
2288 struct user_struct *vuser;
2289 struct smbXsrv_session *session = NULL;
2290 NTSTATUS status;
2292 START_PROFILE(SMBulogoffX);
2294 vuser = get_valid_user_struct(sconn, req->vuid);
2296 if(vuser == NULL) {
2297 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2298 (unsigned long long)req->vuid));
2300 req->vuid = UID_FIELD_INVALID;
2301 reply_force_doserror(req, ERRSRV, ERRbaduid);
2302 END_PROFILE(SMBulogoffX);
2303 return;
2306 session = vuser->session;
2307 vuser = NULL;
2310 * TODO: cancel all outstanding requests on the session
2312 status = smbXsrv_session_logoff(session);
2313 if (!NT_STATUS_IS_OK(status)) {
2314 DEBUG(0, ("reply_ulogoff: "
2315 "smbXsrv_session_logoff() failed: %s\n",
2316 nt_errstr(status)));
2318 * If we hit this case, there is something completely
2319 * wrong, so we better disconnect the transport connection.
2321 END_PROFILE(SMBulogoffX);
2322 exit_server(__location__ ": smbXsrv_session_logoff failed");
2323 return;
2326 TALLOC_FREE(session);
2328 reply_outbuf(req, 2, 0);
2329 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2330 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2332 DEBUG(3, ("ulogoffX vuid=%llu\n",
2333 (unsigned long long)req->vuid));
2335 END_PROFILE(SMBulogoffX);
2336 req->vuid = UID_FIELD_INVALID;
2339 /****************************************************************************
2340 Reply to a mknew or a create.
2341 ****************************************************************************/
2343 void reply_mknew(struct smb_request *req)
2345 connection_struct *conn = req->conn;
2346 struct smb_filename *smb_fname = NULL;
2347 char *fname = NULL;
2348 uint32 fattr = 0;
2349 struct smb_file_time ft;
2350 files_struct *fsp;
2351 int oplock_request = 0;
2352 NTSTATUS status;
2353 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2354 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2355 uint32 create_disposition;
2356 uint32 create_options = 0;
2357 TALLOC_CTX *ctx = talloc_tos();
2359 START_PROFILE(SMBcreate);
2360 ZERO_STRUCT(ft);
2362 if (req->wct < 3) {
2363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2364 goto out;
2367 fattr = SVAL(req->vwv+0, 0);
2368 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2370 /* mtime. */
2371 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2373 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2374 STR_TERMINATE, &status);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 reply_nterror(req, status);
2377 goto out;
2380 status = filename_convert(ctx,
2381 conn,
2382 req->flags2 & FLAGS2_DFS_PATHNAMES,
2383 fname,
2384 UCF_PREP_CREATEFILE,
2385 NULL,
2386 &smb_fname);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2389 reply_botherror(req,
2390 NT_STATUS_PATH_NOT_COVERED,
2391 ERRSRV, ERRbadpath);
2392 goto out;
2394 reply_nterror(req, status);
2395 goto out;
2398 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2399 DEBUG(0,("Attempt to create file (%s) with volid set - "
2400 "please report this\n",
2401 smb_fname_str_dbg(smb_fname)));
2404 if(req->cmd == SMBmknew) {
2405 /* We should fail if file exists. */
2406 create_disposition = FILE_CREATE;
2407 } else {
2408 /* Create if file doesn't exist, truncate if it does. */
2409 create_disposition = FILE_OVERWRITE_IF;
2412 status = SMB_VFS_CREATE_FILE(
2413 conn, /* conn */
2414 req, /* req */
2415 0, /* root_dir_fid */
2416 smb_fname, /* fname */
2417 access_mask, /* access_mask */
2418 share_mode, /* share_access */
2419 create_disposition, /* create_disposition*/
2420 create_options, /* create_options */
2421 fattr, /* file_attributes */
2422 oplock_request, /* oplock_request */
2423 NULL, /* lease */
2424 0, /* allocation_size */
2425 0, /* private_flags */
2426 NULL, /* sd */
2427 NULL, /* ea_list */
2428 &fsp, /* result */
2429 NULL); /* pinfo */
2431 if (!NT_STATUS_IS_OK(status)) {
2432 if (open_was_deferred(req->xconn, req->mid)) {
2433 /* We have re-scheduled this call. */
2434 goto out;
2436 reply_openerror(req, status);
2437 goto out;
2440 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2441 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2442 if (!NT_STATUS_IS_OK(status)) {
2443 END_PROFILE(SMBcreate);
2444 goto out;
2447 reply_outbuf(req, 1, 0);
2448 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2450 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2451 SCVAL(req->outbuf,smb_flg,
2452 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2455 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2456 SCVAL(req->outbuf,smb_flg,
2457 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2460 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2461 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2462 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2463 (unsigned int)fattr));
2465 out:
2466 TALLOC_FREE(smb_fname);
2467 END_PROFILE(SMBcreate);
2468 return;
2471 /****************************************************************************
2472 Reply to a create temporary file.
2473 ****************************************************************************/
2475 void reply_ctemp(struct smb_request *req)
2477 connection_struct *conn = req->conn;
2478 struct smb_filename *smb_fname = NULL;
2479 char *wire_name = NULL;
2480 char *fname = NULL;
2481 uint32 fattr;
2482 files_struct *fsp;
2483 int oplock_request;
2484 char *s;
2485 NTSTATUS status;
2486 int i;
2487 TALLOC_CTX *ctx = talloc_tos();
2489 START_PROFILE(SMBctemp);
2491 if (req->wct < 3) {
2492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2493 goto out;
2496 fattr = SVAL(req->vwv+0, 0);
2497 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2499 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2500 STR_TERMINATE, &status);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 reply_nterror(req, status);
2503 goto out;
2506 for (i = 0; i < 10; i++) {
2507 if (*wire_name) {
2508 fname = talloc_asprintf(ctx,
2509 "%s/TMP%s",
2510 wire_name,
2511 generate_random_str_list(ctx, 5, "0123456789"));
2512 } else {
2513 fname = talloc_asprintf(ctx,
2514 "TMP%s",
2515 generate_random_str_list(ctx, 5, "0123456789"));
2518 if (!fname) {
2519 reply_nterror(req, NT_STATUS_NO_MEMORY);
2520 goto out;
2523 status = filename_convert(ctx, conn,
2524 req->flags2 & FLAGS2_DFS_PATHNAMES,
2525 fname,
2526 UCF_PREP_CREATEFILE,
2527 NULL,
2528 &smb_fname);
2529 if (!NT_STATUS_IS_OK(status)) {
2530 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2531 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2532 ERRSRV, ERRbadpath);
2533 goto out;
2535 reply_nterror(req, status);
2536 goto out;
2539 /* Create the file. */
2540 status = SMB_VFS_CREATE_FILE(
2541 conn, /* conn */
2542 req, /* req */
2543 0, /* root_dir_fid */
2544 smb_fname, /* fname */
2545 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2546 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2547 FILE_CREATE, /* create_disposition*/
2548 0, /* create_options */
2549 fattr, /* file_attributes */
2550 oplock_request, /* oplock_request */
2551 NULL, /* lease */
2552 0, /* allocation_size */
2553 0, /* private_flags */
2554 NULL, /* sd */
2555 NULL, /* ea_list */
2556 &fsp, /* result */
2557 NULL); /* pinfo */
2559 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2560 TALLOC_FREE(fname);
2561 TALLOC_FREE(smb_fname);
2562 continue;
2565 if (!NT_STATUS_IS_OK(status)) {
2566 if (open_was_deferred(req->xconn, req->mid)) {
2567 /* We have re-scheduled this call. */
2568 goto out;
2570 reply_openerror(req, status);
2571 goto out;
2574 break;
2577 if (i == 10) {
2578 /* Collision after 10 times... */
2579 reply_nterror(req, status);
2580 goto out;
2583 reply_outbuf(req, 1, 0);
2584 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2586 /* the returned filename is relative to the directory */
2587 s = strrchr_m(fsp->fsp_name->base_name, '/');
2588 if (!s) {
2589 s = fsp->fsp_name->base_name;
2590 } else {
2591 s++;
2594 #if 0
2595 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2596 thing in the byte section. JRA */
2597 SSVALS(p, 0, -1); /* what is this? not in spec */
2598 #endif
2599 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2600 == -1) {
2601 reply_nterror(req, NT_STATUS_NO_MEMORY);
2602 goto out;
2605 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2606 SCVAL(req->outbuf, smb_flg,
2607 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2610 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2611 SCVAL(req->outbuf, smb_flg,
2612 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2615 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2616 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2617 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2618 out:
2619 TALLOC_FREE(smb_fname);
2620 TALLOC_FREE(wire_name);
2621 END_PROFILE(SMBctemp);
2622 return;
2625 /*******************************************************************
2626 Check if a user is allowed to rename a file.
2627 ********************************************************************/
2629 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2630 uint16 dirtype)
2632 if (!CAN_WRITE(conn)) {
2633 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2636 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2637 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2638 /* Only bother to read the DOS attribute if we might deny the
2639 rename on the grounds of attribute missmatch. */
2640 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2641 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2642 return NT_STATUS_NO_SUCH_FILE;
2646 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2647 if (fsp->posix_open) {
2648 return NT_STATUS_OK;
2651 /* If no pathnames are open below this
2652 directory, allow the rename. */
2654 if (file_find_subpath(fsp)) {
2655 return NT_STATUS_ACCESS_DENIED;
2657 return NT_STATUS_OK;
2660 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2661 return NT_STATUS_OK;
2664 return NT_STATUS_ACCESS_DENIED;
2667 /*******************************************************************
2668 * unlink a file with all relevant access checks
2669 *******************************************************************/
2671 static NTSTATUS do_unlink(connection_struct *conn,
2672 struct smb_request *req,
2673 struct smb_filename *smb_fname,
2674 uint32 dirtype)
2676 uint32 fattr;
2677 files_struct *fsp;
2678 uint32 dirtype_orig = dirtype;
2679 NTSTATUS status;
2680 int ret;
2681 bool posix_paths = lp_posix_pathnames();
2683 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2684 smb_fname_str_dbg(smb_fname),
2685 dirtype));
2687 if (!CAN_WRITE(conn)) {
2688 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2691 if (posix_paths) {
2692 ret = SMB_VFS_LSTAT(conn, smb_fname);
2693 } else {
2694 ret = SMB_VFS_STAT(conn, smb_fname);
2696 if (ret != 0) {
2697 return map_nt_error_from_unix(errno);
2700 fattr = dos_mode(conn, smb_fname);
2702 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2703 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2706 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2707 if (!dirtype) {
2708 return NT_STATUS_NO_SUCH_FILE;
2711 if (!dir_check_ftype(fattr, dirtype)) {
2712 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2713 return NT_STATUS_FILE_IS_A_DIRECTORY;
2715 return NT_STATUS_NO_SUCH_FILE;
2718 if (dirtype_orig & 0x8000) {
2719 /* These will never be set for POSIX. */
2720 return NT_STATUS_NO_SUCH_FILE;
2723 #if 0
2724 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2725 return NT_STATUS_FILE_IS_A_DIRECTORY;
2728 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2729 return NT_STATUS_NO_SUCH_FILE;
2732 if (dirtype & 0xFF00) {
2733 /* These will never be set for POSIX. */
2734 return NT_STATUS_NO_SUCH_FILE;
2737 dirtype &= 0xFF;
2738 if (!dirtype) {
2739 return NT_STATUS_NO_SUCH_FILE;
2742 /* Can't delete a directory. */
2743 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2744 return NT_STATUS_FILE_IS_A_DIRECTORY;
2746 #endif
2748 #if 0 /* JRATEST */
2749 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2750 return NT_STATUS_OBJECT_NAME_INVALID;
2751 #endif /* JRATEST */
2753 /* On open checks the open itself will check the share mode, so
2754 don't do it here as we'll get it wrong. */
2756 status = SMB_VFS_CREATE_FILE
2757 (conn, /* conn */
2758 req, /* req */
2759 0, /* root_dir_fid */
2760 smb_fname, /* fname */
2761 DELETE_ACCESS, /* access_mask */
2762 FILE_SHARE_NONE, /* share_access */
2763 FILE_OPEN, /* create_disposition*/
2764 FILE_NON_DIRECTORY_FILE, /* create_options */
2765 /* file_attributes */
2766 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2767 FILE_ATTRIBUTE_NORMAL,
2768 0, /* oplock_request */
2769 NULL, /* lease */
2770 0, /* allocation_size */
2771 0, /* private_flags */
2772 NULL, /* sd */
2773 NULL, /* ea_list */
2774 &fsp, /* result */
2775 NULL); /* pinfo */
2777 if (!NT_STATUS_IS_OK(status)) {
2778 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2779 nt_errstr(status)));
2780 return status;
2783 status = can_set_delete_on_close(fsp, fattr);
2784 if (!NT_STATUS_IS_OK(status)) {
2785 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2786 "(%s)\n",
2787 smb_fname_str_dbg(smb_fname),
2788 nt_errstr(status)));
2789 close_file(req, fsp, NORMAL_CLOSE);
2790 return status;
2793 /* The set is across all open files on this dev/inode pair. */
2794 if (!set_delete_on_close(fsp, True,
2795 conn->session_info->security_token,
2796 conn->session_info->unix_token)) {
2797 close_file(req, fsp, NORMAL_CLOSE);
2798 return NT_STATUS_ACCESS_DENIED;
2801 return close_file(req, fsp, NORMAL_CLOSE);
2804 /****************************************************************************
2805 The guts of the unlink command, split out so it may be called by the NT SMB
2806 code.
2807 ****************************************************************************/
2809 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2810 uint32 dirtype, struct smb_filename *smb_fname,
2811 bool has_wild)
2813 char *fname_dir = NULL;
2814 char *fname_mask = NULL;
2815 int count=0;
2816 NTSTATUS status = NT_STATUS_OK;
2817 TALLOC_CTX *ctx = talloc_tos();
2819 /* Split up the directory from the filename/mask. */
2820 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2821 &fname_dir, &fname_mask);
2822 if (!NT_STATUS_IS_OK(status)) {
2823 goto out;
2827 * We should only check the mangled cache
2828 * here if unix_convert failed. This means
2829 * that the path in 'mask' doesn't exist
2830 * on the file system and so we need to look
2831 * for a possible mangle. This patch from
2832 * Tine Smukavec <valentin.smukavec@hermes.si>.
2835 if (!VALID_STAT(smb_fname->st) &&
2836 mangle_is_mangled(fname_mask, conn->params)) {
2837 char *new_mask = NULL;
2838 mangle_lookup_name_from_8_3(ctx, fname_mask,
2839 &new_mask, conn->params);
2840 if (new_mask) {
2841 TALLOC_FREE(fname_mask);
2842 fname_mask = new_mask;
2846 if (!has_wild) {
2849 * Only one file needs to be unlinked. Append the mask back
2850 * onto the directory.
2852 TALLOC_FREE(smb_fname->base_name);
2853 if (ISDOT(fname_dir)) {
2854 /* Ensure we use canonical names on open. */
2855 smb_fname->base_name = talloc_asprintf(smb_fname,
2856 "%s",
2857 fname_mask);
2858 } else {
2859 smb_fname->base_name = talloc_asprintf(smb_fname,
2860 "%s/%s",
2861 fname_dir,
2862 fname_mask);
2864 if (!smb_fname->base_name) {
2865 status = NT_STATUS_NO_MEMORY;
2866 goto out;
2868 if (dirtype == 0) {
2869 dirtype = FILE_ATTRIBUTE_NORMAL;
2872 status = check_name(conn, smb_fname->base_name);
2873 if (!NT_STATUS_IS_OK(status)) {
2874 goto out;
2877 status = do_unlink(conn, req, smb_fname, dirtype);
2878 if (!NT_STATUS_IS_OK(status)) {
2879 goto out;
2882 count++;
2883 } else {
2884 struct smb_Dir *dir_hnd = NULL;
2885 long offset = 0;
2886 const char *dname = NULL;
2887 char *talloced = NULL;
2889 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2890 status = NT_STATUS_OBJECT_NAME_INVALID;
2891 goto out;
2894 if (strequal(fname_mask,"????????.???")) {
2895 TALLOC_FREE(fname_mask);
2896 fname_mask = talloc_strdup(ctx, "*");
2897 if (!fname_mask) {
2898 status = NT_STATUS_NO_MEMORY;
2899 goto out;
2903 status = check_name(conn, fname_dir);
2904 if (!NT_STATUS_IS_OK(status)) {
2905 goto out;
2908 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2909 dirtype);
2910 if (dir_hnd == NULL) {
2911 status = map_nt_error_from_unix(errno);
2912 goto out;
2915 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2916 the pattern matches against the long name, otherwise the short name
2917 We don't implement this yet XXXX
2920 status = NT_STATUS_NO_SUCH_FILE;
2922 while ((dname = ReadDirName(dir_hnd, &offset,
2923 &smb_fname->st, &talloced))) {
2924 TALLOC_CTX *frame = talloc_stackframe();
2926 if (!is_visible_file(conn, fname_dir, dname,
2927 &smb_fname->st, true)) {
2928 TALLOC_FREE(frame);
2929 TALLOC_FREE(talloced);
2930 continue;
2933 /* Quick check for "." and ".." */
2934 if (ISDOT(dname) || ISDOTDOT(dname)) {
2935 TALLOC_FREE(frame);
2936 TALLOC_FREE(talloced);
2937 continue;
2940 if(!mask_match(dname, fname_mask,
2941 conn->case_sensitive)) {
2942 TALLOC_FREE(frame);
2943 TALLOC_FREE(talloced);
2944 continue;
2947 TALLOC_FREE(smb_fname->base_name);
2948 if (ISDOT(fname_dir)) {
2949 /* Ensure we use canonical names on open. */
2950 smb_fname->base_name =
2951 talloc_asprintf(smb_fname, "%s",
2952 dname);
2953 } else {
2954 smb_fname->base_name =
2955 talloc_asprintf(smb_fname, "%s/%s",
2956 fname_dir, dname);
2959 if (!smb_fname->base_name) {
2960 TALLOC_FREE(dir_hnd);
2961 status = NT_STATUS_NO_MEMORY;
2962 TALLOC_FREE(frame);
2963 TALLOC_FREE(talloced);
2964 goto out;
2967 status = check_name(conn, smb_fname->base_name);
2968 if (!NT_STATUS_IS_OK(status)) {
2969 TALLOC_FREE(dir_hnd);
2970 TALLOC_FREE(frame);
2971 TALLOC_FREE(talloced);
2972 goto out;
2975 status = do_unlink(conn, req, smb_fname, dirtype);
2976 if (!NT_STATUS_IS_OK(status)) {
2977 TALLOC_FREE(dir_hnd);
2978 TALLOC_FREE(frame);
2979 TALLOC_FREE(talloced);
2980 goto out;
2983 count++;
2984 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2985 smb_fname->base_name));
2987 TALLOC_FREE(frame);
2988 TALLOC_FREE(talloced);
2990 TALLOC_FREE(dir_hnd);
2993 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2994 status = map_nt_error_from_unix(errno);
2997 out:
2998 TALLOC_FREE(fname_dir);
2999 TALLOC_FREE(fname_mask);
3000 return status;
3003 /****************************************************************************
3004 Reply to a unlink
3005 ****************************************************************************/
3007 void reply_unlink(struct smb_request *req)
3009 connection_struct *conn = req->conn;
3010 char *name = NULL;
3011 struct smb_filename *smb_fname = NULL;
3012 uint32 dirtype;
3013 NTSTATUS status;
3014 bool path_contains_wcard = False;
3015 TALLOC_CTX *ctx = talloc_tos();
3017 START_PROFILE(SMBunlink);
3019 if (req->wct < 1) {
3020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3021 goto out;
3024 dirtype = SVAL(req->vwv+0, 0);
3026 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3027 STR_TERMINATE, &status,
3028 &path_contains_wcard);
3029 if (!NT_STATUS_IS_OK(status)) {
3030 reply_nterror(req, status);
3031 goto out;
3034 status = filename_convert(ctx, conn,
3035 req->flags2 & FLAGS2_DFS_PATHNAMES,
3036 name,
3037 UCF_COND_ALLOW_WCARD_LCOMP,
3038 &path_contains_wcard,
3039 &smb_fname);
3040 if (!NT_STATUS_IS_OK(status)) {
3041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3042 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3043 ERRSRV, ERRbadpath);
3044 goto out;
3046 reply_nterror(req, status);
3047 goto out;
3050 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3052 status = unlink_internals(conn, req, dirtype, smb_fname,
3053 path_contains_wcard);
3054 if (!NT_STATUS_IS_OK(status)) {
3055 if (open_was_deferred(req->xconn, req->mid)) {
3056 /* We have re-scheduled this call. */
3057 goto out;
3059 reply_nterror(req, status);
3060 goto out;
3063 reply_outbuf(req, 0, 0);
3064 out:
3065 TALLOC_FREE(smb_fname);
3066 END_PROFILE(SMBunlink);
3067 return;
3070 /****************************************************************************
3071 Fail for readbraw.
3072 ****************************************************************************/
3074 static void fail_readraw(void)
3076 const char *errstr = talloc_asprintf(talloc_tos(),
3077 "FAIL ! reply_readbraw: socket write fail (%s)",
3078 strerror(errno));
3079 if (!errstr) {
3080 errstr = "";
3082 exit_server_cleanly(errstr);
3085 /****************************************************************************
3086 Fake (read/write) sendfile. Returns -1 on read or write fail.
3087 ****************************************************************************/
3089 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3090 off_t startpos, size_t nread)
3092 size_t bufsize;
3093 size_t tosend = nread;
3094 char *buf;
3096 if (nread == 0) {
3097 return 0;
3100 bufsize = MIN(nread, 65536);
3102 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3103 return -1;
3106 while (tosend > 0) {
3107 ssize_t ret;
3108 size_t cur_read;
3110 cur_read = MIN(tosend, bufsize);
3111 ret = read_file(fsp,buf,startpos,cur_read);
3112 if (ret == -1) {
3113 SAFE_FREE(buf);
3114 return -1;
3117 /* If we had a short read, fill with zeros. */
3118 if (ret < cur_read) {
3119 memset(buf + ret, '\0', cur_read - ret);
3122 ret = write_data(xconn->transport.sock, buf, cur_read);
3123 if (ret != cur_read) {
3124 int saved_errno = errno;
3126 * Try and give an error message saying what
3127 * client failed.
3129 DEBUG(0, ("write_data failed for client %s. "
3130 "Error %s\n",
3131 smbXsrv_connection_dbg(xconn),
3132 strerror(saved_errno)));
3133 SAFE_FREE(buf);
3134 errno = saved_errno;
3135 return -1;
3137 tosend -= cur_read;
3138 startpos += cur_read;
3141 SAFE_FREE(buf);
3142 return (ssize_t)nread;
3145 /****************************************************************************
3146 Deal with the case of sendfile reading less bytes from the file than
3147 requested. Fill with zeros (all we can do). Returns 0 on success
3148 ****************************************************************************/
3150 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3151 files_struct *fsp,
3152 ssize_t nread,
3153 size_t headersize,
3154 size_t smb_maxcnt)
3156 #define SHORT_SEND_BUFSIZE 1024
3157 if (nread < headersize) {
3158 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3159 "header for file %s (%s). Terminating\n",
3160 fsp_str_dbg(fsp), strerror(errno)));
3161 return -1;
3164 nread -= headersize;
3166 if (nread < smb_maxcnt) {
3167 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3168 if (!buf) {
3169 DEBUG(0,("sendfile_short_send: malloc failed "
3170 "for file %s (%s). Terminating\n",
3171 fsp_str_dbg(fsp), strerror(errno)));
3172 return -1;
3175 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3176 "with zeros !\n", fsp_str_dbg(fsp)));
3178 while (nread < smb_maxcnt) {
3180 * We asked for the real file size and told sendfile
3181 * to not go beyond the end of the file. But it can
3182 * happen that in between our fstat call and the
3183 * sendfile call the file was truncated. This is very
3184 * bad because we have already announced the larger
3185 * number of bytes to the client.
3187 * The best we can do now is to send 0-bytes, just as
3188 * a read from a hole in a sparse file would do.
3190 * This should happen rarely enough that I don't care
3191 * about efficiency here :-)
3193 size_t to_write;
3194 ssize_t ret;
3196 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3197 ret = write_data(xconn->transport.sock, buf, to_write);
3198 if (ret != to_write) {
3199 int saved_errno = errno;
3201 * Try and give an error message saying what
3202 * client failed.
3204 DEBUG(0, ("write_data failed for client %s. "
3205 "Error %s\n",
3206 smbXsrv_connection_dbg(xconn),
3207 strerror(saved_errno)));
3208 errno = saved_errno;
3209 return -1;
3211 nread += to_write;
3213 SAFE_FREE(buf);
3216 return 0;
3219 /****************************************************************************
3220 Return a readbraw error (4 bytes of zero).
3221 ****************************************************************************/
3223 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3225 char header[4];
3227 SIVAL(header,0,0);
3229 smbd_lock_socket(xconn);
3230 if (write_data(xconn->transport.sock,header,4) != 4) {
3231 int saved_errno = errno;
3233 * Try and give an error message saying what
3234 * client failed.
3236 DEBUG(0, ("write_data failed for client %s. "
3237 "Error %s\n",
3238 smbXsrv_connection_dbg(xconn),
3239 strerror(saved_errno)));
3240 errno = saved_errno;
3242 fail_readraw();
3244 smbd_unlock_socket(xconn);
3247 /****************************************************************************
3248 Use sendfile in readbraw.
3249 ****************************************************************************/
3251 static void send_file_readbraw(connection_struct *conn,
3252 struct smb_request *req,
3253 files_struct *fsp,
3254 off_t startpos,
3255 size_t nread,
3256 ssize_t mincount)
3258 struct smbXsrv_connection *xconn = req->xconn;
3259 char *outbuf = NULL;
3260 ssize_t ret=0;
3263 * We can only use sendfile on a non-chained packet
3264 * but we can use on a non-oplocked file. tridge proved this
3265 * on a train in Germany :-). JRA.
3266 * reply_readbraw has already checked the length.
3269 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3270 (fsp->wcp == NULL) &&
3271 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3272 ssize_t sendfile_read = -1;
3273 char header[4];
3274 DATA_BLOB header_blob;
3276 _smb_setlen(header,nread);
3277 header_blob = data_blob_const(header, 4);
3279 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3280 &header_blob, startpos,
3281 nread);
3282 if (sendfile_read == -1) {
3283 /* Returning ENOSYS means no data at all was sent.
3284 * Do this as a normal read. */
3285 if (errno == ENOSYS) {
3286 goto normal_readbraw;
3290 * Special hack for broken Linux with no working sendfile. If we
3291 * return EINTR we sent the header but not the rest of the data.
3292 * Fake this up by doing read/write calls.
3294 if (errno == EINTR) {
3295 /* Ensure we don't do this again. */
3296 set_use_sendfile(SNUM(conn), False);
3297 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3299 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3300 DEBUG(0,("send_file_readbraw: "
3301 "fake_sendfile failed for "
3302 "file %s (%s).\n",
3303 fsp_str_dbg(fsp),
3304 strerror(errno)));
3305 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3307 return;
3310 DEBUG(0,("send_file_readbraw: sendfile failed for "
3311 "file %s (%s). Terminating\n",
3312 fsp_str_dbg(fsp), strerror(errno)));
3313 exit_server_cleanly("send_file_readbraw sendfile failed");
3314 } else if (sendfile_read == 0) {
3316 * Some sendfile implementations return 0 to indicate
3317 * that there was a short read, but nothing was
3318 * actually written to the socket. In this case,
3319 * fallback to the normal read path so the header gets
3320 * the correct byte count.
3322 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3323 "bytes falling back to the normal read: "
3324 "%s\n", fsp_str_dbg(fsp)));
3325 goto normal_readbraw;
3328 /* Deal with possible short send. */
3329 if (sendfile_read != 4+nread) {
3330 ret = sendfile_short_send(xconn, fsp,
3331 sendfile_read, 4, nread);
3332 if (ret == -1) {
3333 fail_readraw();
3336 return;
3339 normal_readbraw:
3341 outbuf = talloc_array(NULL, char, nread+4);
3342 if (!outbuf) {
3343 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3344 (unsigned)(nread+4)));
3345 reply_readbraw_error(xconn);
3346 return;
3349 if (nread > 0) {
3350 ret = read_file(fsp,outbuf+4,startpos,nread);
3351 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3352 if (ret < mincount)
3353 ret = 0;
3354 #else
3355 if (ret < nread)
3356 ret = 0;
3357 #endif
3360 _smb_setlen(outbuf,ret);
3361 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3362 int saved_errno = errno;
3364 * Try and give an error message saying what
3365 * client failed.
3367 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3368 smbXsrv_connection_dbg(xconn),
3369 strerror(saved_errno)));
3370 errno = saved_errno;
3372 fail_readraw();
3375 TALLOC_FREE(outbuf);
3378 /****************************************************************************
3379 Reply to a readbraw (core+ protocol).
3380 ****************************************************************************/
3382 void reply_readbraw(struct smb_request *req)
3384 connection_struct *conn = req->conn;
3385 struct smbXsrv_connection *xconn = req->xconn;
3386 ssize_t maxcount,mincount;
3387 size_t nread = 0;
3388 off_t startpos;
3389 files_struct *fsp;
3390 struct lock_struct lock;
3391 off_t size = 0;
3393 START_PROFILE(SMBreadbraw);
3395 if (srv_is_signing_active(xconn) || req->encrypted) {
3396 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3397 "raw reads/writes are disallowed.");
3400 if (req->wct < 8) {
3401 reply_readbraw_error(xconn);
3402 END_PROFILE(SMBreadbraw);
3403 return;
3406 if (xconn->smb1.echo_handler.trusted_fde) {
3407 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3408 "'async smb echo handler = yes'\n"));
3409 reply_readbraw_error(xconn);
3410 END_PROFILE(SMBreadbraw);
3411 return;
3415 * Special check if an oplock break has been issued
3416 * and the readraw request croses on the wire, we must
3417 * return a zero length response here.
3420 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3423 * We have to do a check_fsp by hand here, as
3424 * we must always return 4 zero bytes on error,
3425 * not a NTSTATUS.
3428 if (!fsp || !conn || conn != fsp->conn ||
3429 req->vuid != fsp->vuid ||
3430 fsp->is_directory || fsp->fh->fd == -1) {
3432 * fsp could be NULL here so use the value from the packet. JRA.
3434 DEBUG(3,("reply_readbraw: fnum %d not valid "
3435 "- cache prime?\n",
3436 (int)SVAL(req->vwv+0, 0)));
3437 reply_readbraw_error(xconn);
3438 END_PROFILE(SMBreadbraw);
3439 return;
3442 /* Do a "by hand" version of CHECK_READ. */
3443 if (!(fsp->can_read ||
3444 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3445 (fsp->access_mask & FILE_EXECUTE)))) {
3446 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3447 (int)SVAL(req->vwv+0, 0)));
3448 reply_readbraw_error(xconn);
3449 END_PROFILE(SMBreadbraw);
3450 return;
3453 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3455 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3456 if(req->wct == 10) {
3458 * This is a large offset (64 bit) read.
3461 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3463 if(startpos < 0) {
3464 DEBUG(0,("reply_readbraw: negative 64 bit "
3465 "readraw offset (%.0f) !\n",
3466 (double)startpos ));
3467 reply_readbraw_error(xconn);
3468 END_PROFILE(SMBreadbraw);
3469 return;
3473 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3474 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3476 /* ensure we don't overrun the packet size */
3477 maxcount = MIN(65535,maxcount);
3479 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3480 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3481 &lock);
3483 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3484 reply_readbraw_error(xconn);
3485 END_PROFILE(SMBreadbraw);
3486 return;
3489 if (fsp_stat(fsp) == 0) {
3490 size = fsp->fsp_name->st.st_ex_size;
3493 if (startpos >= size) {
3494 nread = 0;
3495 } else {
3496 nread = MIN(maxcount,(size - startpos));
3499 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3500 if (nread < mincount)
3501 nread = 0;
3502 #endif
3504 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3505 "min=%lu nread=%lu\n",
3506 fsp_fnum_dbg(fsp), (double)startpos,
3507 (unsigned long)maxcount,
3508 (unsigned long)mincount,
3509 (unsigned long)nread ) );
3511 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3513 DEBUG(5,("reply_readbraw finished\n"));
3515 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3517 END_PROFILE(SMBreadbraw);
3518 return;
3521 #undef DBGC_CLASS
3522 #define DBGC_CLASS DBGC_LOCKING
3524 /****************************************************************************
3525 Reply to a lockread (core+ protocol).
3526 ****************************************************************************/
3528 void reply_lockread(struct smb_request *req)
3530 connection_struct *conn = req->conn;
3531 ssize_t nread = -1;
3532 char *data;
3533 off_t startpos;
3534 size_t numtoread;
3535 size_t maxtoread;
3536 NTSTATUS status;
3537 files_struct *fsp;
3538 struct byte_range_lock *br_lck = NULL;
3539 char *p = NULL;
3540 struct smbXsrv_connection *xconn = req->xconn;
3542 START_PROFILE(SMBlockread);
3544 if (req->wct < 5) {
3545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3546 END_PROFILE(SMBlockread);
3547 return;
3550 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3552 if (!check_fsp(conn, req, fsp)) {
3553 END_PROFILE(SMBlockread);
3554 return;
3557 if (!CHECK_READ(fsp,req)) {
3558 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3559 END_PROFILE(SMBlockread);
3560 return;
3563 numtoread = SVAL(req->vwv+1, 0);
3564 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3567 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3568 * protocol request that predates the read/write lock concept.
3569 * Thus instead of asking for a read lock here we need to ask
3570 * for a write lock. JRA.
3571 * Note that the requested lock size is unaffected by max_send.
3574 br_lck = do_lock(req->sconn->msg_ctx,
3575 fsp,
3576 (uint64_t)req->smbpid,
3577 (uint64_t)numtoread,
3578 (uint64_t)startpos,
3579 WRITE_LOCK,
3580 WINDOWS_LOCK,
3581 False, /* Non-blocking lock. */
3582 &status,
3583 NULL);
3584 TALLOC_FREE(br_lck);
3586 if (NT_STATUS_V(status)) {
3587 reply_nterror(req, status);
3588 END_PROFILE(SMBlockread);
3589 return;
3593 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3595 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3597 if (numtoread > maxtoread) {
3598 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3599 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3600 (unsigned int)numtoread, (unsigned int)maxtoread,
3601 (unsigned int)xconn->smb1.sessions.max_send));
3602 numtoread = maxtoread;
3605 reply_outbuf(req, 5, numtoread + 3);
3607 data = smb_buf(req->outbuf) + 3;
3609 nread = read_file(fsp,data,startpos,numtoread);
3611 if (nread < 0) {
3612 reply_nterror(req, map_nt_error_from_unix(errno));
3613 END_PROFILE(SMBlockread);
3614 return;
3617 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3619 SSVAL(req->outbuf,smb_vwv0,nread);
3620 SSVAL(req->outbuf,smb_vwv5,nread+3);
3621 p = smb_buf(req->outbuf);
3622 SCVAL(p,0,0); /* pad byte. */
3623 SSVAL(p,1,nread);
3625 DEBUG(3,("lockread %s num=%d nread=%d\n",
3626 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3628 END_PROFILE(SMBlockread);
3629 return;
3632 #undef DBGC_CLASS
3633 #define DBGC_CLASS DBGC_ALL
3635 /****************************************************************************
3636 Reply to a read.
3637 ****************************************************************************/
3639 void reply_read(struct smb_request *req)
3641 connection_struct *conn = req->conn;
3642 size_t numtoread;
3643 size_t maxtoread;
3644 ssize_t nread = 0;
3645 char *data;
3646 off_t startpos;
3647 files_struct *fsp;
3648 struct lock_struct lock;
3649 struct smbXsrv_connection *xconn = req->xconn;
3651 START_PROFILE(SMBread);
3653 if (req->wct < 3) {
3654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3655 END_PROFILE(SMBread);
3656 return;
3659 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3661 if (!check_fsp(conn, req, fsp)) {
3662 END_PROFILE(SMBread);
3663 return;
3666 if (!CHECK_READ(fsp,req)) {
3667 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3668 END_PROFILE(SMBread);
3669 return;
3672 numtoread = SVAL(req->vwv+1, 0);
3673 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3676 * The requested read size cannot be greater than max_send. JRA.
3678 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3680 if (numtoread > maxtoread) {
3681 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3682 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3683 (unsigned int)numtoread, (unsigned int)maxtoread,
3684 (unsigned int)xconn->smb1.sessions.max_send));
3685 numtoread = maxtoread;
3688 reply_outbuf(req, 5, numtoread+3);
3690 data = smb_buf(req->outbuf) + 3;
3692 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3693 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3694 &lock);
3696 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3697 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3698 END_PROFILE(SMBread);
3699 return;
3702 if (numtoread > 0)
3703 nread = read_file(fsp,data,startpos,numtoread);
3705 if (nread < 0) {
3706 reply_nterror(req, map_nt_error_from_unix(errno));
3707 goto strict_unlock;
3710 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3712 SSVAL(req->outbuf,smb_vwv0,nread);
3713 SSVAL(req->outbuf,smb_vwv5,nread+3);
3714 SCVAL(smb_buf(req->outbuf),0,1);
3715 SSVAL(smb_buf(req->outbuf),1,nread);
3717 DEBUG(3, ("read %s num=%d nread=%d\n",
3718 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3720 strict_unlock:
3721 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3723 END_PROFILE(SMBread);
3724 return;
3727 /****************************************************************************
3728 Setup readX header.
3729 ****************************************************************************/
3731 static int setup_readX_header(struct smb_request *req, char *outbuf,
3732 size_t smb_maxcnt)
3734 int outsize;
3736 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3737 False);
3739 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3741 SCVAL(outbuf,smb_vwv0,0xFF);
3742 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3743 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3744 SSVAL(outbuf,smb_vwv6,
3745 (smb_wct - 4) /* offset from smb header to wct */
3746 + 1 /* the wct field */
3747 + 12 * sizeof(uint16_t) /* vwv */
3748 + 2 /* the buflen field */
3749 + 1); /* padding byte */
3750 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3751 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3752 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3753 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3754 _smb_setlen_large(outbuf,
3755 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3756 return outsize;
3759 /****************************************************************************
3760 Reply to a read and X - possibly using sendfile.
3761 ****************************************************************************/
3763 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3764 files_struct *fsp, off_t startpos,
3765 size_t smb_maxcnt)
3767 struct smbXsrv_connection *xconn = req->xconn;
3768 ssize_t nread = -1;
3769 struct lock_struct lock;
3770 int saved_errno = 0;
3772 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3773 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3774 &lock);
3776 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3777 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3778 return;
3782 * We can only use sendfile on a non-chained packet
3783 * but we can use on a non-oplocked file. tridge proved this
3784 * on a train in Germany :-). JRA.
3787 if (!req_is_in_chain(req) &&
3788 !req->encrypted &&
3789 (fsp->base_fsp == NULL) &&
3790 (fsp->wcp == NULL) &&
3791 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3792 uint8 headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3793 DATA_BLOB header;
3795 if(fsp_stat(fsp) == -1) {
3796 reply_nterror(req, map_nt_error_from_unix(errno));
3797 goto strict_unlock;
3800 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3801 (startpos > fsp->fsp_name->st.st_ex_size) ||
3802 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3804 * We already know that we would do a short read, so don't
3805 * try the sendfile() path.
3807 goto nosendfile_read;
3811 * Set up the packet header before send. We
3812 * assume here the sendfile will work (get the
3813 * correct amount of data).
3816 header = data_blob_const(headerbuf, sizeof(headerbuf));
3818 construct_reply_common_req(req, (char *)headerbuf);
3819 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3821 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3822 startpos, smb_maxcnt);
3823 if (nread == -1) {
3824 saved_errno = errno;
3826 /* Returning ENOSYS means no data at all was sent.
3827 Do this as a normal read. */
3828 if (errno == ENOSYS) {
3829 goto normal_read;
3833 * Special hack for broken Linux with no working sendfile. If we
3834 * return EINTR we sent the header but not the rest of the data.
3835 * Fake this up by doing read/write calls.
3838 if (errno == EINTR) {
3839 /* Ensure we don't do this again. */
3840 set_use_sendfile(SNUM(conn), False);
3841 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3842 nread = fake_sendfile(xconn, fsp, startpos,
3843 smb_maxcnt);
3844 if (nread == -1) {
3845 saved_errno = errno;
3846 DEBUG(0,("send_file_readX: "
3847 "fake_sendfile failed for "
3848 "file %s (%s) for client %s. "
3849 "Terminating\n",
3850 fsp_str_dbg(fsp),
3851 smbXsrv_connection_dbg(xconn),
3852 strerror(saved_errno)));
3853 errno = saved_errno;
3854 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3856 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3857 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3858 /* No outbuf here means successful sendfile. */
3859 goto strict_unlock;
3862 DEBUG(0,("send_file_readX: sendfile failed for file "
3863 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3864 strerror(errno)));
3865 exit_server_cleanly("send_file_readX sendfile failed");
3866 } else if (nread == 0) {
3868 * Some sendfile implementations return 0 to indicate
3869 * that there was a short read, but nothing was
3870 * actually written to the socket. In this case,
3871 * fallback to the normal read path so the header gets
3872 * the correct byte count.
3874 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3875 "falling back to the normal read: %s\n",
3876 fsp_str_dbg(fsp)));
3877 goto normal_read;
3880 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3881 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3883 /* Deal with possible short send. */
3884 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3885 ssize_t ret;
3887 ret = sendfile_short_send(xconn, fsp, nread,
3888 sizeof(headerbuf), smb_maxcnt);
3889 if (ret == -1) {
3890 const char *r;
3891 r = "send_file_readX: sendfile_short_send failed";
3892 DEBUG(0,("%s for file %s (%s).\n",
3893 r, fsp_str_dbg(fsp), strerror(errno)));
3894 exit_server_cleanly(r);
3897 /* No outbuf here means successful sendfile. */
3898 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3899 SMB_PERFCOUNT_END(&req->pcd);
3900 goto strict_unlock;
3903 normal_read:
3905 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3906 uint8 headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3907 ssize_t ret;
3909 construct_reply_common_req(req, (char *)headerbuf);
3910 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3912 /* Send out the header. */
3913 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3914 sizeof(headerbuf));
3915 if (ret != sizeof(headerbuf)) {
3916 saved_errno = errno;
3918 * Try and give an error message saying what
3919 * client failed.
3921 DEBUG(0,("send_file_readX: write_data failed for file "
3922 "%s (%s) for client %s. Terminating\n",
3923 fsp_str_dbg(fsp),
3924 smbXsrv_connection_dbg(xconn),
3925 strerror(saved_errno)));
3926 errno = saved_errno;
3927 exit_server_cleanly("send_file_readX sendfile failed");
3929 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3930 if (nread == -1) {
3931 saved_errno = errno;
3932 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3933 "%s (%s) for client %s. Terminating\n",
3934 fsp_str_dbg(fsp),
3935 smbXsrv_connection_dbg(xconn),
3936 strerror(saved_errno)));
3937 errno = saved_errno;
3938 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3940 goto strict_unlock;
3943 nosendfile_read:
3945 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3946 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3947 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3949 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3950 startpos, smb_maxcnt);
3951 saved_errno = errno;
3953 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3955 if (nread < 0) {
3956 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3957 return;
3960 setup_readX_header(req, (char *)req->outbuf, nread);
3962 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3963 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3964 return;
3966 strict_unlock:
3967 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3968 TALLOC_FREE(req->outbuf);
3969 return;
3972 /****************************************************************************
3973 Work out how much space we have for a read return.
3974 ****************************************************************************/
3976 static size_t calc_max_read_pdu(const struct smb_request *req)
3978 struct smbXsrv_connection *xconn = req->xconn;
3980 if (xconn->protocol < PROTOCOL_NT1) {
3981 return xconn->smb1.sessions.max_send;
3984 if (!lp_large_readwrite()) {
3985 return xconn->smb1.sessions.max_send;
3988 if (req_is_in_chain(req)) {
3989 return xconn->smb1.sessions.max_send;
3992 if (req->encrypted) {
3994 * Don't take encrypted traffic up to the
3995 * limit. There are padding considerations
3996 * that make that tricky.
3998 return xconn->smb1.sessions.max_send;
4001 if (srv_is_signing_active(xconn)) {
4002 return 0x1FFFF;
4005 if (!lp_unix_extensions()) {
4006 return 0x1FFFF;
4010 * We can do ultra-large POSIX reads.
4012 return 0xFFFFFF;
4015 /****************************************************************************
4016 Calculate how big a read can be. Copes with all clients. It's always
4017 safe to return a short read - Windows does this.
4018 ****************************************************************************/
4020 static size_t calc_read_size(const struct smb_request *req,
4021 size_t upper_size,
4022 size_t lower_size)
4024 struct smbXsrv_connection *xconn = req->xconn;
4025 size_t max_pdu = calc_max_read_pdu(req);
4026 size_t total_size = 0;
4027 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4028 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4031 * Windows explicitly ignores upper size of 0xFFFF.
4032 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4033 * We must do the same as these will never fit even in
4034 * an extended size NetBIOS packet.
4036 if (upper_size == 0xFFFF) {
4037 upper_size = 0;
4040 if (xconn->protocol < PROTOCOL_NT1) {
4041 upper_size = 0;
4044 total_size = ((upper_size<<16) | lower_size);
4047 * LARGE_READX test shows it's always safe to return
4048 * a short read. Windows does so.
4050 return MIN(total_size, max_len);
4053 /****************************************************************************
4054 Reply to a read and X.
4055 ****************************************************************************/
4057 void reply_read_and_X(struct smb_request *req)
4059 connection_struct *conn = req->conn;
4060 files_struct *fsp;
4061 off_t startpos;
4062 size_t smb_maxcnt;
4063 size_t upper_size;
4064 bool big_readX = False;
4065 #if 0
4066 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4067 #endif
4069 START_PROFILE(SMBreadX);
4071 if ((req->wct != 10) && (req->wct != 12)) {
4072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4073 return;
4076 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4077 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4078 smb_maxcnt = SVAL(req->vwv+5, 0);
4080 /* If it's an IPC, pass off the pipe handler. */
4081 if (IS_IPC(conn)) {
4082 reply_pipe_read_and_X(req);
4083 END_PROFILE(SMBreadX);
4084 return;
4087 if (!check_fsp(conn, req, fsp)) {
4088 END_PROFILE(SMBreadX);
4089 return;
4092 if (!CHECK_READ(fsp,req)) {
4093 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4094 END_PROFILE(SMBreadX);
4095 return;
4098 upper_size = SVAL(req->vwv+7, 0);
4099 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4100 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4102 * This is a heuristic to avoid keeping large
4103 * outgoing buffers around over long-lived aio
4104 * requests.
4106 big_readX = True;
4109 if (req->wct == 12) {
4111 * This is a large offset (64 bit) read.
4113 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4117 if (!big_readX) {
4118 NTSTATUS status = schedule_aio_read_and_X(conn,
4119 req,
4120 fsp,
4121 startpos,
4122 smb_maxcnt);
4123 if (NT_STATUS_IS_OK(status)) {
4124 /* Read scheduled - we're done. */
4125 goto out;
4127 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4128 /* Real error - report to client. */
4129 END_PROFILE(SMBreadX);
4130 reply_nterror(req, status);
4131 return;
4133 /* NT_STATUS_RETRY - fall back to sync read. */
4136 smbd_lock_socket(req->xconn);
4137 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4138 smbd_unlock_socket(req->xconn);
4140 out:
4141 END_PROFILE(SMBreadX);
4142 return;
4145 /****************************************************************************
4146 Error replies to writebraw must have smb_wct == 1. Fix this up.
4147 ****************************************************************************/
4149 void error_to_writebrawerr(struct smb_request *req)
4151 uint8 *old_outbuf = req->outbuf;
4153 reply_outbuf(req, 1, 0);
4155 memcpy(req->outbuf, old_outbuf, smb_size);
4156 TALLOC_FREE(old_outbuf);
4159 /****************************************************************************
4160 Read 4 bytes of a smb packet and return the smb length of the packet.
4161 Store the result in the buffer. This version of the function will
4162 never return a session keepalive (length of zero).
4163 Timeout is in milliseconds.
4164 ****************************************************************************/
4166 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4167 size_t *len)
4169 uint8_t msgtype = NBSSkeepalive;
4171 while (msgtype == NBSSkeepalive) {
4172 NTSTATUS status;
4174 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4175 len);
4176 if (!NT_STATUS_IS_OK(status)) {
4177 char addr[INET6_ADDRSTRLEN];
4178 /* Try and give an error message
4179 * saying what client failed. */
4180 DEBUG(0, ("read_fd_with_timeout failed for "
4181 "client %s read error = %s.\n",
4182 get_peer_addr(fd,addr,sizeof(addr)),
4183 nt_errstr(status)));
4184 return status;
4187 msgtype = CVAL(inbuf, 0);
4190 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4191 (unsigned long)len));
4193 return NT_STATUS_OK;
4196 /****************************************************************************
4197 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4198 ****************************************************************************/
4200 void reply_writebraw(struct smb_request *req)
4202 connection_struct *conn = req->conn;
4203 struct smbXsrv_connection *xconn = req->xconn;
4204 char *buf = NULL;
4205 ssize_t nwritten=0;
4206 ssize_t total_written=0;
4207 size_t numtowrite=0;
4208 size_t tcount;
4209 off_t startpos;
4210 const char *data=NULL;
4211 bool write_through;
4212 files_struct *fsp;
4213 struct lock_struct lock;
4214 NTSTATUS status;
4216 START_PROFILE(SMBwritebraw);
4219 * If we ever reply with an error, it must have the SMB command
4220 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4221 * we're finished.
4223 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4225 if (srv_is_signing_active(xconn)) {
4226 END_PROFILE(SMBwritebraw);
4227 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4228 "raw reads/writes are disallowed.");
4231 if (req->wct < 12) {
4232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4233 error_to_writebrawerr(req);
4234 END_PROFILE(SMBwritebraw);
4235 return;
4238 if (xconn->smb1.echo_handler.trusted_fde) {
4239 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4240 "'async smb echo handler = yes'\n"));
4241 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4242 error_to_writebrawerr(req);
4243 END_PROFILE(SMBwritebraw);
4244 return;
4247 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4248 if (!check_fsp(conn, req, fsp)) {
4249 error_to_writebrawerr(req);
4250 END_PROFILE(SMBwritebraw);
4251 return;
4254 if (!CHECK_WRITE(fsp)) {
4255 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4256 error_to_writebrawerr(req);
4257 END_PROFILE(SMBwritebraw);
4258 return;
4261 tcount = IVAL(req->vwv+1, 0);
4262 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4263 write_through = BITSETW(req->vwv+7,0);
4265 /* We have to deal with slightly different formats depending
4266 on whether we are using the core+ or lanman1.0 protocol */
4268 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4269 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4270 data = smb_buf_const(req->inbuf);
4271 } else {
4272 numtowrite = SVAL(req->vwv+10, 0);
4273 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4276 /* Ensure we don't write bytes past the end of this packet. */
4277 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4279 error_to_writebrawerr(req);
4280 END_PROFILE(SMBwritebraw);
4281 return;
4284 if (!fsp->print_file) {
4285 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4286 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4287 &lock);
4289 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4290 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4291 error_to_writebrawerr(req);
4292 END_PROFILE(SMBwritebraw);
4293 return;
4297 if (numtowrite>0) {
4298 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4301 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4302 "wrote=%d sync=%d\n",
4303 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4304 (int)nwritten, (int)write_through));
4306 if (nwritten < (ssize_t)numtowrite) {
4307 reply_nterror(req, NT_STATUS_DISK_FULL);
4308 error_to_writebrawerr(req);
4309 goto strict_unlock;
4312 total_written = nwritten;
4314 /* Allocate a buffer of 64k + length. */
4315 buf = talloc_array(NULL, char, 65540);
4316 if (!buf) {
4317 reply_nterror(req, NT_STATUS_NO_MEMORY);
4318 error_to_writebrawerr(req);
4319 goto strict_unlock;
4322 /* Return a SMBwritebraw message to the redirector to tell
4323 * it to send more bytes */
4325 memcpy(buf, req->inbuf, smb_size);
4326 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4327 SCVAL(buf,smb_com,SMBwritebraw);
4328 SSVALS(buf,smb_vwv0,0xFFFF);
4329 show_msg(buf);
4330 if (!srv_send_smb(req->xconn,
4331 buf,
4332 false, 0, /* no signing */
4333 IS_CONN_ENCRYPTED(conn),
4334 &req->pcd)) {
4335 exit_server_cleanly("reply_writebraw: srv_send_smb "
4336 "failed.");
4339 /* Now read the raw data into the buffer and write it */
4340 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4341 &numtowrite);
4342 if (!NT_STATUS_IS_OK(status)) {
4343 exit_server_cleanly("secondary writebraw failed");
4346 /* Set up outbuf to return the correct size */
4347 reply_outbuf(req, 1, 0);
4349 if (numtowrite != 0) {
4351 if (numtowrite > 0xFFFF) {
4352 DEBUG(0,("reply_writebraw: Oversize secondary write "
4353 "raw requested (%u). Terminating\n",
4354 (unsigned int)numtowrite ));
4355 exit_server_cleanly("secondary writebraw failed");
4358 if (tcount > nwritten+numtowrite) {
4359 DEBUG(3,("reply_writebraw: Client overestimated the "
4360 "write %d %d %d\n",
4361 (int)tcount,(int)nwritten,(int)numtowrite));
4364 status = read_data(xconn->transport.sock, buf+4, numtowrite);
4366 if (!NT_STATUS_IS_OK(status)) {
4367 /* Try and give an error message
4368 * saying what client failed. */
4369 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4370 "raw read failed (%s) for client %s. "
4371 "Terminating\n", nt_errstr(status),
4372 smbXsrv_connection_dbg(xconn)));
4373 exit_server_cleanly("secondary writebraw failed");
4376 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4377 if (nwritten == -1) {
4378 TALLOC_FREE(buf);
4379 reply_nterror(req, map_nt_error_from_unix(errno));
4380 error_to_writebrawerr(req);
4381 goto strict_unlock;
4384 if (nwritten < (ssize_t)numtowrite) {
4385 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4386 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4389 if (nwritten > 0) {
4390 total_written += nwritten;
4394 TALLOC_FREE(buf);
4395 SSVAL(req->outbuf,smb_vwv0,total_written);
4397 status = sync_file(conn, fsp, write_through);
4398 if (!NT_STATUS_IS_OK(status)) {
4399 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4400 fsp_str_dbg(fsp), nt_errstr(status)));
4401 reply_nterror(req, status);
4402 error_to_writebrawerr(req);
4403 goto strict_unlock;
4406 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4407 "wrote=%d\n",
4408 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4409 (int)total_written));
4411 if (!fsp->print_file) {
4412 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4415 /* We won't return a status if write through is not selected - this
4416 * follows what WfWg does */
4417 END_PROFILE(SMBwritebraw);
4419 if (!write_through && total_written==tcount) {
4421 #if RABBIT_PELLET_FIX
4423 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4424 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4425 * JRA.
4427 if (!send_keepalive(xconn->transport.sock)) {
4428 exit_server_cleanly("reply_writebraw: send of "
4429 "keepalive failed");
4431 #endif
4432 TALLOC_FREE(req->outbuf);
4434 return;
4436 strict_unlock:
4437 if (!fsp->print_file) {
4438 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4441 END_PROFILE(SMBwritebraw);
4442 return;
4445 #undef DBGC_CLASS
4446 #define DBGC_CLASS DBGC_LOCKING
4448 /****************************************************************************
4449 Reply to a writeunlock (core+).
4450 ****************************************************************************/
4452 void reply_writeunlock(struct smb_request *req)
4454 connection_struct *conn = req->conn;
4455 ssize_t nwritten = -1;
4456 size_t numtowrite;
4457 off_t startpos;
4458 const char *data;
4459 NTSTATUS status = NT_STATUS_OK;
4460 files_struct *fsp;
4461 struct lock_struct lock;
4462 int saved_errno = 0;
4464 START_PROFILE(SMBwriteunlock);
4466 if (req->wct < 5) {
4467 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4468 END_PROFILE(SMBwriteunlock);
4469 return;
4472 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4474 if (!check_fsp(conn, req, fsp)) {
4475 END_PROFILE(SMBwriteunlock);
4476 return;
4479 if (!CHECK_WRITE(fsp)) {
4480 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4481 END_PROFILE(SMBwriteunlock);
4482 return;
4485 numtowrite = SVAL(req->vwv+1, 0);
4486 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4487 data = (const char *)req->buf + 3;
4489 if (!fsp->print_file && numtowrite > 0) {
4490 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4491 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4492 &lock);
4494 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4495 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4496 END_PROFILE(SMBwriteunlock);
4497 return;
4501 /* The special X/Open SMB protocol handling of
4502 zero length writes is *NOT* done for
4503 this call */
4504 if(numtowrite == 0) {
4505 nwritten = 0;
4506 } else {
4507 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4508 saved_errno = errno;
4511 status = sync_file(conn, fsp, False /* write through */);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4514 fsp_str_dbg(fsp), nt_errstr(status)));
4515 reply_nterror(req, status);
4516 goto strict_unlock;
4519 if(nwritten < 0) {
4520 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4521 goto strict_unlock;
4524 if((nwritten < numtowrite) && (numtowrite != 0)) {
4525 reply_nterror(req, NT_STATUS_DISK_FULL);
4526 goto strict_unlock;
4529 if (numtowrite && !fsp->print_file) {
4530 status = do_unlock(req->sconn->msg_ctx,
4531 fsp,
4532 (uint64_t)req->smbpid,
4533 (uint64_t)numtowrite,
4534 (uint64_t)startpos,
4535 WINDOWS_LOCK);
4537 if (NT_STATUS_V(status)) {
4538 reply_nterror(req, status);
4539 goto strict_unlock;
4543 reply_outbuf(req, 1, 0);
4545 SSVAL(req->outbuf,smb_vwv0,nwritten);
4547 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4548 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4550 strict_unlock:
4551 if (numtowrite && !fsp->print_file) {
4552 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4555 END_PROFILE(SMBwriteunlock);
4556 return;
4559 #undef DBGC_CLASS
4560 #define DBGC_CLASS DBGC_ALL
4562 /****************************************************************************
4563 Reply to a write.
4564 ****************************************************************************/
4566 void reply_write(struct smb_request *req)
4568 connection_struct *conn = req->conn;
4569 size_t numtowrite;
4570 ssize_t nwritten = -1;
4571 off_t startpos;
4572 const char *data;
4573 files_struct *fsp;
4574 struct lock_struct lock;
4575 NTSTATUS status;
4576 int saved_errno = 0;
4578 START_PROFILE(SMBwrite);
4580 if (req->wct < 5) {
4581 END_PROFILE(SMBwrite);
4582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4583 return;
4586 /* If it's an IPC, pass off the pipe handler. */
4587 if (IS_IPC(conn)) {
4588 reply_pipe_write(req);
4589 END_PROFILE(SMBwrite);
4590 return;
4593 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4595 if (!check_fsp(conn, req, fsp)) {
4596 END_PROFILE(SMBwrite);
4597 return;
4600 if (!CHECK_WRITE(fsp)) {
4601 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4602 END_PROFILE(SMBwrite);
4603 return;
4606 numtowrite = SVAL(req->vwv+1, 0);
4607 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4608 data = (const char *)req->buf + 3;
4610 if (!fsp->print_file) {
4611 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4612 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4613 &lock);
4615 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4616 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4617 END_PROFILE(SMBwrite);
4618 return;
4623 * X/Open SMB protocol says that if smb_vwv1 is
4624 * zero then the file size should be extended or
4625 * truncated to the size given in smb_vwv[2-3].
4628 if(numtowrite == 0) {
4630 * This is actually an allocate call, and set EOF. JRA.
4632 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4633 if (nwritten < 0) {
4634 reply_nterror(req, NT_STATUS_DISK_FULL);
4635 goto strict_unlock;
4637 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4638 if (nwritten < 0) {
4639 reply_nterror(req, NT_STATUS_DISK_FULL);
4640 goto strict_unlock;
4642 trigger_write_time_update_immediate(fsp);
4643 } else {
4644 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4647 status = sync_file(conn, fsp, False);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4650 fsp_str_dbg(fsp), nt_errstr(status)));
4651 reply_nterror(req, status);
4652 goto strict_unlock;
4655 if(nwritten < 0) {
4656 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4657 goto strict_unlock;
4660 if((nwritten == 0) && (numtowrite != 0)) {
4661 reply_nterror(req, NT_STATUS_DISK_FULL);
4662 goto strict_unlock;
4665 reply_outbuf(req, 1, 0);
4667 SSVAL(req->outbuf,smb_vwv0,nwritten);
4669 if (nwritten < (ssize_t)numtowrite) {
4670 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4671 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4674 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4676 strict_unlock:
4677 if (!fsp->print_file) {
4678 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4681 END_PROFILE(SMBwrite);
4682 return;
4685 /****************************************************************************
4686 Ensure a buffer is a valid writeX for recvfile purposes.
4687 ****************************************************************************/
4689 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4690 (2*14) + /* word count (including bcc) */ \
4691 1 /* pad byte */)
4693 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4694 const uint8_t *inbuf)
4696 size_t numtowrite;
4697 unsigned int doff = 0;
4698 size_t len = smb_len_large(inbuf);
4699 uint16_t fnum;
4700 struct smbXsrv_open *op = NULL;
4701 struct files_struct *fsp = NULL;
4702 NTSTATUS status;
4704 if (is_encrypted_packet(inbuf)) {
4705 /* Can't do this on encrypted
4706 * connections. */
4707 return false;
4710 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4711 return false;
4714 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4715 CVAL(inbuf,smb_wct) != 14) {
4716 DEBUG(10,("is_valid_writeX_buffer: chained or "
4717 "invalid word length.\n"));
4718 return false;
4721 fnum = SVAL(inbuf, smb_vwv2);
4722 status = smb1srv_open_lookup(xconn,
4723 fnum,
4724 0, /* now */
4725 &op);
4726 if (!NT_STATUS_IS_OK(status)) {
4727 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4728 return false;
4730 fsp = op->compat;
4731 if (fsp == NULL) {
4732 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4733 return false;
4735 if (fsp->conn == NULL) {
4736 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4737 return false;
4740 if (IS_IPC(fsp->conn)) {
4741 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4742 return false;
4744 if (IS_PRINT(fsp->conn)) {
4745 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4746 return false;
4748 doff = SVAL(inbuf,smb_vwv11);
4750 numtowrite = SVAL(inbuf,smb_vwv10);
4752 if (len > doff && len - doff > 0xFFFF) {
4753 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4756 if (numtowrite == 0) {
4757 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4758 return false;
4761 /* Ensure the sizes match up. */
4762 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4763 /* no pad byte...old smbclient :-( */
4764 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4765 (unsigned int)doff,
4766 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4767 return false;
4770 if (len - doff != numtowrite) {
4771 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4772 "len = %u, doff = %u, numtowrite = %u\n",
4773 (unsigned int)len,
4774 (unsigned int)doff,
4775 (unsigned int)numtowrite ));
4776 return false;
4779 DEBUG(10,("is_valid_writeX_buffer: true "
4780 "len = %u, doff = %u, numtowrite = %u\n",
4781 (unsigned int)len,
4782 (unsigned int)doff,
4783 (unsigned int)numtowrite ));
4785 return true;
4788 /****************************************************************************
4789 Reply to a write and X.
4790 ****************************************************************************/
4792 void reply_write_and_X(struct smb_request *req)
4794 connection_struct *conn = req->conn;
4795 struct smbXsrv_connection *xconn = req->xconn;
4796 files_struct *fsp;
4797 struct lock_struct lock;
4798 off_t startpos;
4799 size_t numtowrite;
4800 bool write_through;
4801 ssize_t nwritten;
4802 unsigned int smb_doff;
4803 unsigned int smblen;
4804 const char *data;
4805 NTSTATUS status;
4806 int saved_errno = 0;
4808 START_PROFILE(SMBwriteX);
4810 if ((req->wct != 12) && (req->wct != 14)) {
4811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4812 goto out;
4815 numtowrite = SVAL(req->vwv+10, 0);
4816 smb_doff = SVAL(req->vwv+11, 0);
4817 smblen = smb_len(req->inbuf);
4819 if (req->unread_bytes > 0xFFFF ||
4820 (smblen > smb_doff &&
4821 smblen - smb_doff > 0xFFFF)) {
4822 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4825 if (req->unread_bytes) {
4826 /* Can't do a recvfile write on IPC$ */
4827 if (IS_IPC(conn)) {
4828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4829 goto out;
4831 if (numtowrite != req->unread_bytes) {
4832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4833 goto out;
4835 } else {
4836 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4837 smb_doff + numtowrite > smblen) {
4838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4839 goto out;
4843 /* If it's an IPC, pass off the pipe handler. */
4844 if (IS_IPC(conn)) {
4845 if (req->unread_bytes) {
4846 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4847 goto out;
4849 reply_pipe_write_and_X(req);
4850 goto out;
4853 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4854 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4855 write_through = BITSETW(req->vwv+7,0);
4857 if (!check_fsp(conn, req, fsp)) {
4858 goto out;
4861 if (!CHECK_WRITE(fsp)) {
4862 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4863 goto out;
4866 data = smb_base(req->inbuf) + smb_doff;
4868 if(req->wct == 14) {
4870 * This is a large offset (64 bit) write.
4872 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4876 /* X/Open SMB protocol says that, unlike SMBwrite
4877 if the length is zero then NO truncation is
4878 done, just a write of zero. To truncate a file,
4879 use SMBwrite. */
4881 if(numtowrite == 0) {
4882 nwritten = 0;
4883 } else {
4884 if (req->unread_bytes == 0) {
4885 status = schedule_aio_write_and_X(conn,
4886 req,
4887 fsp,
4888 data,
4889 startpos,
4890 numtowrite);
4892 if (NT_STATUS_IS_OK(status)) {
4893 /* write scheduled - we're done. */
4894 goto out;
4896 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4897 /* Real error - report to client. */
4898 reply_nterror(req, status);
4899 goto out;
4901 /* NT_STATUS_RETRY - fall through to sync write. */
4904 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4905 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4906 &lock);
4908 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4909 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4910 goto out;
4913 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4914 saved_errno = errno;
4916 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4919 if(nwritten < 0) {
4920 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4921 goto out;
4924 if((nwritten == 0) && (numtowrite != 0)) {
4925 reply_nterror(req, NT_STATUS_DISK_FULL);
4926 goto out;
4929 reply_outbuf(req, 6, 0);
4930 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4931 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4932 SSVAL(req->outbuf,smb_vwv2,nwritten);
4933 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4935 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4936 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4938 status = sync_file(conn, fsp, write_through);
4939 if (!NT_STATUS_IS_OK(status)) {
4940 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4941 fsp_str_dbg(fsp), nt_errstr(status)));
4942 reply_nterror(req, status);
4943 goto out;
4946 END_PROFILE(SMBwriteX);
4947 return;
4949 out:
4950 if (req->unread_bytes) {
4951 /* writeX failed. drain socket. */
4952 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4953 req->unread_bytes) {
4954 smb_panic("failed to drain pending bytes");
4956 req->unread_bytes = 0;
4959 END_PROFILE(SMBwriteX);
4960 return;
4963 /****************************************************************************
4964 Reply to a lseek.
4965 ****************************************************************************/
4967 void reply_lseek(struct smb_request *req)
4969 connection_struct *conn = req->conn;
4970 off_t startpos;
4971 off_t res= -1;
4972 int mode,umode;
4973 files_struct *fsp;
4975 START_PROFILE(SMBlseek);
4977 if (req->wct < 4) {
4978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4979 END_PROFILE(SMBlseek);
4980 return;
4983 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4985 if (!check_fsp(conn, req, fsp)) {
4986 return;
4989 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4991 mode = SVAL(req->vwv+1, 0) & 3;
4992 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4993 startpos = (off_t)IVALS(req->vwv+2, 0);
4995 switch (mode) {
4996 case 0:
4997 umode = SEEK_SET;
4998 res = startpos;
4999 break;
5000 case 1:
5001 umode = SEEK_CUR;
5002 res = fsp->fh->pos + startpos;
5003 break;
5004 case 2:
5005 umode = SEEK_END;
5006 break;
5007 default:
5008 umode = SEEK_SET;
5009 res = startpos;
5010 break;
5013 if (umode == SEEK_END) {
5014 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5015 if(errno == EINVAL) {
5016 off_t current_pos = startpos;
5018 if(fsp_stat(fsp) == -1) {
5019 reply_nterror(req,
5020 map_nt_error_from_unix(errno));
5021 END_PROFILE(SMBlseek);
5022 return;
5025 current_pos += fsp->fsp_name->st.st_ex_size;
5026 if(current_pos < 0)
5027 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5031 if(res == -1) {
5032 reply_nterror(req, map_nt_error_from_unix(errno));
5033 END_PROFILE(SMBlseek);
5034 return;
5038 fsp->fh->pos = res;
5040 reply_outbuf(req, 2, 0);
5041 SIVAL(req->outbuf,smb_vwv0,res);
5043 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5044 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5046 END_PROFILE(SMBlseek);
5047 return;
5050 /****************************************************************************
5051 Reply to a flush.
5052 ****************************************************************************/
5054 void reply_flush(struct smb_request *req)
5056 connection_struct *conn = req->conn;
5057 uint16 fnum;
5058 files_struct *fsp;
5060 START_PROFILE(SMBflush);
5062 if (req->wct < 1) {
5063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5064 return;
5067 fnum = SVAL(req->vwv+0, 0);
5068 fsp = file_fsp(req, fnum);
5070 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5071 return;
5074 if (!fsp) {
5075 file_sync_all(conn);
5076 } else {
5077 NTSTATUS status = sync_file(conn, fsp, True);
5078 if (!NT_STATUS_IS_OK(status)) {
5079 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5080 fsp_str_dbg(fsp), nt_errstr(status)));
5081 reply_nterror(req, status);
5082 END_PROFILE(SMBflush);
5083 return;
5087 reply_outbuf(req, 0, 0);
5089 DEBUG(3,("flush\n"));
5090 END_PROFILE(SMBflush);
5091 return;
5094 /****************************************************************************
5095 Reply to a exit.
5096 conn POINTER CAN BE NULL HERE !
5097 ****************************************************************************/
5099 void reply_exit(struct smb_request *req)
5101 START_PROFILE(SMBexit);
5103 file_close_pid(req->sconn, req->smbpid, req->vuid);
5105 reply_outbuf(req, 0, 0);
5107 DEBUG(3,("exit\n"));
5109 END_PROFILE(SMBexit);
5110 return;
5113 struct reply_close_state {
5114 files_struct *fsp;
5115 struct smb_request *smbreq;
5118 static void do_smb1_close(struct tevent_req *req);
5120 void reply_close(struct smb_request *req)
5122 connection_struct *conn = req->conn;
5123 NTSTATUS status = NT_STATUS_OK;
5124 files_struct *fsp = NULL;
5125 START_PROFILE(SMBclose);
5127 if (req->wct < 3) {
5128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5129 END_PROFILE(SMBclose);
5130 return;
5133 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5136 * We can only use check_fsp if we know it's not a directory.
5139 if (!check_fsp_open(conn, req, fsp)) {
5140 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5141 END_PROFILE(SMBclose);
5142 return;
5145 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5146 fsp->is_directory ? "directory" : "file",
5147 fsp->fh->fd, fsp_fnum_dbg(fsp),
5148 conn->num_files_open));
5150 if (!fsp->is_directory) {
5151 time_t t;
5154 * Take care of any time sent in the close.
5157 t = srv_make_unix_date3(req->vwv+1);
5158 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5161 if (fsp->num_aio_requests != 0) {
5163 struct reply_close_state *state;
5165 DEBUG(10, ("closing with aio %u requests pending\n",
5166 fsp->num_aio_requests));
5169 * We depend on the aio_extra destructor to take care of this
5170 * close request once fsp->num_aio_request drops to 0.
5173 fsp->deferred_close = tevent_wait_send(
5174 fsp, fsp->conn->sconn->ev_ctx);
5175 if (fsp->deferred_close == NULL) {
5176 status = NT_STATUS_NO_MEMORY;
5177 goto done;
5180 state = talloc(fsp, struct reply_close_state);
5181 if (state == NULL) {
5182 TALLOC_FREE(fsp->deferred_close);
5183 status = NT_STATUS_NO_MEMORY;
5184 goto done;
5186 state->fsp = fsp;
5187 state->smbreq = talloc_move(fsp, &req);
5188 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5189 state);
5190 END_PROFILE(SMBclose);
5191 return;
5195 * close_file() returns the unix errno if an error was detected on
5196 * close - normally this is due to a disk full error. If not then it
5197 * was probably an I/O error.
5200 status = close_file(req, fsp, NORMAL_CLOSE);
5201 done:
5202 if (!NT_STATUS_IS_OK(status)) {
5203 reply_nterror(req, status);
5204 END_PROFILE(SMBclose);
5205 return;
5208 reply_outbuf(req, 0, 0);
5209 END_PROFILE(SMBclose);
5210 return;
5213 static void do_smb1_close(struct tevent_req *req)
5215 struct reply_close_state *state = tevent_req_callback_data(
5216 req, struct reply_close_state);
5217 struct smb_request *smbreq;
5218 NTSTATUS status;
5219 int ret;
5221 ret = tevent_wait_recv(req);
5222 TALLOC_FREE(req);
5223 if (ret != 0) {
5224 DEBUG(10, ("tevent_wait_recv returned %s\n",
5225 strerror(ret)));
5227 * Continue anyway, this should never happen
5232 * fsp->smb2_close_request right now is a talloc grandchild of
5233 * fsp. When we close_file(fsp), it would go with it. No chance to
5234 * reply...
5236 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5238 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5239 if (NT_STATUS_IS_OK(status)) {
5240 reply_outbuf(smbreq, 0, 0);
5241 } else {
5242 reply_nterror(smbreq, status);
5244 if (!srv_send_smb(smbreq->xconn,
5245 (char *)smbreq->outbuf,
5246 true,
5247 smbreq->seqnum+1,
5248 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5249 NULL)) {
5250 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5251 "failed.");
5253 TALLOC_FREE(smbreq);
5256 /****************************************************************************
5257 Reply to a writeclose (Core+ protocol).
5258 ****************************************************************************/
5260 void reply_writeclose(struct smb_request *req)
5262 connection_struct *conn = req->conn;
5263 size_t numtowrite;
5264 ssize_t nwritten = -1;
5265 NTSTATUS close_status = NT_STATUS_OK;
5266 off_t startpos;
5267 const char *data;
5268 struct timespec mtime;
5269 files_struct *fsp;
5270 struct lock_struct lock;
5272 START_PROFILE(SMBwriteclose);
5274 if (req->wct < 6) {
5275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5276 END_PROFILE(SMBwriteclose);
5277 return;
5280 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5282 if (!check_fsp(conn, req, fsp)) {
5283 END_PROFILE(SMBwriteclose);
5284 return;
5286 if (!CHECK_WRITE(fsp)) {
5287 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5288 END_PROFILE(SMBwriteclose);
5289 return;
5292 numtowrite = SVAL(req->vwv+1, 0);
5293 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5294 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5295 data = (const char *)req->buf + 1;
5297 if (fsp->print_file == NULL) {
5298 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5299 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5300 &lock);
5302 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5303 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5304 END_PROFILE(SMBwriteclose);
5305 return;
5309 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5311 if (fsp->print_file == NULL) {
5312 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5315 set_close_write_time(fsp, mtime);
5318 * More insanity. W2K only closes the file if writelen > 0.
5319 * JRA.
5322 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5323 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5324 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5326 if (numtowrite) {
5327 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5328 "file %s\n", fsp_str_dbg(fsp)));
5329 close_status = close_file(req, fsp, NORMAL_CLOSE);
5330 fsp = NULL;
5333 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5334 reply_nterror(req, NT_STATUS_DISK_FULL);
5335 goto out;
5338 if(!NT_STATUS_IS_OK(close_status)) {
5339 reply_nterror(req, close_status);
5340 goto out;
5343 reply_outbuf(req, 1, 0);
5345 SSVAL(req->outbuf,smb_vwv0,nwritten);
5347 out:
5349 END_PROFILE(SMBwriteclose);
5350 return;
5353 #undef DBGC_CLASS
5354 #define DBGC_CLASS DBGC_LOCKING
5356 /****************************************************************************
5357 Reply to a lock.
5358 ****************************************************************************/
5360 void reply_lock(struct smb_request *req)
5362 connection_struct *conn = req->conn;
5363 uint64_t count,offset;
5364 NTSTATUS status;
5365 files_struct *fsp;
5366 struct byte_range_lock *br_lck = NULL;
5368 START_PROFILE(SMBlock);
5370 if (req->wct < 5) {
5371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5372 END_PROFILE(SMBlock);
5373 return;
5376 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5378 if (!check_fsp(conn, req, fsp)) {
5379 END_PROFILE(SMBlock);
5380 return;
5383 count = (uint64_t)IVAL(req->vwv+1, 0);
5384 offset = (uint64_t)IVAL(req->vwv+3, 0);
5386 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5387 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5389 br_lck = do_lock(req->sconn->msg_ctx,
5390 fsp,
5391 (uint64_t)req->smbpid,
5392 count,
5393 offset,
5394 WRITE_LOCK,
5395 WINDOWS_LOCK,
5396 False, /* Non-blocking lock. */
5397 &status,
5398 NULL);
5400 TALLOC_FREE(br_lck);
5402 if (NT_STATUS_V(status)) {
5403 reply_nterror(req, status);
5404 END_PROFILE(SMBlock);
5405 return;
5408 reply_outbuf(req, 0, 0);
5410 END_PROFILE(SMBlock);
5411 return;
5414 /****************************************************************************
5415 Reply to a unlock.
5416 ****************************************************************************/
5418 void reply_unlock(struct smb_request *req)
5420 connection_struct *conn = req->conn;
5421 uint64_t count,offset;
5422 NTSTATUS status;
5423 files_struct *fsp;
5425 START_PROFILE(SMBunlock);
5427 if (req->wct < 5) {
5428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5429 END_PROFILE(SMBunlock);
5430 return;
5433 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5435 if (!check_fsp(conn, req, fsp)) {
5436 END_PROFILE(SMBunlock);
5437 return;
5440 count = (uint64_t)IVAL(req->vwv+1, 0);
5441 offset = (uint64_t)IVAL(req->vwv+3, 0);
5443 status = do_unlock(req->sconn->msg_ctx,
5444 fsp,
5445 (uint64_t)req->smbpid,
5446 count,
5447 offset,
5448 WINDOWS_LOCK);
5450 if (NT_STATUS_V(status)) {
5451 reply_nterror(req, status);
5452 END_PROFILE(SMBunlock);
5453 return;
5456 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5457 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5459 reply_outbuf(req, 0, 0);
5461 END_PROFILE(SMBunlock);
5462 return;
5465 #undef DBGC_CLASS
5466 #define DBGC_CLASS DBGC_ALL
5468 /****************************************************************************
5469 Reply to a tdis.
5470 conn POINTER CAN BE NULL HERE !
5471 ****************************************************************************/
5473 void reply_tdis(struct smb_request *req)
5475 NTSTATUS status;
5476 connection_struct *conn = req->conn;
5477 struct smbXsrv_tcon *tcon;
5479 START_PROFILE(SMBtdis);
5481 if (!conn) {
5482 DEBUG(4,("Invalid connection in tdis\n"));
5483 reply_force_doserror(req, ERRSRV, ERRinvnid);
5484 END_PROFILE(SMBtdis);
5485 return;
5488 tcon = conn->tcon;
5489 req->conn = NULL;
5492 * TODO: cancel all outstanding requests on the tcon
5494 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 DEBUG(0, ("reply_tdis: "
5497 "smbXsrv_tcon_disconnect() failed: %s\n",
5498 nt_errstr(status)));
5500 * If we hit this case, there is something completely
5501 * wrong, so we better disconnect the transport connection.
5503 END_PROFILE(SMBtdis);
5504 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5505 return;
5508 TALLOC_FREE(tcon);
5510 reply_outbuf(req, 0, 0);
5511 END_PROFILE(SMBtdis);
5512 return;
5515 /****************************************************************************
5516 Reply to a echo.
5517 conn POINTER CAN BE NULL HERE !
5518 ****************************************************************************/
5520 void reply_echo(struct smb_request *req)
5522 connection_struct *conn = req->conn;
5523 struct smb_perfcount_data local_pcd;
5524 struct smb_perfcount_data *cur_pcd;
5525 int smb_reverb;
5526 int seq_num;
5528 START_PROFILE(SMBecho);
5530 smb_init_perfcount_data(&local_pcd);
5532 if (req->wct < 1) {
5533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5534 END_PROFILE(SMBecho);
5535 return;
5538 smb_reverb = SVAL(req->vwv+0, 0);
5540 reply_outbuf(req, 1, req->buflen);
5542 /* copy any incoming data back out */
5543 if (req->buflen > 0) {
5544 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5547 if (smb_reverb > 100) {
5548 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5549 smb_reverb = 100;
5552 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5554 /* this makes sure we catch the request pcd */
5555 if (seq_num == smb_reverb) {
5556 cur_pcd = &req->pcd;
5557 } else {
5558 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5559 cur_pcd = &local_pcd;
5562 SSVAL(req->outbuf,smb_vwv0,seq_num);
5564 show_msg((char *)req->outbuf);
5565 if (!srv_send_smb(req->xconn,
5566 (char *)req->outbuf,
5567 true, req->seqnum+1,
5568 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5569 cur_pcd))
5570 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5573 DEBUG(3,("echo %d times\n", smb_reverb));
5575 TALLOC_FREE(req->outbuf);
5577 END_PROFILE(SMBecho);
5578 return;
5581 /****************************************************************************
5582 Reply to a printopen.
5583 ****************************************************************************/
5585 void reply_printopen(struct smb_request *req)
5587 connection_struct *conn = req->conn;
5588 files_struct *fsp;
5589 NTSTATUS status;
5591 START_PROFILE(SMBsplopen);
5593 if (req->wct < 2) {
5594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5595 END_PROFILE(SMBsplopen);
5596 return;
5599 if (!CAN_PRINT(conn)) {
5600 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5601 END_PROFILE(SMBsplopen);
5602 return;
5605 status = file_new(req, conn, &fsp);
5606 if(!NT_STATUS_IS_OK(status)) {
5607 reply_nterror(req, status);
5608 END_PROFILE(SMBsplopen);
5609 return;
5612 /* Open for exclusive use, write only. */
5613 status = print_spool_open(fsp, NULL, req->vuid);
5615 if (!NT_STATUS_IS_OK(status)) {
5616 file_free(req, fsp);
5617 reply_nterror(req, status);
5618 END_PROFILE(SMBsplopen);
5619 return;
5622 reply_outbuf(req, 1, 0);
5623 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5625 DEBUG(3,("openprint fd=%d %s\n",
5626 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5628 END_PROFILE(SMBsplopen);
5629 return;
5632 /****************************************************************************
5633 Reply to a printclose.
5634 ****************************************************************************/
5636 void reply_printclose(struct smb_request *req)
5638 connection_struct *conn = req->conn;
5639 files_struct *fsp;
5640 NTSTATUS status;
5642 START_PROFILE(SMBsplclose);
5644 if (req->wct < 1) {
5645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5646 END_PROFILE(SMBsplclose);
5647 return;
5650 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5652 if (!check_fsp(conn, req, fsp)) {
5653 END_PROFILE(SMBsplclose);
5654 return;
5657 if (!CAN_PRINT(conn)) {
5658 reply_force_doserror(req, ERRSRV, ERRerror);
5659 END_PROFILE(SMBsplclose);
5660 return;
5663 DEBUG(3,("printclose fd=%d %s\n",
5664 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5666 status = close_file(req, fsp, NORMAL_CLOSE);
5668 if(!NT_STATUS_IS_OK(status)) {
5669 reply_nterror(req, status);
5670 END_PROFILE(SMBsplclose);
5671 return;
5674 reply_outbuf(req, 0, 0);
5676 END_PROFILE(SMBsplclose);
5677 return;
5680 /****************************************************************************
5681 Reply to a printqueue.
5682 ****************************************************************************/
5684 void reply_printqueue(struct smb_request *req)
5686 connection_struct *conn = req->conn;
5687 int max_count;
5688 int start_index;
5690 START_PROFILE(SMBsplretq);
5692 if (req->wct < 2) {
5693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5694 END_PROFILE(SMBsplretq);
5695 return;
5698 max_count = SVAL(req->vwv+0, 0);
5699 start_index = SVAL(req->vwv+1, 0);
5701 /* we used to allow the client to get the cnum wrong, but that
5702 is really quite gross and only worked when there was only
5703 one printer - I think we should now only accept it if they
5704 get it right (tridge) */
5705 if (!CAN_PRINT(conn)) {
5706 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5707 END_PROFILE(SMBsplretq);
5708 return;
5711 reply_outbuf(req, 2, 3);
5712 SSVAL(req->outbuf,smb_vwv0,0);
5713 SSVAL(req->outbuf,smb_vwv1,0);
5714 SCVAL(smb_buf(req->outbuf),0,1);
5715 SSVAL(smb_buf(req->outbuf),1,0);
5717 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5718 start_index, max_count));
5721 TALLOC_CTX *mem_ctx = talloc_tos();
5722 NTSTATUS status;
5723 WERROR werr;
5724 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5725 struct rpc_pipe_client *cli = NULL;
5726 struct dcerpc_binding_handle *b = NULL;
5727 struct policy_handle handle;
5728 struct spoolss_DevmodeContainer devmode_ctr;
5729 union spoolss_JobInfo *info;
5730 uint32_t count;
5731 uint32_t num_to_get;
5732 uint32_t first;
5733 uint32_t i;
5735 ZERO_STRUCT(handle);
5737 status = rpc_pipe_open_interface(conn,
5738 &ndr_table_spoolss,
5739 conn->session_info,
5740 conn->sconn->remote_address,
5741 conn->sconn->msg_ctx,
5742 &cli);
5743 if (!NT_STATUS_IS_OK(status)) {
5744 DEBUG(0, ("reply_printqueue: "
5745 "could not connect to spoolss: %s\n",
5746 nt_errstr(status)));
5747 reply_nterror(req, status);
5748 goto out;
5750 b = cli->binding_handle;
5752 ZERO_STRUCT(devmode_ctr);
5754 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5755 sharename,
5756 NULL, devmode_ctr,
5757 SEC_FLAG_MAXIMUM_ALLOWED,
5758 &handle,
5759 &werr);
5760 if (!NT_STATUS_IS_OK(status)) {
5761 reply_nterror(req, status);
5762 goto out;
5764 if (!W_ERROR_IS_OK(werr)) {
5765 reply_nterror(req, werror_to_ntstatus(werr));
5766 goto out;
5769 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5770 &handle,
5771 0, /* firstjob */
5772 0xff, /* numjobs */
5773 2, /* level */
5774 0, /* offered */
5775 &count,
5776 &info);
5777 if (!W_ERROR_IS_OK(werr)) {
5778 reply_nterror(req, werror_to_ntstatus(werr));
5779 goto out;
5782 if (max_count > 0) {
5783 first = start_index;
5784 } else {
5785 first = start_index + max_count + 1;
5788 if (first >= count) {
5789 num_to_get = first;
5790 } else {
5791 num_to_get = first + MIN(ABS(max_count), count - first);
5794 for (i = first; i < num_to_get; i++) {
5795 char blob[28];
5796 char *p = blob;
5797 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5798 int qstatus;
5799 size_t len = 0;
5800 uint16_t qrapjobid = pjobid_to_rap(sharename,
5801 info[i].info2.job_id);
5803 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5804 qstatus = 2;
5805 } else {
5806 qstatus = 3;
5809 srv_put_dos_date2(p, 0, qtime);
5810 SCVAL(p, 4, qstatus);
5811 SSVAL(p, 5, qrapjobid);
5812 SIVAL(p, 7, info[i].info2.size);
5813 SCVAL(p, 11, 0);
5814 status = srvstr_push(blob, req->flags2, p+12,
5815 info[i].info2.notify_name, 16, STR_ASCII, &len);
5816 if (!NT_STATUS_IS_OK(status)) {
5817 reply_nterror(req, status);
5818 goto out;
5820 if (message_push_blob(
5821 &req->outbuf,
5822 data_blob_const(
5823 blob, sizeof(blob))) == -1) {
5824 reply_nterror(req, NT_STATUS_NO_MEMORY);
5825 goto out;
5829 if (count > 0) {
5830 SSVAL(req->outbuf,smb_vwv0,count);
5831 SSVAL(req->outbuf,smb_vwv1,
5832 (max_count>0?first+count:first-1));
5833 SCVAL(smb_buf(req->outbuf),0,1);
5834 SSVAL(smb_buf(req->outbuf),1,28*count);
5838 DEBUG(3, ("%u entries returned in queue\n",
5839 (unsigned)count));
5841 out:
5842 if (b && is_valid_policy_hnd(&handle)) {
5843 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5848 END_PROFILE(SMBsplretq);
5849 return;
5852 /****************************************************************************
5853 Reply to a printwrite.
5854 ****************************************************************************/
5856 void reply_printwrite(struct smb_request *req)
5858 connection_struct *conn = req->conn;
5859 int numtowrite;
5860 const char *data;
5861 files_struct *fsp;
5863 START_PROFILE(SMBsplwr);
5865 if (req->wct < 1) {
5866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5867 END_PROFILE(SMBsplwr);
5868 return;
5871 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5873 if (!check_fsp(conn, req, fsp)) {
5874 END_PROFILE(SMBsplwr);
5875 return;
5878 if (!fsp->print_file) {
5879 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5880 END_PROFILE(SMBsplwr);
5881 return;
5884 if (!CHECK_WRITE(fsp)) {
5885 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5886 END_PROFILE(SMBsplwr);
5887 return;
5890 numtowrite = SVAL(req->buf, 1);
5892 if (req->buflen < numtowrite + 3) {
5893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5894 END_PROFILE(SMBsplwr);
5895 return;
5898 data = (const char *)req->buf + 3;
5900 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5901 reply_nterror(req, map_nt_error_from_unix(errno));
5902 END_PROFILE(SMBsplwr);
5903 return;
5906 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5908 END_PROFILE(SMBsplwr);
5909 return;
5912 /****************************************************************************
5913 Reply to a mkdir.
5914 ****************************************************************************/
5916 void reply_mkdir(struct smb_request *req)
5918 connection_struct *conn = req->conn;
5919 struct smb_filename *smb_dname = NULL;
5920 char *directory = NULL;
5921 NTSTATUS status;
5922 TALLOC_CTX *ctx = talloc_tos();
5924 START_PROFILE(SMBmkdir);
5926 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5927 STR_TERMINATE, &status);
5928 if (!NT_STATUS_IS_OK(status)) {
5929 reply_nterror(req, status);
5930 goto out;
5933 status = filename_convert(ctx, conn,
5934 req->flags2 & FLAGS2_DFS_PATHNAMES,
5935 directory,
5936 UCF_PREP_CREATEFILE,
5937 NULL,
5938 &smb_dname);
5939 if (!NT_STATUS_IS_OK(status)) {
5940 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5941 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5942 ERRSRV, ERRbadpath);
5943 goto out;
5945 reply_nterror(req, status);
5946 goto out;
5949 status = create_directory(conn, req, smb_dname);
5951 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5953 if (!NT_STATUS_IS_OK(status)) {
5955 if (!use_nt_status()
5956 && NT_STATUS_EQUAL(status,
5957 NT_STATUS_OBJECT_NAME_COLLISION)) {
5959 * Yes, in the DOS error code case we get a
5960 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5961 * samba4 torture test.
5963 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5966 reply_nterror(req, status);
5967 goto out;
5970 reply_outbuf(req, 0, 0);
5972 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5973 out:
5974 TALLOC_FREE(smb_dname);
5975 END_PROFILE(SMBmkdir);
5976 return;
5979 /****************************************************************************
5980 Reply to a rmdir.
5981 ****************************************************************************/
5983 void reply_rmdir(struct smb_request *req)
5985 connection_struct *conn = req->conn;
5986 struct smb_filename *smb_dname = NULL;
5987 char *directory = NULL;
5988 NTSTATUS status;
5989 TALLOC_CTX *ctx = talloc_tos();
5990 files_struct *fsp = NULL;
5991 int info = 0;
5992 struct smbd_server_connection *sconn = req->sconn;
5994 START_PROFILE(SMBrmdir);
5996 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5997 STR_TERMINATE, &status);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 reply_nterror(req, status);
6000 goto out;
6003 status = filename_convert(ctx, conn,
6004 req->flags2 & FLAGS2_DFS_PATHNAMES,
6005 directory,
6007 NULL,
6008 &smb_dname);
6009 if (!NT_STATUS_IS_OK(status)) {
6010 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6011 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6012 ERRSRV, ERRbadpath);
6013 goto out;
6015 reply_nterror(req, status);
6016 goto out;
6019 if (is_ntfs_stream_smb_fname(smb_dname)) {
6020 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6021 goto out;
6024 status = SMB_VFS_CREATE_FILE(
6025 conn, /* conn */
6026 req, /* req */
6027 0, /* root_dir_fid */
6028 smb_dname, /* fname */
6029 DELETE_ACCESS, /* access_mask */
6030 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6031 FILE_SHARE_DELETE),
6032 FILE_OPEN, /* create_disposition*/
6033 FILE_DIRECTORY_FILE, /* create_options */
6034 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6035 0, /* oplock_request */
6036 NULL, /* lease */
6037 0, /* allocation_size */
6038 0, /* private_flags */
6039 NULL, /* sd */
6040 NULL, /* ea_list */
6041 &fsp, /* result */
6042 &info); /* pinfo */
6044 if (!NT_STATUS_IS_OK(status)) {
6045 if (open_was_deferred(req->xconn, req->mid)) {
6046 /* We have re-scheduled this call. */
6047 goto out;
6049 reply_nterror(req, status);
6050 goto out;
6053 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6054 if (!NT_STATUS_IS_OK(status)) {
6055 close_file(req, fsp, ERROR_CLOSE);
6056 reply_nterror(req, status);
6057 goto out;
6060 if (!set_delete_on_close(fsp, true,
6061 conn->session_info->security_token,
6062 conn->session_info->unix_token)) {
6063 close_file(req, fsp, ERROR_CLOSE);
6064 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6065 goto out;
6068 status = close_file(req, fsp, NORMAL_CLOSE);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 reply_nterror(req, status);
6071 } else {
6072 reply_outbuf(req, 0, 0);
6075 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6077 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6078 out:
6079 TALLOC_FREE(smb_dname);
6080 END_PROFILE(SMBrmdir);
6081 return;
6084 /*******************************************************************
6085 Resolve wildcards in a filename rename.
6086 ********************************************************************/
6088 static bool resolve_wildcards(TALLOC_CTX *ctx,
6089 const char *name1,
6090 const char *name2,
6091 char **pp_newname)
6093 char *name2_copy = NULL;
6094 char *root1 = NULL;
6095 char *root2 = NULL;
6096 char *ext1 = NULL;
6097 char *ext2 = NULL;
6098 char *p,*p2, *pname1, *pname2;
6100 name2_copy = talloc_strdup(ctx, name2);
6101 if (!name2_copy) {
6102 return False;
6105 pname1 = strrchr_m(name1,'/');
6106 pname2 = strrchr_m(name2_copy,'/');
6108 if (!pname1 || !pname2) {
6109 return False;
6112 /* Truncate the copy of name2 at the last '/' */
6113 *pname2 = '\0';
6115 /* Now go past the '/' */
6116 pname1++;
6117 pname2++;
6119 root1 = talloc_strdup(ctx, pname1);
6120 root2 = talloc_strdup(ctx, pname2);
6122 if (!root1 || !root2) {
6123 return False;
6126 p = strrchr_m(root1,'.');
6127 if (p) {
6128 *p = 0;
6129 ext1 = talloc_strdup(ctx, p+1);
6130 } else {
6131 ext1 = talloc_strdup(ctx, "");
6133 p = strrchr_m(root2,'.');
6134 if (p) {
6135 *p = 0;
6136 ext2 = talloc_strdup(ctx, p+1);
6137 } else {
6138 ext2 = talloc_strdup(ctx, "");
6141 if (!ext1 || !ext2) {
6142 return False;
6145 p = root1;
6146 p2 = root2;
6147 while (*p2) {
6148 if (*p2 == '?') {
6149 /* Hmmm. Should this be mb-aware ? */
6150 *p2 = *p;
6151 p2++;
6152 } else if (*p2 == '*') {
6153 *p2 = '\0';
6154 root2 = talloc_asprintf(ctx, "%s%s",
6155 root2,
6157 if (!root2) {
6158 return False;
6160 break;
6161 } else {
6162 p2++;
6164 if (*p) {
6165 p++;
6169 p = ext1;
6170 p2 = ext2;
6171 while (*p2) {
6172 if (*p2 == '?') {
6173 /* Hmmm. Should this be mb-aware ? */
6174 *p2 = *p;
6175 p2++;
6176 } else if (*p2 == '*') {
6177 *p2 = '\0';
6178 ext2 = talloc_asprintf(ctx, "%s%s",
6179 ext2,
6181 if (!ext2) {
6182 return False;
6184 break;
6185 } else {
6186 p2++;
6188 if (*p) {
6189 p++;
6193 if (*ext2) {
6194 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6195 name2_copy,
6196 root2,
6197 ext2);
6198 } else {
6199 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6200 name2_copy,
6201 root2);
6204 if (!*pp_newname) {
6205 return False;
6208 return True;
6211 /****************************************************************************
6212 Ensure open files have their names updated. Updated to notify other smbd's
6213 asynchronously.
6214 ****************************************************************************/
6216 static void rename_open_files(connection_struct *conn,
6217 struct share_mode_lock *lck,
6218 struct file_id id,
6219 uint32_t orig_name_hash,
6220 const struct smb_filename *smb_fname_dst)
6222 files_struct *fsp;
6223 bool did_rename = False;
6224 NTSTATUS status;
6225 uint32_t new_name_hash = 0;
6227 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6228 fsp = file_find_di_next(fsp)) {
6229 /* fsp_name is a relative path under the fsp. To change this for other
6230 sharepaths we need to manipulate relative paths. */
6231 /* TODO - create the absolute path and manipulate the newname
6232 relative to the sharepath. */
6233 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6234 continue;
6236 if (fsp->name_hash != orig_name_hash) {
6237 continue;
6239 DEBUG(10, ("rename_open_files: renaming file %s "
6240 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6241 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6242 smb_fname_str_dbg(smb_fname_dst)));
6244 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6245 if (NT_STATUS_IS_OK(status)) {
6246 did_rename = True;
6247 new_name_hash = fsp->name_hash;
6251 if (!did_rename) {
6252 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6253 "for %s\n", file_id_string_tos(&id),
6254 smb_fname_str_dbg(smb_fname_dst)));
6257 /* Send messages to all smbd's (not ourself) that the name has changed. */
6258 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6259 orig_name_hash, new_name_hash,
6260 smb_fname_dst);
6264 /****************************************************************************
6265 We need to check if the source path is a parent directory of the destination
6266 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6267 refuse the rename with a sharing violation. Under UNIX the above call can
6268 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6269 probably need to check that the client is a Windows one before disallowing
6270 this as a UNIX client (one with UNIX extensions) can know the source is a
6271 symlink and make this decision intelligently. Found by an excellent bug
6272 report from <AndyLiebman@aol.com>.
6273 ****************************************************************************/
6275 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6276 const struct smb_filename *smb_fname_dst)
6278 const char *psrc = smb_fname_src->base_name;
6279 const char *pdst = smb_fname_dst->base_name;
6280 size_t slen;
6282 if (psrc[0] == '.' && psrc[1] == '/') {
6283 psrc += 2;
6285 if (pdst[0] == '.' && pdst[1] == '/') {
6286 pdst += 2;
6288 if ((slen = strlen(psrc)) > strlen(pdst)) {
6289 return False;
6291 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6295 * Do the notify calls from a rename
6298 static void notify_rename(connection_struct *conn, bool is_dir,
6299 const struct smb_filename *smb_fname_src,
6300 const struct smb_filename *smb_fname_dst)
6302 char *parent_dir_src = NULL;
6303 char *parent_dir_dst = NULL;
6304 uint32 mask;
6306 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6307 : FILE_NOTIFY_CHANGE_FILE_NAME;
6309 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6310 &parent_dir_src, NULL) ||
6311 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6312 &parent_dir_dst, NULL)) {
6313 goto out;
6316 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6317 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6318 smb_fname_src->base_name);
6319 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6320 smb_fname_dst->base_name);
6322 else {
6323 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6324 smb_fname_src->base_name);
6325 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6326 smb_fname_dst->base_name);
6329 /* this is a strange one. w2k3 gives an additional event for
6330 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6331 files, but not directories */
6332 if (!is_dir) {
6333 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6334 FILE_NOTIFY_CHANGE_ATTRIBUTES
6335 |FILE_NOTIFY_CHANGE_CREATION,
6336 smb_fname_dst->base_name);
6338 out:
6339 TALLOC_FREE(parent_dir_src);
6340 TALLOC_FREE(parent_dir_dst);
6343 /****************************************************************************
6344 Returns an error if the parent directory for a filename is open in an
6345 incompatible way.
6346 ****************************************************************************/
6348 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6349 const struct smb_filename *smb_fname_dst_in)
6351 char *parent_dir = NULL;
6352 struct smb_filename smb_fname_parent;
6353 struct file_id id;
6354 files_struct *fsp = NULL;
6355 int ret;
6357 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6358 &parent_dir, NULL)) {
6359 return NT_STATUS_NO_MEMORY;
6361 ZERO_STRUCT(smb_fname_parent);
6362 smb_fname_parent.base_name = parent_dir;
6364 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6365 if (ret == -1) {
6366 return map_nt_error_from_unix(errno);
6370 * We're only checking on this smbd here, mostly good
6371 * enough.. and will pass tests.
6374 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6375 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6376 fsp = file_find_di_next(fsp)) {
6377 if (fsp->access_mask & DELETE_ACCESS) {
6378 return NT_STATUS_SHARING_VIOLATION;
6381 return NT_STATUS_OK;
6384 /****************************************************************************
6385 Rename an open file - given an fsp.
6386 ****************************************************************************/
6388 NTSTATUS rename_internals_fsp(connection_struct *conn,
6389 files_struct *fsp,
6390 const struct smb_filename *smb_fname_dst_in,
6391 uint32 attrs,
6392 bool replace_if_exists)
6394 TALLOC_CTX *ctx = talloc_tos();
6395 struct smb_filename *smb_fname_dst = NULL;
6396 NTSTATUS status = NT_STATUS_OK;
6397 struct share_mode_lock *lck = NULL;
6398 bool dst_exists, old_is_stream, new_is_stream;
6400 status = check_name(conn, smb_fname_dst_in->base_name);
6401 if (!NT_STATUS_IS_OK(status)) {
6402 return status;
6405 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6406 if (!NT_STATUS_IS_OK(status)) {
6407 return status;
6410 /* Make a copy of the dst smb_fname structs */
6412 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6413 if (smb_fname_dst == NULL) {
6414 status = NT_STATUS_NO_MEMORY;
6415 goto out;
6419 * Check for special case with case preserving and not
6420 * case sensitive. If the old last component differs from the original
6421 * last component only by case, then we should allow
6422 * the rename (user is trying to change the case of the
6423 * filename).
6425 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6426 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6427 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6428 char *last_slash;
6429 char *fname_dst_lcomp_base_mod = NULL;
6430 struct smb_filename *smb_fname_orig_lcomp = NULL;
6433 * Get the last component of the destination name.
6435 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6436 if (last_slash) {
6437 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6438 } else {
6439 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6441 if (!fname_dst_lcomp_base_mod) {
6442 status = NT_STATUS_NO_MEMORY;
6443 goto out;
6447 * Create an smb_filename struct using the original last
6448 * component of the destination.
6450 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6451 ctx, smb_fname_dst->original_lcomp, NULL);
6452 if (smb_fname_orig_lcomp == NULL) {
6453 status = NT_STATUS_NO_MEMORY;
6454 TALLOC_FREE(fname_dst_lcomp_base_mod);
6455 goto out;
6458 /* If the base names only differ by case, use original. */
6459 if(!strcsequal(fname_dst_lcomp_base_mod,
6460 smb_fname_orig_lcomp->base_name)) {
6461 char *tmp;
6463 * Replace the modified last component with the
6464 * original.
6466 if (last_slash) {
6467 *last_slash = '\0'; /* Truncate at the '/' */
6468 tmp = talloc_asprintf(smb_fname_dst,
6469 "%s/%s",
6470 smb_fname_dst->base_name,
6471 smb_fname_orig_lcomp->base_name);
6472 } else {
6473 tmp = talloc_asprintf(smb_fname_dst,
6474 "%s",
6475 smb_fname_orig_lcomp->base_name);
6477 if (tmp == NULL) {
6478 status = NT_STATUS_NO_MEMORY;
6479 TALLOC_FREE(fname_dst_lcomp_base_mod);
6480 TALLOC_FREE(smb_fname_orig_lcomp);
6481 goto out;
6483 TALLOC_FREE(smb_fname_dst->base_name);
6484 smb_fname_dst->base_name = tmp;
6487 /* If the stream_names only differ by case, use original. */
6488 if(!strcsequal(smb_fname_dst->stream_name,
6489 smb_fname_orig_lcomp->stream_name)) {
6490 char *tmp = NULL;
6491 /* Use the original stream. */
6492 tmp = talloc_strdup(smb_fname_dst,
6493 smb_fname_orig_lcomp->stream_name);
6494 if (tmp == NULL) {
6495 status = NT_STATUS_NO_MEMORY;
6496 TALLOC_FREE(fname_dst_lcomp_base_mod);
6497 TALLOC_FREE(smb_fname_orig_lcomp);
6498 goto out;
6500 TALLOC_FREE(smb_fname_dst->stream_name);
6501 smb_fname_dst->stream_name = tmp;
6503 TALLOC_FREE(fname_dst_lcomp_base_mod);
6504 TALLOC_FREE(smb_fname_orig_lcomp);
6508 * If the src and dest names are identical - including case,
6509 * don't do the rename, just return success.
6512 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6513 strcsequal(fsp->fsp_name->stream_name,
6514 smb_fname_dst->stream_name)) {
6515 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6516 "- returning success\n",
6517 smb_fname_str_dbg(smb_fname_dst)));
6518 status = NT_STATUS_OK;
6519 goto out;
6522 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6523 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6525 /* Return the correct error code if both names aren't streams. */
6526 if (!old_is_stream && new_is_stream) {
6527 status = NT_STATUS_OBJECT_NAME_INVALID;
6528 goto out;
6531 if (old_is_stream && !new_is_stream) {
6532 status = NT_STATUS_INVALID_PARAMETER;
6533 goto out;
6536 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6538 if(!replace_if_exists && dst_exists) {
6539 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6540 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6541 smb_fname_str_dbg(smb_fname_dst)));
6542 status = NT_STATUS_OBJECT_NAME_COLLISION;
6543 goto out;
6546 if (dst_exists) {
6547 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6548 &smb_fname_dst->st);
6549 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6550 fileid);
6551 /* The file can be open when renaming a stream */
6552 if (dst_fsp && !new_is_stream) {
6553 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6554 status = NT_STATUS_ACCESS_DENIED;
6555 goto out;
6559 /* Ensure we have a valid stat struct for the source. */
6560 status = vfs_stat_fsp(fsp);
6561 if (!NT_STATUS_IS_OK(status)) {
6562 goto out;
6565 status = can_rename(conn, fsp, attrs);
6567 if (!NT_STATUS_IS_OK(status)) {
6568 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6569 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6570 smb_fname_str_dbg(smb_fname_dst)));
6571 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6572 status = NT_STATUS_ACCESS_DENIED;
6573 goto out;
6576 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6577 status = NT_STATUS_ACCESS_DENIED;
6580 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6583 * We have the file open ourselves, so not being able to get the
6584 * corresponding share mode lock is a fatal error.
6587 SMB_ASSERT(lck != NULL);
6589 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6590 uint32 create_options = fsp->fh->private_options;
6592 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6593 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6594 smb_fname_str_dbg(smb_fname_dst)));
6596 if (!fsp->is_directory &&
6597 !lp_posix_pathnames() &&
6598 (lp_map_archive(SNUM(conn)) ||
6599 lp_store_dos_attributes(SNUM(conn)))) {
6600 /* We must set the archive bit on the newly
6601 renamed file. */
6602 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6603 uint32_t old_dosmode = dos_mode(conn,
6604 smb_fname_dst);
6605 file_set_dosmode(conn,
6606 smb_fname_dst,
6607 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6608 NULL,
6609 true);
6613 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6614 smb_fname_dst);
6616 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6617 smb_fname_dst);
6620 * A rename acts as a new file create w.r.t. allowing an initial delete
6621 * on close, probably because in Windows there is a new handle to the
6622 * new file. If initial delete on close was requested but not
6623 * originally set, we need to set it here. This is probably not 100% correct,
6624 * but will work for the CIFSFS client which in non-posix mode
6625 * depends on these semantics. JRA.
6628 if (create_options & FILE_DELETE_ON_CLOSE) {
6629 status = can_set_delete_on_close(fsp, 0);
6631 if (NT_STATUS_IS_OK(status)) {
6632 /* Note that here we set the *inital* delete on close flag,
6633 * not the regular one. The magic gets handled in close. */
6634 fsp->initial_delete_on_close = True;
6637 TALLOC_FREE(lck);
6638 status = NT_STATUS_OK;
6639 goto out;
6642 TALLOC_FREE(lck);
6644 if (errno == ENOTDIR || errno == EISDIR) {
6645 status = NT_STATUS_OBJECT_NAME_COLLISION;
6646 } else {
6647 status = map_nt_error_from_unix(errno);
6650 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6651 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6652 smb_fname_str_dbg(smb_fname_dst)));
6654 out:
6655 TALLOC_FREE(smb_fname_dst);
6657 return status;
6660 /****************************************************************************
6661 The guts of the rename command, split out so it may be called by the NT SMB
6662 code.
6663 ****************************************************************************/
6665 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6666 connection_struct *conn,
6667 struct smb_request *req,
6668 struct smb_filename *smb_fname_src,
6669 struct smb_filename *smb_fname_dst,
6670 uint32 attrs,
6671 bool replace_if_exists,
6672 bool src_has_wild,
6673 bool dest_has_wild,
6674 uint32_t access_mask)
6676 char *fname_src_dir = NULL;
6677 char *fname_src_mask = NULL;
6678 int count=0;
6679 NTSTATUS status = NT_STATUS_OK;
6680 struct smb_Dir *dir_hnd = NULL;
6681 const char *dname = NULL;
6682 char *talloced = NULL;
6683 long offset = 0;
6684 int create_options = 0;
6685 bool posix_pathnames = lp_posix_pathnames();
6686 int rc;
6689 * Split the old name into directory and last component
6690 * strings. Note that unix_convert may have stripped off a
6691 * leading ./ from both name and newname if the rename is
6692 * at the root of the share. We need to make sure either both
6693 * name and newname contain a / character or neither of them do
6694 * as this is checked in resolve_wildcards().
6697 /* Split up the directory from the filename/mask. */
6698 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6699 &fname_src_dir, &fname_src_mask);
6700 if (!NT_STATUS_IS_OK(status)) {
6701 status = NT_STATUS_NO_MEMORY;
6702 goto out;
6706 * We should only check the mangled cache
6707 * here if unix_convert failed. This means
6708 * that the path in 'mask' doesn't exist
6709 * on the file system and so we need to look
6710 * for a possible mangle. This patch from
6711 * Tine Smukavec <valentin.smukavec@hermes.si>.
6714 if (!VALID_STAT(smb_fname_src->st) &&
6715 mangle_is_mangled(fname_src_mask, conn->params)) {
6716 char *new_mask = NULL;
6717 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6718 conn->params);
6719 if (new_mask) {
6720 TALLOC_FREE(fname_src_mask);
6721 fname_src_mask = new_mask;
6725 if (!src_has_wild) {
6726 files_struct *fsp;
6729 * Only one file needs to be renamed. Append the mask back
6730 * onto the directory.
6732 TALLOC_FREE(smb_fname_src->base_name);
6733 if (ISDOT(fname_src_dir)) {
6734 /* Ensure we use canonical names on open. */
6735 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6736 "%s",
6737 fname_src_mask);
6738 } else {
6739 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6740 "%s/%s",
6741 fname_src_dir,
6742 fname_src_mask);
6744 if (!smb_fname_src->base_name) {
6745 status = NT_STATUS_NO_MEMORY;
6746 goto out;
6749 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6750 "case_preserve = %d, short case preserve = %d, "
6751 "directory = %s, newname = %s, "
6752 "last_component_dest = %s\n",
6753 conn->case_sensitive, conn->case_preserve,
6754 conn->short_case_preserve,
6755 smb_fname_str_dbg(smb_fname_src),
6756 smb_fname_str_dbg(smb_fname_dst),
6757 smb_fname_dst->original_lcomp));
6759 /* The dest name still may have wildcards. */
6760 if (dest_has_wild) {
6761 char *fname_dst_mod = NULL;
6762 if (!resolve_wildcards(smb_fname_dst,
6763 smb_fname_src->base_name,
6764 smb_fname_dst->base_name,
6765 &fname_dst_mod)) {
6766 DEBUG(6, ("rename_internals: resolve_wildcards "
6767 "%s %s failed\n",
6768 smb_fname_src->base_name,
6769 smb_fname_dst->base_name));
6770 status = NT_STATUS_NO_MEMORY;
6771 goto out;
6773 TALLOC_FREE(smb_fname_dst->base_name);
6774 smb_fname_dst->base_name = fname_dst_mod;
6777 ZERO_STRUCT(smb_fname_src->st);
6778 if (posix_pathnames) {
6779 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6780 } else {
6781 rc = SMB_VFS_STAT(conn, smb_fname_src);
6783 if (rc == -1) {
6784 status = map_nt_error_from_unix_common(errno);
6785 goto out;
6788 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6789 create_options |= FILE_DIRECTORY_FILE;
6792 status = SMB_VFS_CREATE_FILE(
6793 conn, /* conn */
6794 req, /* req */
6795 0, /* root_dir_fid */
6796 smb_fname_src, /* fname */
6797 access_mask, /* access_mask */
6798 (FILE_SHARE_READ | /* share_access */
6799 FILE_SHARE_WRITE),
6800 FILE_OPEN, /* create_disposition*/
6801 create_options, /* create_options */
6802 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6803 0, /* oplock_request */
6804 NULL, /* lease */
6805 0, /* allocation_size */
6806 0, /* private_flags */
6807 NULL, /* sd */
6808 NULL, /* ea_list */
6809 &fsp, /* result */
6810 NULL); /* pinfo */
6812 if (!NT_STATUS_IS_OK(status)) {
6813 DEBUG(3, ("Could not open rename source %s: %s\n",
6814 smb_fname_str_dbg(smb_fname_src),
6815 nt_errstr(status)));
6816 goto out;
6819 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6820 attrs, replace_if_exists);
6822 close_file(req, fsp, NORMAL_CLOSE);
6824 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6825 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6826 smb_fname_str_dbg(smb_fname_dst)));
6828 goto out;
6832 * Wildcards - process each file that matches.
6834 if (strequal(fname_src_mask, "????????.???")) {
6835 TALLOC_FREE(fname_src_mask);
6836 fname_src_mask = talloc_strdup(ctx, "*");
6837 if (!fname_src_mask) {
6838 status = NT_STATUS_NO_MEMORY;
6839 goto out;
6843 status = check_name(conn, fname_src_dir);
6844 if (!NT_STATUS_IS_OK(status)) {
6845 goto out;
6848 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6849 attrs);
6850 if (dir_hnd == NULL) {
6851 status = map_nt_error_from_unix(errno);
6852 goto out;
6855 status = NT_STATUS_NO_SUCH_FILE;
6857 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6858 * - gentest fix. JRA
6861 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6862 &talloced))) {
6863 files_struct *fsp = NULL;
6864 char *destname = NULL;
6865 bool sysdir_entry = False;
6867 /* Quick check for "." and ".." */
6868 if (ISDOT(dname) || ISDOTDOT(dname)) {
6869 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6870 sysdir_entry = True;
6871 } else {
6872 TALLOC_FREE(talloced);
6873 continue;
6877 if (!is_visible_file(conn, fname_src_dir, dname,
6878 &smb_fname_src->st, false)) {
6879 TALLOC_FREE(talloced);
6880 continue;
6883 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6884 TALLOC_FREE(talloced);
6885 continue;
6888 if (sysdir_entry) {
6889 status = NT_STATUS_OBJECT_NAME_INVALID;
6890 break;
6893 TALLOC_FREE(smb_fname_src->base_name);
6894 if (ISDOT(fname_src_dir)) {
6895 /* Ensure we use canonical names on open. */
6896 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6897 "%s",
6898 dname);
6899 } else {
6900 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6901 "%s/%s",
6902 fname_src_dir,
6903 dname);
6905 if (!smb_fname_src->base_name) {
6906 status = NT_STATUS_NO_MEMORY;
6907 goto out;
6910 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6911 smb_fname_dst->base_name,
6912 &destname)) {
6913 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6914 smb_fname_src->base_name, destname));
6915 TALLOC_FREE(talloced);
6916 continue;
6918 if (!destname) {
6919 status = NT_STATUS_NO_MEMORY;
6920 goto out;
6923 TALLOC_FREE(smb_fname_dst->base_name);
6924 smb_fname_dst->base_name = destname;
6926 ZERO_STRUCT(smb_fname_src->st);
6927 if (posix_pathnames) {
6928 SMB_VFS_LSTAT(conn, smb_fname_src);
6929 } else {
6930 SMB_VFS_STAT(conn, smb_fname_src);
6933 create_options = 0;
6935 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6936 create_options |= FILE_DIRECTORY_FILE;
6939 status = SMB_VFS_CREATE_FILE(
6940 conn, /* conn */
6941 req, /* req */
6942 0, /* root_dir_fid */
6943 smb_fname_src, /* fname */
6944 access_mask, /* access_mask */
6945 (FILE_SHARE_READ | /* share_access */
6946 FILE_SHARE_WRITE),
6947 FILE_OPEN, /* create_disposition*/
6948 create_options, /* create_options */
6949 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6950 0, /* oplock_request */
6951 NULL, /* lease */
6952 0, /* allocation_size */
6953 0, /* private_flags */
6954 NULL, /* sd */
6955 NULL, /* ea_list */
6956 &fsp, /* result */
6957 NULL); /* pinfo */
6959 if (!NT_STATUS_IS_OK(status)) {
6960 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6961 "returned %s rename %s -> %s\n",
6962 nt_errstr(status),
6963 smb_fname_str_dbg(smb_fname_src),
6964 smb_fname_str_dbg(smb_fname_dst)));
6965 break;
6968 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6969 dname);
6970 if (!smb_fname_dst->original_lcomp) {
6971 status = NT_STATUS_NO_MEMORY;
6972 goto out;
6975 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6976 attrs, replace_if_exists);
6978 close_file(req, fsp, NORMAL_CLOSE);
6980 if (!NT_STATUS_IS_OK(status)) {
6981 DEBUG(3, ("rename_internals_fsp returned %s for "
6982 "rename %s -> %s\n", nt_errstr(status),
6983 smb_fname_str_dbg(smb_fname_src),
6984 smb_fname_str_dbg(smb_fname_dst)));
6985 break;
6988 count++;
6990 DEBUG(3,("rename_internals: doing rename on %s -> "
6991 "%s\n", smb_fname_str_dbg(smb_fname_src),
6992 smb_fname_str_dbg(smb_fname_src)));
6993 TALLOC_FREE(talloced);
6995 TALLOC_FREE(dir_hnd);
6997 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6998 status = map_nt_error_from_unix(errno);
7001 out:
7002 TALLOC_FREE(talloced);
7003 TALLOC_FREE(fname_src_dir);
7004 TALLOC_FREE(fname_src_mask);
7005 return status;
7008 /****************************************************************************
7009 Reply to a mv.
7010 ****************************************************************************/
7012 void reply_mv(struct smb_request *req)
7014 connection_struct *conn = req->conn;
7015 char *name = NULL;
7016 char *newname = NULL;
7017 const char *p;
7018 uint32 attrs;
7019 NTSTATUS status;
7020 bool src_has_wcard = False;
7021 bool dest_has_wcard = False;
7022 TALLOC_CTX *ctx = talloc_tos();
7023 struct smb_filename *smb_fname_src = NULL;
7024 struct smb_filename *smb_fname_dst = NULL;
7025 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
7026 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
7027 bool stream_rename = false;
7029 START_PROFILE(SMBmv);
7031 if (req->wct < 1) {
7032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7033 goto out;
7036 attrs = SVAL(req->vwv+0, 0);
7038 p = (const char *)req->buf + 1;
7039 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7040 &status, &src_has_wcard);
7041 if (!NT_STATUS_IS_OK(status)) {
7042 reply_nterror(req, status);
7043 goto out;
7045 p++;
7046 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7047 &status, &dest_has_wcard);
7048 if (!NT_STATUS_IS_OK(status)) {
7049 reply_nterror(req, status);
7050 goto out;
7053 if (!lp_posix_pathnames()) {
7054 /* The newname must begin with a ':' if the
7055 name contains a ':'. */
7056 if (strchr_m(name, ':')) {
7057 if (newname[0] != ':') {
7058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7059 goto out;
7061 stream_rename = true;
7065 status = filename_convert(ctx,
7066 conn,
7067 req->flags2 & FLAGS2_DFS_PATHNAMES,
7068 name,
7069 src_ucf_flags,
7070 &src_has_wcard,
7071 &smb_fname_src);
7073 if (!NT_STATUS_IS_OK(status)) {
7074 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7075 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7076 ERRSRV, ERRbadpath);
7077 goto out;
7079 reply_nterror(req, status);
7080 goto out;
7083 status = filename_convert(ctx,
7084 conn,
7085 req->flags2 & FLAGS2_DFS_PATHNAMES,
7086 newname,
7087 dst_ucf_flags,
7088 &dest_has_wcard,
7089 &smb_fname_dst);
7091 if (!NT_STATUS_IS_OK(status)) {
7092 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7093 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7094 ERRSRV, ERRbadpath);
7095 goto out;
7097 reply_nterror(req, status);
7098 goto out;
7101 if (stream_rename) {
7102 /* smb_fname_dst->base_name must be the same as
7103 smb_fname_src->base_name. */
7104 TALLOC_FREE(smb_fname_dst->base_name);
7105 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7106 smb_fname_src->base_name);
7107 if (!smb_fname_dst->base_name) {
7108 reply_nterror(req, NT_STATUS_NO_MEMORY);
7109 goto out;
7113 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7114 smb_fname_str_dbg(smb_fname_dst)));
7116 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7117 attrs, False, src_has_wcard, dest_has_wcard,
7118 DELETE_ACCESS);
7119 if (!NT_STATUS_IS_OK(status)) {
7120 if (open_was_deferred(req->xconn, req->mid)) {
7121 /* We have re-scheduled this call. */
7122 goto out;
7124 reply_nterror(req, status);
7125 goto out;
7128 reply_outbuf(req, 0, 0);
7129 out:
7130 TALLOC_FREE(smb_fname_src);
7131 TALLOC_FREE(smb_fname_dst);
7132 END_PROFILE(SMBmv);
7133 return;
7136 /*******************************************************************
7137 Copy a file as part of a reply_copy.
7138 ******************************************************************/
7141 * TODO: check error codes on all callers
7144 NTSTATUS copy_file(TALLOC_CTX *ctx,
7145 connection_struct *conn,
7146 struct smb_filename *smb_fname_src,
7147 struct smb_filename *smb_fname_dst,
7148 int ofun,
7149 int count,
7150 bool target_is_directory)
7152 struct smb_filename *smb_fname_dst_tmp = NULL;
7153 off_t ret=-1;
7154 files_struct *fsp1,*fsp2;
7155 uint32 dosattrs;
7156 uint32 new_create_disposition;
7157 NTSTATUS status;
7160 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7161 if (smb_fname_dst_tmp == NULL) {
7162 return NT_STATUS_NO_MEMORY;
7166 * If the target is a directory, extract the last component from the
7167 * src filename and append it to the dst filename
7169 if (target_is_directory) {
7170 const char *p;
7172 /* dest/target can't be a stream if it's a directory. */
7173 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7175 p = strrchr_m(smb_fname_src->base_name,'/');
7176 if (p) {
7177 p++;
7178 } else {
7179 p = smb_fname_src->base_name;
7181 smb_fname_dst_tmp->base_name =
7182 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7184 if (!smb_fname_dst_tmp->base_name) {
7185 status = NT_STATUS_NO_MEMORY;
7186 goto out;
7190 status = vfs_file_exist(conn, smb_fname_src);
7191 if (!NT_STATUS_IS_OK(status)) {
7192 goto out;
7195 if (!target_is_directory && count) {
7196 new_create_disposition = FILE_OPEN;
7197 } else {
7198 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7199 0, ofun,
7200 NULL, NULL,
7201 &new_create_disposition,
7202 NULL,
7203 NULL)) {
7204 status = NT_STATUS_INVALID_PARAMETER;
7205 goto out;
7209 /* Open the src file for reading. */
7210 status = SMB_VFS_CREATE_FILE(
7211 conn, /* conn */
7212 NULL, /* req */
7213 0, /* root_dir_fid */
7214 smb_fname_src, /* fname */
7215 FILE_GENERIC_READ, /* access_mask */
7216 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7217 FILE_OPEN, /* create_disposition*/
7218 0, /* create_options */
7219 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7220 INTERNAL_OPEN_ONLY, /* oplock_request */
7221 NULL, /* lease */
7222 0, /* allocation_size */
7223 0, /* private_flags */
7224 NULL, /* sd */
7225 NULL, /* ea_list */
7226 &fsp1, /* result */
7227 NULL); /* psbuf */
7229 if (!NT_STATUS_IS_OK(status)) {
7230 goto out;
7233 dosattrs = dos_mode(conn, smb_fname_src);
7235 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7236 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7239 /* Open the dst file for writing. */
7240 status = SMB_VFS_CREATE_FILE(
7241 conn, /* conn */
7242 NULL, /* req */
7243 0, /* root_dir_fid */
7244 smb_fname_dst, /* fname */
7245 FILE_GENERIC_WRITE, /* access_mask */
7246 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7247 new_create_disposition, /* create_disposition*/
7248 0, /* create_options */
7249 dosattrs, /* file_attributes */
7250 INTERNAL_OPEN_ONLY, /* oplock_request */
7251 NULL, /* lease */
7252 0, /* allocation_size */
7253 0, /* private_flags */
7254 NULL, /* sd */
7255 NULL, /* ea_list */
7256 &fsp2, /* result */
7257 NULL); /* psbuf */
7259 if (!NT_STATUS_IS_OK(status)) {
7260 close_file(NULL, fsp1, ERROR_CLOSE);
7261 goto out;
7264 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7265 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7266 if (ret == -1) {
7267 DEBUG(0, ("error - vfs lseek returned error %s\n",
7268 strerror(errno)));
7269 status = map_nt_error_from_unix(errno);
7270 close_file(NULL, fsp1, ERROR_CLOSE);
7271 close_file(NULL, fsp2, ERROR_CLOSE);
7272 goto out;
7276 /* Do the actual copy. */
7277 if (smb_fname_src->st.st_ex_size) {
7278 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7279 } else {
7280 ret = 0;
7283 close_file(NULL, fsp1, NORMAL_CLOSE);
7285 /* Ensure the modtime is set correctly on the destination file. */
7286 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7289 * As we are opening fsp1 read-only we only expect
7290 * an error on close on fsp2 if we are out of space.
7291 * Thus we don't look at the error return from the
7292 * close of fsp1.
7294 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7296 if (!NT_STATUS_IS_OK(status)) {
7297 goto out;
7300 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7301 status = NT_STATUS_DISK_FULL;
7302 goto out;
7305 status = NT_STATUS_OK;
7307 out:
7308 TALLOC_FREE(smb_fname_dst_tmp);
7309 return status;
7312 /****************************************************************************
7313 Reply to a file copy.
7314 ****************************************************************************/
7316 void reply_copy(struct smb_request *req)
7318 connection_struct *conn = req->conn;
7319 struct smb_filename *smb_fname_src = NULL;
7320 struct smb_filename *smb_fname_dst = NULL;
7321 char *fname_src = NULL;
7322 char *fname_dst = NULL;
7323 char *fname_src_mask = NULL;
7324 char *fname_src_dir = NULL;
7325 const char *p;
7326 int count=0;
7327 int error = ERRnoaccess;
7328 int tid2;
7329 int ofun;
7330 int flags;
7331 bool target_is_directory=False;
7332 bool source_has_wild = False;
7333 bool dest_has_wild = False;
7334 NTSTATUS status;
7335 TALLOC_CTX *ctx = talloc_tos();
7337 START_PROFILE(SMBcopy);
7339 if (req->wct < 3) {
7340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7341 goto out;
7344 tid2 = SVAL(req->vwv+0, 0);
7345 ofun = SVAL(req->vwv+1, 0);
7346 flags = SVAL(req->vwv+2, 0);
7348 p = (const char *)req->buf;
7349 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7350 &status, &source_has_wild);
7351 if (!NT_STATUS_IS_OK(status)) {
7352 reply_nterror(req, status);
7353 goto out;
7355 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7356 &status, &dest_has_wild);
7357 if (!NT_STATUS_IS_OK(status)) {
7358 reply_nterror(req, status);
7359 goto out;
7362 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7364 if (tid2 != conn->cnum) {
7365 /* can't currently handle inter share copies XXXX */
7366 DEBUG(3,("Rejecting inter-share copy\n"));
7367 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7368 goto out;
7371 status = filename_convert(ctx, conn,
7372 req->flags2 & FLAGS2_DFS_PATHNAMES,
7373 fname_src,
7374 UCF_COND_ALLOW_WCARD_LCOMP,
7375 &source_has_wild,
7376 &smb_fname_src);
7377 if (!NT_STATUS_IS_OK(status)) {
7378 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7379 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7380 ERRSRV, ERRbadpath);
7381 goto out;
7383 reply_nterror(req, status);
7384 goto out;
7387 status = filename_convert(ctx, conn,
7388 req->flags2 & FLAGS2_DFS_PATHNAMES,
7389 fname_dst,
7390 UCF_COND_ALLOW_WCARD_LCOMP,
7391 &dest_has_wild,
7392 &smb_fname_dst);
7393 if (!NT_STATUS_IS_OK(status)) {
7394 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7395 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7396 ERRSRV, ERRbadpath);
7397 goto out;
7399 reply_nterror(req, status);
7400 goto out;
7403 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7405 if ((flags&1) && target_is_directory) {
7406 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7407 goto out;
7410 if ((flags&2) && !target_is_directory) {
7411 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7412 goto out;
7415 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7416 /* wants a tree copy! XXXX */
7417 DEBUG(3,("Rejecting tree copy\n"));
7418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7419 goto out;
7422 /* Split up the directory from the filename/mask. */
7423 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7424 &fname_src_dir, &fname_src_mask);
7425 if (!NT_STATUS_IS_OK(status)) {
7426 reply_nterror(req, NT_STATUS_NO_MEMORY);
7427 goto out;
7431 * We should only check the mangled cache
7432 * here if unix_convert failed. This means
7433 * that the path in 'mask' doesn't exist
7434 * on the file system and so we need to look
7435 * for a possible mangle. This patch from
7436 * Tine Smukavec <valentin.smukavec@hermes.si>.
7438 if (!VALID_STAT(smb_fname_src->st) &&
7439 mangle_is_mangled(fname_src_mask, conn->params)) {
7440 char *new_mask = NULL;
7441 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7442 &new_mask, conn->params);
7444 /* Use demangled name if one was successfully found. */
7445 if (new_mask) {
7446 TALLOC_FREE(fname_src_mask);
7447 fname_src_mask = new_mask;
7451 if (!source_has_wild) {
7454 * Only one file needs to be copied. Append the mask back onto
7455 * the directory.
7457 TALLOC_FREE(smb_fname_src->base_name);
7458 if (ISDOT(fname_src_dir)) {
7459 /* Ensure we use canonical names on open. */
7460 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7461 "%s",
7462 fname_src_mask);
7463 } else {
7464 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7465 "%s/%s",
7466 fname_src_dir,
7467 fname_src_mask);
7469 if (!smb_fname_src->base_name) {
7470 reply_nterror(req, NT_STATUS_NO_MEMORY);
7471 goto out;
7474 if (dest_has_wild) {
7475 char *fname_dst_mod = NULL;
7476 if (!resolve_wildcards(smb_fname_dst,
7477 smb_fname_src->base_name,
7478 smb_fname_dst->base_name,
7479 &fname_dst_mod)) {
7480 reply_nterror(req, NT_STATUS_NO_MEMORY);
7481 goto out;
7483 TALLOC_FREE(smb_fname_dst->base_name);
7484 smb_fname_dst->base_name = fname_dst_mod;
7487 status = check_name(conn, smb_fname_src->base_name);
7488 if (!NT_STATUS_IS_OK(status)) {
7489 reply_nterror(req, status);
7490 goto out;
7493 status = check_name(conn, smb_fname_dst->base_name);
7494 if (!NT_STATUS_IS_OK(status)) {
7495 reply_nterror(req, status);
7496 goto out;
7499 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7500 ofun, count, target_is_directory);
7502 if(!NT_STATUS_IS_OK(status)) {
7503 reply_nterror(req, status);
7504 goto out;
7505 } else {
7506 count++;
7508 } else {
7509 struct smb_Dir *dir_hnd = NULL;
7510 const char *dname = NULL;
7511 char *talloced = NULL;
7512 long offset = 0;
7515 * There is a wildcard that requires us to actually read the
7516 * src dir and copy each file matching the mask to the dst.
7517 * Right now streams won't be copied, but this could
7518 * presumably be added with a nested loop for reach dir entry.
7520 SMB_ASSERT(!smb_fname_src->stream_name);
7521 SMB_ASSERT(!smb_fname_dst->stream_name);
7523 smb_fname_src->stream_name = NULL;
7524 smb_fname_dst->stream_name = NULL;
7526 if (strequal(fname_src_mask,"????????.???")) {
7527 TALLOC_FREE(fname_src_mask);
7528 fname_src_mask = talloc_strdup(ctx, "*");
7529 if (!fname_src_mask) {
7530 reply_nterror(req, NT_STATUS_NO_MEMORY);
7531 goto out;
7535 status = check_name(conn, fname_src_dir);
7536 if (!NT_STATUS_IS_OK(status)) {
7537 reply_nterror(req, status);
7538 goto out;
7541 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7542 if (dir_hnd == NULL) {
7543 status = map_nt_error_from_unix(errno);
7544 reply_nterror(req, status);
7545 goto out;
7548 error = ERRbadfile;
7550 /* Iterate over the src dir copying each entry to the dst. */
7551 while ((dname = ReadDirName(dir_hnd, &offset,
7552 &smb_fname_src->st, &talloced))) {
7553 char *destname = NULL;
7555 if (ISDOT(dname) || ISDOTDOT(dname)) {
7556 TALLOC_FREE(talloced);
7557 continue;
7560 if (!is_visible_file(conn, fname_src_dir, dname,
7561 &smb_fname_src->st, false)) {
7562 TALLOC_FREE(talloced);
7563 continue;
7566 if(!mask_match(dname, fname_src_mask,
7567 conn->case_sensitive)) {
7568 TALLOC_FREE(talloced);
7569 continue;
7572 error = ERRnoaccess;
7574 /* Get the src smb_fname struct setup. */
7575 TALLOC_FREE(smb_fname_src->base_name);
7576 if (ISDOT(fname_src_dir)) {
7577 /* Ensure we use canonical names on open. */
7578 smb_fname_src->base_name =
7579 talloc_asprintf(smb_fname_src, "%s",
7580 dname);
7581 } else {
7582 smb_fname_src->base_name =
7583 talloc_asprintf(smb_fname_src, "%s/%s",
7584 fname_src_dir, dname);
7587 if (!smb_fname_src->base_name) {
7588 TALLOC_FREE(dir_hnd);
7589 TALLOC_FREE(talloced);
7590 reply_nterror(req, NT_STATUS_NO_MEMORY);
7591 goto out;
7594 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7595 smb_fname_dst->base_name,
7596 &destname)) {
7597 TALLOC_FREE(talloced);
7598 continue;
7600 if (!destname) {
7601 TALLOC_FREE(dir_hnd);
7602 TALLOC_FREE(talloced);
7603 reply_nterror(req, NT_STATUS_NO_MEMORY);
7604 goto out;
7607 TALLOC_FREE(smb_fname_dst->base_name);
7608 smb_fname_dst->base_name = destname;
7610 status = check_name(conn, smb_fname_src->base_name);
7611 if (!NT_STATUS_IS_OK(status)) {
7612 TALLOC_FREE(dir_hnd);
7613 TALLOC_FREE(talloced);
7614 reply_nterror(req, status);
7615 goto out;
7618 status = check_name(conn, smb_fname_dst->base_name);
7619 if (!NT_STATUS_IS_OK(status)) {
7620 TALLOC_FREE(dir_hnd);
7621 TALLOC_FREE(talloced);
7622 reply_nterror(req, status);
7623 goto out;
7626 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7627 smb_fname_src->base_name,
7628 smb_fname_dst->base_name));
7630 status = copy_file(ctx, conn, smb_fname_src,
7631 smb_fname_dst, ofun, count,
7632 target_is_directory);
7633 if (NT_STATUS_IS_OK(status)) {
7634 count++;
7637 TALLOC_FREE(talloced);
7639 TALLOC_FREE(dir_hnd);
7642 if (count == 0) {
7643 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7644 goto out;
7647 reply_outbuf(req, 1, 0);
7648 SSVAL(req->outbuf,smb_vwv0,count);
7649 out:
7650 TALLOC_FREE(smb_fname_src);
7651 TALLOC_FREE(smb_fname_dst);
7652 TALLOC_FREE(fname_src);
7653 TALLOC_FREE(fname_dst);
7654 TALLOC_FREE(fname_src_mask);
7655 TALLOC_FREE(fname_src_dir);
7657 END_PROFILE(SMBcopy);
7658 return;
7661 #undef DBGC_CLASS
7662 #define DBGC_CLASS DBGC_LOCKING
7664 /****************************************************************************
7665 Get a lock pid, dealing with large count requests.
7666 ****************************************************************************/
7668 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7669 bool large_file_format)
7671 if(!large_file_format)
7672 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7673 else
7674 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7677 /****************************************************************************
7678 Get a lock count, dealing with large count requests.
7679 ****************************************************************************/
7681 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7682 bool large_file_format)
7684 uint64_t count = 0;
7686 if(!large_file_format) {
7687 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7688 } else {
7690 * No BVAL, this is reversed!
7692 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7693 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7696 return count;
7699 /****************************************************************************
7700 Get a lock offset, dealing with large offset requests.
7701 ****************************************************************************/
7703 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7704 bool large_file_format)
7706 uint64_t offset = 0;
7708 if(!large_file_format) {
7709 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7710 } else {
7712 * No BVAL, this is reversed!
7714 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7715 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7718 return offset;
7721 NTSTATUS smbd_do_locking(struct smb_request *req,
7722 files_struct *fsp,
7723 uint8_t type,
7724 int32_t timeout,
7725 uint16_t num_locks,
7726 struct smbd_lock_element *locks,
7727 bool *async)
7729 connection_struct *conn = req->conn;
7730 int i;
7731 NTSTATUS status = NT_STATUS_OK;
7733 *async = false;
7735 /* Setup the timeout in seconds. */
7737 if (!lp_blocking_locks(SNUM(conn))) {
7738 timeout = 0;
7741 for(i = 0; i < (int)num_locks; i++) {
7742 struct smbd_lock_element *e = &locks[i];
7744 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7745 "%llu, file %s timeout = %d\n",
7746 (double)e->offset,
7747 (double)e->count,
7748 (unsigned long long)e->smblctx,
7749 fsp_str_dbg(fsp),
7750 (int)timeout));
7752 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7753 struct blocking_lock_record *blr = NULL;
7755 if (num_locks > 1) {
7757 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7758 * if the lock vector contains one entry. When given multiple cancel
7759 * requests in a single PDU we expect the server to return an
7760 * error. Windows servers seem to accept the request but only
7761 * cancel the first lock.
7762 * JRA - Do what Windows does (tm) :-).
7765 #if 0
7766 /* MS-CIFS (2.2.4.32.1) behavior. */
7767 return NT_STATUS_DOS(ERRDOS,
7768 ERRcancelviolation);
7769 #else
7770 /* Windows behavior. */
7771 if (i != 0) {
7772 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7773 "cancel request\n"));
7774 continue;
7776 #endif
7779 if (lp_blocking_locks(SNUM(conn))) {
7781 /* Schedule a message to ourselves to
7782 remove the blocking lock record and
7783 return the right error. */
7785 blr = blocking_lock_cancel_smb1(fsp,
7786 e->smblctx,
7787 e->offset,
7788 e->count,
7789 WINDOWS_LOCK,
7790 type,
7791 NT_STATUS_FILE_LOCK_CONFLICT);
7792 if (blr == NULL) {
7793 return NT_STATUS_DOS(
7794 ERRDOS,
7795 ERRcancelviolation);
7798 /* Remove a matching pending lock. */
7799 status = do_lock_cancel(fsp,
7800 e->smblctx,
7801 e->count,
7802 e->offset,
7803 WINDOWS_LOCK);
7804 } else {
7805 bool blocking_lock = timeout ? true : false;
7806 bool defer_lock = false;
7807 struct byte_range_lock *br_lck;
7808 uint64_t block_smblctx;
7810 br_lck = do_lock(req->sconn->msg_ctx,
7811 fsp,
7812 e->smblctx,
7813 e->count,
7814 e->offset,
7815 e->brltype,
7816 WINDOWS_LOCK,
7817 blocking_lock,
7818 &status,
7819 &block_smblctx);
7821 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7822 /* Windows internal resolution for blocking locks seems
7823 to be about 200ms... Don't wait for less than that. JRA. */
7824 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7825 timeout = lp_lock_spin_time();
7827 defer_lock = true;
7830 /* If a lock sent with timeout of zero would fail, and
7831 * this lock has been requested multiple times,
7832 * according to brl_lock_failed() we convert this
7833 * request to a blocking lock with a timeout of between
7834 * 150 - 300 milliseconds.
7836 * If lp_lock_spin_time() has been set to 0, we skip
7837 * this blocking retry and fail immediately.
7839 * Replacement for do_lock_spin(). JRA. */
7841 if (!req->sconn->using_smb2 &&
7842 br_lck && lp_blocking_locks(SNUM(conn)) &&
7843 lp_lock_spin_time() && !blocking_lock &&
7844 NT_STATUS_EQUAL((status),
7845 NT_STATUS_FILE_LOCK_CONFLICT))
7847 defer_lock = true;
7848 timeout = lp_lock_spin_time();
7851 if (br_lck && defer_lock) {
7853 * A blocking lock was requested. Package up
7854 * this smb into a queued request and push it
7855 * onto the blocking lock queue.
7857 if(push_blocking_lock_request(br_lck,
7858 req,
7859 fsp,
7860 timeout,
7862 e->smblctx,
7863 e->brltype,
7864 WINDOWS_LOCK,
7865 e->offset,
7866 e->count,
7867 block_smblctx)) {
7868 TALLOC_FREE(br_lck);
7869 *async = true;
7870 return NT_STATUS_OK;
7874 TALLOC_FREE(br_lck);
7877 if (!NT_STATUS_IS_OK(status)) {
7878 break;
7882 /* If any of the above locks failed, then we must unlock
7883 all of the previous locks (X/Open spec). */
7885 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7887 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7888 i = -1; /* we want to skip the for loop */
7892 * Ensure we don't do a remove on the lock that just failed,
7893 * as under POSIX rules, if we have a lock already there, we
7894 * will delete it (and we shouldn't) .....
7896 for(i--; i >= 0; i--) {
7897 struct smbd_lock_element *e = &locks[i];
7899 do_unlock(req->sconn->msg_ctx,
7900 fsp,
7901 e->smblctx,
7902 e->count,
7903 e->offset,
7904 WINDOWS_LOCK);
7906 return status;
7909 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7910 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7912 return NT_STATUS_OK;
7915 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7916 files_struct *fsp,
7917 uint16_t num_ulocks,
7918 struct smbd_lock_element *ulocks)
7920 int i;
7922 for(i = 0; i < (int)num_ulocks; i++) {
7923 struct smbd_lock_element *e = &ulocks[i];
7924 NTSTATUS status;
7926 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7927 "pid %u, file %s\n", __func__,
7928 (double)e->offset,
7929 (double)e->count,
7930 (unsigned int)e->smblctx,
7931 fsp_str_dbg(fsp)));
7933 if (e->brltype != UNLOCK_LOCK) {
7934 /* this can only happen with SMB2 */
7935 return NT_STATUS_INVALID_PARAMETER;
7938 status = do_unlock(req->sconn->msg_ctx,
7939 fsp,
7940 e->smblctx,
7941 e->count,
7942 e->offset,
7943 WINDOWS_LOCK);
7945 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7946 nt_errstr(status)));
7948 if (!NT_STATUS_IS_OK(status)) {
7949 return status;
7953 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7954 num_ulocks));
7956 return NT_STATUS_OK;
7959 /****************************************************************************
7960 Reply to a lockingX request.
7961 ****************************************************************************/
7963 void reply_lockingX(struct smb_request *req)
7965 connection_struct *conn = req->conn;
7966 files_struct *fsp;
7967 unsigned char locktype;
7968 unsigned char oplocklevel;
7969 uint16 num_ulocks;
7970 uint16 num_locks;
7971 int32 lock_timeout;
7972 int i;
7973 const uint8_t *data;
7974 bool large_file_format;
7975 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7976 struct smbd_lock_element *ulocks;
7977 struct smbd_lock_element *locks;
7978 bool async = false;
7980 START_PROFILE(SMBlockingX);
7982 if (req->wct < 8) {
7983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7984 END_PROFILE(SMBlockingX);
7985 return;
7988 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7989 locktype = CVAL(req->vwv+3, 0);
7990 oplocklevel = CVAL(req->vwv+3, 1);
7991 num_ulocks = SVAL(req->vwv+6, 0);
7992 num_locks = SVAL(req->vwv+7, 0);
7993 lock_timeout = IVAL(req->vwv+4, 0);
7994 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7996 if (!check_fsp(conn, req, fsp)) {
7997 END_PROFILE(SMBlockingX);
7998 return;
8001 data = req->buf;
8003 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8004 /* we don't support these - and CANCEL_LOCK makes w2k
8005 and XP reboot so I don't really want to be
8006 compatible! (tridge) */
8007 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8008 END_PROFILE(SMBlockingX);
8009 return;
8012 /* Check if this is an oplock break on a file
8013 we have granted an oplock on.
8015 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8016 /* Client can insist on breaking to none. */
8017 bool break_to_none = (oplocklevel == 0);
8018 bool result;
8020 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8021 "for %s\n", (unsigned int)oplocklevel,
8022 fsp_fnum_dbg(fsp)));
8025 * Make sure we have granted an exclusive or batch oplock on
8026 * this file.
8029 if (fsp->oplock_type == 0) {
8031 /* The Samba4 nbench simulator doesn't understand
8032 the difference between break to level2 and break
8033 to none from level2 - it sends oplock break
8034 replies in both cases. Don't keep logging an error
8035 message here - just ignore it. JRA. */
8037 DEBUG(5,("reply_lockingX: Error : oplock break from "
8038 "client for %s (oplock=%d) and no "
8039 "oplock granted on this file (%s).\n",
8040 fsp_fnum_dbg(fsp), fsp->oplock_type,
8041 fsp_str_dbg(fsp)));
8043 /* if this is a pure oplock break request then don't
8044 * send a reply */
8045 if (num_locks == 0 && num_ulocks == 0) {
8046 END_PROFILE(SMBlockingX);
8047 return;
8048 } else {
8049 END_PROFILE(SMBlockingX);
8050 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8051 return;
8055 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8056 (break_to_none)) {
8057 result = remove_oplock(fsp);
8058 } else {
8059 result = downgrade_oplock(fsp);
8062 if (!result) {
8063 DEBUG(0, ("reply_lockingX: error in removing "
8064 "oplock on file %s\n", fsp_str_dbg(fsp)));
8065 /* Hmmm. Is this panic justified? */
8066 smb_panic("internal tdb error");
8069 /* if this is a pure oplock break request then don't send a
8070 * reply */
8071 if (num_locks == 0 && num_ulocks == 0) {
8072 /* Sanity check - ensure a pure oplock break is not a
8073 chained request. */
8074 if (CVAL(req->vwv+0, 0) != 0xff) {
8075 DEBUG(0,("reply_lockingX: Error : pure oplock "
8076 "break is a chained %d request !\n",
8077 (unsigned int)CVAL(req->vwv+0, 0)));
8079 END_PROFILE(SMBlockingX);
8080 return;
8084 if (req->buflen <
8085 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8087 END_PROFILE(SMBlockingX);
8088 return;
8091 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8092 if (ulocks == NULL) {
8093 reply_nterror(req, NT_STATUS_NO_MEMORY);
8094 END_PROFILE(SMBlockingX);
8095 return;
8098 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8099 if (locks == NULL) {
8100 reply_nterror(req, NT_STATUS_NO_MEMORY);
8101 END_PROFILE(SMBlockingX);
8102 return;
8105 /* Data now points at the beginning of the list
8106 of smb_unlkrng structs */
8107 for(i = 0; i < (int)num_ulocks; i++) {
8108 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8109 ulocks[i].count = get_lock_count(data, i, large_file_format);
8110 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8111 ulocks[i].brltype = UNLOCK_LOCK;
8114 /* Now do any requested locks */
8115 data += ((large_file_format ? 20 : 10)*num_ulocks);
8117 /* Data now points at the beginning of the list
8118 of smb_lkrng structs */
8120 for(i = 0; i < (int)num_locks; i++) {
8121 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8122 locks[i].count = get_lock_count(data, i, large_file_format);
8123 locks[i].offset = get_lock_offset(data, i, large_file_format);
8125 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8126 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8127 locks[i].brltype = PENDING_READ_LOCK;
8128 } else {
8129 locks[i].brltype = READ_LOCK;
8131 } else {
8132 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8133 locks[i].brltype = PENDING_WRITE_LOCK;
8134 } else {
8135 locks[i].brltype = WRITE_LOCK;
8140 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8141 if (!NT_STATUS_IS_OK(status)) {
8142 END_PROFILE(SMBlockingX);
8143 reply_nterror(req, status);
8144 return;
8147 status = smbd_do_locking(req, fsp,
8148 locktype, lock_timeout,
8149 num_locks, locks,
8150 &async);
8151 if (!NT_STATUS_IS_OK(status)) {
8152 END_PROFILE(SMBlockingX);
8153 reply_nterror(req, status);
8154 return;
8156 if (async) {
8157 END_PROFILE(SMBlockingX);
8158 return;
8161 reply_outbuf(req, 2, 0);
8162 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8163 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8165 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8166 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8168 END_PROFILE(SMBlockingX);
8171 #undef DBGC_CLASS
8172 #define DBGC_CLASS DBGC_ALL
8174 /****************************************************************************
8175 Reply to a SMBreadbmpx (read block multiplex) request.
8176 Always reply with an error, if someone has a platform really needs this,
8177 please contact vl@samba.org
8178 ****************************************************************************/
8180 void reply_readbmpx(struct smb_request *req)
8182 START_PROFILE(SMBreadBmpx);
8183 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8184 END_PROFILE(SMBreadBmpx);
8185 return;
8188 /****************************************************************************
8189 Reply to a SMBreadbs (read block multiplex secondary) request.
8190 Always reply with an error, if someone has a platform really needs this,
8191 please contact vl@samba.org
8192 ****************************************************************************/
8194 void reply_readbs(struct smb_request *req)
8196 START_PROFILE(SMBreadBs);
8197 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8198 END_PROFILE(SMBreadBs);
8199 return;
8202 /****************************************************************************
8203 Reply to a SMBsetattrE.
8204 ****************************************************************************/
8206 void reply_setattrE(struct smb_request *req)
8208 connection_struct *conn = req->conn;
8209 struct smb_file_time ft;
8210 files_struct *fsp;
8211 NTSTATUS status;
8213 START_PROFILE(SMBsetattrE);
8214 ZERO_STRUCT(ft);
8216 if (req->wct < 7) {
8217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8218 goto out;
8221 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8223 if(!fsp || (fsp->conn != conn)) {
8224 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8225 goto out;
8229 * Convert the DOS times into unix times.
8232 ft.atime = convert_time_t_to_timespec(
8233 srv_make_unix_date2(req->vwv+3));
8234 ft.mtime = convert_time_t_to_timespec(
8235 srv_make_unix_date2(req->vwv+5));
8236 ft.create_time = convert_time_t_to_timespec(
8237 srv_make_unix_date2(req->vwv+1));
8239 reply_outbuf(req, 0, 0);
8242 * Patch from Ray Frush <frush@engr.colostate.edu>
8243 * Sometimes times are sent as zero - ignore them.
8246 /* Ensure we have a valid stat struct for the source. */
8247 status = vfs_stat_fsp(fsp);
8248 if (!NT_STATUS_IS_OK(status)) {
8249 reply_nterror(req, status);
8250 goto out;
8253 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8254 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8255 goto out;
8258 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8259 if (!NT_STATUS_IS_OK(status)) {
8260 reply_nterror(req, status);
8261 goto out;
8264 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8265 " createtime=%u\n",
8266 fsp_fnum_dbg(fsp),
8267 (unsigned int)ft.atime.tv_sec,
8268 (unsigned int)ft.mtime.tv_sec,
8269 (unsigned int)ft.create_time.tv_sec
8271 out:
8272 END_PROFILE(SMBsetattrE);
8273 return;
8277 /* Back from the dead for OS/2..... JRA. */
8279 /****************************************************************************
8280 Reply to a SMBwritebmpx (write block multiplex primary) request.
8281 Always reply with an error, if someone has a platform really needs this,
8282 please contact vl@samba.org
8283 ****************************************************************************/
8285 void reply_writebmpx(struct smb_request *req)
8287 START_PROFILE(SMBwriteBmpx);
8288 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8289 END_PROFILE(SMBwriteBmpx);
8290 return;
8293 /****************************************************************************
8294 Reply to a SMBwritebs (write block multiplex secondary) request.
8295 Always reply with an error, if someone has a platform really needs this,
8296 please contact vl@samba.org
8297 ****************************************************************************/
8299 void reply_writebs(struct smb_request *req)
8301 START_PROFILE(SMBwriteBs);
8302 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8303 END_PROFILE(SMBwriteBs);
8304 return;
8307 /****************************************************************************
8308 Reply to a SMBgetattrE.
8309 ****************************************************************************/
8311 void reply_getattrE(struct smb_request *req)
8313 connection_struct *conn = req->conn;
8314 int mode;
8315 files_struct *fsp;
8316 struct timespec create_ts;
8318 START_PROFILE(SMBgetattrE);
8320 if (req->wct < 1) {
8321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8322 END_PROFILE(SMBgetattrE);
8323 return;
8326 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8328 if(!fsp || (fsp->conn != conn)) {
8329 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8330 END_PROFILE(SMBgetattrE);
8331 return;
8334 /* Do an fstat on this file */
8335 if(fsp_stat(fsp)) {
8336 reply_nterror(req, map_nt_error_from_unix(errno));
8337 END_PROFILE(SMBgetattrE);
8338 return;
8341 mode = dos_mode(conn, fsp->fsp_name);
8344 * Convert the times into dos times. Set create
8345 * date to be last modify date as UNIX doesn't save
8346 * this.
8349 reply_outbuf(req, 11, 0);
8351 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8352 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8353 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8354 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8355 /* Should we check pending modtime here ? JRA */
8356 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8357 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8359 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8360 SIVAL(req->outbuf, smb_vwv6, 0);
8361 SIVAL(req->outbuf, smb_vwv8, 0);
8362 } else {
8363 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8364 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8365 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8367 SSVAL(req->outbuf,smb_vwv10, mode);
8369 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8371 END_PROFILE(SMBgetattrE);
8372 return;