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;
509 struct smbd_server_connection *sconn = smbd_server_conn;
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
516 char outbuf[smb_size];
520 memset(outbuf, '\0', sizeof(outbuf));
522 smb_setlen(outbuf,0);
525 case 0x81: /* session request */
527 if (sconn->nbt.got_session) {
528 exit_server_cleanly("multiple session request not permitted");
531 SCVAL(outbuf,0,0x82);
533 if (name_len(inbuf+4) > 50 ||
534 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
535 DEBUG(0,("Invalid name length in session request\n"));
538 name_type1 = name_extract(inbuf,4,name1);
539 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
540 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541 name1, name_type1, name2, name_type2));
543 if (netbios_session_retarget(name1, name_type1)) {
544 exit_server_cleanly("retargeted client");
547 set_local_machine_name(name1, True);
548 set_remote_machine_name(name2, True);
550 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551 get_local_machine_name(), get_remote_machine_name(),
554 if (name_type2 == 'R') {
555 /* We are being asked for a pathworks session ---
557 SCVAL(outbuf, 0,0x83);
561 /* only add the client's machine name to the list
562 of possibly valid usernames if we are operating
563 in share mode security */
564 if (lp_security() == SEC_SHARE) {
565 add_session_user(sconn, get_remote_machine_name());
568 reload_services(True);
571 sconn->nbt.got_session = true;
574 case 0x89: /* session keepalive request
575 (some old clients produce this?) */
576 SCVAL(outbuf,0,SMBkeepalive);
580 case 0x82: /* positive session response */
581 case 0x83: /* negative session response */
582 case 0x84: /* retarget session response */
583 DEBUG(0,("Unexpected session response\n"));
586 case SMBkeepalive: /* session keepalive */
591 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592 msg_type, msg_flags));
594 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
598 /****************************************************************************
600 conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
603 void reply_tcon(struct smb_request *req)
605 connection_struct *conn = req->conn;
607 char *service_buf = NULL;
608 char *password = NULL;
613 DATA_BLOB password_blob;
614 TALLOC_CTX *ctx = talloc_tos();
615 struct smbd_server_connection *sconn = smbd_server_conn;
617 START_PROFILE(SMBtcon);
619 if (req->buflen < 4) {
620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
621 END_PROFILE(SMBtcon);
625 p = (const char *)req->buf + 1;
626 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
628 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
630 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
633 if (service_buf == NULL || password == NULL || dev == NULL) {
634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635 END_PROFILE(SMBtcon);
638 p = strrchr_m(service_buf,'\\');
642 service = service_buf;
645 password_blob = data_blob(password, pwlen+1);
647 conn = make_connection(sconn,service,password_blob,dev,
648 req->vuid,&nt_status);
651 data_blob_clear_free(&password_blob);
654 reply_nterror(req, nt_status);
655 END_PROFILE(SMBtcon);
659 reply_outbuf(req, 2, 0);
660 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
661 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
662 SSVAL(req->outbuf,smb_tid,conn->cnum);
664 DEBUG(3,("tcon service=%s cnum=%d\n",
665 service, conn->cnum));
667 END_PROFILE(SMBtcon);
671 /****************************************************************************
672 Reply to a tcon and X.
673 conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
676 void reply_tcon_and_X(struct smb_request *req)
678 connection_struct *conn = req->conn;
679 const char *service = NULL;
681 TALLOC_CTX *ctx = talloc_tos();
682 /* what the cleint thinks the device is */
683 char *client_devicetype = NULL;
684 /* what the server tells the client the share represents */
685 const char *server_devicetype;
691 struct smbd_server_connection *sconn = smbd_server_conn;
693 START_PROFILE(SMBtconX);
696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
697 END_PROFILE(SMBtconX);
701 passlen = SVAL(req->vwv+3, 0);
702 tcon_flags = SVAL(req->vwv+2, 0);
704 /* we might have to close an old one */
705 if ((tcon_flags & 0x1) && conn) {
706 close_cnum(sconn, conn,req->vuid);
711 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
712 reply_doserror(req, ERRDOS, ERRbuftoosmall);
713 END_PROFILE(SMBtconX);
717 if (sconn->smb1.negprot.encrypted_passwords) {
718 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
719 if (lp_security() == SEC_SHARE) {
721 * Security = share always has a pad byte
722 * after the password.
724 p = (const char *)req->buf + passlen + 1;
726 p = (const char *)req->buf + passlen;
729 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
730 /* Ensure correct termination */
731 password.data[passlen]=0;
732 p = (const char *)req->buf + passlen + 1;
735 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
738 data_blob_clear_free(&password);
739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
740 END_PROFILE(SMBtconX);
745 * the service name can be either: \\server\share
746 * or share directly like on the DELL PowerVault 705
749 q = strchr_m(path+2,'\\');
751 data_blob_clear_free(&password);
752 reply_doserror(req, ERRDOS, ERRnosuchshare);
753 END_PROFILE(SMBtconX);
761 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
762 &client_devicetype, p,
763 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
765 if (client_devicetype == NULL) {
766 data_blob_clear_free(&password);
767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
768 END_PROFILE(SMBtconX);
772 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
774 conn = make_connection(sconn, service, password, client_devicetype,
775 req->vuid, &nt_status);
778 data_blob_clear_free(&password);
781 reply_nterror(req, nt_status);
782 END_PROFILE(SMBtconX);
787 server_devicetype = "IPC";
788 else if ( IS_PRINT(conn) )
789 server_devicetype = "LPT1:";
791 server_devicetype = "A:";
793 if (Protocol < PROTOCOL_NT1) {
794 reply_outbuf(req, 2, 0);
795 if (message_push_string(&req->outbuf, server_devicetype,
796 STR_TERMINATE|STR_ASCII) == -1) {
797 reply_nterror(req, NT_STATUS_NO_MEMORY);
798 END_PROFILE(SMBtconX);
802 /* NT sets the fstype of IPC$ to the null string */
803 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
805 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
806 /* Return permissions. */
810 reply_outbuf(req, 7, 0);
813 perm1 = FILE_ALL_ACCESS;
814 perm2 = FILE_ALL_ACCESS;
816 perm1 = CAN_WRITE(conn) ?
821 SIVAL(req->outbuf, smb_vwv3, perm1);
822 SIVAL(req->outbuf, smb_vwv5, perm2);
824 reply_outbuf(req, 3, 0);
827 if ((message_push_string(&req->outbuf, server_devicetype,
828 STR_TERMINATE|STR_ASCII) == -1)
829 || (message_push_string(&req->outbuf, fstype,
830 STR_TERMINATE) == -1)) {
831 reply_nterror(req, NT_STATUS_NO_MEMORY);
832 END_PROFILE(SMBtconX);
836 /* what does setting this bit do? It is set by NT4 and
837 may affect the ability to autorun mounted cdroms */
838 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
839 (lp_csc_policy(SNUM(conn)) << 2));
841 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
842 DEBUG(2,("Serving %s as a Dfs root\n",
843 lp_servicename(SNUM(conn)) ));
844 SSVAL(req->outbuf, smb_vwv2,
845 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
850 DEBUG(3,("tconX service=%s \n",
853 /* set the incoming and outgoing tid to the just created one */
854 SSVAL(req->inbuf,smb_tid,conn->cnum);
855 SSVAL(req->outbuf,smb_tid,conn->cnum);
857 END_PROFILE(SMBtconX);
859 req->tid = conn->cnum;
864 /****************************************************************************
865 Reply to an unknown type.
866 ****************************************************************************/
868 void reply_unknown_new(struct smb_request *req, uint8 type)
870 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
871 smb_fn_name(type), type, type));
872 reply_doserror(req, ERRSRV, ERRunknownsmb);
876 /****************************************************************************
878 conn POINTER CAN BE NULL HERE !
879 ****************************************************************************/
881 void reply_ioctl(struct smb_request *req)
883 connection_struct *conn = req->conn;
890 START_PROFILE(SMBioctl);
893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
894 END_PROFILE(SMBioctl);
898 device = SVAL(req->vwv+1, 0);
899 function = SVAL(req->vwv+2, 0);
900 ioctl_code = (device << 16) + function;
902 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
904 switch (ioctl_code) {
905 case IOCTL_QUERY_JOB_INFO:
909 reply_doserror(req, ERRSRV, ERRnosupport);
910 END_PROFILE(SMBioctl);
914 reply_outbuf(req, 8, replysize+1);
915 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
916 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
917 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
918 p = smb_buf(req->outbuf);
919 memset(p, '\0', replysize+1); /* valgrind-safe. */
920 p += 1; /* Allow for alignment */
922 switch (ioctl_code) {
923 case IOCTL_QUERY_JOB_INFO:
925 files_struct *fsp = file_fsp(
926 req, SVAL(req->vwv+0, 0));
928 reply_doserror(req, ERRDOS, ERRbadfid);
929 END_PROFILE(SMBioctl);
932 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
933 srvstr_push((char *)req->outbuf, req->flags2, p+2,
935 STR_TERMINATE|STR_ASCII);
937 srvstr_push((char *)req->outbuf, req->flags2,
938 p+18, lp_servicename(SNUM(conn)),
939 13, STR_TERMINATE|STR_ASCII);
947 END_PROFILE(SMBioctl);
951 /****************************************************************************
952 Strange checkpath NTSTATUS mapping.
953 ****************************************************************************/
955 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
957 /* Strange DOS error code semantics only for checkpath... */
958 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
959 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
960 /* We need to map to ERRbadpath */
961 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
967 /****************************************************************************
968 Reply to a checkpath.
969 ****************************************************************************/
971 void reply_checkpath(struct smb_request *req)
973 connection_struct *conn = req->conn;
974 struct smb_filename *smb_fname = NULL;
977 TALLOC_CTX *ctx = talloc_tos();
979 START_PROFILE(SMBcheckpath);
981 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
982 STR_TERMINATE, &status);
984 if (!NT_STATUS_IS_OK(status)) {
985 status = map_checkpath_error(req->flags2, status);
986 reply_nterror(req, status);
987 END_PROFILE(SMBcheckpath);
991 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
993 status = filename_convert(ctx,
995 req->flags2 & FLAGS2_DFS_PATHNAMES,
1000 if (!NT_STATUS_IS_OK(status)) {
1001 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1002 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1003 ERRSRV, ERRbadpath);
1004 END_PROFILE(SMBcheckpath);
1010 if (!VALID_STAT(smb_fname->st) &&
1011 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1012 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1013 smb_fname_str_dbg(smb_fname), strerror(errno)));
1014 status = map_nt_error_from_unix(errno);
1018 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1019 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1020 ERRDOS, ERRbadpath);
1024 reply_outbuf(req, 0, 0);
1027 /* We special case this - as when a Windows machine
1028 is parsing a path is steps through the components
1029 one at a time - if a component fails it expects
1030 ERRbadpath, not ERRbadfile.
1032 status = map_checkpath_error(req->flags2, status);
1033 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1035 * Windows returns different error codes if
1036 * the parent directory is valid but not the
1037 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1038 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1039 * if the path is invalid.
1041 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1042 ERRDOS, ERRbadpath);
1046 reply_nterror(req, status);
1049 TALLOC_FREE(smb_fname);
1050 END_PROFILE(SMBcheckpath);
1054 /****************************************************************************
1056 ****************************************************************************/
1058 void reply_getatr(struct smb_request *req)
1060 connection_struct *conn = req->conn;
1061 struct smb_filename *smb_fname = NULL;
1068 TALLOC_CTX *ctx = talloc_tos();
1069 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1071 START_PROFILE(SMBgetatr);
1073 p = (const char *)req->buf + 1;
1074 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 reply_nterror(req, status);
1080 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1081 under WfWg - weird! */
1082 if (*fname == '\0') {
1083 mode = aHIDDEN | aDIR;
1084 if (!CAN_WRITE(conn)) {
1090 status = filename_convert(ctx,
1092 req->flags2 & FLAGS2_DFS_PATHNAMES,
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1099 ERRSRV, ERRbadpath);
1102 reply_nterror(req, status);
1105 if (!VALID_STAT(smb_fname->st) &&
1106 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1107 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1108 smb_fname_str_dbg(smb_fname),
1110 reply_nterror(req, map_nt_error_from_unix(errno));
1114 mode = dos_mode(conn, smb_fname);
1115 size = smb_fname->st.st_ex_size;
1117 if (ask_sharemode) {
1118 struct timespec write_time_ts;
1119 struct file_id fileid;
1121 ZERO_STRUCT(write_time_ts);
1122 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1123 get_file_infos(fileid, NULL, &write_time_ts);
1124 if (!null_timespec(write_time_ts)) {
1125 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1129 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1135 reply_outbuf(req, 10, 0);
1137 SSVAL(req->outbuf,smb_vwv0,mode);
1138 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1139 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1141 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1143 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1145 if (Protocol >= PROTOCOL_NT1) {
1146 SSVAL(req->outbuf, smb_flg2,
1147 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1150 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1151 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1154 TALLOC_FREE(smb_fname);
1156 END_PROFILE(SMBgetatr);
1160 /****************************************************************************
1162 ****************************************************************************/
1164 void reply_setatr(struct smb_request *req)
1166 struct smb_file_time ft;
1167 connection_struct *conn = req->conn;
1168 struct smb_filename *smb_fname = NULL;
1174 TALLOC_CTX *ctx = talloc_tos();
1176 START_PROFILE(SMBsetatr);
1181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1185 p = (const char *)req->buf + 1;
1186 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1187 if (!NT_STATUS_IS_OK(status)) {
1188 reply_nterror(req, status);
1192 status = filename_convert(ctx,
1194 req->flags2 & FLAGS2_DFS_PATHNAMES,
1198 if (!NT_STATUS_IS_OK(status)) {
1199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1200 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1201 ERRSRV, ERRbadpath);
1204 reply_nterror(req, status);
1208 if (smb_fname->base_name[0] == '.' &&
1209 smb_fname->base_name[1] == '\0') {
1211 * Not sure here is the right place to catch this
1212 * condition. Might be moved to somewhere else later -- vl
1214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 mode = SVAL(req->vwv+0, 0);
1219 mtime = srv_make_unix_date3(req->vwv+1);
1221 ft.mtime = convert_time_t_to_timespec(mtime);
1222 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 reply_nterror(req, status);
1228 if (mode != FILE_ATTRIBUTE_NORMAL) {
1229 if (VALID_STAT_OF_DIR(smb_fname->st))
1234 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1236 reply_nterror(req, map_nt_error_from_unix(errno));
1241 reply_outbuf(req, 0, 0);
1243 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1246 TALLOC_FREE(smb_fname);
1247 END_PROFILE(SMBsetatr);
1251 /****************************************************************************
1253 ****************************************************************************/
1255 void reply_dskattr(struct smb_request *req)
1257 connection_struct *conn = req->conn;
1258 uint64_t dfree,dsize,bsize;
1259 START_PROFILE(SMBdskattr);
1261 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1262 reply_nterror(req, map_nt_error_from_unix(errno));
1263 END_PROFILE(SMBdskattr);
1267 reply_outbuf(req, 5, 0);
1269 if (Protocol <= PROTOCOL_LANMAN2) {
1270 double total_space, free_space;
1271 /* we need to scale this to a number that DOS6 can handle. We
1272 use floating point so we can handle large drives on systems
1273 that don't have 64 bit integers
1275 we end up displaying a maximum of 2G to DOS systems
1277 total_space = dsize * (double)bsize;
1278 free_space = dfree * (double)bsize;
1280 dsize = (uint64_t)((total_space+63*512) / (64*512));
1281 dfree = (uint64_t)((free_space+63*512) / (64*512));
1283 if (dsize > 0xFFFF) dsize = 0xFFFF;
1284 if (dfree > 0xFFFF) dfree = 0xFFFF;
1286 SSVAL(req->outbuf,smb_vwv0,dsize);
1287 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1288 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1289 SSVAL(req->outbuf,smb_vwv3,dfree);
1291 SSVAL(req->outbuf,smb_vwv0,dsize);
1292 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1293 SSVAL(req->outbuf,smb_vwv2,512);
1294 SSVAL(req->outbuf,smb_vwv3,dfree);
1297 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1299 END_PROFILE(SMBdskattr);
1304 * Utility function to split the filename from the directory.
1306 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1307 char **fname_dir_out,
1308 char **fname_mask_out)
1310 const char *p = NULL;
1311 char *fname_dir = NULL;
1312 char *fname_mask = NULL;
1314 p = strrchr_m(fname_in, '/');
1316 fname_dir = talloc_strdup(ctx, ".");
1317 fname_mask = talloc_strdup(ctx, fname_in);
1319 fname_dir = talloc_strndup(ctx, fname_in,
1320 PTR_DIFF(p, fname_in));
1321 fname_mask = talloc_strdup(ctx, p+1);
1324 if (!fname_dir || !fname_mask) {
1325 TALLOC_FREE(fname_dir);
1326 TALLOC_FREE(fname_mask);
1327 return NT_STATUS_NO_MEMORY;
1330 *fname_dir_out = fname_dir;
1331 *fname_mask_out = fname_mask;
1332 return NT_STATUS_OK;
1335 /****************************************************************************
1337 Can be called from SMBsearch, SMBffirst or SMBfunique.
1338 ****************************************************************************/
1340 void reply_search(struct smb_request *req)
1342 connection_struct *conn = req->conn;
1344 const char *mask = NULL;
1345 char *directory = NULL;
1349 struct timespec date;
1351 unsigned int numentries = 0;
1352 unsigned int maxentries = 0;
1353 bool finished = False;
1358 bool check_descend = False;
1359 bool expect_close = False;
1361 bool mask_contains_wcard = False;
1362 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1363 TALLOC_CTX *ctx = talloc_tos();
1364 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1366 START_PROFILE(SMBsearch);
1369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1370 END_PROFILE(SMBsearch);
1374 if (lp_posix_pathnames()) {
1375 reply_unknown_new(req, req->cmd);
1376 END_PROFILE(SMBsearch);
1380 /* If we were called as SMBffirst then we must expect close. */
1381 if(req->cmd == SMBffirst) {
1382 expect_close = True;
1385 reply_outbuf(req, 1, 3);
1386 maxentries = SVAL(req->vwv+0, 0);
1387 dirtype = SVAL(req->vwv+1, 0);
1388 p = (const char *)req->buf + 1;
1389 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1390 &nt_status, &mask_contains_wcard);
1391 if (!NT_STATUS_IS_OK(nt_status)) {
1392 reply_nterror(req, nt_status);
1393 END_PROFILE(SMBsearch);
1398 status_len = SVAL(p, 0);
1401 /* dirtype &= ~aDIR; */
1403 if (status_len == 0) {
1404 struct smb_filename *smb_fname = NULL;
1406 nt_status = resolve_dfspath_wcard(ctx, conn,
1407 req->flags2 & FLAGS2_DFS_PATHNAMES,
1410 &mask_contains_wcard);
1411 if (!NT_STATUS_IS_OK(nt_status)) {
1412 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1413 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1414 ERRSRV, ERRbadpath);
1415 END_PROFILE(SMBsearch);
1418 reply_nterror(req, nt_status);
1419 END_PROFILE(SMBsearch);
1423 nt_status = unix_convert(ctx, conn, path, &smb_fname,
1424 UCF_ALLOW_WCARD_LCOMP);
1425 if (!NT_STATUS_IS_OK(nt_status)) {
1426 reply_nterror(req, nt_status);
1427 END_PROFILE(SMBsearch);
1431 nt_status = get_full_smb_filename(ctx, smb_fname, &directory);
1432 TALLOC_FREE(smb_fname);
1433 if (!NT_STATUS_IS_OK(nt_status)) {
1434 reply_nterror(req, nt_status);
1435 END_PROFILE(SMBsearch);
1439 nt_status = check_name(conn, directory);
1440 if (!NT_STATUS_IS_OK(nt_status)) {
1441 reply_nterror(req, nt_status);
1442 END_PROFILE(SMBsearch);
1446 p = strrchr_m(directory,'/');
1447 if ((p != NULL) && (*directory != '/')) {
1449 directory = talloc_strndup(ctx, directory,
1450 PTR_DIFF(p, directory));
1453 directory = talloc_strdup(ctx,".");
1457 reply_nterror(req, NT_STATUS_NO_MEMORY);
1458 END_PROFILE(SMBsearch);
1462 memset((char *)status,'\0',21);
1463 SCVAL(status,0,(dirtype & 0x1F));
1465 nt_status = dptr_create(conn,
1471 mask_contains_wcard,
1474 if (!NT_STATUS_IS_OK(nt_status)) {
1475 reply_nterror(req, nt_status);
1476 END_PROFILE(SMBsearch);
1479 dptr_num = dptr_dnum(conn->dirptr);
1483 memcpy(status,p,21);
1484 status_dirtype = CVAL(status,0) & 0x1F;
1485 if (status_dirtype != (dirtype & 0x1F)) {
1486 dirtype = status_dirtype;
1489 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1490 if (!conn->dirptr) {
1493 string_set(&conn->dirpath,dptr_path(dptr_num));
1494 mask = dptr_wcard(dptr_num);
1499 * For a 'continue' search we have no string. So
1500 * check from the initial saved string.
1502 mask_contains_wcard = ms_has_wild(mask);
1503 dirtype = dptr_attr(dptr_num);
1506 DEBUG(4,("dptr_num is %d\n",dptr_num));
1508 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1509 dptr_init_search_op(conn->dirptr);
1511 if ((dirtype&0x1F) == aVOLID) {
1512 char buf[DIR_STRUCT_SIZE];
1513 memcpy(buf,status,21);
1514 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1515 0,aVOLID,0,!allow_long_path_components)) {
1516 reply_nterror(req, NT_STATUS_NO_MEMORY);
1517 END_PROFILE(SMBsearch);
1520 dptr_fill(buf+12,dptr_num);
1521 if (dptr_zero(buf+12) && (status_len==0)) {
1526 if (message_push_blob(&req->outbuf,
1527 data_blob_const(buf, sizeof(buf)))
1529 reply_nterror(req, NT_STATUS_NO_MEMORY);
1530 END_PROFILE(SMBsearch);
1538 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1542 conn->dirpath,lp_dontdescend(SNUM(conn))));
1543 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1544 check_descend = True;
1547 for (i=numentries;(i<maxentries) && !finished;i++) {
1548 finished = !get_dir_entry(ctx,
1559 char buf[DIR_STRUCT_SIZE];
1560 memcpy(buf,status,21);
1561 if (!make_dir_struct(ctx,
1567 convert_timespec_to_time_t(date),
1568 !allow_long_path_components)) {
1569 reply_nterror(req, NT_STATUS_NO_MEMORY);
1570 END_PROFILE(SMBsearch);
1573 if (!dptr_fill(buf+12,dptr_num)) {
1576 if (message_push_blob(&req->outbuf,
1577 data_blob_const(buf, sizeof(buf)))
1579 reply_nterror(req, NT_STATUS_NO_MEMORY);
1580 END_PROFILE(SMBsearch);
1590 /* If we were called as SMBffirst with smb_search_id == NULL
1591 and no entries were found then return error and close dirptr
1594 if (numentries == 0) {
1595 dptr_close(&dptr_num);
1596 } else if(expect_close && status_len == 0) {
1597 /* Close the dptr - we know it's gone */
1598 dptr_close(&dptr_num);
1601 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1602 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1603 dptr_close(&dptr_num);
1606 if ((numentries == 0) && !mask_contains_wcard) {
1607 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1608 END_PROFILE(SMBsearch);
1612 SSVAL(req->outbuf,smb_vwv0,numentries);
1613 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1614 SCVAL(smb_buf(req->outbuf),0,5);
1615 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1617 /* The replies here are never long name. */
1618 SSVAL(req->outbuf, smb_flg2,
1619 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1620 if (!allow_long_path_components) {
1621 SSVAL(req->outbuf, smb_flg2,
1622 SVAL(req->outbuf, smb_flg2)
1623 & (~FLAGS2_LONG_PATH_COMPONENTS));
1626 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1627 SSVAL(req->outbuf, smb_flg2,
1628 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1631 directory = dptr_path(dptr_num);
1634 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1635 smb_fn_name(req->cmd),
1637 directory ? directory : "./",
1642 END_PROFILE(SMBsearch);
1646 /****************************************************************************
1647 Reply to a fclose (stop directory search).
1648 ****************************************************************************/
1650 void reply_fclose(struct smb_request *req)
1658 bool path_contains_wcard = False;
1659 TALLOC_CTX *ctx = talloc_tos();
1661 START_PROFILE(SMBfclose);
1663 if (lp_posix_pathnames()) {
1664 reply_unknown_new(req, req->cmd);
1665 END_PROFILE(SMBfclose);
1669 p = (const char *)req->buf + 1;
1670 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1671 &err, &path_contains_wcard);
1672 if (!NT_STATUS_IS_OK(err)) {
1673 reply_nterror(req, err);
1674 END_PROFILE(SMBfclose);
1678 status_len = SVAL(p,0);
1681 if (status_len == 0) {
1682 reply_doserror(req, ERRSRV, ERRsrverror);
1683 END_PROFILE(SMBfclose);
1687 memcpy(status,p,21);
1689 if(dptr_fetch(status+12,&dptr_num)) {
1690 /* Close the dptr - we know it's gone */
1691 dptr_close(&dptr_num);
1694 reply_outbuf(req, 1, 0);
1695 SSVAL(req->outbuf,smb_vwv0,0);
1697 DEBUG(3,("search close\n"));
1699 END_PROFILE(SMBfclose);
1703 /****************************************************************************
1705 ****************************************************************************/
1707 void reply_open(struct smb_request *req)
1709 connection_struct *conn = req->conn;
1710 struct smb_filename *smb_fname = NULL;
1722 uint32 create_disposition;
1723 uint32 create_options = 0;
1725 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1726 TALLOC_CTX *ctx = talloc_tos();
1728 START_PROFILE(SMBopen);
1731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1735 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1736 deny_mode = SVAL(req->vwv+0, 0);
1737 dos_attr = SVAL(req->vwv+1, 0);
1739 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1740 STR_TERMINATE, &status);
1741 if (!NT_STATUS_IS_OK(status)) {
1742 reply_nterror(req, status);
1746 status = filename_convert(ctx,
1748 req->flags2 & FLAGS2_DFS_PATHNAMES,
1752 if (!NT_STATUS_IS_OK(status)) {
1753 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1754 reply_botherror(req,
1755 NT_STATUS_PATH_NOT_COVERED,
1756 ERRSRV, ERRbadpath);
1759 reply_nterror(req, status);
1763 if (!map_open_params_to_ntcreate(
1764 smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN,
1765 &access_mask, &share_mode, &create_disposition,
1767 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1771 status = SMB_VFS_CREATE_FILE(
1774 0, /* root_dir_fid */
1775 smb_fname, /* fname */
1776 access_mask, /* access_mask */
1777 share_mode, /* share_access */
1778 create_disposition, /* create_disposition*/
1779 create_options, /* create_options */
1780 dos_attr, /* file_attributes */
1781 oplock_request, /* oplock_request */
1782 0, /* allocation_size */
1788 if (!NT_STATUS_IS_OK(status)) {
1789 if (open_was_deferred(req->mid)) {
1790 /* We have re-scheduled this call. */
1793 reply_openerror(req, status);
1797 size = smb_fname->st.st_ex_size;
1798 fattr = dos_mode(conn, smb_fname);
1800 /* Deal with other possible opens having a modified
1802 if (ask_sharemode) {
1803 struct timespec write_time_ts;
1805 ZERO_STRUCT(write_time_ts);
1806 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1807 if (!null_timespec(write_time_ts)) {
1808 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1812 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1815 DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
1816 close_file(req, fsp, ERROR_CLOSE);
1817 reply_doserror(req, ERRDOS,ERRnoaccess);
1821 reply_outbuf(req, 7, 0);
1822 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1823 SSVAL(req->outbuf,smb_vwv1,fattr);
1824 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1825 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1827 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1829 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1830 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1832 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1833 SCVAL(req->outbuf,smb_flg,
1834 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1837 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1838 SCVAL(req->outbuf,smb_flg,
1839 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1842 TALLOC_FREE(smb_fname);
1843 END_PROFILE(SMBopen);
1847 /****************************************************************************
1848 Reply to an open and X.
1849 ****************************************************************************/
1851 void reply_open_and_X(struct smb_request *req)
1853 connection_struct *conn = req->conn;
1854 struct smb_filename *smb_fname = NULL;
1859 /* Breakout the oplock request bits so we can set the
1860 reply bits separately. */
1861 int ex_oplock_request;
1862 int core_oplock_request;
1865 int smb_sattr = SVAL(req->vwv+4, 0);
1866 uint32 smb_time = make_unix_date3(req->vwv+6);
1874 uint64_t allocation_size;
1875 ssize_t retval = -1;
1878 uint32 create_disposition;
1879 uint32 create_options = 0;
1880 TALLOC_CTX *ctx = talloc_tos();
1882 START_PROFILE(SMBopenX);
1884 if (req->wct < 15) {
1885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1889 open_flags = SVAL(req->vwv+2, 0);
1890 deny_mode = SVAL(req->vwv+3, 0);
1891 smb_attr = SVAL(req->vwv+5, 0);
1892 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1893 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1894 oplock_request = ex_oplock_request | core_oplock_request;
1895 smb_ofun = SVAL(req->vwv+8, 0);
1896 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1898 /* If it's an IPC, pass off the pipe handler. */
1900 if (lp_nt_pipe_support()) {
1901 reply_open_pipe_and_X(conn, req);
1903 reply_doserror(req, ERRSRV, ERRaccess);
1908 /* XXXX we need to handle passed times, sattr and flags */
1909 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1910 STR_TERMINATE, &status);
1911 if (!NT_STATUS_IS_OK(status)) {
1912 reply_nterror(req, status);
1916 status = filename_convert(ctx,
1918 req->flags2 & FLAGS2_DFS_PATHNAMES,
1922 if (!NT_STATUS_IS_OK(status)) {
1923 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1924 reply_botherror(req,
1925 NT_STATUS_PATH_NOT_COVERED,
1926 ERRSRV, ERRbadpath);
1929 reply_nterror(req, status);
1933 if (!map_open_params_to_ntcreate(
1934 smb_fname->base_name, deny_mode, smb_ofun, &access_mask,
1935 &share_mode, &create_disposition, &create_options)) {
1936 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1940 status = SMB_VFS_CREATE_FILE(
1943 0, /* root_dir_fid */
1944 smb_fname, /* fname */
1945 access_mask, /* access_mask */
1946 share_mode, /* share_access */
1947 create_disposition, /* create_disposition*/
1948 create_options, /* create_options */
1949 smb_attr, /* file_attributes */
1950 oplock_request, /* oplock_request */
1951 0, /* allocation_size */
1955 &smb_action); /* pinfo */
1957 if (!NT_STATUS_IS_OK(status)) {
1958 if (open_was_deferred(req->mid)) {
1959 /* We have re-scheduled this call. */
1962 reply_openerror(req, status);
1966 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1967 if the file is truncated or created. */
1968 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1969 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1970 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1971 close_file(req, fsp, ERROR_CLOSE);
1972 reply_nterror(req, NT_STATUS_DISK_FULL);
1975 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1977 close_file(req, fsp, ERROR_CLOSE);
1978 reply_nterror(req, NT_STATUS_DISK_FULL);
1981 smb_fname->st.st_ex_size =
1982 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1985 fattr = dos_mode(conn, smb_fname);
1986 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1988 close_file(req, fsp, ERROR_CLOSE);
1989 reply_doserror(req, ERRDOS, ERRnoaccess);
1993 /* If the caller set the extended oplock request bit
1994 and we granted one (by whatever means) - set the
1995 correct bit for extended oplock reply.
1998 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1999 smb_action |= EXTENDED_OPLOCK_GRANTED;
2002 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2003 smb_action |= EXTENDED_OPLOCK_GRANTED;
2006 /* If the caller set the core oplock request bit
2007 and we granted one (by whatever means) - set the
2008 correct bit for core oplock reply.
2011 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2012 reply_outbuf(req, 19, 0);
2014 reply_outbuf(req, 15, 0);
2017 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018 SCVAL(req->outbuf, smb_flg,
2019 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2022 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2023 SCVAL(req->outbuf, smb_flg,
2024 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2027 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2028 SSVAL(req->outbuf,smb_vwv3,fattr);
2029 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2030 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2032 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2034 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2035 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2036 SSVAL(req->outbuf,smb_vwv11,smb_action);
2038 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2039 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2044 TALLOC_FREE(smb_fname);
2045 END_PROFILE(SMBopenX);
2049 /****************************************************************************
2050 Reply to a SMBulogoffX.
2051 ****************************************************************************/
2053 void reply_ulogoffX(struct smb_request *req)
2055 struct smbd_server_connection *sconn = smbd_server_conn;
2058 START_PROFILE(SMBulogoffX);
2060 vuser = get_valid_user_struct(sconn, req->vuid);
2063 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2067 /* in user level security we are supposed to close any files
2068 open by this user */
2069 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2070 file_close_user(req->vuid);
2073 invalidate_vuid(sconn, req->vuid);
2075 reply_outbuf(req, 2, 0);
2077 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2079 END_PROFILE(SMBulogoffX);
2080 req->vuid = UID_FIELD_INVALID;
2084 /****************************************************************************
2085 Reply to a mknew or a create.
2086 ****************************************************************************/
2088 void reply_mknew(struct smb_request *req)
2090 connection_struct *conn = req->conn;
2091 struct smb_filename *smb_fname = NULL;
2094 struct smb_file_time ft;
2096 int oplock_request = 0;
2098 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2099 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2100 uint32 create_disposition;
2101 uint32 create_options = 0;
2102 TALLOC_CTX *ctx = talloc_tos();
2104 START_PROFILE(SMBcreate);
2108 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2112 fattr = SVAL(req->vwv+0, 0);
2113 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2116 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2118 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2119 STR_TERMINATE, &status);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 reply_nterror(req, status);
2125 status = filename_convert(ctx,
2127 req->flags2 & FLAGS2_DFS_PATHNAMES,
2131 if (!NT_STATUS_IS_OK(status)) {
2132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2133 reply_botherror(req,
2134 NT_STATUS_PATH_NOT_COVERED,
2135 ERRSRV, ERRbadpath);
2138 reply_nterror(req, status);
2142 if (fattr & aVOLID) {
2143 DEBUG(0,("Attempt to create file (%s) with volid set - "
2144 "please report this\n",
2145 smb_fname_str_dbg(smb_fname)));
2148 if(req->cmd == SMBmknew) {
2149 /* We should fail if file exists. */
2150 create_disposition = FILE_CREATE;
2152 /* Create if file doesn't exist, truncate if it does. */
2153 create_disposition = FILE_OVERWRITE_IF;
2156 status = SMB_VFS_CREATE_FILE(
2159 0, /* root_dir_fid */
2160 smb_fname, /* fname */
2161 access_mask, /* access_mask */
2162 share_mode, /* share_access */
2163 create_disposition, /* create_disposition*/
2164 create_options, /* create_options */
2165 fattr, /* file_attributes */
2166 oplock_request, /* oplock_request */
2167 0, /* allocation_size */
2173 if (!NT_STATUS_IS_OK(status)) {
2174 if (open_was_deferred(req->mid)) {
2175 /* We have re-scheduled this call. */
2178 reply_openerror(req, status);
2182 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2183 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2184 if (!NT_STATUS_IS_OK(status)) {
2185 END_PROFILE(SMBcreate);
2189 reply_outbuf(req, 1, 0);
2190 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2192 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2193 SCVAL(req->outbuf,smb_flg,
2194 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2197 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2198 SCVAL(req->outbuf,smb_flg,
2199 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2202 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2203 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2204 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2205 (unsigned int)fattr));
2208 TALLOC_FREE(smb_fname);
2209 END_PROFILE(SMBcreate);
2213 /****************************************************************************
2214 Reply to a create temporary file.
2215 ****************************************************************************/
2217 void reply_ctemp(struct smb_request *req)
2219 connection_struct *conn = req->conn;
2220 struct smb_filename *smb_fname = NULL;
2228 TALLOC_CTX *ctx = talloc_tos();
2230 START_PROFILE(SMBctemp);
2233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2237 fattr = SVAL(req->vwv+0, 0);
2238 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2240 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2241 STR_TERMINATE, &status);
2242 if (!NT_STATUS_IS_OK(status)) {
2243 reply_nterror(req, status);
2247 fname = talloc_asprintf(ctx,
2251 fname = talloc_strdup(ctx, "TMXXXXXX");
2255 reply_nterror(req, NT_STATUS_NO_MEMORY);
2259 status = filename_convert(ctx, conn,
2260 req->flags2 & FLAGS2_DFS_PATHNAMES,
2264 if (!NT_STATUS_IS_OK(status)) {
2265 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2266 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2267 ERRSRV, ERRbadpath);
2270 reply_nterror(req, status);
2274 tmpfd = mkstemp(smb_fname->base_name);
2276 reply_nterror(req, map_nt_error_from_unix(errno));
2280 SMB_VFS_STAT(conn, smb_fname);
2282 /* We should fail if file does not exist. */
2283 status = SMB_VFS_CREATE_FILE(
2286 0, /* root_dir_fid */
2287 smb_fname, /* fname */
2288 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2289 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2290 FILE_OPEN, /* create_disposition*/
2291 0, /* create_options */
2292 fattr, /* file_attributes */
2293 oplock_request, /* oplock_request */
2294 0, /* allocation_size */
2300 /* close fd from mkstemp() */
2303 if (!NT_STATUS_IS_OK(status)) {
2304 if (open_was_deferred(req->mid)) {
2305 /* We have re-scheduled this call. */
2308 reply_openerror(req, status);
2312 reply_outbuf(req, 1, 0);
2313 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2315 /* the returned filename is relative to the directory */
2316 s = strrchr_m(fsp->fsp_name, '/');
2324 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2325 thing in the byte section. JRA */
2326 SSVALS(p, 0, -1); /* what is this? not in spec */
2328 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2330 reply_nterror(req, NT_STATUS_NO_MEMORY);
2334 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2335 SCVAL(req->outbuf, smb_flg,
2336 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2339 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2340 SCVAL(req->outbuf, smb_flg,
2341 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2344 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
2345 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
2346 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2348 TALLOC_FREE(smb_fname);
2349 END_PROFILE(SMBctemp);
2353 /*******************************************************************
2354 Check if a user is allowed to rename a file.
2355 ********************************************************************/
2357 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2358 uint16 dirtype, SMB_STRUCT_STAT *pst)
2360 struct smb_filename *smb_fname = NULL;
2364 if (!CAN_WRITE(conn)) {
2365 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2368 status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name,
2370 if (!NT_STATUS_IS_OK(status)) {
2374 fmode = dos_mode(conn, smb_fname);
2375 TALLOC_FREE(smb_fname);
2376 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2377 return NT_STATUS_NO_SUCH_FILE;
2380 if (S_ISDIR(pst->st_ex_mode)) {
2381 if (fsp->posix_open) {
2382 return NT_STATUS_OK;
2385 /* If no pathnames are open below this
2386 directory, allow the rename. */
2388 if (file_find_subpath(fsp)) {
2389 return NT_STATUS_ACCESS_DENIED;
2391 return NT_STATUS_OK;
2394 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2395 return NT_STATUS_OK;
2398 return NT_STATUS_ACCESS_DENIED;
2401 /*******************************************************************
2402 * unlink a file with all relevant access checks
2403 *******************************************************************/
2405 static NTSTATUS do_unlink(connection_struct *conn,
2406 struct smb_request *req,
2407 struct smb_filename *smb_fname,
2412 uint32 dirtype_orig = dirtype;
2415 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2416 smb_fname_str_dbg(smb_fname),
2419 if (!CAN_WRITE(conn)) {
2420 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2423 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2424 return map_nt_error_from_unix(errno);
2427 fattr = dos_mode(conn, smb_fname);
2429 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2430 dirtype = aDIR|aARCH|aRONLY;
2433 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2435 return NT_STATUS_NO_SUCH_FILE;
2438 if (!dir_check_ftype(conn, fattr, dirtype)) {
2440 return NT_STATUS_FILE_IS_A_DIRECTORY;
2442 return NT_STATUS_NO_SUCH_FILE;
2445 if (dirtype_orig & 0x8000) {
2446 /* These will never be set for POSIX. */
2447 return NT_STATUS_NO_SUCH_FILE;
2451 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2452 return NT_STATUS_FILE_IS_A_DIRECTORY;
2455 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2456 return NT_STATUS_NO_SUCH_FILE;
2459 if (dirtype & 0xFF00) {
2460 /* These will never be set for POSIX. */
2461 return NT_STATUS_NO_SUCH_FILE;
2466 return NT_STATUS_NO_SUCH_FILE;
2469 /* Can't delete a directory. */
2471 return NT_STATUS_FILE_IS_A_DIRECTORY;
2476 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2477 return NT_STATUS_OBJECT_NAME_INVALID;
2478 #endif /* JRATEST */
2480 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2482 On a Windows share, a file with read-only dosmode can be opened with
2483 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2484 fails with NT_STATUS_CANNOT_DELETE error.
2486 This semantic causes a problem that a user can not
2487 rename a file with read-only dosmode on a Samba share
2488 from a Windows command prompt (i.e. cmd.exe, but can rename
2489 from Windows Explorer).
2492 if (!lp_delete_readonly(SNUM(conn))) {
2493 if (fattr & aRONLY) {
2494 return NT_STATUS_CANNOT_DELETE;
2498 /* On open checks the open itself will check the share mode, so
2499 don't do it here as we'll get it wrong. */
2501 status = SMB_VFS_CREATE_FILE
2504 0, /* root_dir_fid */
2505 smb_fname, /* fname */
2506 DELETE_ACCESS, /* access_mask */
2507 FILE_SHARE_NONE, /* share_access */
2508 FILE_OPEN, /* create_disposition*/
2509 FILE_NON_DIRECTORY_FILE, /* create_options */
2510 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2511 0, /* oplock_request */
2512 0, /* allocation_size */
2518 if (!NT_STATUS_IS_OK(status)) {
2519 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2520 nt_errstr(status)));
2524 /* The set is across all open files on this dev/inode pair. */
2525 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2526 close_file(req, fsp, NORMAL_CLOSE);
2527 return NT_STATUS_ACCESS_DENIED;
2530 return close_file(req, fsp, NORMAL_CLOSE);
2533 /****************************************************************************
2534 The guts of the unlink command, split out so it may be called by the NT SMB
2536 ****************************************************************************/
2538 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2539 uint32 dirtype, const char *name_in, bool has_wild)
2541 struct smb_filename *smb_fname = NULL;
2542 char *fname_dir = NULL;
2543 char *fname_mask = NULL;
2545 NTSTATUS status = NT_STATUS_OK;
2546 TALLOC_CTX *ctx = talloc_tos();
2548 status = unix_convert(ctx, conn, name_in, &smb_fname,
2549 has_wild ? UCF_ALLOW_WCARD_LCOMP : 0);
2550 if (!NT_STATUS_IS_OK(status)) {
2554 /* Split up the directory from the filename/mask. */
2555 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2556 &fname_dir, &fname_mask);
2557 if (!NT_STATUS_IS_OK(status)) {
2562 * We should only check the mangled cache
2563 * here if unix_convert failed. This means
2564 * that the path in 'mask' doesn't exist
2565 * on the file system and so we need to look
2566 * for a possible mangle. This patch from
2567 * Tine Smukavec <valentin.smukavec@hermes.si>.
2570 if (!VALID_STAT(smb_fname->st) &&
2571 mangle_is_mangled(fname_mask, conn->params)) {
2572 char *new_mask = NULL;
2573 mangle_lookup_name_from_8_3(ctx, fname_mask,
2574 &new_mask, conn->params);
2576 TALLOC_FREE(fname_mask);
2577 fname_mask = new_mask;
2584 * Only one file needs to be unlinked. Append the mask back
2585 * onto the directory.
2587 TALLOC_FREE(smb_fname->base_name);
2588 smb_fname->base_name = talloc_asprintf(smb_fname,
2592 if (!smb_fname->base_name) {
2593 status = NT_STATUS_NO_MEMORY;
2597 dirtype = FILE_ATTRIBUTE_NORMAL;
2600 status = check_name(conn, smb_fname->base_name);
2601 if (!NT_STATUS_IS_OK(status)) {
2605 status = do_unlink(conn, req, smb_fname, dirtype);
2606 if (!NT_STATUS_IS_OK(status)) {
2612 struct smb_Dir *dir_hnd = NULL;
2616 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2617 status = NT_STATUS_OBJECT_NAME_INVALID;
2621 if (strequal(fname_mask,"????????.???")) {
2622 TALLOC_FREE(fname_mask);
2623 fname_mask = talloc_strdup(ctx, "*");
2625 status = NT_STATUS_NO_MEMORY;
2630 status = check_name(conn, fname_dir);
2631 if (!NT_STATUS_IS_OK(status)) {
2635 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2637 if (dir_hnd == NULL) {
2638 status = map_nt_error_from_unix(errno);
2642 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2643 the pattern matches against the long name, otherwise the short name
2644 We don't implement this yet XXXX
2647 status = NT_STATUS_NO_SUCH_FILE;
2649 while ((dname = ReadDirName(dir_hnd, &offset,
2651 TALLOC_CTX *frame = talloc_stackframe();
2653 if (!is_visible_file(conn, fname_dir, dname,
2654 &smb_fname->st, true)) {
2659 /* Quick check for "." and ".." */
2660 if (ISDOT(dname) || ISDOTDOT(dname)) {
2665 if(!mask_match(dname, fname_mask,
2666 conn->case_sensitive)) {
2671 TALLOC_FREE(smb_fname->base_name);
2672 smb_fname->base_name =
2673 talloc_asprintf(smb_fname, "%s/%s",
2676 if (!smb_fname->base_name) {
2677 TALLOC_FREE(dir_hnd);
2678 status = NT_STATUS_NO_MEMORY;
2683 status = check_name(conn, smb_fname->base_name);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 TALLOC_FREE(dir_hnd);
2690 status = do_unlink(conn, req, smb_fname, dirtype);
2691 if (!NT_STATUS_IS_OK(status)) {
2697 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2698 smb_fname->base_name));
2702 TALLOC_FREE(dir_hnd);
2705 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2706 status = map_nt_error_from_unix(errno);
2710 TALLOC_FREE(smb_fname);
2711 TALLOC_FREE(fname_dir);
2712 TALLOC_FREE(fname_mask);
2716 /****************************************************************************
2718 ****************************************************************************/
2720 void reply_unlink(struct smb_request *req)
2722 connection_struct *conn = req->conn;
2726 bool path_contains_wcard = False;
2727 TALLOC_CTX *ctx = talloc_tos();
2729 START_PROFILE(SMBunlink);
2732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2733 END_PROFILE(SMBunlink);
2737 dirtype = SVAL(req->vwv+0, 0);
2739 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2740 STR_TERMINATE, &status,
2741 &path_contains_wcard);
2742 if (!NT_STATUS_IS_OK(status)) {
2743 reply_nterror(req, status);
2744 END_PROFILE(SMBunlink);
2748 status = resolve_dfspath_wcard(ctx, conn,
2749 req->flags2 & FLAGS2_DFS_PATHNAMES,
2752 &path_contains_wcard);
2753 if (!NT_STATUS_IS_OK(status)) {
2754 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2755 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2756 ERRSRV, ERRbadpath);
2757 END_PROFILE(SMBunlink);
2760 reply_nterror(req, status);
2761 END_PROFILE(SMBunlink);
2765 DEBUG(3,("reply_unlink : %s\n",name));
2767 status = unlink_internals(conn, req, dirtype, name,
2768 path_contains_wcard);
2769 if (!NT_STATUS_IS_OK(status)) {
2770 if (open_was_deferred(req->mid)) {
2771 /* We have re-scheduled this call. */
2772 END_PROFILE(SMBunlink);
2775 reply_nterror(req, status);
2776 END_PROFILE(SMBunlink);
2780 reply_outbuf(req, 0, 0);
2781 END_PROFILE(SMBunlink);
2786 /****************************************************************************
2788 ****************************************************************************/
2790 static void fail_readraw(void)
2792 const char *errstr = talloc_asprintf(talloc_tos(),
2793 "FAIL ! reply_readbraw: socket write fail (%s)",
2798 exit_server_cleanly(errstr);
2801 /****************************************************************************
2802 Fake (read/write) sendfile. Returns -1 on read or write fail.
2803 ****************************************************************************/
2805 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2809 size_t tosend = nread;
2816 bufsize = MIN(nread, 65536);
2818 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2822 while (tosend > 0) {
2826 if (tosend > bufsize) {
2831 ret = read_file(fsp,buf,startpos,cur_read);
2837 /* If we had a short read, fill with zeros. */
2838 if (ret < cur_read) {
2839 memset(buf + ret, '\0', cur_read - ret);
2842 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2847 startpos += cur_read;
2851 return (ssize_t)nread;
2854 #if defined(WITH_SENDFILE)
2855 /****************************************************************************
2856 Deal with the case of sendfile reading less bytes from the file than
2857 requested. Fill with zeros (all we can do).
2858 ****************************************************************************/
2860 static void sendfile_short_send(files_struct *fsp,
2865 #define SHORT_SEND_BUFSIZE 1024
2866 if (nread < headersize) {
2867 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2868 "header for file %s (%s). Terminating\n",
2869 fsp->fsp_name, strerror(errno) ));
2870 exit_server_cleanly("sendfile_short_send failed");
2873 nread -= headersize;
2875 if (nread < smb_maxcnt) {
2876 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2878 exit_server_cleanly("sendfile_short_send: "
2882 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2883 "with zeros !\n", fsp->fsp_name));
2885 while (nread < smb_maxcnt) {
2887 * We asked for the real file size and told sendfile
2888 * to not go beyond the end of the file. But it can
2889 * happen that in between our fstat call and the
2890 * sendfile call the file was truncated. This is very
2891 * bad because we have already announced the larger
2892 * number of bytes to the client.
2894 * The best we can do now is to send 0-bytes, just as
2895 * a read from a hole in a sparse file would do.
2897 * This should happen rarely enough that I don't care
2898 * about efficiency here :-)
2902 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2903 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2904 exit_server_cleanly("sendfile_short_send: "
2905 "write_data failed");
2912 #endif /* defined WITH_SENDFILE */
2914 /****************************************************************************
2915 Return a readbraw error (4 bytes of zero).
2916 ****************************************************************************/
2918 static void reply_readbraw_error(void)
2922 if (write_data(smbd_server_fd(),header,4) != 4) {
2927 /****************************************************************************
2928 Use sendfile in readbraw.
2929 ****************************************************************************/
2931 static void send_file_readbraw(connection_struct *conn,
2932 struct smb_request *req,
2938 char *outbuf = NULL;
2941 #if defined(WITH_SENDFILE)
2943 * We can only use sendfile on a non-chained packet
2944 * but we can use on a non-oplocked file. tridge proved this
2945 * on a train in Germany :-). JRA.
2946 * reply_readbraw has already checked the length.
2949 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2950 (fsp->wcp == NULL) &&
2951 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2952 ssize_t sendfile_read = -1;
2954 DATA_BLOB header_blob;
2956 _smb_setlen(header,nread);
2957 header_blob = data_blob_const(header, 4);
2959 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2960 &header_blob, startpos, nread)) == -1) {
2961 /* Returning ENOSYS means no data at all was sent.
2962 * Do this as a normal read. */
2963 if (errno == ENOSYS) {
2964 goto normal_readbraw;
2968 * Special hack for broken Linux with no working sendfile. If we
2969 * return EINTR we sent the header but not the rest of the data.
2970 * Fake this up by doing read/write calls.
2972 if (errno == EINTR) {
2973 /* Ensure we don't do this again. */
2974 set_use_sendfile(SNUM(conn), False);
2975 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2977 if (fake_sendfile(fsp, startpos, nread) == -1) {
2978 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2979 fsp->fsp_name, strerror(errno) ));
2980 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2985 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2986 fsp->fsp_name, strerror(errno) ));
2987 exit_server_cleanly("send_file_readbraw sendfile failed");
2988 } else if (sendfile_read == 0) {
2990 * Some sendfile implementations return 0 to indicate
2991 * that there was a short read, but nothing was
2992 * actually written to the socket. In this case,
2993 * fallback to the normal read path so the header gets
2994 * the correct byte count.
2996 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2997 "bytes falling back to the normal read: "
2998 "%s\n", fsp->fsp_name));
2999 goto normal_readbraw;
3002 /* Deal with possible short send. */
3003 if (sendfile_read != 4+nread) {
3004 sendfile_short_send(fsp, sendfile_read, 4, nread);
3012 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3014 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3015 (unsigned)(nread+4)));
3016 reply_readbraw_error();
3021 ret = read_file(fsp,outbuf+4,startpos,nread);
3022 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3031 _smb_setlen(outbuf,ret);
3032 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3035 TALLOC_FREE(outbuf);
3038 /****************************************************************************
3039 Reply to a readbraw (core+ protocol).
3040 ****************************************************************************/
3042 void reply_readbraw(struct smb_request *req)
3044 connection_struct *conn = req->conn;
3045 ssize_t maxcount,mincount;
3049 struct lock_struct lock;
3053 START_PROFILE(SMBreadbraw);
3055 if (srv_is_signing_active(smbd_server_conn) ||
3056 is_encrypted_packet(req->inbuf)) {
3057 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3058 "raw reads/writes are disallowed.");
3062 reply_readbraw_error();
3063 END_PROFILE(SMBreadbraw);
3068 * Special check if an oplock break has been issued
3069 * and the readraw request croses on the wire, we must
3070 * return a zero length response here.
3073 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3076 * We have to do a check_fsp by hand here, as
3077 * we must always return 4 zero bytes on error,
3081 if (!fsp || !conn || conn != fsp->conn ||
3082 req->vuid != fsp->vuid ||
3083 fsp->is_directory || fsp->fh->fd == -1) {
3085 * fsp could be NULL here so use the value from the packet. JRA.
3087 DEBUG(3,("reply_readbraw: fnum %d not valid "
3089 (int)SVAL(req->vwv+0, 0)));
3090 reply_readbraw_error();
3091 END_PROFILE(SMBreadbraw);
3095 /* Do a "by hand" version of CHECK_READ. */
3096 if (!(fsp->can_read ||
3097 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3098 (fsp->access_mask & FILE_EXECUTE)))) {
3099 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3100 (int)SVAL(req->vwv+0, 0)));
3101 reply_readbraw_error();
3102 END_PROFILE(SMBreadbraw);
3106 flush_write_cache(fsp, READRAW_FLUSH);
3108 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3109 if(req->wct == 10) {
3111 * This is a large offset (64 bit) read.
3113 #ifdef LARGE_SMB_OFF_T
3115 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3117 #else /* !LARGE_SMB_OFF_T */
3120 * Ensure we haven't been sent a >32 bit offset.
3123 if(IVAL(req->vwv+8, 0) != 0) {
3124 DEBUG(0,("reply_readbraw: large offset "
3125 "(%x << 32) used and we don't support "
3126 "64 bit offsets.\n",
3127 (unsigned int)IVAL(req->vwv+8, 0) ));
3128 reply_readbraw_error();
3129 END_PROFILE(SMBreadbraw);
3133 #endif /* LARGE_SMB_OFF_T */
3136 DEBUG(0,("reply_readbraw: negative 64 bit "
3137 "readraw offset (%.0f) !\n",
3138 (double)startpos ));
3139 reply_readbraw_error();
3140 END_PROFILE(SMBreadbraw);
3145 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3146 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3148 /* ensure we don't overrun the packet size */
3149 maxcount = MIN(65535,maxcount);
3151 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3152 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3155 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3156 reply_readbraw_error();
3157 END_PROFILE(SMBreadbraw);
3161 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3162 size = st.st_ex_size;
3165 if (startpos >= size) {
3168 nread = MIN(maxcount,(size - startpos));