s3:smbd: use reply_force_doserror(req, ERRSRV, ERRbaduid) on SMBulogoff
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blobd01ff905a374a6ac6b52e456bf1caef532a6857c
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"
45 /****************************************************************************
46 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
47 path or anything including wildcards.
48 We're assuming here that '/' is not the second byte in any multibyte char
49 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
50 set.
51 ****************************************************************************/
53 /* Custom version for processing POSIX paths. */
54 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56 static NTSTATUS check_path_syntax_internal(char *path,
57 bool posix_path,
58 bool *p_last_component_contains_wcard)
60 char *d = path;
61 const char *s = path;
62 NTSTATUS ret = NT_STATUS_OK;
63 bool start_of_name_component = True;
64 bool stream_started = false;
66 *p_last_component_contains_wcard = False;
68 while (*s) {
69 if (stream_started) {
70 switch (*s) {
71 case '/':
72 case '\\':
73 return NT_STATUS_OBJECT_NAME_INVALID;
74 case ':':
75 if (s[1] == '\0') {
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 if (strchr_m(&s[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 break;
85 if ((*s == ':') && !posix_path && !stream_started) {
86 if (*p_last_component_contains_wcard) {
87 return NT_STATUS_OBJECT_NAME_INVALID;
89 /* Stream names allow more characters than file names.
90 We're overloading posix_path here to allow a wider
91 range of characters. If stream_started is true this
92 is still a Windows path even if posix_path is true.
93 JRA.
95 stream_started = true;
96 start_of_name_component = false;
97 posix_path = true;
99 if (s[1] == '\0') {
100 return NT_STATUS_OBJECT_NAME_INVALID;
104 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
106 * Safe to assume is not the second part of a mb char
107 * as this is handled below.
109 /* Eat multiple '/' or '\\' */
110 while (IS_PATH_SEP(*s,posix_path)) {
111 s++;
113 if ((d != path) && (*s != '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
115 *d++ = '/';
118 start_of_name_component = True;
119 /* New component. */
120 *p_last_component_contains_wcard = False;
121 continue;
124 if (start_of_name_component) {
125 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
126 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
129 * No mb char starts with '.' so we're safe checking the directory separator here.
132 /* If we just added a '/' - delete it */
133 if ((d > path) && (*(d-1) == '/')) {
134 *(d-1) = '\0';
135 d--;
138 /* Are we at the start ? Can't go back further if so. */
139 if (d <= path) {
140 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
141 break;
143 /* Go back one level... */
144 /* We know this is safe as '/' cannot be part of a mb sequence. */
145 /* NOTE - if this assumption is invalid we are not in good shape... */
146 /* Decrement d first as d points to the *next* char to write into. */
147 for (d--; d > path; d--) {
148 if (*d == '/')
149 break;
151 s += 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
153 continue;
155 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
156 if (posix_path) {
157 /* Eat the '.' */
158 s++;
159 continue;
165 if (!(*s & 0x80)) {
166 if (!posix_path) {
167 if (*s <= 0x1f || *s == '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID;
170 switch (*s) {
171 case '*':
172 case '?':
173 case '<':
174 case '>':
175 case '"':
176 *p_last_component_contains_wcard = True;
177 break;
178 default:
179 break;
182 *d++ = *s++;
183 } else {
184 size_t siz;
185 /* Get the size of the next MB character. */
186 next_codepoint(s,&siz);
187 switch(siz) {
188 case 5:
189 *d++ = *s++;
190 /*fall through*/
191 case 4:
192 *d++ = *s++;
193 /*fall through*/
194 case 3:
195 *d++ = *s++;
196 /*fall through*/
197 case 2:
198 *d++ = *s++;
199 /*fall through*/
200 case 1:
201 *d++ = *s++;
202 break;
203 default:
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
205 *d = '\0';
206 return NT_STATUS_INVALID_PARAMETER;
209 start_of_name_component = False;
212 *d = '\0';
214 return ret;
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 No wildcards allowed.
220 ****************************************************************************/
222 NTSTATUS check_path_syntax(char *path)
224 bool ignore;
225 return check_path_syntax_internal(path, False, &ignore);
228 /****************************************************************************
229 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
230 Wildcards allowed - p_contains_wcard returns true if the last component contained
231 a wildcard.
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
236 return check_path_syntax_internal(path, False, p_contains_wcard);
239 /****************************************************************************
240 Check the path for a POSIX client.
241 We're assuming here that '/' is not the second byte in any multibyte char
242 set (a safe assumption).
243 ****************************************************************************/
245 NTSTATUS check_path_syntax_posix(char *path)
247 bool ignore;
248 return check_path_syntax_internal(path, True, &ignore);
251 /****************************************************************************
252 Pull a string and check the path allowing a wilcard - provide for error return.
253 ****************************************************************************/
255 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
256 const char *base_ptr,
257 uint16 smb_flags2,
258 char **pp_dest,
259 const char *src,
260 size_t src_len,
261 int flags,
262 NTSTATUS *err,
263 bool *contains_wcard)
265 size_t ret;
267 *pp_dest = NULL;
269 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
270 src_len, flags);
272 if (!*pp_dest) {
273 *err = NT_STATUS_INVALID_PARAMETER;
274 return ret;
277 *contains_wcard = False;
279 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
281 * For a DFS path the function parse_dfs_path()
282 * will do the path processing, just make a copy.
284 *err = NT_STATUS_OK;
285 return ret;
288 if (lp_posix_pathnames()) {
289 *err = check_path_syntax_posix(*pp_dest);
290 } else {
291 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
294 return ret;
297 /****************************************************************************
298 Pull a string and check the path - provide for error return.
299 ****************************************************************************/
301 size_t srvstr_get_path(TALLOC_CTX *ctx,
302 const char *base_ptr,
303 uint16 smb_flags2,
304 char **pp_dest,
305 const char *src,
306 size_t src_len,
307 int flags,
308 NTSTATUS *err)
310 bool ignore;
311 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
312 src_len, flags, err, &ignore);
315 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
317 NTSTATUS *err, bool *contains_wcard)
319 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
320 pp_dest, src, smbreq_bufrem(req, src),
321 flags, err, contains_wcard);
324 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
325 char **pp_dest, const char *src, int flags,
326 NTSTATUS *err)
328 bool ignore;
329 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
330 flags, err, &ignore);
333 /****************************************************************************
334 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
335 ****************************************************************************/
337 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
338 files_struct *fsp)
340 if ((fsp == NULL) || (conn == NULL)) {
341 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
342 return False;
344 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
345 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
346 return False;
348 return True;
351 /****************************************************************************
352 Check if we have a correct fsp pointing to a file.
353 ****************************************************************************/
355 bool check_fsp(connection_struct *conn, struct smb_request *req,
356 files_struct *fsp)
358 if (!check_fsp_open(conn, req, fsp)) {
359 return False;
361 if (fsp->is_directory) {
362 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
363 return False;
365 if (fsp->fh->fd == -1) {
366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
367 return False;
369 fsp->num_smb_operations++;
370 return True;
373 /****************************************************************************
374 Check if we have a correct fsp pointing to a quota fake file. Replacement for
375 the CHECK_NTQUOTA_HANDLE_OK macro.
376 ****************************************************************************/
378 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
379 files_struct *fsp)
381 if (!check_fsp_open(conn, req, fsp)) {
382 return false;
385 if (fsp->is_directory) {
386 return false;
389 if (fsp->fake_file_handle == NULL) {
390 return false;
393 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
394 return false;
397 if (fsp->fake_file_handle->private_data == NULL) {
398 return false;
401 return true;
404 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
405 const char *name, int name_type)
407 char *trim_name;
408 char *trim_name_type;
409 const char *retarget_parm;
410 char *retarget;
411 char *p;
412 int retarget_type = 0x20;
413 int retarget_port = NBT_SMB_PORT;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
416 bool ret = false;
417 uint8_t outbuf[10];
419 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
420 return false;
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
425 goto fail;
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
430 name_type);
431 if (trim_name_type == NULL) {
432 goto fail;
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
439 trim_name, NULL);
441 if (retarget_parm == NULL) {
442 goto fail;
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
447 goto fail;
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
453 if (p != NULL) {
454 *p++ = '\0';
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
459 if (p != NULL) {
460 *p++ = '\0';
461 if (sscanf(p, "%x", &retarget_type) != 1) {
462 goto fail;
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
467 if (!ret) {
468 DEBUG(10, ("could not resolve %s\n", retarget));
469 goto fail;
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
474 goto fail;
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
485 NULL)) {
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
487 "failed.");
490 ret = true;
491 fail:
492 TALLOC_FREE(trim_name);
493 return ret;
496 static void reply_called_name_not_present(char *outbuf)
498 smb_setlen(outbuf, 1);
499 SCVAL(outbuf, 0, 0x83);
500 SCVAL(outbuf, 4, 0x82);
503 /****************************************************************************
504 Reply to a (netbios-level) special message.
505 ****************************************************************************/
507 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
509 int msg_type = CVAL(inbuf,0);
510 int msg_flags = CVAL(inbuf,1);
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
514 * header.
516 char outbuf[smb_size];
518 memset(outbuf, '\0', sizeof(outbuf));
520 smb_setlen(outbuf,0);
522 switch (msg_type) {
523 case NBSSrequest: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
526 fstring name1,name2;
527 int name_type1, name_type2;
528 int name_len1, name_len2;
530 *name1 = *name2 = 0;
532 if (sconn->nbt.got_session) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf,0,NBSSpositive);
537 SCVAL(outbuf,3,0);
539 /* inbuf_size is guaranteed to be at least 4. */
540 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
541 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
542 DEBUG(0,("Invalid name length in session request\n"));
543 reply_called_name_not_present(outbuf);
544 break;
546 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
547 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
548 DEBUG(0,("Invalid name length in session request\n"));
549 reply_called_name_not_present(outbuf);
550 break;
553 name_type1 = name_extract((unsigned char *)inbuf,
554 inbuf_size,(unsigned int)4,name1);
555 name_type2 = name_extract((unsigned char *)inbuf,
556 inbuf_size,(unsigned int)(4 + name_len1),name2);
558 if (name_type1 == -1 || name_type2 == -1) {
559 DEBUG(0,("Invalid name type in session request\n"));
560 reply_called_name_not_present(outbuf);
561 break;
564 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
565 name1, name_type1, name2, name_type2));
567 if (netbios_session_retarget(sconn, name1, name_type1)) {
568 exit_server_cleanly("retargeted client");
572 * Windows NT/2k uses "*SMBSERVER" and XP uses
573 * "*SMBSERV" arrggg!!!
575 if (strequal(name1, "*SMBSERVER ")
576 || strequal(name1, "*SMBSERV ")) {
577 char *raddr;
579 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
580 talloc_tos());
581 if (raddr == NULL) {
582 exit_server_cleanly("could not allocate raddr");
585 fstrcpy(name1, raddr);
588 set_local_machine_name(name1, True);
589 set_remote_machine_name(name2, True);
591 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
592 get_local_machine_name(), get_remote_machine_name(),
593 name_type2));
595 if (name_type2 == 'R') {
596 /* We are being asked for a pathworks session ---
597 no thanks! */
598 reply_called_name_not_present(outbuf);
599 break;
602 reload_services(sconn, conn_snum_used, true);
603 reopen_logs();
605 sconn->nbt.got_session = true;
606 break;
609 case 0x89: /* session keepalive request
610 (some old clients produce this?) */
611 SCVAL(outbuf,0,NBSSkeepalive);
612 SCVAL(outbuf,3,0);
613 break;
615 case NBSSpositive: /* positive session response */
616 case NBSSnegative: /* negative session response */
617 case NBSSretarget: /* retarget session response */
618 DEBUG(0,("Unexpected session response\n"));
619 break;
621 case NBSSkeepalive: /* session keepalive */
622 default:
623 return;
626 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
627 msg_type, msg_flags));
629 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
631 if (CVAL(outbuf, 0) != 0x82) {
632 exit_server_cleanly("invalid netbios session");
634 return;
637 /****************************************************************************
638 Reply to a tcon.
639 conn POINTER CAN BE NULL HERE !
640 ****************************************************************************/
642 void reply_tcon(struct smb_request *req)
644 connection_struct *conn = req->conn;
645 const char *service;
646 char *service_buf = NULL;
647 char *password = NULL;
648 char *dev = NULL;
649 int pwlen=0;
650 NTSTATUS nt_status;
651 const char *p;
652 TALLOC_CTX *ctx = talloc_tos();
653 struct smbd_server_connection *sconn = req->sconn;
655 START_PROFILE(SMBtcon);
657 if (req->buflen < 4) {
658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
659 END_PROFILE(SMBtcon);
660 return;
663 p = (const char *)req->buf + 1;
664 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
665 p += 1;
666 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
667 p += pwlen+1;
668 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
669 p += 1;
671 if (service_buf == NULL || password == NULL || dev == NULL) {
672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
673 END_PROFILE(SMBtcon);
674 return;
676 p = strrchr_m(service_buf,'\\');
677 if (p) {
678 service = p+1;
679 } else {
680 service = service_buf;
683 conn = make_connection(sconn,service,dev,
684 req->vuid,&nt_status);
685 req->conn = conn;
687 if (!conn) {
688 reply_nterror(req, nt_status);
689 END_PROFILE(SMBtcon);
690 return;
693 reply_outbuf(req, 2, 0);
694 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
695 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
696 SSVAL(req->outbuf,smb_tid,conn->cnum);
698 DEBUG(3,("tcon service=%s cnum=%d\n",
699 service, conn->cnum));
701 END_PROFILE(SMBtcon);
702 return;
705 /****************************************************************************
706 Reply to a tcon and X.
707 conn POINTER CAN BE NULL HERE !
708 ****************************************************************************/
710 void reply_tcon_and_X(struct smb_request *req)
712 connection_struct *conn = req->conn;
713 const char *service = NULL;
714 TALLOC_CTX *ctx = talloc_tos();
715 /* what the cleint thinks the device is */
716 char *client_devicetype = NULL;
717 /* what the server tells the client the share represents */
718 const char *server_devicetype;
719 NTSTATUS nt_status;
720 int passlen;
721 char *path = NULL;
722 const char *p, *q;
723 uint16 tcon_flags;
724 struct smbd_server_connection *sconn = req->sconn;
726 START_PROFILE(SMBtconX);
728 if (req->wct < 4) {
729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
730 END_PROFILE(SMBtconX);
731 return;
734 passlen = SVAL(req->vwv+3, 0);
735 tcon_flags = SVAL(req->vwv+2, 0);
737 /* we might have to close an old one */
738 if ((tcon_flags & 0x1) && conn) {
739 close_cnum(conn,req->vuid);
740 req->conn = NULL;
741 conn = NULL;
744 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
745 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
746 END_PROFILE(SMBtconX);
747 return;
750 if (sconn->smb1.negprot.encrypted_passwords) {
751 p = (const char *)req->buf + passlen;
752 } else {
753 p = (const char *)req->buf + passlen + 1;
756 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
758 if (path == NULL) {
759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
760 END_PROFILE(SMBtconX);
761 return;
765 * the service name can be either: \\server\share
766 * or share directly like on the DELL PowerVault 705
768 if (*path=='\\') {
769 q = strchr_m(path+2,'\\');
770 if (!q) {
771 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
772 END_PROFILE(SMBtconX);
773 return;
775 service = q+1;
776 } else {
777 service = path;
780 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
781 &client_devicetype, p,
782 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
784 if (client_devicetype == NULL) {
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 END_PROFILE(SMBtconX);
787 return;
790 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
792 conn = make_connection(sconn, service, client_devicetype,
793 req->vuid, &nt_status);
794 req->conn =conn;
796 if (!conn) {
797 reply_nterror(req, nt_status);
798 END_PROFILE(SMBtconX);
799 return;
802 if ( IS_IPC(conn) )
803 server_devicetype = "IPC";
804 else if ( IS_PRINT(conn) )
805 server_devicetype = "LPT1:";
806 else
807 server_devicetype = "A:";
809 if (get_Protocol() < PROTOCOL_NT1) {
810 reply_outbuf(req, 2, 0);
811 if (message_push_string(&req->outbuf, server_devicetype,
812 STR_TERMINATE|STR_ASCII) == -1) {
813 reply_nterror(req, NT_STATUS_NO_MEMORY);
814 END_PROFILE(SMBtconX);
815 return;
817 } else {
818 /* NT sets the fstype of IPC$ to the null string */
819 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
821 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
822 /* Return permissions. */
823 uint32 perm1 = 0;
824 uint32 perm2 = 0;
826 reply_outbuf(req, 7, 0);
828 if (IS_IPC(conn)) {
829 perm1 = FILE_ALL_ACCESS;
830 perm2 = FILE_ALL_ACCESS;
831 } else {
832 perm1 = conn->share_access;
835 SIVAL(req->outbuf, smb_vwv3, perm1);
836 SIVAL(req->outbuf, smb_vwv5, perm2);
837 } else {
838 reply_outbuf(req, 3, 0);
841 if ((message_push_string(&req->outbuf, server_devicetype,
842 STR_TERMINATE|STR_ASCII) == -1)
843 || (message_push_string(&req->outbuf, fstype,
844 STR_TERMINATE) == -1)) {
845 reply_nterror(req, NT_STATUS_NO_MEMORY);
846 END_PROFILE(SMBtconX);
847 return;
850 /* what does setting this bit do? It is set by NT4 and
851 may affect the ability to autorun mounted cdroms */
852 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
853 (lp_csc_policy(SNUM(conn)) << 2));
855 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
856 DEBUG(2,("Serving %s as a Dfs root\n",
857 lp_servicename(SNUM(conn)) ));
858 SSVAL(req->outbuf, smb_vwv2,
859 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
863 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
864 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
866 DEBUG(3,("tconX service=%s \n",
867 service));
869 /* set the incoming and outgoing tid to the just created one */
870 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
871 SSVAL(req->outbuf,smb_tid,conn->cnum);
873 END_PROFILE(SMBtconX);
875 req->tid = conn->cnum;
878 /****************************************************************************
879 Reply to an unknown type.
880 ****************************************************************************/
882 void reply_unknown_new(struct smb_request *req, uint8 type)
884 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
885 smb_fn_name(type), type, type));
886 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
887 return;
890 /****************************************************************************
891 Reply to an ioctl.
892 conn POINTER CAN BE NULL HERE !
893 ****************************************************************************/
895 void reply_ioctl(struct smb_request *req)
897 connection_struct *conn = req->conn;
898 uint16 device;
899 uint16 function;
900 uint32 ioctl_code;
901 int replysize;
902 char *p;
904 START_PROFILE(SMBioctl);
906 if (req->wct < 3) {
907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
908 END_PROFILE(SMBioctl);
909 return;
912 device = SVAL(req->vwv+1, 0);
913 function = SVAL(req->vwv+2, 0);
914 ioctl_code = (device << 16) + function;
916 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
918 switch (ioctl_code) {
919 case IOCTL_QUERY_JOB_INFO:
920 replysize = 32;
921 break;
922 default:
923 reply_force_doserror(req, ERRSRV, ERRnosupport);
924 END_PROFILE(SMBioctl);
925 return;
928 reply_outbuf(req, 8, replysize+1);
929 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
930 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
931 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
932 p = smb_buf(req->outbuf);
933 memset(p, '\0', replysize+1); /* valgrind-safe. */
934 p += 1; /* Allow for alignment */
936 switch (ioctl_code) {
937 case IOCTL_QUERY_JOB_INFO:
939 files_struct *fsp = file_fsp(
940 req, SVAL(req->vwv+0, 0));
941 if (!fsp) {
942 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
943 END_PROFILE(SMBioctl);
944 return;
946 /* Job number */
947 if (fsp->print_file) {
948 SSVAL(p, 0, fsp->print_file->rap_jobid);
949 } else {
950 SSVAL(p, 0, 0);
952 srvstr_push((char *)req->outbuf, req->flags2, p+2,
953 lp_netbios_name(), 15,
954 STR_TERMINATE|STR_ASCII);
955 if (conn) {
956 srvstr_push((char *)req->outbuf, req->flags2,
957 p+18, lp_servicename(SNUM(conn)),
958 13, STR_TERMINATE|STR_ASCII);
959 } else {
960 memset(p+18, 0, 13);
962 break;
966 END_PROFILE(SMBioctl);
967 return;
970 /****************************************************************************
971 Strange checkpath NTSTATUS mapping.
972 ****************************************************************************/
974 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
976 /* Strange DOS error code semantics only for checkpath... */
977 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
978 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
979 /* We need to map to ERRbadpath */
980 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
983 return status;
986 /****************************************************************************
987 Reply to a checkpath.
988 ****************************************************************************/
990 void reply_checkpath(struct smb_request *req)
992 connection_struct *conn = req->conn;
993 struct smb_filename *smb_fname = NULL;
994 char *name = NULL;
995 NTSTATUS status;
996 TALLOC_CTX *ctx = talloc_tos();
998 START_PROFILE(SMBcheckpath);
1000 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1001 STR_TERMINATE, &status);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 status = map_checkpath_error(req->flags2, status);
1005 reply_nterror(req, status);
1006 END_PROFILE(SMBcheckpath);
1007 return;
1010 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1012 status = filename_convert(ctx,
1013 conn,
1014 req->flags2 & FLAGS2_DFS_PATHNAMES,
1015 name,
1017 NULL,
1018 &smb_fname);
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1022 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1023 ERRSRV, ERRbadpath);
1024 END_PROFILE(SMBcheckpath);
1025 return;
1027 goto path_err;
1030 if (!VALID_STAT(smb_fname->st) &&
1031 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1032 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1033 smb_fname_str_dbg(smb_fname), strerror(errno)));
1034 status = map_nt_error_from_unix(errno);
1035 goto path_err;
1038 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1039 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1040 ERRDOS, ERRbadpath);
1041 goto out;
1044 reply_outbuf(req, 0, 0);
1046 path_err:
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1063 goto out;
1066 reply_nterror(req, status);
1068 out:
1069 TALLOC_FREE(smb_fname);
1070 END_PROFILE(SMBcheckpath);
1071 return;
1074 /****************************************************************************
1075 Reply to a getatr.
1076 ****************************************************************************/
1078 void reply_getatr(struct smb_request *req)
1080 connection_struct *conn = req->conn;
1081 struct smb_filename *smb_fname = NULL;
1082 char *fname = NULL;
1083 int mode=0;
1084 off_t size=0;
1085 time_t mtime=0;
1086 const char *p;
1087 NTSTATUS status;
1088 TALLOC_CTX *ctx = talloc_tos();
1089 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1091 START_PROFILE(SMBgetatr);
1093 p = (const char *)req->buf + 1;
1094 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 reply_nterror(req, status);
1097 goto out;
1100 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1101 under WfWg - weird! */
1102 if (*fname == '\0') {
1103 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1104 if (!CAN_WRITE(conn)) {
1105 mode |= FILE_ATTRIBUTE_READONLY;
1107 size = 0;
1108 mtime = 0;
1109 } else {
1110 status = filename_convert(ctx,
1111 conn,
1112 req->flags2 & FLAGS2_DFS_PATHNAMES,
1113 fname,
1115 NULL,
1116 &smb_fname);
1117 if (!NT_STATUS_IS_OK(status)) {
1118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1119 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1120 ERRSRV, ERRbadpath);
1121 goto out;
1123 reply_nterror(req, status);
1124 goto out;
1126 if (!VALID_STAT(smb_fname->st) &&
1127 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1128 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1129 smb_fname_str_dbg(smb_fname),
1130 strerror(errno)));
1131 reply_nterror(req, map_nt_error_from_unix(errno));
1132 goto out;
1135 mode = dos_mode(conn, smb_fname);
1136 size = smb_fname->st.st_ex_size;
1138 if (ask_sharemode) {
1139 struct timespec write_time_ts;
1140 struct file_id fileid;
1142 ZERO_STRUCT(write_time_ts);
1143 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1144 get_file_infos(fileid, 0, NULL, &write_time_ts);
1145 if (!null_timespec(write_time_ts)) {
1146 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1150 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1151 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1152 size = 0;
1156 reply_outbuf(req, 10, 0);
1158 SSVAL(req->outbuf,smb_vwv0,mode);
1159 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1160 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1161 } else {
1162 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1164 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1166 if (get_Protocol() >= PROTOCOL_NT1) {
1167 SSVAL(req->outbuf, smb_flg2,
1168 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1171 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1172 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1174 out:
1175 TALLOC_FREE(smb_fname);
1176 TALLOC_FREE(fname);
1177 END_PROFILE(SMBgetatr);
1178 return;
1181 /****************************************************************************
1182 Reply to a setatr.
1183 ****************************************************************************/
1185 void reply_setatr(struct smb_request *req)
1187 struct smb_file_time ft;
1188 connection_struct *conn = req->conn;
1189 struct smb_filename *smb_fname = NULL;
1190 char *fname = NULL;
1191 int mode;
1192 time_t mtime;
1193 const char *p;
1194 NTSTATUS status;
1195 TALLOC_CTX *ctx = talloc_tos();
1197 START_PROFILE(SMBsetatr);
1199 ZERO_STRUCT(ft);
1201 if (req->wct < 2) {
1202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1203 goto out;
1206 p = (const char *)req->buf + 1;
1207 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1210 goto out;
1213 status = filename_convert(ctx,
1214 conn,
1215 req->flags2 & FLAGS2_DFS_PATHNAMES,
1216 fname,
1218 NULL,
1219 &smb_fname);
1220 if (!NT_STATUS_IS_OK(status)) {
1221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1222 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1223 ERRSRV, ERRbadpath);
1224 goto out;
1226 reply_nterror(req, status);
1227 goto out;
1230 if (smb_fname->base_name[0] == '.' &&
1231 smb_fname->base_name[1] == '\0') {
1233 * Not sure here is the right place to catch this
1234 * condition. Might be moved to somewhere else later -- vl
1236 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1237 goto out;
1240 mode = SVAL(req->vwv+0, 0);
1241 mtime = srv_make_unix_date3(req->vwv+1);
1243 if (mode != FILE_ATTRIBUTE_NORMAL) {
1244 if (VALID_STAT_OF_DIR(smb_fname->st))
1245 mode |= FILE_ATTRIBUTE_DIRECTORY;
1246 else
1247 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1249 status = check_access(conn, NULL, smb_fname,
1250 FILE_WRITE_ATTRIBUTES);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_nterror(req, status);
1253 goto out;
1256 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1257 false) != 0) {
1258 reply_nterror(req, map_nt_error_from_unix(errno));
1259 goto out;
1263 ft.mtime = convert_time_t_to_timespec(mtime);
1264 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 reply_nterror(req, status);
1267 goto out;
1270 reply_outbuf(req, 0, 0);
1272 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1273 mode));
1274 out:
1275 TALLOC_FREE(smb_fname);
1276 END_PROFILE(SMBsetatr);
1277 return;
1280 /****************************************************************************
1281 Reply to a dskattr.
1282 ****************************************************************************/
1284 void reply_dskattr(struct smb_request *req)
1286 connection_struct *conn = req->conn;
1287 uint64_t dfree,dsize,bsize;
1288 START_PROFILE(SMBdskattr);
1290 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1291 reply_nterror(req, map_nt_error_from_unix(errno));
1292 END_PROFILE(SMBdskattr);
1293 return;
1296 reply_outbuf(req, 5, 0);
1298 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1299 double total_space, free_space;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space = dsize * (double)bsize;
1307 free_space = dfree * (double)bsize;
1309 dsize = (uint64_t)((total_space+63*512) / (64*512));
1310 dfree = (uint64_t)((free_space+63*512) / (64*512));
1312 if (dsize > 0xFFFF) dsize = 0xFFFF;
1313 if (dfree > 0xFFFF) dfree = 0xFFFF;
1315 SSVAL(req->outbuf,smb_vwv0,dsize);
1316 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1317 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1318 SSVAL(req->outbuf,smb_vwv3,dfree);
1319 } else {
1320 SSVAL(req->outbuf,smb_vwv0,dsize);
1321 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1322 SSVAL(req->outbuf,smb_vwv2,512);
1323 SSVAL(req->outbuf,smb_vwv3,dfree);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1328 END_PROFILE(SMBdskattr);
1329 return;
1333 * Utility function to split the filename from the directory.
1335 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1336 char **fname_dir_out,
1337 char **fname_mask_out)
1339 const char *p = NULL;
1340 char *fname_dir = NULL;
1341 char *fname_mask = NULL;
1343 p = strrchr_m(fname_in, '/');
1344 if (!p) {
1345 fname_dir = talloc_strdup(ctx, ".");
1346 fname_mask = talloc_strdup(ctx, fname_in);
1347 } else {
1348 fname_dir = talloc_strndup(ctx, fname_in,
1349 PTR_DIFF(p, fname_in));
1350 fname_mask = talloc_strdup(ctx, p+1);
1353 if (!fname_dir || !fname_mask) {
1354 TALLOC_FREE(fname_dir);
1355 TALLOC_FREE(fname_mask);
1356 return NT_STATUS_NO_MEMORY;
1359 *fname_dir_out = fname_dir;
1360 *fname_mask_out = fname_mask;
1361 return NT_STATUS_OK;
1364 /****************************************************************************
1365 Reply to a search.
1366 Can be called from SMBsearch, SMBffirst or SMBfunique.
1367 ****************************************************************************/
1369 void reply_search(struct smb_request *req)
1371 connection_struct *conn = req->conn;
1372 char *path = NULL;
1373 const char *mask = NULL;
1374 char *directory = NULL;
1375 struct smb_filename *smb_fname = NULL;
1376 char *fname = NULL;
1377 off_t size;
1378 uint32 mode;
1379 struct timespec date;
1380 uint32 dirtype;
1381 unsigned int numentries = 0;
1382 unsigned int maxentries = 0;
1383 bool finished = False;
1384 const char *p;
1385 int status_len;
1386 char status[21];
1387 int dptr_num= -1;
1388 bool check_descend = False;
1389 bool expect_close = False;
1390 NTSTATUS nt_status;
1391 bool mask_contains_wcard = False;
1392 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1393 TALLOC_CTX *ctx = talloc_tos();
1394 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1395 struct dptr_struct *dirptr = NULL;
1396 struct smbd_server_connection *sconn = req->sconn;
1398 START_PROFILE(SMBsearch);
1400 if (req->wct < 2) {
1401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1402 goto out;
1405 if (lp_posix_pathnames()) {
1406 reply_unknown_new(req, req->cmd);
1407 goto out;
1410 /* If we were called as SMBffirst then we must expect close. */
1411 if(req->cmd == SMBffirst) {
1412 expect_close = True;
1415 reply_outbuf(req, 1, 3);
1416 maxentries = SVAL(req->vwv+0, 0);
1417 dirtype = SVAL(req->vwv+1, 0);
1418 p = (const char *)req->buf + 1;
1419 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1420 &nt_status, &mask_contains_wcard);
1421 if (!NT_STATUS_IS_OK(nt_status)) {
1422 reply_nterror(req, nt_status);
1423 goto out;
1426 p++;
1427 status_len = SVAL(p, 0);
1428 p += 2;
1430 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1432 if (status_len == 0) {
1433 nt_status = filename_convert(ctx, conn,
1434 req->flags2 & FLAGS2_DFS_PATHNAMES,
1435 path,
1436 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1437 &mask_contains_wcard,
1438 &smb_fname);
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1440 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1441 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1442 ERRSRV, ERRbadpath);
1443 goto out;
1445 reply_nterror(req, nt_status);
1446 goto out;
1449 directory = smb_fname->base_name;
1451 p = strrchr_m(directory,'/');
1452 if ((p != NULL) && (*directory != '/')) {
1453 mask = p + 1;
1454 directory = talloc_strndup(ctx, directory,
1455 PTR_DIFF(p, directory));
1456 } else {
1457 mask = directory;
1458 directory = talloc_strdup(ctx,".");
1461 if (!directory) {
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1463 goto out;
1466 memset((char *)status,'\0',21);
1467 SCVAL(status,0,(dirtype & 0x1F));
1469 nt_status = dptr_create(conn,
1470 NULL, /* req */
1471 NULL, /* fsp */
1472 directory,
1473 True,
1474 expect_close,
1475 req->smbpid,
1476 mask,
1477 mask_contains_wcard,
1478 dirtype,
1479 &dirptr);
1480 if (!NT_STATUS_IS_OK(nt_status)) {
1481 reply_nterror(req, nt_status);
1482 goto out;
1484 dptr_num = dptr_dnum(dirptr);
1485 } else {
1486 int status_dirtype;
1487 const char *dirpath;
1489 memcpy(status,p,21);
1490 status_dirtype = CVAL(status,0) & 0x1F;
1491 if (status_dirtype != (dirtype & 0x1F)) {
1492 dirtype = status_dirtype;
1495 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1496 if (!dirptr) {
1497 goto SearchEmpty;
1499 dirpath = dptr_path(sconn, dptr_num);
1500 directory = talloc_strdup(ctx, dirpath);
1501 if (!directory) {
1502 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 goto out;
1506 mask = dptr_wcard(sconn, dptr_num);
1507 if (!mask) {
1508 goto SearchEmpty;
1511 * For a 'continue' search we have no string. So
1512 * check from the initial saved string.
1514 mask_contains_wcard = ms_has_wild(mask);
1515 dirtype = dptr_attr(sconn, dptr_num);
1518 DEBUG(4,("dptr_num is %d\n",dptr_num));
1520 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1521 dptr_init_search_op(dirptr);
1523 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1524 char buf[DIR_STRUCT_SIZE];
1525 memcpy(buf,status,21);
1526 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1527 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1528 reply_nterror(req, NT_STATUS_NO_MEMORY);
1529 goto out;
1531 dptr_fill(sconn, buf+12,dptr_num);
1532 if (dptr_zero(buf+12) && (status_len==0)) {
1533 numentries = 1;
1534 } else {
1535 numentries = 0;
1537 if (message_push_blob(&req->outbuf,
1538 data_blob_const(buf, sizeof(buf)))
1539 == -1) {
1540 reply_nterror(req, NT_STATUS_NO_MEMORY);
1541 goto out;
1543 } else {
1544 unsigned int i;
1545 maxentries = MIN(
1546 maxentries,
1547 ((BUFFER_SIZE -
1548 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1549 /DIR_STRUCT_SIZE));
1551 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1552 directory,lp_dontdescend(SNUM(conn))));
1553 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1554 check_descend = True;
1557 for (i=numentries;(i<maxentries) && !finished;i++) {
1558 finished = !get_dir_entry(ctx,
1559 dirptr,
1560 mask,
1561 dirtype,
1562 &fname,
1563 &size,
1564 &mode,
1565 &date,
1566 check_descend,
1567 ask_sharemode);
1568 if (!finished) {
1569 char buf[DIR_STRUCT_SIZE];
1570 memcpy(buf,status,21);
1571 if (!make_dir_struct(ctx,
1572 buf,
1573 mask,
1574 fname,
1575 size,
1576 mode,
1577 convert_timespec_to_time_t(date),
1578 !allow_long_path_components)) {
1579 reply_nterror(req, NT_STATUS_NO_MEMORY);
1580 goto out;
1582 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1583 break;
1585 if (message_push_blob(&req->outbuf,
1586 data_blob_const(buf, sizeof(buf)))
1587 == -1) {
1588 reply_nterror(req, NT_STATUS_NO_MEMORY);
1589 goto out;
1591 numentries++;
1596 SearchEmpty:
1598 /* If we were called as SMBffirst with smb_search_id == NULL
1599 and no entries were found then return error and close dirptr
1600 (X/Open spec) */
1602 if (numentries == 0) {
1603 dptr_close(sconn, &dptr_num);
1604 } else if(expect_close && status_len == 0) {
1605 /* Close the dptr - we know it's gone */
1606 dptr_close(sconn, &dptr_num);
1609 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1610 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1611 dptr_close(sconn, &dptr_num);
1614 if ((numentries == 0) && !mask_contains_wcard) {
1615 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1616 goto out;
1619 SSVAL(req->outbuf,smb_vwv0,numentries);
1620 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1621 SCVAL(smb_buf(req->outbuf),0,5);
1622 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1624 /* The replies here are never long name. */
1625 SSVAL(req->outbuf, smb_flg2,
1626 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1627 if (!allow_long_path_components) {
1628 SSVAL(req->outbuf, smb_flg2,
1629 SVAL(req->outbuf, smb_flg2)
1630 & (~FLAGS2_LONG_PATH_COMPONENTS));
1633 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1634 SSVAL(req->outbuf, smb_flg2,
1635 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1637 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1638 smb_fn_name(req->cmd),
1639 mask,
1640 directory,
1641 dirtype,
1642 numentries,
1643 maxentries ));
1644 out:
1645 TALLOC_FREE(directory);
1646 TALLOC_FREE(smb_fname);
1647 END_PROFILE(SMBsearch);
1648 return;
1651 /****************************************************************************
1652 Reply to a fclose (stop directory search).
1653 ****************************************************************************/
1655 void reply_fclose(struct smb_request *req)
1657 int status_len;
1658 char status[21];
1659 int dptr_num= -2;
1660 const char *p;
1661 char *path = NULL;
1662 NTSTATUS err;
1663 bool path_contains_wcard = False;
1664 TALLOC_CTX *ctx = talloc_tos();
1665 struct smbd_server_connection *sconn = req->sconn;
1667 START_PROFILE(SMBfclose);
1669 if (lp_posix_pathnames()) {
1670 reply_unknown_new(req, req->cmd);
1671 END_PROFILE(SMBfclose);
1672 return;
1675 p = (const char *)req->buf + 1;
1676 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1677 &err, &path_contains_wcard);
1678 if (!NT_STATUS_IS_OK(err)) {
1679 reply_nterror(req, err);
1680 END_PROFILE(SMBfclose);
1681 return;
1683 p++;
1684 status_len = SVAL(p,0);
1685 p += 2;
1687 if (status_len == 0) {
1688 reply_force_doserror(req, ERRSRV, ERRsrverror);
1689 END_PROFILE(SMBfclose);
1690 return;
1693 memcpy(status,p,21);
1695 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1696 /* Close the dptr - we know it's gone */
1697 dptr_close(sconn, &dptr_num);
1700 reply_outbuf(req, 1, 0);
1701 SSVAL(req->outbuf,smb_vwv0,0);
1703 DEBUG(3,("search close\n"));
1705 END_PROFILE(SMBfclose);
1706 return;
1709 /****************************************************************************
1710 Reply to an open.
1711 ****************************************************************************/
1713 void reply_open(struct smb_request *req)
1715 connection_struct *conn = req->conn;
1716 struct smb_filename *smb_fname = NULL;
1717 char *fname = NULL;
1718 uint32 fattr=0;
1719 off_t size = 0;
1720 time_t mtime=0;
1721 int info;
1722 files_struct *fsp;
1723 int oplock_request;
1724 int deny_mode;
1725 uint32 dos_attr;
1726 uint32 access_mask;
1727 uint32 share_mode;
1728 uint32 create_disposition;
1729 uint32 create_options = 0;
1730 uint32_t private_flags = 0;
1731 NTSTATUS status;
1732 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1733 TALLOC_CTX *ctx = talloc_tos();
1735 START_PROFILE(SMBopen);
1737 if (req->wct < 2) {
1738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1739 goto out;
1742 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1743 deny_mode = SVAL(req->vwv+0, 0);
1744 dos_attr = SVAL(req->vwv+1, 0);
1746 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1747 STR_TERMINATE, &status);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 reply_nterror(req, status);
1750 goto out;
1753 status = filename_convert(ctx,
1754 conn,
1755 req->flags2 & FLAGS2_DFS_PATHNAMES,
1756 fname,
1758 NULL,
1759 &smb_fname);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1762 reply_botherror(req,
1763 NT_STATUS_PATH_NOT_COVERED,
1764 ERRSRV, ERRbadpath);
1765 goto out;
1767 reply_nterror(req, status);
1768 goto out;
1771 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1772 OPENX_FILE_EXISTS_OPEN, &access_mask,
1773 &share_mode, &create_disposition,
1774 &create_options, &private_flags)) {
1775 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1776 goto out;
1779 status = SMB_VFS_CREATE_FILE(
1780 conn, /* conn */
1781 req, /* req */
1782 0, /* root_dir_fid */
1783 smb_fname, /* fname */
1784 access_mask, /* access_mask */
1785 share_mode, /* share_access */
1786 create_disposition, /* create_disposition*/
1787 create_options, /* create_options */
1788 dos_attr, /* file_attributes */
1789 oplock_request, /* oplock_request */
1790 0, /* allocation_size */
1791 private_flags,
1792 NULL, /* sd */
1793 NULL, /* ea_list */
1794 &fsp, /* result */
1795 &info); /* pinfo */
1797 if (!NT_STATUS_IS_OK(status)) {
1798 if (open_was_deferred(req->sconn, req->mid)) {
1799 /* We have re-scheduled this call. */
1800 goto out;
1802 reply_openerror(req, status);
1803 goto out;
1806 size = smb_fname->st.st_ex_size;
1807 fattr = dos_mode(conn, smb_fname);
1809 /* Deal with other possible opens having a modified
1810 write time. JRA. */
1811 if (ask_sharemode) {
1812 struct timespec write_time_ts;
1814 ZERO_STRUCT(write_time_ts);
1815 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1816 if (!null_timespec(write_time_ts)) {
1817 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1821 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1823 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1824 DEBUG(3,("attempt to open a directory %s\n",
1825 fsp_str_dbg(fsp)));
1826 close_file(req, fsp, ERROR_CLOSE);
1827 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1828 ERRDOS, ERRnoaccess);
1829 goto out;
1832 reply_outbuf(req, 7, 0);
1833 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1834 SSVAL(req->outbuf,smb_vwv1,fattr);
1835 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1837 } else {
1838 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1840 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1841 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1843 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844 SCVAL(req->outbuf,smb_flg,
1845 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1848 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1849 SCVAL(req->outbuf,smb_flg,
1850 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1852 out:
1853 TALLOC_FREE(smb_fname);
1854 END_PROFILE(SMBopen);
1855 return;
1858 /****************************************************************************
1859 Reply to an open and X.
1860 ****************************************************************************/
1862 void reply_open_and_X(struct smb_request *req)
1864 connection_struct *conn = req->conn;
1865 struct smb_filename *smb_fname = NULL;
1866 char *fname = NULL;
1867 uint16 open_flags;
1868 int deny_mode;
1869 uint32 smb_attr;
1870 /* Breakout the oplock request bits so we can set the
1871 reply bits separately. */
1872 int ex_oplock_request;
1873 int core_oplock_request;
1874 int oplock_request;
1875 #if 0
1876 int smb_sattr = SVAL(req->vwv+4, 0);
1877 uint32 smb_time = make_unix_date3(req->vwv+6);
1878 #endif
1879 int smb_ofun;
1880 uint32 fattr=0;
1881 int mtime=0;
1882 int smb_action = 0;
1883 files_struct *fsp;
1884 NTSTATUS status;
1885 uint64_t allocation_size;
1886 ssize_t retval = -1;
1887 uint32 access_mask;
1888 uint32 share_mode;
1889 uint32 create_disposition;
1890 uint32 create_options = 0;
1891 uint32_t private_flags = 0;
1892 TALLOC_CTX *ctx = talloc_tos();
1894 START_PROFILE(SMBopenX);
1896 if (req->wct < 15) {
1897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1898 goto out;
1901 open_flags = SVAL(req->vwv+2, 0);
1902 deny_mode = SVAL(req->vwv+3, 0);
1903 smb_attr = SVAL(req->vwv+5, 0);
1904 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1905 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1906 oplock_request = ex_oplock_request | core_oplock_request;
1907 smb_ofun = SVAL(req->vwv+8, 0);
1908 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1910 /* If it's an IPC, pass off the pipe handler. */
1911 if (IS_IPC(conn)) {
1912 if (lp_nt_pipe_support()) {
1913 reply_open_pipe_and_X(conn, req);
1914 } else {
1915 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1917 goto out;
1920 /* XXXX we need to handle passed times, sattr and flags */
1921 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1922 STR_TERMINATE, &status);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 reply_nterror(req, status);
1925 goto out;
1928 status = filename_convert(ctx,
1929 conn,
1930 req->flags2 & FLAGS2_DFS_PATHNAMES,
1931 fname,
1933 NULL,
1934 &smb_fname);
1935 if (!NT_STATUS_IS_OK(status)) {
1936 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1937 reply_botherror(req,
1938 NT_STATUS_PATH_NOT_COVERED,
1939 ERRSRV, ERRbadpath);
1940 goto out;
1942 reply_nterror(req, status);
1943 goto out;
1946 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1947 smb_ofun,
1948 &access_mask, &share_mode,
1949 &create_disposition,
1950 &create_options,
1951 &private_flags)) {
1952 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1953 goto out;
1956 status = SMB_VFS_CREATE_FILE(
1957 conn, /* conn */
1958 req, /* req */
1959 0, /* root_dir_fid */
1960 smb_fname, /* fname */
1961 access_mask, /* access_mask */
1962 share_mode, /* share_access */
1963 create_disposition, /* create_disposition*/
1964 create_options, /* create_options */
1965 smb_attr, /* file_attributes */
1966 oplock_request, /* oplock_request */
1967 0, /* allocation_size */
1968 private_flags,
1969 NULL, /* sd */
1970 NULL, /* ea_list */
1971 &fsp, /* result */
1972 &smb_action); /* pinfo */
1974 if (!NT_STATUS_IS_OK(status)) {
1975 if (open_was_deferred(req->sconn, req->mid)) {
1976 /* We have re-scheduled this call. */
1977 goto out;
1979 reply_openerror(req, status);
1980 goto out;
1983 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1984 if the file is truncated or created. */
1985 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1986 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1987 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1988 close_file(req, fsp, ERROR_CLOSE);
1989 reply_nterror(req, NT_STATUS_DISK_FULL);
1990 goto out;
1992 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1993 if (retval < 0) {
1994 close_file(req, fsp, ERROR_CLOSE);
1995 reply_nterror(req, NT_STATUS_DISK_FULL);
1996 goto out;
1998 status = vfs_stat_fsp(fsp);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 close_file(req, fsp, ERROR_CLOSE);
2001 reply_nterror(req, status);
2002 goto out;
2006 fattr = dos_mode(conn, fsp->fsp_name);
2007 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2008 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2011 goto out;
2014 /* If the caller set the extended oplock request bit
2015 and we granted one (by whatever means) - set the
2016 correct bit for extended oplock reply.
2019 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2020 smb_action |= EXTENDED_OPLOCK_GRANTED;
2023 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2024 smb_action |= EXTENDED_OPLOCK_GRANTED;
2027 /* If the caller set the core oplock request bit
2028 and we granted one (by whatever means) - set the
2029 correct bit for core oplock reply.
2032 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2033 reply_outbuf(req, 19, 0);
2034 } else {
2035 reply_outbuf(req, 15, 0);
2038 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2039 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2041 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2042 SCVAL(req->outbuf, smb_flg,
2043 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2046 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2047 SCVAL(req->outbuf, smb_flg,
2048 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2051 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2052 SSVAL(req->outbuf,smb_vwv3,fattr);
2053 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2054 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2055 } else {
2056 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2058 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2059 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2060 SSVAL(req->outbuf,smb_vwv11,smb_action);
2062 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2063 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2066 out:
2067 TALLOC_FREE(smb_fname);
2068 END_PROFILE(SMBopenX);
2069 return;
2072 /****************************************************************************
2073 Reply to a SMBulogoffX.
2074 ****************************************************************************/
2076 void reply_ulogoffX(struct smb_request *req)
2078 struct smbd_server_connection *sconn = req->sconn;
2079 user_struct *vuser;
2081 START_PROFILE(SMBulogoffX);
2083 vuser = get_valid_user_struct(sconn, req->vuid);
2085 if(vuser == NULL) {
2086 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2087 req->vuid));
2089 req->vuid = UID_FIELD_INVALID;
2090 reply_force_doserror(req, ERRSRV, ERRbaduid);
2091 END_PROFILE(SMBulogoffX);
2092 return;
2095 /* in user level security we are supposed to close any files
2096 open by this user */
2097 if (vuser != NULL) {
2098 file_close_user(sconn, req->vuid);
2101 invalidate_vuid(sconn, req->vuid);
2103 reply_outbuf(req, 2, 0);
2104 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2105 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2107 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2109 END_PROFILE(SMBulogoffX);
2110 req->vuid = UID_FIELD_INVALID;
2113 /****************************************************************************
2114 Reply to a mknew or a create.
2115 ****************************************************************************/
2117 void reply_mknew(struct smb_request *req)
2119 connection_struct *conn = req->conn;
2120 struct smb_filename *smb_fname = NULL;
2121 char *fname = NULL;
2122 uint32 fattr = 0;
2123 struct smb_file_time ft;
2124 files_struct *fsp;
2125 int oplock_request = 0;
2126 NTSTATUS status;
2127 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2128 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2129 uint32 create_disposition;
2130 uint32 create_options = 0;
2131 TALLOC_CTX *ctx = talloc_tos();
2133 START_PROFILE(SMBcreate);
2134 ZERO_STRUCT(ft);
2136 if (req->wct < 3) {
2137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2138 goto out;
2141 fattr = SVAL(req->vwv+0, 0);
2142 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2144 /* mtime. */
2145 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2147 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2148 STR_TERMINATE, &status);
2149 if (!NT_STATUS_IS_OK(status)) {
2150 reply_nterror(req, status);
2151 goto out;
2154 status = filename_convert(ctx,
2155 conn,
2156 req->flags2 & FLAGS2_DFS_PATHNAMES,
2157 fname,
2159 NULL,
2160 &smb_fname);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2163 reply_botherror(req,
2164 NT_STATUS_PATH_NOT_COVERED,
2165 ERRSRV, ERRbadpath);
2166 goto out;
2168 reply_nterror(req, status);
2169 goto out;
2172 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2173 DEBUG(0,("Attempt to create file (%s) with volid set - "
2174 "please report this\n",
2175 smb_fname_str_dbg(smb_fname)));
2178 if(req->cmd == SMBmknew) {
2179 /* We should fail if file exists. */
2180 create_disposition = FILE_CREATE;
2181 } else {
2182 /* Create if file doesn't exist, truncate if it does. */
2183 create_disposition = FILE_OVERWRITE_IF;
2186 status = SMB_VFS_CREATE_FILE(
2187 conn, /* conn */
2188 req, /* req */
2189 0, /* root_dir_fid */
2190 smb_fname, /* fname */
2191 access_mask, /* access_mask */
2192 share_mode, /* share_access */
2193 create_disposition, /* create_disposition*/
2194 create_options, /* create_options */
2195 fattr, /* file_attributes */
2196 oplock_request, /* oplock_request */
2197 0, /* allocation_size */
2198 0, /* private_flags */
2199 NULL, /* sd */
2200 NULL, /* ea_list */
2201 &fsp, /* result */
2202 NULL); /* pinfo */
2204 if (!NT_STATUS_IS_OK(status)) {
2205 if (open_was_deferred(req->sconn, req->mid)) {
2206 /* We have re-scheduled this call. */
2207 goto out;
2209 reply_openerror(req, status);
2210 goto out;
2213 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2214 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2215 if (!NT_STATUS_IS_OK(status)) {
2216 END_PROFILE(SMBcreate);
2217 goto out;
2220 reply_outbuf(req, 1, 0);
2221 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2223 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2224 SCVAL(req->outbuf,smb_flg,
2225 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2228 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2229 SCVAL(req->outbuf,smb_flg,
2230 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2233 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2234 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2235 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2236 (unsigned int)fattr));
2238 out:
2239 TALLOC_FREE(smb_fname);
2240 END_PROFILE(SMBcreate);
2241 return;
2244 /****************************************************************************
2245 Reply to a create temporary file.
2246 ****************************************************************************/
2248 void reply_ctemp(struct smb_request *req)
2250 connection_struct *conn = req->conn;
2251 struct smb_filename *smb_fname = NULL;
2252 char *fname = NULL;
2253 uint32 fattr;
2254 files_struct *fsp;
2255 int oplock_request;
2256 int tmpfd;
2257 char *s;
2258 NTSTATUS status;
2259 TALLOC_CTX *ctx = talloc_tos();
2261 START_PROFILE(SMBctemp);
2263 if (req->wct < 3) {
2264 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2265 goto out;
2268 fattr = SVAL(req->vwv+0, 0);
2269 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2271 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2272 STR_TERMINATE, &status);
2273 if (!NT_STATUS_IS_OK(status)) {
2274 reply_nterror(req, status);
2275 goto out;
2277 if (*fname) {
2278 fname = talloc_asprintf(ctx,
2279 "%s/TMXXXXXX",
2280 fname);
2281 } else {
2282 fname = talloc_strdup(ctx, "TMXXXXXX");
2285 if (!fname) {
2286 reply_nterror(req, NT_STATUS_NO_MEMORY);
2287 goto out;
2290 status = filename_convert(ctx, conn,
2291 req->flags2 & FLAGS2_DFS_PATHNAMES,
2292 fname,
2294 NULL,
2295 &smb_fname);
2296 if (!NT_STATUS_IS_OK(status)) {
2297 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2298 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2299 ERRSRV, ERRbadpath);
2300 goto out;
2302 reply_nterror(req, status);
2303 goto out;
2306 tmpfd = mkstemp(smb_fname->base_name);
2307 if (tmpfd == -1) {
2308 reply_nterror(req, map_nt_error_from_unix(errno));
2309 goto out;
2312 SMB_VFS_STAT(conn, smb_fname);
2314 /* We should fail if file does not exist. */
2315 status = SMB_VFS_CREATE_FILE(
2316 conn, /* conn */
2317 req, /* req */
2318 0, /* root_dir_fid */
2319 smb_fname, /* fname */
2320 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2321 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2322 FILE_OPEN, /* create_disposition*/
2323 0, /* create_options */
2324 fattr, /* file_attributes */
2325 oplock_request, /* oplock_request */
2326 0, /* allocation_size */
2327 0, /* private_flags */
2328 NULL, /* sd */
2329 NULL, /* ea_list */
2330 &fsp, /* result */
2331 NULL); /* pinfo */
2333 /* close fd from mkstemp() */
2334 close(tmpfd);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 if (open_was_deferred(req->sconn, req->mid)) {
2338 /* We have re-scheduled this call. */
2339 goto out;
2341 reply_openerror(req, status);
2342 goto out;
2345 reply_outbuf(req, 1, 0);
2346 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2348 /* the returned filename is relative to the directory */
2349 s = strrchr_m(fsp->fsp_name->base_name, '/');
2350 if (!s) {
2351 s = fsp->fsp_name->base_name;
2352 } else {
2353 s++;
2356 #if 0
2357 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2358 thing in the byte section. JRA */
2359 SSVALS(p, 0, -1); /* what is this? not in spec */
2360 #endif
2361 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2362 == -1) {
2363 reply_nterror(req, NT_STATUS_NO_MEMORY);
2364 goto out;
2367 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2368 SCVAL(req->outbuf, smb_flg,
2369 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2372 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2373 SCVAL(req->outbuf, smb_flg,
2374 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2377 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2378 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2379 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2380 out:
2381 TALLOC_FREE(smb_fname);
2382 END_PROFILE(SMBctemp);
2383 return;
2386 /*******************************************************************
2387 Check if a user is allowed to rename a file.
2388 ********************************************************************/
2390 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2391 uint16 dirtype)
2393 if (!CAN_WRITE(conn)) {
2394 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2397 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2398 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2399 /* Only bother to read the DOS attribute if we might deny the
2400 rename on the grounds of attribute missmatch. */
2401 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2402 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2403 return NT_STATUS_NO_SUCH_FILE;
2407 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2408 if (fsp->posix_open) {
2409 return NT_STATUS_OK;
2412 /* If no pathnames are open below this
2413 directory, allow the rename. */
2415 if (file_find_subpath(fsp)) {
2416 return NT_STATUS_ACCESS_DENIED;
2418 return NT_STATUS_OK;
2421 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2422 return NT_STATUS_OK;
2425 return NT_STATUS_ACCESS_DENIED;
2428 /*******************************************************************
2429 * unlink a file with all relevant access checks
2430 *******************************************************************/
2432 static NTSTATUS do_unlink(connection_struct *conn,
2433 struct smb_request *req,
2434 struct smb_filename *smb_fname,
2435 uint32 dirtype)
2437 uint32 fattr;
2438 files_struct *fsp;
2439 uint32 dirtype_orig = dirtype;
2440 NTSTATUS status;
2441 int ret;
2442 bool posix_paths = lp_posix_pathnames();
2444 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2445 smb_fname_str_dbg(smb_fname),
2446 dirtype));
2448 if (!CAN_WRITE(conn)) {
2449 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2452 if (posix_paths) {
2453 ret = SMB_VFS_LSTAT(conn, smb_fname);
2454 } else {
2455 ret = SMB_VFS_STAT(conn, smb_fname);
2457 if (ret != 0) {
2458 return map_nt_error_from_unix(errno);
2461 fattr = dos_mode(conn, smb_fname);
2463 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2464 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2467 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2468 if (!dirtype) {
2469 return NT_STATUS_NO_SUCH_FILE;
2472 if (!dir_check_ftype(conn, fattr, dirtype)) {
2473 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2474 return NT_STATUS_FILE_IS_A_DIRECTORY;
2476 return NT_STATUS_NO_SUCH_FILE;
2479 if (dirtype_orig & 0x8000) {
2480 /* These will never be set for POSIX. */
2481 return NT_STATUS_NO_SUCH_FILE;
2484 #if 0
2485 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2486 return NT_STATUS_FILE_IS_A_DIRECTORY;
2489 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2490 return NT_STATUS_NO_SUCH_FILE;
2493 if (dirtype & 0xFF00) {
2494 /* These will never be set for POSIX. */
2495 return NT_STATUS_NO_SUCH_FILE;
2498 dirtype &= 0xFF;
2499 if (!dirtype) {
2500 return NT_STATUS_NO_SUCH_FILE;
2503 /* Can't delete a directory. */
2504 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2505 return NT_STATUS_FILE_IS_A_DIRECTORY;
2507 #endif
2509 #if 0 /* JRATEST */
2510 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2511 return NT_STATUS_OBJECT_NAME_INVALID;
2512 #endif /* JRATEST */
2514 /* On open checks the open itself will check the share mode, so
2515 don't do it here as we'll get it wrong. */
2517 status = SMB_VFS_CREATE_FILE
2518 (conn, /* conn */
2519 req, /* req */
2520 0, /* root_dir_fid */
2521 smb_fname, /* fname */
2522 DELETE_ACCESS, /* access_mask */
2523 FILE_SHARE_NONE, /* share_access */
2524 FILE_OPEN, /* create_disposition*/
2525 FILE_NON_DIRECTORY_FILE, /* create_options */
2526 /* file_attributes */
2527 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2528 FILE_ATTRIBUTE_NORMAL,
2529 0, /* oplock_request */
2530 0, /* allocation_size */
2531 0, /* private_flags */
2532 NULL, /* sd */
2533 NULL, /* ea_list */
2534 &fsp, /* result */
2535 NULL); /* pinfo */
2537 if (!NT_STATUS_IS_OK(status)) {
2538 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2539 nt_errstr(status)));
2540 return status;
2543 status = can_set_delete_on_close(fsp, fattr);
2544 if (!NT_STATUS_IS_OK(status)) {
2545 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2546 "(%s)\n",
2547 smb_fname_str_dbg(smb_fname),
2548 nt_errstr(status)));
2549 close_file(req, fsp, NORMAL_CLOSE);
2550 return status;
2553 /* The set is across all open files on this dev/inode pair. */
2554 if (!set_delete_on_close(fsp, True,
2555 conn->session_info->security_token,
2556 conn->session_info->unix_token)) {
2557 close_file(req, fsp, NORMAL_CLOSE);
2558 return NT_STATUS_ACCESS_DENIED;
2561 return close_file(req, fsp, NORMAL_CLOSE);
2564 /****************************************************************************
2565 The guts of the unlink command, split out so it may be called by the NT SMB
2566 code.
2567 ****************************************************************************/
2569 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2570 uint32 dirtype, struct smb_filename *smb_fname,
2571 bool has_wild)
2573 char *fname_dir = NULL;
2574 char *fname_mask = NULL;
2575 int count=0;
2576 NTSTATUS status = NT_STATUS_OK;
2577 TALLOC_CTX *ctx = talloc_tos();
2579 /* Split up the directory from the filename/mask. */
2580 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2581 &fname_dir, &fname_mask);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 goto out;
2587 * We should only check the mangled cache
2588 * here if unix_convert failed. This means
2589 * that the path in 'mask' doesn't exist
2590 * on the file system and so we need to look
2591 * for a possible mangle. This patch from
2592 * Tine Smukavec <valentin.smukavec@hermes.si>.
2595 if (!VALID_STAT(smb_fname->st) &&
2596 mangle_is_mangled(fname_mask, conn->params)) {
2597 char *new_mask = NULL;
2598 mangle_lookup_name_from_8_3(ctx, fname_mask,
2599 &new_mask, conn->params);
2600 if (new_mask) {
2601 TALLOC_FREE(fname_mask);
2602 fname_mask = new_mask;
2606 if (!has_wild) {
2609 * Only one file needs to be unlinked. Append the mask back
2610 * onto the directory.
2612 TALLOC_FREE(smb_fname->base_name);
2613 if (ISDOT(fname_dir)) {
2614 /* Ensure we use canonical names on open. */
2615 smb_fname->base_name = talloc_asprintf(smb_fname,
2616 "%s",
2617 fname_mask);
2618 } else {
2619 smb_fname->base_name = talloc_asprintf(smb_fname,
2620 "%s/%s",
2621 fname_dir,
2622 fname_mask);
2624 if (!smb_fname->base_name) {
2625 status = NT_STATUS_NO_MEMORY;
2626 goto out;
2628 if (dirtype == 0) {
2629 dirtype = FILE_ATTRIBUTE_NORMAL;
2632 status = check_name(conn, smb_fname->base_name);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 goto out;
2637 status = do_unlink(conn, req, smb_fname, dirtype);
2638 if (!NT_STATUS_IS_OK(status)) {
2639 goto out;
2642 count++;
2643 } else {
2644 struct smb_Dir *dir_hnd = NULL;
2645 long offset = 0;
2646 const char *dname = NULL;
2647 char *talloced = NULL;
2649 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2650 status = NT_STATUS_OBJECT_NAME_INVALID;
2651 goto out;
2654 if (strequal(fname_mask,"????????.???")) {
2655 TALLOC_FREE(fname_mask);
2656 fname_mask = talloc_strdup(ctx, "*");
2657 if (!fname_mask) {
2658 status = NT_STATUS_NO_MEMORY;
2659 goto out;
2663 status = check_name(conn, fname_dir);
2664 if (!NT_STATUS_IS_OK(status)) {
2665 goto out;
2668 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2669 dirtype);
2670 if (dir_hnd == NULL) {
2671 status = map_nt_error_from_unix(errno);
2672 goto out;
2675 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2676 the pattern matches against the long name, otherwise the short name
2677 We don't implement this yet XXXX
2680 status = NT_STATUS_NO_SUCH_FILE;
2682 while ((dname = ReadDirName(dir_hnd, &offset,
2683 &smb_fname->st, &talloced))) {
2684 TALLOC_CTX *frame = talloc_stackframe();
2686 if (!is_visible_file(conn, fname_dir, dname,
2687 &smb_fname->st, true)) {
2688 TALLOC_FREE(frame);
2689 TALLOC_FREE(talloced);
2690 continue;
2693 /* Quick check for "." and ".." */
2694 if (ISDOT(dname) || ISDOTDOT(dname)) {
2695 TALLOC_FREE(frame);
2696 TALLOC_FREE(talloced);
2697 continue;
2700 if(!mask_match(dname, fname_mask,
2701 conn->case_sensitive)) {
2702 TALLOC_FREE(frame);
2703 TALLOC_FREE(talloced);
2704 continue;
2707 TALLOC_FREE(smb_fname->base_name);
2708 if (ISDOT(fname_dir)) {
2709 /* Ensure we use canonical names on open. */
2710 smb_fname->base_name =
2711 talloc_asprintf(smb_fname, "%s",
2712 dname);
2713 } else {
2714 smb_fname->base_name =
2715 talloc_asprintf(smb_fname, "%s/%s",
2716 fname_dir, dname);
2719 if (!smb_fname->base_name) {
2720 TALLOC_FREE(dir_hnd);
2721 status = NT_STATUS_NO_MEMORY;
2722 TALLOC_FREE(frame);
2723 TALLOC_FREE(talloced);
2724 goto out;
2727 status = check_name(conn, smb_fname->base_name);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 TALLOC_FREE(dir_hnd);
2730 TALLOC_FREE(frame);
2731 TALLOC_FREE(talloced);
2732 goto out;
2735 status = do_unlink(conn, req, smb_fname, dirtype);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 TALLOC_FREE(frame);
2738 TALLOC_FREE(talloced);
2739 continue;
2742 count++;
2743 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2744 smb_fname->base_name));
2746 TALLOC_FREE(frame);
2747 TALLOC_FREE(talloced);
2749 TALLOC_FREE(dir_hnd);
2752 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2753 status = map_nt_error_from_unix(errno);
2756 out:
2757 TALLOC_FREE(fname_dir);
2758 TALLOC_FREE(fname_mask);
2759 return status;
2762 /****************************************************************************
2763 Reply to a unlink
2764 ****************************************************************************/
2766 void reply_unlink(struct smb_request *req)
2768 connection_struct *conn = req->conn;
2769 char *name = NULL;
2770 struct smb_filename *smb_fname = NULL;
2771 uint32 dirtype;
2772 NTSTATUS status;
2773 bool path_contains_wcard = False;
2774 TALLOC_CTX *ctx = talloc_tos();
2776 START_PROFILE(SMBunlink);
2778 if (req->wct < 1) {
2779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2780 goto out;
2783 dirtype = SVAL(req->vwv+0, 0);
2785 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2786 STR_TERMINATE, &status,
2787 &path_contains_wcard);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 reply_nterror(req, status);
2790 goto out;
2793 status = filename_convert(ctx, conn,
2794 req->flags2 & FLAGS2_DFS_PATHNAMES,
2795 name,
2796 UCF_COND_ALLOW_WCARD_LCOMP,
2797 &path_contains_wcard,
2798 &smb_fname);
2799 if (!NT_STATUS_IS_OK(status)) {
2800 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2801 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2802 ERRSRV, ERRbadpath);
2803 goto out;
2805 reply_nterror(req, status);
2806 goto out;
2809 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2811 status = unlink_internals(conn, req, dirtype, smb_fname,
2812 path_contains_wcard);
2813 if (!NT_STATUS_IS_OK(status)) {
2814 if (open_was_deferred(req->sconn, req->mid)) {
2815 /* We have re-scheduled this call. */
2816 goto out;
2818 reply_nterror(req, status);
2819 goto out;
2822 reply_outbuf(req, 0, 0);
2823 out:
2824 TALLOC_FREE(smb_fname);
2825 END_PROFILE(SMBunlink);
2826 return;
2829 /****************************************************************************
2830 Fail for readbraw.
2831 ****************************************************************************/
2833 static void fail_readraw(void)
2835 const char *errstr = talloc_asprintf(talloc_tos(),
2836 "FAIL ! reply_readbraw: socket write fail (%s)",
2837 strerror(errno));
2838 if (!errstr) {
2839 errstr = "";
2841 exit_server_cleanly(errstr);
2844 /****************************************************************************
2845 Fake (read/write) sendfile. Returns -1 on read or write fail.
2846 ****************************************************************************/
2848 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2850 size_t bufsize;
2851 size_t tosend = nread;
2852 char *buf;
2854 if (nread == 0) {
2855 return 0;
2858 bufsize = MIN(nread, 65536);
2860 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2861 return -1;
2864 while (tosend > 0) {
2865 ssize_t ret;
2866 size_t cur_read;
2868 if (tosend > bufsize) {
2869 cur_read = bufsize;
2870 } else {
2871 cur_read = tosend;
2873 ret = read_file(fsp,buf,startpos,cur_read);
2874 if (ret == -1) {
2875 SAFE_FREE(buf);
2876 return -1;
2879 /* If we had a short read, fill with zeros. */
2880 if (ret < cur_read) {
2881 memset(buf + ret, '\0', cur_read - ret);
2884 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2885 != cur_read) {
2886 char addr[INET6_ADDRSTRLEN];
2888 * Try and give an error message saying what
2889 * client failed.
2891 DEBUG(0, ("write_data failed for client %s. "
2892 "Error %s\n",
2893 get_peer_addr(fsp->conn->sconn->sock, addr,
2894 sizeof(addr)),
2895 strerror(errno)));
2896 SAFE_FREE(buf);
2897 return -1;
2899 tosend -= cur_read;
2900 startpos += cur_read;
2903 SAFE_FREE(buf);
2904 return (ssize_t)nread;
2907 /****************************************************************************
2908 Deal with the case of sendfile reading less bytes from the file than
2909 requested. Fill with zeros (all we can do).
2910 ****************************************************************************/
2912 void sendfile_short_send(files_struct *fsp,
2913 ssize_t nread,
2914 size_t headersize,
2915 size_t smb_maxcnt)
2917 #define SHORT_SEND_BUFSIZE 1024
2918 if (nread < headersize) {
2919 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2920 "header for file %s (%s). Terminating\n",
2921 fsp_str_dbg(fsp), strerror(errno)));
2922 exit_server_cleanly("sendfile_short_send failed");
2925 nread -= headersize;
2927 if (nread < smb_maxcnt) {
2928 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2929 if (!buf) {
2930 exit_server_cleanly("sendfile_short_send: "
2931 "malloc failed");
2934 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2935 "with zeros !\n", fsp_str_dbg(fsp)));
2937 while (nread < smb_maxcnt) {
2939 * We asked for the real file size and told sendfile
2940 * to not go beyond the end of the file. But it can
2941 * happen that in between our fstat call and the
2942 * sendfile call the file was truncated. This is very
2943 * bad because we have already announced the larger
2944 * number of bytes to the client.
2946 * The best we can do now is to send 0-bytes, just as
2947 * a read from a hole in a sparse file would do.
2949 * This should happen rarely enough that I don't care
2950 * about efficiency here :-)
2952 size_t to_write;
2954 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2955 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2956 != to_write) {
2957 char addr[INET6_ADDRSTRLEN];
2959 * Try and give an error message saying what
2960 * client failed.
2962 DEBUG(0, ("write_data failed for client %s. "
2963 "Error %s\n",
2964 get_peer_addr(
2965 fsp->conn->sconn->sock, addr,
2966 sizeof(addr)),
2967 strerror(errno)));
2968 exit_server_cleanly("sendfile_short_send: "
2969 "write_data failed");
2971 nread += to_write;
2973 SAFE_FREE(buf);
2977 /****************************************************************************
2978 Return a readbraw error (4 bytes of zero).
2979 ****************************************************************************/
2981 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2983 char header[4];
2985 SIVAL(header,0,0);
2987 smbd_lock_socket(sconn);
2988 if (write_data(sconn->sock,header,4) != 4) {
2989 char addr[INET6_ADDRSTRLEN];
2991 * Try and give an error message saying what
2992 * client failed.
2994 DEBUG(0, ("write_data failed for client %s. "
2995 "Error %s\n",
2996 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2997 strerror(errno)));
2999 fail_readraw();
3001 smbd_unlock_socket(sconn);
3004 /****************************************************************************
3005 Use sendfile in readbraw.
3006 ****************************************************************************/
3008 static void send_file_readbraw(connection_struct *conn,
3009 struct smb_request *req,
3010 files_struct *fsp,
3011 off_t startpos,
3012 size_t nread,
3013 ssize_t mincount)
3015 struct smbd_server_connection *sconn = req->sconn;
3016 char *outbuf = NULL;
3017 ssize_t ret=0;
3020 * We can only use sendfile on a non-chained packet
3021 * but we can use on a non-oplocked file. tridge proved this
3022 * on a train in Germany :-). JRA.
3023 * reply_readbraw has already checked the length.
3026 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3027 (fsp->wcp == NULL) &&
3028 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3029 ssize_t sendfile_read = -1;
3030 char header[4];
3031 DATA_BLOB header_blob;
3033 _smb_setlen(header,nread);
3034 header_blob = data_blob_const(header, 4);
3036 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3037 &header_blob, startpos,
3038 nread);
3039 if (sendfile_read == -1) {
3040 /* Returning ENOSYS means no data at all was sent.
3041 * Do this as a normal read. */
3042 if (errno == ENOSYS) {
3043 goto normal_readbraw;
3047 * Special hack for broken Linux with no working sendfile. If we
3048 * return EINTR we sent the header but not the rest of the data.
3049 * Fake this up by doing read/write calls.
3051 if (errno == EINTR) {
3052 /* Ensure we don't do this again. */
3053 set_use_sendfile(SNUM(conn), False);
3054 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3056 if (fake_sendfile(fsp, startpos, nread) == -1) {
3057 DEBUG(0,("send_file_readbraw: "
3058 "fake_sendfile failed for "
3059 "file %s (%s).\n",
3060 fsp_str_dbg(fsp),
3061 strerror(errno)));
3062 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3064 return;
3067 DEBUG(0,("send_file_readbraw: sendfile failed for "
3068 "file %s (%s). Terminating\n",
3069 fsp_str_dbg(fsp), strerror(errno)));
3070 exit_server_cleanly("send_file_readbraw sendfile failed");
3071 } else if (sendfile_read == 0) {
3073 * Some sendfile implementations return 0 to indicate
3074 * that there was a short read, but nothing was
3075 * actually written to the socket. In this case,
3076 * fallback to the normal read path so the header gets
3077 * the correct byte count.
3079 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3080 "bytes falling back to the normal read: "
3081 "%s\n", fsp_str_dbg(fsp)));
3082 goto normal_readbraw;
3085 /* Deal with possible short send. */
3086 if (sendfile_read != 4+nread) {
3087 sendfile_short_send(fsp, sendfile_read, 4, nread);
3089 return;
3092 normal_readbraw:
3094 outbuf = talloc_array(NULL, char, nread+4);
3095 if (!outbuf) {
3096 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3097 (unsigned)(nread+4)));
3098 reply_readbraw_error(sconn);
3099 return;
3102 if (nread > 0) {
3103 ret = read_file(fsp,outbuf+4,startpos,nread);
3104 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3105 if (ret < mincount)
3106 ret = 0;
3107 #else
3108 if (ret < nread)
3109 ret = 0;
3110 #endif
3113 _smb_setlen(outbuf,ret);
3114 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3115 char addr[INET6_ADDRSTRLEN];
3117 * Try and give an error message saying what
3118 * client failed.
3120 DEBUG(0, ("write_data failed for client %s. "
3121 "Error %s\n",
3122 get_peer_addr(fsp->conn->sconn->sock, addr,
3123 sizeof(addr)),
3124 strerror(errno)));
3126 fail_readraw();
3129 TALLOC_FREE(outbuf);
3132 /****************************************************************************
3133 Reply to a readbraw (core+ protocol).
3134 ****************************************************************************/
3136 void reply_readbraw(struct smb_request *req)
3138 connection_struct *conn = req->conn;
3139 struct smbd_server_connection *sconn = req->sconn;
3140 ssize_t maxcount,mincount;
3141 size_t nread = 0;
3142 off_t startpos;
3143 files_struct *fsp;
3144 struct lock_struct lock;
3145 off_t size = 0;
3147 START_PROFILE(SMBreadbraw);
3149 if (srv_is_signing_active(sconn) ||
3150 is_encrypted_packet(sconn, req->inbuf)) {
3151 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3152 "raw reads/writes are disallowed.");
3155 if (req->wct < 8) {
3156 reply_readbraw_error(sconn);
3157 END_PROFILE(SMBreadbraw);
3158 return;
3161 if (sconn->smb1.echo_handler.trusted_fde) {
3162 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3163 "'async smb echo handler = yes'\n"));
3164 reply_readbraw_error(sconn);
3165 END_PROFILE(SMBreadbraw);
3166 return;
3170 * Special check if an oplock break has been issued
3171 * and the readraw request croses on the wire, we must
3172 * return a zero length response here.
3175 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3178 * We have to do a check_fsp by hand here, as
3179 * we must always return 4 zero bytes on error,
3180 * not a NTSTATUS.
3183 if (!fsp || !conn || conn != fsp->conn ||
3184 req->vuid != fsp->vuid ||
3185 fsp->is_directory || fsp->fh->fd == -1) {
3187 * fsp could be NULL here so use the value from the packet. JRA.
3189 DEBUG(3,("reply_readbraw: fnum %d not valid "
3190 "- cache prime?\n",
3191 (int)SVAL(req->vwv+0, 0)));
3192 reply_readbraw_error(sconn);
3193 END_PROFILE(SMBreadbraw);
3194 return;
3197 /* Do a "by hand" version of CHECK_READ. */
3198 if (!(fsp->can_read ||
3199 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3200 (fsp->access_mask & FILE_EXECUTE)))) {
3201 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3202 (int)SVAL(req->vwv+0, 0)));
3203 reply_readbraw_error(sconn);
3204 END_PROFILE(SMBreadbraw);
3205 return;
3208 flush_write_cache(fsp, READRAW_FLUSH);
3210 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3211 if(req->wct == 10) {
3213 * This is a large offset (64 bit) read.
3216 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3218 if(startpos < 0) {
3219 DEBUG(0,("reply_readbraw: negative 64 bit "
3220 "readraw offset (%.0f) !\n",
3221 (double)startpos ));
3222 reply_readbraw_error(sconn);
3223 END_PROFILE(SMBreadbraw);
3224 return;
3228 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3229 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3231 /* ensure we don't overrun the packet size */
3232 maxcount = MIN(65535,maxcount);
3234 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3235 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3236 &lock);
3238 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3239 reply_readbraw_error(sconn);
3240 END_PROFILE(SMBreadbraw);
3241 return;
3244 if (fsp_stat(fsp) == 0) {
3245 size = fsp->fsp_name->st.st_ex_size;
3248 if (startpos >= size) {
3249 nread = 0;
3250 } else {
3251 nread = MIN(maxcount,(size - startpos));
3254 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3255 if (nread < mincount)
3256 nread = 0;
3257 #endif
3259 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3260 "min=%lu nread=%lu\n",
3261 fsp->fnum, (double)startpos,
3262 (unsigned long)maxcount,
3263 (unsigned long)mincount,
3264 (unsigned long)nread ) );
3266 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3268 DEBUG(5,("reply_readbraw finished\n"));
3270 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3272 END_PROFILE(SMBreadbraw);
3273 return;
3276 #undef DBGC_CLASS
3277 #define DBGC_CLASS DBGC_LOCKING
3279 /****************************************************************************
3280 Reply to a lockread (core+ protocol).
3281 ****************************************************************************/
3283 void reply_lockread(struct smb_request *req)
3285 connection_struct *conn = req->conn;
3286 ssize_t nread = -1;
3287 char *data;
3288 off_t startpos;
3289 size_t numtoread;
3290 NTSTATUS status;
3291 files_struct *fsp;
3292 struct byte_range_lock *br_lck = NULL;
3293 char *p = NULL;
3294 struct smbd_server_connection *sconn = req->sconn;
3296 START_PROFILE(SMBlockread);
3298 if (req->wct < 5) {
3299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3300 END_PROFILE(SMBlockread);
3301 return;
3304 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3306 if (!check_fsp(conn, req, fsp)) {
3307 END_PROFILE(SMBlockread);
3308 return;
3311 if (!CHECK_READ(fsp,req)) {
3312 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3313 END_PROFILE(SMBlockread);
3314 return;
3317 numtoread = SVAL(req->vwv+1, 0);
3318 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3320 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3322 reply_outbuf(req, 5, numtoread + 3);
3324 data = smb_buf(req->outbuf) + 3;
3327 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3328 * protocol request that predates the read/write lock concept.
3329 * Thus instead of asking for a read lock here we need to ask
3330 * for a write lock. JRA.
3331 * Note that the requested lock size is unaffected by max_recv.
3334 br_lck = do_lock(req->sconn->msg_ctx,
3335 fsp,
3336 (uint64_t)req->smbpid,
3337 (uint64_t)numtoread,
3338 (uint64_t)startpos,
3339 WRITE_LOCK,
3340 WINDOWS_LOCK,
3341 False, /* Non-blocking lock. */
3342 &status,
3343 NULL,
3344 NULL);
3345 TALLOC_FREE(br_lck);
3347 if (NT_STATUS_V(status)) {
3348 reply_nterror(req, status);
3349 END_PROFILE(SMBlockread);
3350 return;
3354 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3357 if (numtoread > sconn->smb1.negprot.max_recv) {
3358 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3359 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3360 (unsigned int)numtoread,
3361 (unsigned int)sconn->smb1.negprot.max_recv));
3362 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3364 nread = read_file(fsp,data,startpos,numtoread);
3366 if (nread < 0) {
3367 reply_nterror(req, map_nt_error_from_unix(errno));
3368 END_PROFILE(SMBlockread);
3369 return;
3372 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3374 SSVAL(req->outbuf,smb_vwv0,nread);
3375 SSVAL(req->outbuf,smb_vwv5,nread+3);
3376 p = smb_buf(req->outbuf);
3377 SCVAL(p,0,0); /* pad byte. */
3378 SSVAL(p,1,nread);
3380 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3381 fsp->fnum, (int)numtoread, (int)nread));
3383 END_PROFILE(SMBlockread);
3384 return;
3387 #undef DBGC_CLASS
3388 #define DBGC_CLASS DBGC_ALL
3390 /****************************************************************************
3391 Reply to a read.
3392 ****************************************************************************/
3394 void reply_read(struct smb_request *req)
3396 connection_struct *conn = req->conn;
3397 size_t numtoread;
3398 ssize_t nread = 0;
3399 char *data;
3400 off_t startpos;
3401 int outsize = 0;
3402 files_struct *fsp;
3403 struct lock_struct lock;
3404 struct smbd_server_connection *sconn = req->sconn;
3406 START_PROFILE(SMBread);
3408 if (req->wct < 3) {
3409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3410 END_PROFILE(SMBread);
3411 return;
3414 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3416 if (!check_fsp(conn, req, fsp)) {
3417 END_PROFILE(SMBread);
3418 return;
3421 if (!CHECK_READ(fsp,req)) {
3422 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3423 END_PROFILE(SMBread);
3424 return;
3427 numtoread = SVAL(req->vwv+1, 0);
3428 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3430 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3433 * The requested read size cannot be greater than max_recv. JRA.
3435 if (numtoread > sconn->smb1.negprot.max_recv) {
3436 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3437 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3438 (unsigned int)numtoread,
3439 (unsigned int)sconn->smb1.negprot.max_recv));
3440 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3443 reply_outbuf(req, 5, numtoread+3);
3445 data = smb_buf(req->outbuf) + 3;
3447 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3448 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3449 &lock);
3451 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3452 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3453 END_PROFILE(SMBread);
3454 return;
3457 if (numtoread > 0)
3458 nread = read_file(fsp,data,startpos,numtoread);
3460 if (nread < 0) {
3461 reply_nterror(req, map_nt_error_from_unix(errno));
3462 goto strict_unlock;
3465 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3467 SSVAL(req->outbuf,smb_vwv0,nread);
3468 SSVAL(req->outbuf,smb_vwv5,nread+3);
3469 SCVAL(smb_buf(req->outbuf),0,1);
3470 SSVAL(smb_buf(req->outbuf),1,nread);
3472 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3473 fsp->fnum, (int)numtoread, (int)nread ) );
3475 strict_unlock:
3476 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3478 END_PROFILE(SMBread);
3479 return;
3482 /****************************************************************************
3483 Setup readX header.
3484 ****************************************************************************/
3486 static int setup_readX_header(struct smb_request *req, char *outbuf,
3487 size_t smb_maxcnt)
3489 int outsize;
3491 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3493 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3495 SCVAL(outbuf,smb_vwv0,0xFF);
3496 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3497 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3498 SSVAL(outbuf,smb_vwv6,
3499 (smb_wct - 4) /* offset from smb header to wct */
3500 + 1 /* the wct field */
3501 + 12 * sizeof(uint16_t) /* vwv */
3502 + 2); /* the buflen field */
3503 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3504 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3505 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3506 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3507 return outsize;
3510 /****************************************************************************
3511 Reply to a read and X - possibly using sendfile.
3512 ****************************************************************************/
3514 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3515 files_struct *fsp, off_t startpos,
3516 size_t smb_maxcnt)
3518 ssize_t nread = -1;
3519 struct lock_struct lock;
3520 int saved_errno = 0;
3522 if(fsp_stat(fsp) == -1) {
3523 reply_nterror(req, map_nt_error_from_unix(errno));
3524 return;
3527 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3528 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3529 &lock);
3531 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3532 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3533 return;
3536 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3537 (startpos > fsp->fsp_name->st.st_ex_size)
3538 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3540 * We already know that we would do a short read, so don't
3541 * try the sendfile() path.
3543 goto nosendfile_read;
3547 * We can only use sendfile on a non-chained packet
3548 * but we can use on a non-oplocked file. tridge proved this
3549 * on a train in Germany :-). JRA.
3552 if (!req_is_in_chain(req) &&
3553 !is_encrypted_packet(req->sconn, req->inbuf) &&
3554 (fsp->base_fsp == NULL) &&
3555 (fsp->wcp == NULL) &&
3556 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3557 uint8 headerbuf[smb_size + 12 * 2];
3558 DATA_BLOB header;
3561 * Set up the packet header before send. We
3562 * assume here the sendfile will work (get the
3563 * correct amount of data).
3566 header = data_blob_const(headerbuf, sizeof(headerbuf));
3568 construct_reply_common_req(req, (char *)headerbuf);
3569 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3571 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3572 startpos, smb_maxcnt);
3573 if (nread == -1) {
3574 /* Returning ENOSYS means no data at all was sent.
3575 Do this as a normal read. */
3576 if (errno == ENOSYS) {
3577 goto normal_read;
3581 * Special hack for broken Linux with no working sendfile. If we
3582 * return EINTR we sent the header but not the rest of the data.
3583 * Fake this up by doing read/write calls.
3586 if (errno == EINTR) {
3587 /* Ensure we don't do this again. */
3588 set_use_sendfile(SNUM(conn), False);
3589 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3590 nread = fake_sendfile(fsp, startpos,
3591 smb_maxcnt);
3592 if (nread == -1) {
3593 DEBUG(0,("send_file_readX: "
3594 "fake_sendfile failed for "
3595 "file %s (%s).\n",
3596 fsp_str_dbg(fsp),
3597 strerror(errno)));
3598 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3600 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3601 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3602 /* No outbuf here means successful sendfile. */
3603 goto strict_unlock;
3606 DEBUG(0,("send_file_readX: sendfile failed for file "
3607 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3608 strerror(errno)));
3609 exit_server_cleanly("send_file_readX sendfile failed");
3610 } else if (nread == 0) {
3612 * Some sendfile implementations return 0 to indicate
3613 * that there was a short read, but nothing was
3614 * actually written to the socket. In this case,
3615 * fallback to the normal read path so the header gets
3616 * the correct byte count.
3618 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3619 "falling back to the normal read: %s\n",
3620 fsp_str_dbg(fsp)));
3621 goto normal_read;
3624 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3625 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3627 /* Deal with possible short send. */
3628 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3629 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3631 /* No outbuf here means successful sendfile. */
3632 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);