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
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS check_path_syntax_internal(char *path,
45 bool *p_last_component_contains_wcard)
49 NTSTATUS ret = NT_STATUS_OK;
50 bool start_of_name_component = True;
51 bool stream_started = false;
53 *p_last_component_contains_wcard = False;
60 return NT_STATUS_OBJECT_NAME_INVALID;
63 return NT_STATUS_OBJECT_NAME_INVALID;
65 if (strchr_m(&s[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID;
68 if (StrCaseCmp(s, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER;
75 if (!posix_path && !stream_started && *s == ':') {
76 if (*p_last_component_contains_wcard) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started = true;
86 start_of_name_component = false;
90 return NT_STATUS_OBJECT_NAME_INVALID;
94 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s,posix_path)) {
103 if ((d != path) && (*s != '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component = True;
110 *p_last_component_contains_wcard = False;
114 if (start_of_name_component) {
115 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d > path) && (*(d-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d--; d > path; d--) {
141 s += 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
157 if (*s <= 0x1f || *s == '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID;
166 *p_last_component_contains_wcard = True;
175 /* Get the size of the next MB character. */
176 next_codepoint(s,&siz);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER;
199 start_of_name_component = False;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS check_path_syntax(char *path)
215 return check_path_syntax_internal(path, False, &ignore);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
226 return check_path_syntax_internal(path, False, p_contains_wcard);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS check_path_syntax_posix(char *path)
238 return check_path_syntax_internal(path, True, &ignore);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
246 const char *base_ptr,
253 bool *contains_wcard)
259 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
263 *err = NT_STATUS_INVALID_PARAMETER;
267 *contains_wcard = False;
269 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err = check_path_syntax_posix(*pp_dest);
281 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX *ctx,
292 const char *base_ptr,
301 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
302 src_len, flags, err, &ignore);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
306 char **pp_dest, const char *src, int flags,
307 NTSTATUS *err, bool *contains_wcard)
309 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
310 pp_dest, src, smbreq_bufrem(req, src),
311 flags, err, contains_wcard);
314 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
315 char **pp_dest, const char *src, int flags,
319 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
320 flags, err, &ignore);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
330 if (!(fsp) || !(conn)) {
331 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
334 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct *conn, struct smb_request *req,
348 if (!check_fsp_open(conn, req, fsp)) {
351 if ((fsp)->is_directory) {
352 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
355 if ((fsp)->fh->fd == -1) {
356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
359 (fsp)->num_smb_operations++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
371 if (!check_fsp_open(conn, req, fsp)) {
375 if (fsp->is_directory) {
379 if (fsp->fake_file_handle == NULL) {
383 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
387 if (fsp->fake_file_handle->private_data == NULL) {
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
401 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
402 && (req->vuid == (fsp)->vuid)) {
406 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
410 static bool netbios_session_retarget(const char *name, int name_type)
413 char *trim_name_type;
414 const char *retarget_parm;
417 int retarget_type = 0x20;
418 int retarget_port = 139;
419 struct sockaddr_storage retarget_addr;
420 struct sockaddr_in *in_addr;
424 if (get_socket_port(smbd_server_fd()) != 139) {
428 trim_name = talloc_strdup(talloc_tos(), name);
429 if (trim_name == NULL) {
432 trim_char(trim_name, ' ', ' ');
434 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
436 if (trim_name_type == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type, NULL);
442 if (retarget_parm == NULL) {
443 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
446 if (retarget_parm == NULL) {
450 retarget = talloc_strdup(trim_name, retarget_parm);
451 if (retarget == NULL) {
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
457 p = strchr(retarget, ':');
460 retarget_port = atoi(p);
463 p = strchr_m(retarget, '#');
466 sscanf(p, "%x", &retarget_type);
469 ret = resolve_name(retarget, &retarget_addr, retarget_type);
471 DEBUG(10, ("could not resolve %s\n", retarget));
475 if (retarget_addr.ss_family != AF_INET) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
480 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
482 _smb_setlen(outbuf, 6);
483 SCVAL(outbuf, 0, 0x84);
484 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
485 *(uint16_t *)(outbuf+8) = htons(retarget_port);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
495 TALLOC_FREE(trim_name);
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf)
505 int msg_type = CVAL(inbuf,0);
506 int msg_flags = CVAL(inbuf,1);
508 char name_type1, name_type2;
511 * We only really use 4 bytes of the outbuf, but for the smb_setlen
512 * calculation & friends (srv_send_smb uses that) we need the full smb
515 char outbuf[smb_size];
519 memset(outbuf, '\0', sizeof(outbuf));
521 smb_setlen(outbuf,0);
524 case 0x81: /* session request */
526 if (already_got_session) {
527 exit_server_cleanly("multiple session request not permitted");
530 SCVAL(outbuf,0,0x82);
532 if (name_len(inbuf+4) > 50 ||
533 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
534 DEBUG(0,("Invalid name length in session request\n"));
537 name_type1 = name_extract(inbuf,4,name1);
538 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
539 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
540 name1, name_type1, name2, name_type2));
542 if (netbios_session_retarget(name1, name_type1)) {
543 exit_server_cleanly("retargeted client");
546 set_local_machine_name(name1, True);
547 set_remote_machine_name(name2, True);
549 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
550 get_local_machine_name(), get_remote_machine_name(),
553 if (name_type2 == 'R') {
554 /* We are being asked for a pathworks session ---
556 SCVAL(outbuf, 0,0x83);
560 /* only add the client's machine name to the list
561 of possibly valid usernames if we are operating
562 in share mode security */
563 if (lp_security() == SEC_SHARE) {
564 add_session_user(get_remote_machine_name());
567 reload_services(True);
570 already_got_session = True;
573 case 0x89: /* session keepalive request
574 (some old clients produce this?) */
575 SCVAL(outbuf,0,SMBkeepalive);
579 case 0x82: /* positive session response */
580 case 0x83: /* negative session response */
581 case 0x84: /* retarget session response */
582 DEBUG(0,("Unexpected session response\n"));
585 case SMBkeepalive: /* session keepalive */
590 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
591 msg_type, msg_flags));
593 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
597 /****************************************************************************
599 conn POINTER CAN BE NULL HERE !
600 ****************************************************************************/
602 void reply_tcon(struct smb_request *req)
604 connection_struct *conn = req->conn;
606 char *service_buf = NULL;
607 char *password = NULL;
612 DATA_BLOB password_blob;
613 TALLOC_CTX *ctx = talloc_tos();
615 START_PROFILE(SMBtcon);
617 if (req->buflen < 4) {
618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
619 END_PROFILE(SMBtcon);
623 p = (const char *)req->buf + 1;
624 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
626 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
628 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
631 if (service_buf == NULL || password == NULL || dev == NULL) {
632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
633 END_PROFILE(SMBtcon);
636 p = strrchr_m(service_buf,'\\');
640 service = service_buf;
643 password_blob = data_blob(password, pwlen+1);
645 conn = make_connection(service,password_blob,dev,req->vuid,&nt_status);
648 data_blob_clear_free(&password_blob);
651 reply_nterror(req, nt_status);
652 END_PROFILE(SMBtcon);
656 reply_outbuf(req, 2, 0);
657 SSVAL(req->outbuf,smb_vwv0,max_recv);
658 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659 SSVAL(req->outbuf,smb_tid,conn->cnum);
661 DEBUG(3,("tcon service=%s cnum=%d\n",
662 service, conn->cnum));
664 END_PROFILE(SMBtcon);
668 /****************************************************************************
669 Reply to a tcon and X.
670 conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
673 void reply_tcon_and_X(struct smb_request *req)
675 connection_struct *conn = req->conn;
676 const char *service = NULL;
678 TALLOC_CTX *ctx = talloc_tos();
679 /* what the cleint thinks the device is */
680 char *client_devicetype = NULL;
681 /* what the server tells the client the share represents */
682 const char *server_devicetype;
689 START_PROFILE(SMBtconX);
692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
693 END_PROFILE(SMBtconX);
697 passlen = SVAL(req->vwv+3, 0);
698 tcon_flags = SVAL(req->vwv+2, 0);
700 /* we might have to close an old one */
701 if ((tcon_flags & 0x1) && conn) {
702 close_cnum(conn,req->vuid);
707 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
708 reply_doserror(req, ERRDOS, ERRbuftoosmall);
709 END_PROFILE(SMBtconX);
713 if (global_encrypted_passwords_negotiated) {
714 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
715 if (lp_security() == SEC_SHARE) {
717 * Security = share always has a pad byte
718 * after the password.
720 p = (const char *)req->buf + passlen + 1;
722 p = (const char *)req->buf + passlen;
725 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
726 /* Ensure correct termination */
727 password.data[passlen]=0;
728 p = (const char *)req->buf + passlen + 1;
731 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
734 data_blob_clear_free(&password);
735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
736 END_PROFILE(SMBtconX);
741 * the service name can be either: \\server\share
742 * or share directly like on the DELL PowerVault 705
745 q = strchr_m(path+2,'\\');
747 data_blob_clear_free(&password);
748 reply_doserror(req, ERRDOS, ERRnosuchshare);
749 END_PROFILE(SMBtconX);
757 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
758 &client_devicetype, p,
759 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
761 if (client_devicetype == NULL) {
762 data_blob_clear_free(&password);
763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
764 END_PROFILE(SMBtconX);
768 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
770 conn = make_connection(service, password, client_devicetype,
771 req->vuid, &nt_status);
774 data_blob_clear_free(&password);
777 reply_nterror(req, nt_status);
778 END_PROFILE(SMBtconX);
783 server_devicetype = "IPC";
784 else if ( IS_PRINT(conn) )
785 server_devicetype = "LPT1:";
787 server_devicetype = "A:";
789 if (Protocol < PROTOCOL_NT1) {
790 reply_outbuf(req, 2, 0);
791 if (message_push_string(&req->outbuf, server_devicetype,
792 STR_TERMINATE|STR_ASCII) == -1) {
793 reply_nterror(req, NT_STATUS_NO_MEMORY);
794 END_PROFILE(SMBtconX);
798 /* NT sets the fstype of IPC$ to the null string */
799 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
801 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
802 /* Return permissions. */
806 reply_outbuf(req, 7, 0);
809 perm1 = FILE_ALL_ACCESS;
810 perm2 = FILE_ALL_ACCESS;
812 perm1 = CAN_WRITE(conn) ?
817 SIVAL(req->outbuf, smb_vwv3, perm1);
818 SIVAL(req->outbuf, smb_vwv5, perm2);
820 reply_outbuf(req, 3, 0);
823 if ((message_push_string(&req->outbuf, server_devicetype,
824 STR_TERMINATE|STR_ASCII) == -1)
825 || (message_push_string(&req->outbuf, fstype,
826 STR_TERMINATE) == -1)) {
827 reply_nterror(req, NT_STATUS_NO_MEMORY);
828 END_PROFILE(SMBtconX);
832 /* what does setting this bit do? It is set by NT4 and
833 may affect the ability to autorun mounted cdroms */
834 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
835 (lp_csc_policy(SNUM(conn)) << 2));
837 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
838 DEBUG(2,("Serving %s as a Dfs root\n",
839 lp_servicename(SNUM(conn)) ));
840 SSVAL(req->outbuf, smb_vwv2,
841 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
846 DEBUG(3,("tconX service=%s \n",
849 /* set the incoming and outgoing tid to the just created one */
850 SSVAL(req->inbuf,smb_tid,conn->cnum);
851 SSVAL(req->outbuf,smb_tid,conn->cnum);
853 END_PROFILE(SMBtconX);
859 /****************************************************************************
860 Reply to an unknown type.
861 ****************************************************************************/
863 void reply_unknown_new(struct smb_request *req, uint8 type)
865 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
866 smb_fn_name(type), type, type));
867 reply_doserror(req, ERRSRV, ERRunknownsmb);
871 /****************************************************************************
873 conn POINTER CAN BE NULL HERE !
874 ****************************************************************************/
876 void reply_ioctl(struct smb_request *req)
878 connection_struct *conn = req->conn;
885 START_PROFILE(SMBioctl);
888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889 END_PROFILE(SMBioctl);
893 device = SVAL(req->vwv+1, 0);
894 function = SVAL(req->vwv+2, 0);
895 ioctl_code = (device << 16) + function;
897 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
899 switch (ioctl_code) {
900 case IOCTL_QUERY_JOB_INFO:
904 reply_doserror(req, ERRSRV, ERRnosupport);
905 END_PROFILE(SMBioctl);
909 reply_outbuf(req, 8, replysize+1);
910 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
911 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
912 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
913 p = smb_buf(req->outbuf);
914 memset(p, '\0', replysize+1); /* valgrind-safe. */
915 p += 1; /* Allow for alignment */
917 switch (ioctl_code) {
918 case IOCTL_QUERY_JOB_INFO:
920 files_struct *fsp = file_fsp(
921 req, SVAL(req->vwv+0, 0));
923 reply_doserror(req, ERRDOS, ERRbadfid);
924 END_PROFILE(SMBioctl);
927 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
928 srvstr_push((char *)req->outbuf, req->flags2, p+2,
930 STR_TERMINATE|STR_ASCII);
932 srvstr_push((char *)req->outbuf, req->flags2,
933 p+18, lp_servicename(SNUM(conn)),
934 13, STR_TERMINATE|STR_ASCII);
942 END_PROFILE(SMBioctl);
946 /****************************************************************************
947 Strange checkpath NTSTATUS mapping.
948 ****************************************************************************/
950 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
952 /* Strange DOS error code semantics only for checkpath... */
953 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
954 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
955 /* We need to map to ERRbadpath */
956 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
962 /****************************************************************************
963 Reply to a checkpath.
964 ****************************************************************************/
966 void reply_checkpath(struct smb_request *req)
968 connection_struct *conn = req->conn;
969 struct smb_filename *smb_fname = NULL;
972 TALLOC_CTX *ctx = talloc_tos();
974 START_PROFILE(SMBcheckpath);
976 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
977 STR_TERMINATE, &status);
979 if (!NT_STATUS_IS_OK(status)) {
980 status = map_checkpath_error(req->flags2, status);
981 reply_nterror(req, status);
982 END_PROFILE(SMBcheckpath);
986 status = resolve_dfspath(ctx, conn,
987 req->flags2 & FLAGS2_DFS_PATHNAMES,
990 if (!NT_STATUS_IS_OK(status)) {
991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
994 END_PROFILE(SMBcheckpath);
1000 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1002 status = unix_convert(ctx, conn, name, &smb_fname, 0);
1003 if (!NT_STATUS_IS_OK(status)) {
1007 status = get_full_smb_filename(ctx, smb_fname, &name);
1008 if (!NT_STATUS_IS_OK(status)) {
1012 status = check_name(conn, name);
1013 if (!NT_STATUS_IS_OK(status)) {
1014 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
1018 if (!VALID_STAT(smb_fname->st) &&
1019 (SMB_VFS_STAT(conn, name, &smb_fname->st) != 0)) {
1020 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
1021 status = map_nt_error_from_unix(errno);
1025 if (!S_ISDIR(smb_fname->st.st_mode)) {
1026 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1027 ERRDOS, ERRbadpath);
1031 reply_outbuf(req, 0, 0);
1033 TALLOC_FREE(smb_fname);
1034 END_PROFILE(SMBcheckpath);
1039 TALLOC_FREE(smb_fname);
1041 END_PROFILE(SMBcheckpath);
1043 /* We special case this - as when a Windows machine
1044 is parsing a path is steps through the components
1045 one at a time - if a component fails it expects
1046 ERRbadpath, not ERRbadfile.
1048 status = map_checkpath_error(req->flags2, status);
1049 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1051 * Windows returns different error codes if
1052 * the parent directory is valid but not the
1053 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1054 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1055 * if the path is invalid.
1057 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1058 ERRDOS, ERRbadpath);
1062 reply_nterror(req, status);
1065 /****************************************************************************
1067 ****************************************************************************/
1069 void reply_getatr(struct smb_request *req)
1071 connection_struct *conn = req->conn;
1072 struct smb_filename *smb_fname = NULL;
1079 TALLOC_CTX *ctx = talloc_tos();
1081 START_PROFILE(SMBgetatr);
1083 p = (const char *)req->buf + 1;
1084 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1085 if (!NT_STATUS_IS_OK(status)) {
1086 reply_nterror(req, status);
1090 status = resolve_dfspath(ctx, conn,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1094 if (!NT_STATUS_IS_OK(status)) {
1095 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1096 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1097 ERRSRV, ERRbadpath);
1100 reply_nterror(req, status);
1104 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1105 under WfWg - weird! */
1106 if (*fname == '\0') {
1107 mode = aHIDDEN | aDIR;
1108 if (!CAN_WRITE(conn)) {
1114 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1119 status = get_full_smb_filename(ctx, smb_fname, &fname);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 reply_nterror(req, status);
1124 status = check_name(conn, fname);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
1127 reply_nterror(req, status);
1130 if (!VALID_STAT(smb_fname->st) &&
1131 (SMB_VFS_STAT(conn, fname, &smb_fname->st) != 0)) {
1132 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
1133 reply_unixerror(req, ERRDOS,ERRbadfile);
1137 mode = dos_mode(conn, fname, &smb_fname->st);
1138 size = smb_fname->st.st_size;
1139 mtime = smb_fname->st.st_mtime;
1145 reply_outbuf(req, 10, 0);
1147 SSVAL(req->outbuf,smb_vwv0,mode);
1148 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1149 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1151 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1153 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1155 if (Protocol >= PROTOCOL_NT1) {
1156 SSVAL(req->outbuf, smb_flg2,
1157 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1160 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
1163 TALLOC_FREE(smb_fname);
1164 END_PROFILE(SMBgetatr);
1168 /****************************************************************************
1170 ****************************************************************************/
1172 void reply_setatr(struct smb_request *req)
1174 struct smb_file_time ft;
1175 connection_struct *conn = req->conn;
1176 struct smb_filename *smb_fname = NULL;
1182 TALLOC_CTX *ctx = talloc_tos();
1184 START_PROFILE(SMBsetatr);
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1193 p = (const char *)req->buf + 1;
1194 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1195 if (!NT_STATUS_IS_OK(status)) {
1196 reply_nterror(req, status);
1200 status = resolve_dfspath(ctx, conn,
1201 req->flags2 & FLAGS2_DFS_PATHNAMES,
1204 if (!NT_STATUS_IS_OK(status)) {
1205 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1206 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1207 ERRSRV, ERRbadpath);
1210 reply_nterror(req, status);
1214 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 reply_nterror(req, status);
1220 status = get_full_smb_filename(ctx, smb_fname, &fname);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 reply_nterror(req, status);
1226 status = check_name(conn, fname);
1227 if (!NT_STATUS_IS_OK(status)) {
1228 reply_nterror(req, status);
1232 if (fname[0] == '.' && fname[1] == '\0') {
1234 * Not sure here is the right place to catch this
1235 * condition. Might be moved to somewhere else later -- vl
1237 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1241 mode = SVAL(req->vwv+0, 0);
1242 mtime = srv_make_unix_date3(req->vwv+1);
1244 ft.mtime = convert_time_t_to_timespec(mtime);
1245 status = smb_set_file_time(conn, NULL, fname,
1246 &smb_fname->st, &ft, true);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 reply_unixerror(req, ERRDOS, ERRnoaccess);
1252 if (mode != FILE_ATTRIBUTE_NORMAL) {
1253 if (VALID_STAT_OF_DIR(smb_fname->st))
1258 if (file_set_dosmode(conn, fname, mode, &smb_fname->st, NULL,
1260 reply_unixerror(req, ERRDOS, ERRnoaccess);
1265 reply_outbuf(req, 0, 0);
1267 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
1269 TALLOC_FREE(smb_fname);
1270 END_PROFILE(SMBsetatr);
1274 /****************************************************************************
1276 ****************************************************************************/
1278 void reply_dskattr(struct smb_request *req)
1280 connection_struct *conn = req->conn;
1281 uint64_t dfree,dsize,bsize;
1282 START_PROFILE(SMBdskattr);
1284 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1285 reply_unixerror(req, ERRHRD, ERRgeneral);
1286 END_PROFILE(SMBdskattr);
1290 reply_outbuf(req, 5, 0);
1292 if (Protocol <= PROTOCOL_LANMAN2) {
1293 double total_space, free_space;
1294 /* we need to scale this to a number that DOS6 can handle. We
1295 use floating point so we can handle large drives on systems
1296 that don't have 64 bit integers
1298 we end up displaying a maximum of 2G to DOS systems
1300 total_space = dsize * (double)bsize;
1301 free_space = dfree * (double)bsize;
1303 dsize = (uint64_t)((total_space+63*512) / (64*512));
1304 dfree = (uint64_t)((free_space+63*512) / (64*512));
1306 if (dsize > 0xFFFF) dsize = 0xFFFF;
1307 if (dfree > 0xFFFF) dfree = 0xFFFF;
1309 SSVAL(req->outbuf,smb_vwv0,dsize);
1310 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1311 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1312 SSVAL(req->outbuf,smb_vwv3,dfree);
1314 SSVAL(req->outbuf,smb_vwv0,dsize);
1315 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1316 SSVAL(req->outbuf,smb_vwv2,512);
1317 SSVAL(req->outbuf,smb_vwv3,dfree);
1320 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1322 END_PROFILE(SMBdskattr);
1326 /****************************************************************************
1328 Can be called from SMBsearch, SMBffirst or SMBfunique.
1329 ****************************************************************************/
1331 void reply_search(struct smb_request *req)
1333 connection_struct *conn = req->conn;
1334 const char *mask = NULL;
1335 char *directory = NULL;
1341 unsigned int numentries = 0;
1342 unsigned int maxentries = 0;
1343 bool finished = False;
1349 bool check_descend = False;
1350 bool expect_close = False;
1352 bool mask_contains_wcard = False;
1353 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1354 TALLOC_CTX *ctx = talloc_tos();
1355 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1357 START_PROFILE(SMBsearch);
1360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1361 END_PROFILE(SMBsearch);
1365 if (lp_posix_pathnames()) {
1366 reply_unknown_new(req, req->cmd);
1367 END_PROFILE(SMBsearch);
1371 /* If we were called as SMBffirst then we must expect close. */
1372 if(req->cmd == SMBffirst) {
1373 expect_close = True;
1376 reply_outbuf(req, 1, 3);
1377 maxentries = SVAL(req->vwv+0, 0);
1378 dirtype = SVAL(req->vwv+1, 0);
1379 p = (const char *)req->buf + 1;
1380 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1381 &nt_status, &mask_contains_wcard);
1382 if (!NT_STATUS_IS_OK(nt_status)) {
1383 reply_nterror(req, nt_status);
1384 END_PROFILE(SMBsearch);
1388 nt_status = resolve_dfspath_wcard(ctx, conn,
1389 req->flags2 & FLAGS2_DFS_PATHNAMES,
1392 &mask_contains_wcard);
1393 if (!NT_STATUS_IS_OK(nt_status)) {
1394 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1395 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1396 ERRSRV, ERRbadpath);
1397 END_PROFILE(SMBsearch);
1400 reply_nterror(req, nt_status);
1401 END_PROFILE(SMBsearch);
1406 status_len = SVAL(p, 0);
1409 /* dirtype &= ~aDIR; */
1411 if (status_len == 0) {
1412 struct smb_filename *smb_fname = NULL;
1414 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1415 UCF_ALLOW_WCARD_LCOMP);
1416 if (!NT_STATUS_IS_OK(nt_status)) {
1417 reply_nterror(req, nt_status);
1418 END_PROFILE(SMBsearch);
1422 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1423 TALLOC_FREE(smb_fname);
1424 if (!NT_STATUS_IS_OK(nt_status)) {
1425 reply_nterror(req, nt_status);
1426 END_PROFILE(SMBsearch);
1430 nt_status = check_name(conn, directory);
1431 if (!NT_STATUS_IS_OK(nt_status)) {
1432 reply_nterror(req, nt_status);
1433 END_PROFILE(SMBsearch);
1437 p = strrchr_m(directory,'/');
1438 if ((p != NULL) && (*directory != '/')) {
1440 directory = talloc_strndup(ctx, directory,
1441 PTR_DIFF(p, directory));
1444 directory = talloc_strdup(ctx,".");
1448 reply_nterror(req, NT_STATUS_NO_MEMORY);
1449 END_PROFILE(SMBsearch);
1453 memset((char *)status,'\0',21);
1454 SCVAL(status,0,(dirtype & 0x1F));
1456 nt_status = dptr_create(conn,
1462 mask_contains_wcard,
1465 if (!NT_STATUS_IS_OK(nt_status)) {
1466 reply_nterror(req, nt_status);
1467 END_PROFILE(SMBsearch);
1470 dptr_num = dptr_dnum(conn->dirptr);
1474 memcpy(status,p,21);
1475 status_dirtype = CVAL(status,0) & 0x1F;
1476 if (status_dirtype != (dirtype & 0x1F)) {
1477 dirtype = status_dirtype;
1480 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1481 if (!conn->dirptr) {
1484 string_set(&conn->dirpath,dptr_path(dptr_num));
1485 mask = dptr_wcard(dptr_num);
1490 * For a 'continue' search we have no string. So
1491 * check from the initial saved string.
1493 mask_contains_wcard = ms_has_wild(mask);
1494 dirtype = dptr_attr(dptr_num);
1497 DEBUG(4,("dptr_num is %d\n",dptr_num));
1499 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1500 dptr_init_search_op(conn->dirptr);
1502 if ((dirtype&0x1F) == aVOLID) {
1503 char buf[DIR_STRUCT_SIZE];
1504 memcpy(buf,status,21);
1505 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1506 0,aVOLID,0,!allow_long_path_components)) {
1507 reply_nterror(req, NT_STATUS_NO_MEMORY);
1508 END_PROFILE(SMBsearch);
1511 dptr_fill(buf+12,dptr_num);
1512 if (dptr_zero(buf+12) && (status_len==0)) {
1517 if (message_push_blob(&req->outbuf,
1518 data_blob_const(buf, sizeof(buf)))
1520 reply_nterror(req, NT_STATUS_NO_MEMORY);
1521 END_PROFILE(SMBsearch);
1529 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1532 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1533 conn->dirpath,lp_dontdescend(SNUM(conn))));
1534 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1535 check_descend = True;
1538 for (i=numentries;(i<maxentries) && !finished;i++) {
1539 finished = !get_dir_entry(ctx,
1550 char buf[DIR_STRUCT_SIZE];
1551 memcpy(buf,status,21);
1552 if (!make_dir_struct(ctx,
1559 !allow_long_path_components)) {
1560 reply_nterror(req, NT_STATUS_NO_MEMORY);
1561 END_PROFILE(SMBsearch);
1564 if (!dptr_fill(buf+12,dptr_num)) {
1567 if (message_push_blob(&req->outbuf,
1568 data_blob_const(buf, sizeof(buf)))
1570 reply_nterror(req, NT_STATUS_NO_MEMORY);
1571 END_PROFILE(SMBsearch);
1581 /* If we were called as SMBffirst with smb_search_id == NULL
1582 and no entries were found then return error and close dirptr
1585 if (numentries == 0) {
1586 dptr_close(&dptr_num);
1587 } else if(expect_close && status_len == 0) {
1588 /* Close the dptr - we know it's gone */
1589 dptr_close(&dptr_num);
1592 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1593 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1594 dptr_close(&dptr_num);
1597 if ((numentries == 0) && !mask_contains_wcard) {
1598 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1599 END_PROFILE(SMBsearch);
1603 SSVAL(req->outbuf,smb_vwv0,numentries);
1604 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1605 SCVAL(smb_buf(req->outbuf),0,5);
1606 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1608 /* The replies here are never long name. */
1609 SSVAL(req->outbuf, smb_flg2,
1610 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1611 if (!allow_long_path_components) {
1612 SSVAL(req->outbuf, smb_flg2,
1613 SVAL(req->outbuf, smb_flg2)
1614 & (~FLAGS2_LONG_PATH_COMPONENTS));
1617 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1618 SSVAL(req->outbuf, smb_flg2,
1619 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1622 directory = dptr_path(dptr_num);
1625 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1626 smb_fn_name(req->cmd),
1628 directory ? directory : "./",
1633 END_PROFILE(SMBsearch);
1637 /****************************************************************************
1638 Reply to a fclose (stop directory search).
1639 ****************************************************************************/
1641 void reply_fclose(struct smb_request *req)
1649 bool path_contains_wcard = False;
1650 TALLOC_CTX *ctx = talloc_tos();
1652 START_PROFILE(SMBfclose);
1654 if (lp_posix_pathnames()) {
1655 reply_unknown_new(req, req->cmd);
1656 END_PROFILE(SMBfclose);
1660 p = (const char *)req->buf + 1;
1661 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1662 &err, &path_contains_wcard);
1663 if (!NT_STATUS_IS_OK(err)) {
1664 reply_nterror(req, err);
1665 END_PROFILE(SMBfclose);
1669 status_len = SVAL(p,0);
1672 if (status_len == 0) {
1673 reply_doserror(req, ERRSRV, ERRsrverror);
1674 END_PROFILE(SMBfclose);
1678 memcpy(status,p,21);
1680 if(dptr_fetch(status+12,&dptr_num)) {
1681 /* Close the dptr - we know it's gone */
1682 dptr_close(&dptr_num);
1685 reply_outbuf(req, 1, 0);
1686 SSVAL(req->outbuf,smb_vwv0,0);
1688 DEBUG(3,("search close\n"));
1690 END_PROFILE(SMBfclose);
1694 /****************************************************************************
1696 ****************************************************************************/
1698 void reply_open(struct smb_request *req)
1700 connection_struct *conn = req->conn;
1706 SMB_STRUCT_STAT sbuf;
1713 uint32 create_disposition;
1714 uint32 create_options = 0;
1716 TALLOC_CTX *ctx = talloc_tos();
1718 START_PROFILE(SMBopen);
1720 SET_STAT_INVALID(sbuf);
1723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1724 END_PROFILE(SMBopen);
1728 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1729 deny_mode = SVAL(req->vwv+0, 0);
1730 dos_attr = SVAL(req->vwv+1, 0);
1732 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1733 STR_TERMINATE, &status);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 reply_nterror(req, status);
1736 END_PROFILE(SMBopen);
1740 if (!map_open_params_to_ntcreate(
1741 fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask,
1742 &share_mode, &create_disposition, &create_options)) {
1743 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1744 END_PROFILE(SMBopen);
1748 status = SMB_VFS_CREATE_FILE(
1751 0, /* root_dir_fid */
1753 CFF_DOS_PATH, /* create_file_flags */
1754 access_mask, /* access_mask */
1755 share_mode, /* share_access */
1756 create_disposition, /* create_disposition*/
1757 create_options, /* create_options */
1758 dos_attr, /* file_attributes */
1759 oplock_request, /* oplock_request */
1760 0, /* allocation_size */
1767 if (!NT_STATUS_IS_OK(status)) {
1768 if (open_was_deferred(req->mid)) {
1769 /* We have re-scheduled this call. */
1770 END_PROFILE(SMBopen);
1773 reply_openerror(req, status);
1774 END_PROFILE(SMBopen);
1778 size = sbuf.st_size;
1779 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1780 mtime = sbuf.st_mtime;
1783 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1784 close_file(req, fsp, ERROR_CLOSE);
1785 reply_doserror(req, ERRDOS,ERRnoaccess);
1786 END_PROFILE(SMBopen);
1790 reply_outbuf(req, 7, 0);
1791 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1792 SSVAL(req->outbuf,smb_vwv1,fattr);
1793 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1794 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1796 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1798 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1799 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1801 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1802 SCVAL(req->outbuf,smb_flg,
1803 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1806 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1807 SCVAL(req->outbuf,smb_flg,
1808 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1810 END_PROFILE(SMBopen);
1814 /****************************************************************************
1815 Reply to an open and X.
1816 ****************************************************************************/
1818 void reply_open_and_X(struct smb_request *req)
1820 connection_struct *conn = req->conn;
1825 /* Breakout the oplock request bits so we can set the
1826 reply bits separately. */
1827 int ex_oplock_request;
1828 int core_oplock_request;
1831 int smb_sattr = SVAL(req->vwv+4, 0);
1832 uint32 smb_time = make_unix_date3(req->vwv+6);
1837 SMB_STRUCT_STAT sbuf;
1841 uint64_t allocation_size;
1842 ssize_t retval = -1;
1845 uint32 create_disposition;
1846 uint32 create_options = 0;
1847 TALLOC_CTX *ctx = talloc_tos();
1849 START_PROFILE(SMBopenX);
1851 if (req->wct < 15) {
1852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1853 END_PROFILE(SMBopenX);
1857 SET_STAT_INVALID(sbuf);
1859 open_flags = SVAL(req->vwv+2, 0);
1860 deny_mode = SVAL(req->vwv+3, 0);
1861 smb_attr = SVAL(req->vwv+5, 0);
1862 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1863 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1864 oplock_request = ex_oplock_request | core_oplock_request;
1865 smb_ofun = SVAL(req->vwv+8, 0);
1866 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1868 /* If it's an IPC, pass off the pipe handler. */
1870 if (lp_nt_pipe_support()) {
1871 reply_open_pipe_and_X(conn, req);
1873 reply_doserror(req, ERRSRV, ERRaccess);
1875 END_PROFILE(SMBopenX);
1879 /* XXXX we need to handle passed times, sattr and flags */
1880 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1881 STR_TERMINATE, &status);
1882 if (!NT_STATUS_IS_OK(status)) {
1883 reply_nterror(req, status);
1884 END_PROFILE(SMBopenX);
1888 if (!map_open_params_to_ntcreate(
1889 fname, deny_mode, smb_ofun, &access_mask,
1890 &share_mode, &create_disposition, &create_options)) {
1891 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1892 END_PROFILE(SMBopenX);
1896 status = SMB_VFS_CREATE_FILE(
1899 0, /* root_dir_fid */
1901 CFF_DOS_PATH, /* create_file_flags */
1902 access_mask, /* access_mask */
1903 share_mode, /* share_access */
1904 create_disposition, /* create_disposition*/
1905 create_options, /* create_options */
1906 smb_attr, /* file_attributes */
1907 oplock_request, /* oplock_request */
1908 0, /* allocation_size */
1912 &smb_action, /* pinfo */
1915 if (!NT_STATUS_IS_OK(status)) {
1916 END_PROFILE(SMBopenX);
1917 if (open_was_deferred(req->mid)) {
1918 /* We have re-scheduled this call. */
1921 reply_openerror(req, status);
1925 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1926 if the file is truncated or created. */
1927 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1928 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1929 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1930 close_file(req, fsp, ERROR_CLOSE);
1931 reply_nterror(req, NT_STATUS_DISK_FULL);
1932 END_PROFILE(SMBopenX);
1935 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1937 close_file(req, fsp, ERROR_CLOSE);
1938 reply_nterror(req, NT_STATUS_DISK_FULL);
1939 END_PROFILE(SMBopenX);
1942 sbuf.st_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
1945 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1946 mtime = sbuf.st_mtime;
1948 close_file(req, fsp, ERROR_CLOSE);
1949 reply_doserror(req, ERRDOS, ERRnoaccess);
1950 END_PROFILE(SMBopenX);
1954 /* If the caller set the extended oplock request bit
1955 and we granted one (by whatever means) - set the
1956 correct bit for extended oplock reply.
1959 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1960 smb_action |= EXTENDED_OPLOCK_GRANTED;
1963 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1964 smb_action |= EXTENDED_OPLOCK_GRANTED;
1967 /* If the caller set the core oplock request bit
1968 and we granted one (by whatever means) - set the
1969 correct bit for core oplock reply.
1972 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1973 reply_outbuf(req, 19, 0);
1975 reply_outbuf(req, 15, 0);
1978 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1979 SCVAL(req->outbuf, smb_flg,
1980 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1983 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1984 SCVAL(req->outbuf, smb_flg,
1985 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1988 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1989 SSVAL(req->outbuf,smb_vwv3,fattr);
1990 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1991 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1993 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1995 SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_size);
1996 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1997 SSVAL(req->outbuf,smb_vwv11,smb_action);
1999 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2000 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2003 END_PROFILE(SMBopenX);
2008 /****************************************************************************
2009 Reply to a SMBulogoffX.
2010 ****************************************************************************/
2012 void reply_ulogoffX(struct smb_request *req)
2016 START_PROFILE(SMBulogoffX);
2018 vuser = get_valid_user_struct(req->vuid);
2021 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2025 /* in user level security we are supposed to close any files
2026 open by this user */
2027 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2028 file_close_user(req->vuid);
2031 invalidate_vuid(req->vuid);
2033 reply_outbuf(req, 2, 0);
2035 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2037 END_PROFILE(SMBulogoffX);
2041 /****************************************************************************
2042 Reply to a mknew or a create.
2043 ****************************************************************************/
2045 void reply_mknew(struct smb_request *req)
2047 connection_struct *conn = req->conn;
2050 struct smb_file_time ft;
2052 int oplock_request = 0;
2053 SMB_STRUCT_STAT sbuf;
2055 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2056 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2057 uint32 create_disposition;
2058 uint32 create_options = 0;
2059 TALLOC_CTX *ctx = talloc_tos();
2061 START_PROFILE(SMBcreate);
2063 SET_STAT_INVALID(sbuf);
2066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2067 END_PROFILE(SMBcreate);
2071 fattr = SVAL(req->vwv+0, 0);
2072 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2075 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2077 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2078 STR_TERMINATE, &status);
2079 if (!NT_STATUS_IS_OK(status)) {
2080 reply_nterror(req, status);
2081 END_PROFILE(SMBcreate);
2085 if (fattr & aVOLID) {
2086 DEBUG(0,("Attempt to create file (%s) with volid set - "
2087 "please report this\n", fname));
2090 if(req->cmd == SMBmknew) {
2091 /* We should fail if file exists. */
2092 create_disposition = FILE_CREATE;
2094 /* Create if file doesn't exist, truncate if it does. */
2095 create_disposition = FILE_OVERWRITE_IF;
2098 status = SMB_VFS_CREATE_FILE(
2101 0, /* root_dir_fid */
2103 CFF_DOS_PATH, /* create_file_flags */
2104 access_mask, /* access_mask */
2105 share_mode, /* share_access */
2106 create_disposition, /* create_disposition*/
2107 create_options, /* create_options */
2108 fattr, /* file_attributes */
2109 oplock_request, /* oplock_request */
2110 0, /* allocation_size */
2117 if (!NT_STATUS_IS_OK(status)) {
2118 END_PROFILE(SMBcreate);
2119 if (open_was_deferred(req->mid)) {
2120 /* We have re-scheduled this call. */
2123 reply_openerror(req, status);
2127 ft.atime = get_atimespec(&sbuf); /* atime. */
2128 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 END_PROFILE(SMBcreate);
2131 reply_openerror(req, status);
2135 reply_outbuf(req, 1, 0);
2136 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2138 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2139 SCVAL(req->outbuf,smb_flg,
2140 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2143 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2144 SCVAL(req->outbuf,smb_flg,
2145 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2148 DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
2149 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
2150 fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
2152 END_PROFILE(SMBcreate);
2156 /****************************************************************************
2157 Reply to a create temporary file.
2158 ****************************************************************************/
2160 void reply_ctemp(struct smb_request *req)
2162 connection_struct *conn = req->conn;
2163 struct smb_filename *smb_fname = NULL;
2171 TALLOC_CTX *ctx = talloc_tos();
2173 START_PROFILE(SMBctemp);
2176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2180 fattr = SVAL(req->vwv+0, 0);
2181 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2183 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2184 STR_TERMINATE, &status);
2185 if (!NT_STATUS_IS_OK(status)) {
2186 reply_nterror(req, status);
2190 fname = talloc_asprintf(ctx,
2194 fname = talloc_strdup(ctx, "TMXXXXXX");
2198 reply_nterror(req, NT_STATUS_NO_MEMORY);
2202 status = resolve_dfspath(ctx, conn,
2203 req->flags2 & FLAGS2_DFS_PATHNAMES,
2206 if (!NT_STATUS_IS_OK(status)) {
2207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2208 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2209 ERRSRV, ERRbadpath);
2212 reply_nterror(req, status);
2216 status = unix_convert(ctx, conn, fname, &smb_fname, 0);
2217 if (!NT_STATUS_IS_OK(status)) {
2218 reply_nterror(req, status);
2222 status = get_full_smb_filename(ctx, smb_fname, &fname);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 reply_nterror(req, status);
2228 status = check_name(conn, fname);
2229 if (!NT_STATUS_IS_OK(status)) {
2230 reply_nterror(req, status);
2234 tmpfd = mkstemp(fname);
2236 reply_unixerror(req, ERRDOS, ERRnoaccess);
2240 SET_STAT_INVALID(smb_fname->st);
2241 SMB_VFS_STAT(conn, fname, &smb_fname->st);
2243 /* We should fail if file does not exist. */
2244 status = SMB_VFS_CREATE_FILE(
2247 0, /* root_dir_fid */
2249 0, /* create_file_flags */
2250 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2251 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2252 FILE_OPEN, /* create_disposition*/
2253 0, /* create_options */
2254 fattr, /* file_attributes */
2255 oplock_request, /* oplock_request */
2256 0, /* allocation_size */
2261 &smb_fname->st); /* psbuf */
2263 /* close fd from mkstemp() */
2266 if (!NT_STATUS_IS_OK(status)) {
2267 if (open_was_deferred(req->mid)) {
2268 /* We have re-scheduled this call. */
2271 reply_openerror(req, status);
2275 reply_outbuf(req, 1, 0);
2276 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2278 /* the returned filename is relative to the directory */
2279 s = strrchr_m(fsp->fsp_name, '/');
2287 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2288 thing in the byte section. JRA */
2289 SSVALS(p, 0, -1); /* what is this? not in spec */
2291 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2293 reply_nterror(req, NT_STATUS_NO_MEMORY);
2297 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2298 SCVAL(req->outbuf, smb_flg,
2299 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2302 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2303 SCVAL(req->outbuf, smb_flg,
2304 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2307 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2308 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2309 fsp->fh->fd, (unsigned int)smb_fname->st.st_mode));
2311 TALLOC_FREE(smb_fname);
2312 END_PROFILE(SMBctemp);
2316 /*******************************************************************
2317 Check if a user is allowed to rename a file.
2318 ********************************************************************/
2320 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2321 uint16 dirtype, SMB_STRUCT_STAT *pst)
2325 if (!CAN_WRITE(conn)) {
2326 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2329 fmode = dos_mode(conn, fsp->fsp_name, pst);
2330 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2331 return NT_STATUS_NO_SUCH_FILE;
2334 if (S_ISDIR(pst->st_mode)) {
2335 if (fsp->posix_open) {
2336 return NT_STATUS_OK;
2339 /* If no pathnames are open below this
2340 directory, allow the rename. */
2342 if (file_find_subpath(fsp)) {
2343 return NT_STATUS_ACCESS_DENIED;
2345 return NT_STATUS_OK;
2348 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2349 return NT_STATUS_OK;
2352 return NT_STATUS_ACCESS_DENIED;
2355 /*******************************************************************
2356 * unlink a file with all relevant access checks
2357 *******************************************************************/
2359 static NTSTATUS do_unlink(connection_struct *conn,
2360 struct smb_request *req,
2364 SMB_STRUCT_STAT sbuf;
2367 uint32 dirtype_orig = dirtype;
2370 DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
2372 if (!CAN_WRITE(conn)) {
2373 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2376 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
2377 return map_nt_error_from_unix(errno);
2380 fattr = dos_mode(conn,fname,&sbuf);
2382 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2383 dirtype = aDIR|aARCH|aRONLY;
2386 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2388 return NT_STATUS_NO_SUCH_FILE;
2391 if (!dir_check_ftype(conn, fattr, dirtype)) {
2393 return NT_STATUS_FILE_IS_A_DIRECTORY;
2395 return NT_STATUS_NO_SUCH_FILE;
2398 if (dirtype_orig & 0x8000) {
2399 /* These will never be set for POSIX. */
2400 return NT_STATUS_NO_SUCH_FILE;
2404 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2405 return NT_STATUS_FILE_IS_A_DIRECTORY;
2408 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2409 return NT_STATUS_NO_SUCH_FILE;
2412 if (dirtype & 0xFF00) {
2413 /* These will never be set for POSIX. */
2414 return NT_STATUS_NO_SUCH_FILE;
2419 return NT_STATUS_NO_SUCH_FILE;
2422 /* Can't delete a directory. */
2424 return NT_STATUS_FILE_IS_A_DIRECTORY;
2429 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2430 return NT_STATUS_OBJECT_NAME_INVALID;
2431 #endif /* JRATEST */
2433 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2435 On a Windows share, a file with read-only dosmode can be opened with
2436 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2437 fails with NT_STATUS_CANNOT_DELETE error.
2439 This semantic causes a problem that a user can not
2440 rename a file with read-only dosmode on a Samba share
2441 from a Windows command prompt (i.e. cmd.exe, but can rename
2442 from Windows Explorer).
2445 if (!lp_delete_readonly(SNUM(conn))) {
2446 if (fattr & aRONLY) {
2447 return NT_STATUS_CANNOT_DELETE;
2451 /* On open checks the open itself will check the share mode, so
2452 don't do it here as we'll get it wrong. */
2454 status = SMB_VFS_CREATE_FILE
2457 0, /* root_dir_fid */
2459 0, /* create_file_flags */
2460 DELETE_ACCESS, /* access_mask */
2461 FILE_SHARE_NONE, /* share_access */
2462 FILE_OPEN, /* create_disposition*/
2463 FILE_NON_DIRECTORY_FILE, /* create_options */
2464 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2465 0, /* oplock_request */
2466 0, /* allocation_size */
2473 if (!NT_STATUS_IS_OK(status)) {
2474 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2475 nt_errstr(status)));
2479 /* The set is across all open files on this dev/inode pair. */
2480 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2481 close_file(req, fsp, NORMAL_CLOSE);
2482 return NT_STATUS_ACCESS_DENIED;
2485 return close_file(req, fsp, NORMAL_CLOSE);
2488 /****************************************************************************
2489 The guts of the unlink command, split out so it may be called by the NT SMB
2491 ****************************************************************************/
2493 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2494 uint32 dirtype, const char *name_in, bool has_wild)
2496 struct smb_filename *smb_fname = NULL;
2497 const char *directory = NULL;
2502 NTSTATUS status = NT_STATUS_OK;
2504 TALLOC_CTX *ctx = talloc_tos();
2506 status = unix_convert(ctx, conn, name_in, &smb_fname,
2507 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2508 if (!NT_STATUS_IS_OK(status)) {
2512 status = get_full_smb_filename(ctx, smb_fname, &name);
2513 if (!NT_STATUS_IS_OK(status)) {
2514 TALLOC_FREE(smb_fname);
2518 p = strrchr_m(name,'/');
2520 directory = talloc_strdup(ctx, ".");
2522 TALLOC_FREE(smb_fname);
2523 return NT_STATUS_NO_MEMORY;
2533 * We should only check the mangled cache
2534 * here if unix_convert failed. This means
2535 * that the path in 'mask' doesn't exist
2536 * on the file system and so we need to look
2537 * for a possible mangle. This patch from
2538 * Tine Smukavec <valentin.smukavec@hermes.si>.
2541 if (!VALID_STAT(smb_fname->st) && mangle_is_mangled(mask,conn->params)) {
2542 char *new_mask = NULL;
2543 mangle_lookup_name_from_8_3(ctx,
2551 TALLOC_FREE(smb_fname);
2554 directory = talloc_asprintf(ctx,
2559 return NT_STATUS_NO_MEMORY;
2562 dirtype = FILE_ATTRIBUTE_NORMAL;
2565 status = check_name(conn, directory);
2566 if (!NT_STATUS_IS_OK(status)) {
2570 status = do_unlink(conn, req, directory, dirtype);
2571 if (!NT_STATUS_IS_OK(status)) {
2577 struct smb_Dir *dir_hnd = NULL;
2581 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2582 return NT_STATUS_OBJECT_NAME_INVALID;
2585 if (strequal(mask,"????????.???")) {
2590 status = check_name(conn, directory);
2591 if (!NT_STATUS_IS_OK(status)) {
2595 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask,
2597 if (dir_hnd == NULL) {
2598 return map_nt_error_from_unix(errno);
2601 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2602 the pattern matches against the long name, otherwise the short name
2603 We don't implement this yet XXXX
2606 status = NT_STATUS_NO_SUCH_FILE;
2608 while ((dname = ReadDirName(dir_hnd, &offset, &st))) {
2611 if (!is_visible_file(conn, directory, dname, &st,
2617 /* Quick check for "." and ".." */
2618 if (ISDOT(dname) || ISDOTDOT(dname)) {
2622 if(!mask_match(dname, mask, conn->case_sensitive)) {
2626 fname = talloc_asprintf(ctx, "%s/%s",
2630 return NT_STATUS_NO_MEMORY;
2633 status = check_name(conn, fname);
2634 if (!NT_STATUS_IS_OK(status)) {
2635 TALLOC_FREE(dir_hnd);
2639 status = do_unlink(conn, req, fname, dirtype);
2640 if (!NT_STATUS_IS_OK(status)) {
2646 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2651 TALLOC_FREE(dir_hnd);
2654 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2655 status = map_nt_error_from_unix(errno);
2661 /****************************************************************************
2663 ****************************************************************************/
2665 void reply_unlink(struct smb_request *req)
2667 connection_struct *conn = req->conn;
2671 bool path_contains_wcard = False;
2672 TALLOC_CTX *ctx = talloc_tos();
2674 START_PROFILE(SMBunlink);
2677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2678 END_PROFILE(SMBunlink);
2682 dirtype = SVAL(req->vwv+0, 0);
2684 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2685 STR_TERMINATE, &status,
2686 &path_contains_wcard);
2687 if (!NT_STATUS_IS_OK(status)) {
2688 reply_nterror(req, status);
2689 END_PROFILE(SMBunlink);
2693 status = resolve_dfspath_wcard(ctx, conn,
2694 req->flags2 & FLAGS2_DFS_PATHNAMES,
2697 &path_contains_wcard);
2698 if (!NT_STATUS_IS_OK(status)) {
2699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2700 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2701 ERRSRV, ERRbadpath);
2702 END_PROFILE(SMBunlink);
2705 reply_nterror(req, status);
2706 END_PROFILE(SMBunlink);
2710 DEBUG(3,("reply_unlink : %s\n",name));
2712 status = unlink_internals(conn, req, dirtype, name,
2713 path_contains_wcard);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 if (open_was_deferred(req->mid)) {
2716 /* We have re-scheduled this call. */
2717 END_PROFILE(SMBunlink);
2720 reply_nterror(req, status);
2721 END_PROFILE(SMBunlink);
2725 reply_outbuf(req, 0, 0);
2726 END_PROFILE(SMBunlink);
2731 /****************************************************************************
2733 ****************************************************************************/
2735 static void fail_readraw(void)
2737 const char *errstr = talloc_asprintf(talloc_tos(),
2738 "FAIL ! reply_readbraw: socket write fail (%s)",
2743 exit_server_cleanly(errstr);
2746 /****************************************************************************
2747 Fake (read/write) sendfile. Returns -1 on read or write fail.
2748 ****************************************************************************/
2750 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2754 size_t tosend = nread;
2761 bufsize = MIN(nread, 65536);
2763 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2767 while (tosend > 0) {
2771 if (tosend > bufsize) {
2776 ret = read_file(fsp,buf,startpos,cur_read);
2782 /* If we had a short read, fill with zeros. */
2783 if (ret < cur_read) {
2784 memset(buf + ret, '\0', cur_read - ret);
2787 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2792 startpos += cur_read;
2796 return (ssize_t)nread;
2799 #if defined(WITH_SENDFILE)
2800 /****************************************************************************
2801 Deal with the case of sendfile reading less bytes from the file than
2802 requested. Fill with zeros (all we can do).
2803 ****************************************************************************/
2805 static void sendfile_short_send(files_struct *fsp,
2810 #define SHORT_SEND_BUFSIZE 1024
2811 if (nread < headersize) {
2812 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2813 "header for file %s (%s). Terminating\n",
2814 fsp->fsp_name, strerror(errno) ));
2815 exit_server_cleanly("sendfile_short_send failed");
2818 nread -= headersize;
2820 if (nread < smb_maxcnt) {
2821 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2823 exit_server_cleanly("sendfile_short_send: "
2827 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2828 "with zeros !\n", fsp->fsp_name));
2830 while (nread < smb_maxcnt) {
2832 * We asked for the real file size and told sendfile
2833 * to not go beyond the end of the file. But it can
2834 * happen that in between our fstat call and the
2835 * sendfile call the file was truncated. This is very
2836 * bad because we have already announced the larger
2837 * number of bytes to the client.
2839 * The best we can do now is to send 0-bytes, just as
2840 * a read from a hole in a sparse file would do.
2842 * This should happen rarely enough that I don't care
2843 * about efficiency here :-)
2847 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2848 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2849 exit_server_cleanly("sendfile_short_send: "
2850 "write_data failed");
2857 #endif /* defined WITH_SENDFILE */
2859 /****************************************************************************
2860 Return a readbraw error (4 bytes of zero).
2861 ****************************************************************************/
2863 static void reply_readbraw_error(void)
2867 if (write_data(smbd_server_fd(),header,4) != 4) {
2872 /****************************************************************************
2873 Use sendfile in readbraw.
2874 ****************************************************************************/
2876 static void send_file_readbraw(connection_struct *conn,
2877 struct smb_request *req,
2883 char *outbuf = NULL;
2886 #if defined(WITH_SENDFILE)
2888 * We can only use sendfile on a non-chained packet
2889 * but we can use on a non-oplocked file. tridge proved this
2890 * on a train in Germany :-). JRA.
2891 * reply_readbraw has already checked the length.
2894 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2895 (fsp->wcp == NULL) &&
2896 lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
2897 ssize_t sendfile_read = -1;
2899 DATA_BLOB header_blob;
2901 _smb_setlen(header,nread);
2902 header_blob = data_blob_const(header, 4);
2904 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2905 &header_blob, startpos, nread)) == -1) {
2906 /* Returning ENOSYS means no data at all was sent.
2907 * Do this as a normal read. */
2908 if (errno == ENOSYS) {
2909 goto normal_readbraw;
2913 * Special hack for broken Linux with no working sendfile. If we
2914 * return EINTR we sent the header but not the rest of the data.
2915 * Fake this up by doing read/write calls.
2917 if (errno == EINTR) {
2918 /* Ensure we don't do this again. */
2919 set_use_sendfile(SNUM(conn), False);
2920 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2922 if (fake_sendfile(fsp, startpos, nread) == -1) {
2923 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2924 fsp->fsp_name, strerror(errno) ));
2925 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2930 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2931 fsp->fsp_name, strerror(errno) ));
2932 exit_server_cleanly("send_file_readbraw sendfile failed");
2933 } else if (sendfile_read == 0) {
2935 * Some sendfile implementations return 0 to indicate
2936 * that there was a short read, but nothing was
2937 * actually written to the socket. In this case,
2938 * fallback to the normal read path so the header gets
2939 * the correct byte count.
2941 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2942 "bytes falling back to the normal read: "
2943 "%s\n", fsp->fsp_name));
2944 goto normal_readbraw;
2947 /* Deal with possible short send. */
2948 if (sendfile_read != 4+nread) {
2949 sendfile_short_send(fsp, sendfile_read, 4, nread);
2957 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2959 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2960 (unsigned)(nread+4)));
2961 reply_readbraw_error();
2966 ret = read_file(fsp,outbuf+4,startpos,nread);
2967 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2976 _smb_setlen(outbuf,ret);
2977 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2980 TALLOC_FREE(outbuf);
2983 /****************************************************************************
2984 Reply to a readbraw (core+ protocol).
2985 ****************************************************************************/
2987 void reply_readbraw(struct smb_request *req)
2989 connection_struct *conn = req->conn;
2990 ssize_t maxcount,mincount;
2994 struct lock_struct lock;
2998 START_PROFILE(SMBreadbraw);
3000 if (srv_is_signing_active(smbd_server_conn) ||
3001 is_encrypted_packet(req->inbuf)) {
3002 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3003 "raw reads/writes are disallowed.");
3007 reply_readbraw_error();
3008 END_PROFILE(SMBreadbraw);
3013 * Special check if an oplock break has been issued
3014 * and the readraw request croses on the wire, we must
3015 * return a zero length response here.
3018 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3021 * We have to do a check_fsp by hand here, as
3022 * we must always return 4 zero bytes on error,
3026 if (!fsp || !conn || conn != fsp->conn ||
3027 req->vuid != fsp->vuid ||
3028 fsp->is_directory || fsp->fh->fd == -1) {
3030 * fsp could be NULL here so use the value from the packet. JRA.
3032 DEBUG(3,("reply_readbraw: fnum %d not valid "
3034 (int)SVAL(req->vwv+0, 0)));
3035 reply_readbraw_error();
3036 END_PROFILE(SMBreadbraw);
3040 /* Do a "by hand" version of CHECK_READ. */
3041 if (!(fsp->can_read ||
3042 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3043 (fsp->access_mask & FILE_EXECUTE)))) {
3044 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3045 (int)SVAL(req->vwv+0, 0)));
3046 reply_readbraw_error();
3047 END_PROFILE(SMBreadbraw);
3051 flush_write_cache(fsp, READRAW_FLUSH);
3053 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3054 if(req->wct == 10) {
3056 * This is a large offset (64 bit) read.
3058 #ifdef LARGE_SMB_OFF_T
3060 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3062 #else /* !LARGE_SMB_OFF_T */
3065 * Ensure we haven't been sent a >32 bit offset.
3068 if(IVAL(req->vwv+8, 0) != 0) {
3069 DEBUG(0,("reply_readbraw: large offset "
3070 "(%x << 32) used and we don't support "
3071 "64 bit offsets.\n",
3072 (unsigned int)IVAL(req->vwv+8, 0) ));
3073 reply_readbraw_error();
3074 END_PROFILE(SMBreadbraw);
3078 #endif /* LARGE_SMB_OFF_T */
3081 DEBUG(0,("reply_readbraw: negative 64 bit "
3082 "readraw offset (%.0f) !\n",
3083 (double)startpos ));
3084 reply_readbraw_error();
3085 END_PROFILE(SMBreadbraw);
3090 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3091 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3093 /* ensure we don't overrun the packet size */
3094 maxcount = MIN(65535,maxcount);
3096 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3097 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3100 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3101 reply_readbraw_error();
3102 END_PROFILE(SMBreadbraw);
3106 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3110 if (startpos >= size) {
3113 nread = MIN(maxcount,(size - startpos));
3116 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3117 if (nread < mincount)
3121 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3122 "min=%lu nread=%lu\n",
3123 fsp->fnum, (double)startpos,
3124 (unsigned long)maxcount,
3125 (unsigned long)mincount,
3126 (unsigned long)nread ) );
3128 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3130 DEBUG(5,("reply_readbraw finished\n"));
3132 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3134 END_PROFILE(SMBreadbraw);
3139 #define DBGC_CLASS DBGC_LOCKING
3141 /****************************************************************************
3142 Reply to a lockread (core+ protocol).
3143 ****************************************************************************/
3145 void reply_lockread(struct smb_request *req)
3147 connection_struct *conn = req->conn;
3154 struct byte_range_lock *br_lck = NULL;
3157 START_PROFILE(SMBlockread);
3160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3161 END_PROFILE(SMBlockread);
3165 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3167 if (!check_fsp(conn, req, fsp)) {
3168 END_PROFILE(SMBlockread);
3172 if (!CHECK_READ(fsp,req)) {
3173 reply_doserror(req, ERRDOS, ERRbadaccess);
3174 END_PROFILE(SMBlockread);
3178 numtoread = SVAL(req->vwv+1, 0);
3179 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3181 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3183 reply_outbuf(req, 5, numtoread + 3);
3185 data = smb_buf(req->outbuf) + 3;
3188 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3189 * protocol request that predates the read/write lock concept.
3190 * Thus instead of asking for a read lock here we need to ask
3191 * for a write lock. JRA.
3192 * Note that the requested lock size is unaffected by max_recv.