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 "libsmb/namequery.h"
29 #include "system/filesys.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "smbd/smbXsrv_open.h"
35 #include "fake_file.h"
36 #include "rpc_client/rpc_client.h"
37 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "rpc_client/cli_spoolss.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_server/rpc_ncacn_np.h"
41 #include "libcli/security/security.h"
42 #include "libsmb/nmblib.h"
44 #include "smbprofile.h"
45 #include "../lib/tsocket/tsocket.h"
46 #include "lib/util/tevent_ntstatus.h"
47 #include "libcli/smb/smb_signing.h"
48 #include "lib/util/sys_rw_data.h"
49 #include "librpc/gen_ndr/open_files.h"
50 #include "smb1_utils.h"
51 #include "libcli/smb/smb2_posix.h"
52 #include "lib/util/string_wrappers.h"
53 #include "source3/printing/rap_jobid.h"
54 #include "source3/lib/substitute.h"
56 /****************************************************************************
58 conn POINTER CAN BE NULL HERE !
59 ****************************************************************************/
61 void reply_tcon(struct smb_request *req)
63 connection_struct *conn = req->conn;
65 char *service_buf = NULL;
66 char *password = NULL;
72 TALLOC_CTX *ctx = talloc_tos();
73 struct smbXsrv_connection *xconn = req->xconn;
74 NTTIME now = timeval_to_nttime(&req->request_time);
76 START_PROFILE(SMBtcon);
78 if (req->buflen < 4) {
79 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
85 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
87 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
89 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
92 if (service_buf == NULL || password == NULL || dev == NULL) {
93 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
97 p2 = strrchr_m(service_buf,'\\');
101 service = service_buf;
104 conn = make_connection(req, now, service, dev,
105 req->vuid,&nt_status);
109 reply_nterror(req, nt_status);
110 END_PROFILE(SMBtcon);
114 reply_outbuf(req, 2, 0);
115 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
116 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
117 SSVAL(req->outbuf,smb_tid,conn->cnum);
119 DEBUG(3,("tcon service=%s cnum=%d\n",
120 service, conn->cnum));
122 END_PROFILE(SMBtcon);
126 /****************************************************************************
127 Reply to a tcon and X.
128 conn POINTER CAN BE NULL HERE !
129 ****************************************************************************/
131 void reply_tcon_and_X(struct smb_request *req)
133 const struct loadparm_substitution *lp_sub =
134 loadparm_s3_global_substitution();
135 connection_struct *conn = req->conn;
136 const char *service = NULL;
137 TALLOC_CTX *ctx = talloc_tos();
138 /* what the client thinks the device is */
139 char *client_devicetype = NULL;
140 /* what the server tells the client the share represents */
141 const char *server_devicetype;
148 struct smbXsrv_session *session = NULL;
149 NTTIME now = timeval_to_nttime(&req->request_time);
150 bool session_key_updated = false;
151 uint16_t optional_support = 0;
152 struct smbXsrv_connection *xconn = req->xconn;
154 START_PROFILE(SMBtconX);
157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
158 END_PROFILE(SMBtconX);
162 passlen = SVAL(req->vwv+3, 0);
163 tcon_flags = SVAL(req->vwv+2, 0);
165 /* we might have to close an old one */
166 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
167 struct smbXsrv_tcon *tcon;
175 * TODO: cancel all outstanding requests on the tcon
177 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
178 if (!NT_STATUS_IS_OK(status)) {
179 DEBUG(0, ("reply_tcon_and_X: "
180 "smbXsrv_tcon_disconnect() failed: %s\n",
183 * If we hit this case, there is something completely
184 * wrong, so we better disconnect the transport connection.
186 END_PROFILE(SMBtconX);
187 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
193 * This tree id is gone. Make sure we can't re-use it
199 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
200 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
201 END_PROFILE(SMBtconX);
205 if (xconn->smb1.negprot.encrypted_passwords) {
206 p = req->buf + passlen;
208 p = req->buf + passlen + 1;
211 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
215 END_PROFILE(SMBtconX);
220 * the service name can be either: \\server\share
221 * or share directly like on the DELL PowerVault 705
224 q = strchr_m(path+2,'\\');
226 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
227 END_PROFILE(SMBtconX);
235 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
236 &client_devicetype, p,
237 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
239 if (client_devicetype == NULL) {
240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
241 END_PROFILE(SMBtconX);
245 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
247 nt_status = smb1srv_session_lookup(xconn,
248 req->vuid, now, &session);
249 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
250 reply_force_doserror(req, ERRSRV, ERRbaduid);
251 END_PROFILE(SMBtconX);
254 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
255 reply_nterror(req, nt_status);
256 END_PROFILE(SMBtconX);
259 if (!NT_STATUS_IS_OK(nt_status)) {
260 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
261 END_PROFILE(SMBtconX);
265 if (session->global->auth_session_info == NULL) {
266 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
267 END_PROFILE(SMBtconX);
272 * If there is no application key defined yet
275 * This means we setup the application key on the
276 * first tcon that happens via the given session.
278 * Once the application key is defined, it does not
281 if (session->global->application_key_blob.length == 0 &&
282 smb2_signing_key_valid(session->global->signing_key))
284 struct smbXsrv_session *x = session;
285 struct auth_session_info *session_info =
286 session->global->auth_session_info;
287 uint8_t session_key[16];
289 ZERO_STRUCT(session_key);
290 memcpy(session_key, x->global->signing_key->blob.data,
291 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
294 * The application key is truncated/padded to 16 bytes
296 x->global->application_key_blob = data_blob_talloc(x->global,
298 sizeof(session_key));
299 ZERO_STRUCT(session_key);
300 if (x->global->application_key_blob.data == NULL) {
301 reply_nterror(req, NT_STATUS_NO_MEMORY);
302 END_PROFILE(SMBtconX);
305 talloc_keep_secret(x->global->application_key_blob.data);
307 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
310 status = smb1_key_derivation(x->global->application_key_blob.data,
311 x->global->application_key_blob.length,
312 x->global->application_key_blob.data);
313 if (!NT_STATUS_IS_OK(status)) {
314 DBG_ERR("smb1_key_derivation failed: %s\n",
316 END_PROFILE(SMBtconX);
319 optional_support |= SMB_EXTENDED_SIGNATURES;
323 * Place the application key into the session_info
325 data_blob_clear_free(&session_info->session_key);
326 session_info->session_key = data_blob_dup_talloc(session_info,
327 x->global->application_key_blob);
328 if (session_info->session_key.data == NULL) {
329 data_blob_clear_free(&x->global->application_key_blob);
330 reply_nterror(req, NT_STATUS_NO_MEMORY);
331 END_PROFILE(SMBtconX);
334 talloc_keep_secret(session_info->session_key.data);
335 session_key_updated = true;
338 conn = make_connection(req, now, service, client_devicetype,
339 req->vuid, &nt_status);
343 if (session_key_updated) {
344 struct smbXsrv_session *x = session;
345 struct auth_session_info *session_info =
346 session->global->auth_session_info;
347 data_blob_clear_free(&x->global->application_key_blob);
348 data_blob_clear_free(&session_info->session_key);
350 reply_nterror(req, nt_status);
351 END_PROFILE(SMBtconX);
356 server_devicetype = "IPC";
357 else if ( IS_PRINT(conn) )
358 server_devicetype = "LPT1:";
360 server_devicetype = "A:";
362 if (get_Protocol() < PROTOCOL_NT1) {
363 reply_outbuf(req, 2, 0);
364 if (message_push_string(&req->outbuf, server_devicetype,
365 STR_TERMINATE|STR_ASCII) == -1) {
366 reply_nterror(req, NT_STATUS_NO_MEMORY);
367 END_PROFILE(SMBtconX);
371 /* NT sets the fstype of IPC$ to the null string */
372 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
374 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
375 /* Return permissions. */
379 reply_outbuf(req, 7, 0);
382 perm1 = FILE_ALL_ACCESS;
383 perm2 = FILE_ALL_ACCESS;
385 perm1 = conn->share_access;
388 SIVAL(req->outbuf, smb_vwv3, perm1);
389 SIVAL(req->outbuf, smb_vwv5, perm2);
391 reply_outbuf(req, 3, 0);
394 if ((message_push_string(&req->outbuf, server_devicetype,
395 STR_TERMINATE|STR_ASCII) == -1)
396 || (message_push_string(&req->outbuf, fstype,
397 STR_TERMINATE) == -1)) {
398 reply_nterror(req, NT_STATUS_NO_MEMORY);
399 END_PROFILE(SMBtconX);
403 /* what does setting this bit do? It is set by NT4 and
404 may affect the ability to autorun mounted cdroms */
405 optional_support |= SMB_SUPPORT_SEARCH_BITS;
407 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
409 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
410 DEBUG(2,("Serving %s as a Dfs root\n",
411 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
412 optional_support |= SMB_SHARE_IN_DFS;
415 SSVAL(req->outbuf, smb_vwv2, optional_support);
418 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
419 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
421 DEBUG(3,("tconX service=%s \n",
424 /* set the incoming and outgoing tid to the just created one */
425 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
426 SSVAL(req->outbuf,smb_tid,conn->cnum);
428 END_PROFILE(SMBtconX);
430 req->tid = conn->cnum;
433 /****************************************************************************
434 Reply to an unknown type.
435 ****************************************************************************/
437 void reply_unknown_new(struct smb_request *req, uint8_t type)
439 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
440 smb_fn_name(type), type, type));
441 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
445 /****************************************************************************
447 conn POINTER CAN BE NULL HERE !
448 ****************************************************************************/
450 void reply_ioctl(struct smb_request *req)
452 const struct loadparm_substitution *lp_sub =
453 loadparm_s3_global_substitution();
454 connection_struct *conn = req->conn;
461 START_PROFILE(SMBioctl);
464 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
465 END_PROFILE(SMBioctl);
469 device = SVAL(req->vwv+1, 0);
470 function = SVAL(req->vwv+2, 0);
471 ioctl_code = (device << 16) + function;
473 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
475 switch (ioctl_code) {
476 case IOCTL_QUERY_JOB_INFO:
480 reply_force_doserror(req, ERRSRV, ERRnosupport);
481 END_PROFILE(SMBioctl);
485 reply_outbuf(req, 8, replysize+1);
486 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
487 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
488 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
489 p = smb_buf(req->outbuf);
490 memset(p, '\0', replysize+1); /* valgrind-safe. */
491 p += 1; /* Allow for alignment */
493 switch (ioctl_code) {
494 case IOCTL_QUERY_JOB_INFO:
498 files_struct *fsp = file_fsp(
499 req, SVAL(req->vwv+0, 0));
501 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
502 END_PROFILE(SMBioctl);
506 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
508 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
509 lp_netbios_name(), 15,
510 STR_TERMINATE|STR_ASCII, &len);
511 if (!NT_STATUS_IS_OK(status)) {
512 reply_nterror(req, status);
513 END_PROFILE(SMBioctl);
517 status = srvstr_push((char *)req->outbuf, req->flags2,
519 lp_servicename(talloc_tos(),
522 13, STR_TERMINATE|STR_ASCII, &len);
523 if (!NT_STATUS_IS_OK(status)) {
524 reply_nterror(req, status);
525 END_PROFILE(SMBioctl);
535 END_PROFILE(SMBioctl);
539 /****************************************************************************
540 Strange checkpath NTSTATUS mapping.
541 ****************************************************************************/
543 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
545 /* Strange DOS error code semantics only for checkpath... */
546 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
547 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
548 /* We need to map to ERRbadpath */
549 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
555 /****************************************************************************
556 Reply to a checkpath.
557 ****************************************************************************/
559 void reply_checkpath(struct smb_request *req)
561 connection_struct *conn = req->conn;
562 struct smb_filename *smb_fname = NULL;
565 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
566 TALLOC_CTX *ctx = talloc_tos();
568 START_PROFILE(SMBcheckpath);
570 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
571 STR_TERMINATE, &status);
573 if (!NT_STATUS_IS_OK(status)) {
574 status = map_checkpath_error(req->flags2, status);
575 reply_nterror(req, status);
576 END_PROFILE(SMBcheckpath);
580 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
582 status = filename_convert(ctx,
589 if (!NT_STATUS_IS_OK(status)) {
590 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
591 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
593 END_PROFILE(SMBcheckpath);
599 if (!VALID_STAT(smb_fname->st) &&
600 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
601 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
602 smb_fname_str_dbg(smb_fname), strerror(errno)));
603 status = map_nt_error_from_unix(errno);
607 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
608 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
613 reply_outbuf(req, 0, 0);
616 /* We special case this - as when a Windows machine
617 is parsing a path is steps through the components
618 one at a time - if a component fails it expects
619 ERRbadpath, not ERRbadfile.
621 status = map_checkpath_error(req->flags2, status);
622 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
624 * Windows returns different error codes if
625 * the parent directory is valid but not the
626 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
627 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
628 * if the path is invalid.
630 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
635 reply_nterror(req, status);
638 TALLOC_FREE(smb_fname);
639 END_PROFILE(SMBcheckpath);
643 /****************************************************************************
645 ****************************************************************************/
647 void reply_getatr(struct smb_request *req)
649 connection_struct *conn = req->conn;
650 struct smb_filename *smb_fname = NULL;
657 TALLOC_CTX *ctx = talloc_tos();
658 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
660 START_PROFILE(SMBgetatr);
662 p = (const char *)req->buf + 1;
663 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
664 if (!NT_STATUS_IS_OK(status)) {
665 reply_nterror(req, status);
669 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
670 under WfWg - weird! */
671 if (*fname == '\0') {
672 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
673 if (!CAN_WRITE(conn)) {
674 mode |= FILE_ATTRIBUTE_READONLY;
679 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
680 status = filename_convert(ctx,
686 if (!NT_STATUS_IS_OK(status)) {
687 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
688 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
692 reply_nterror(req, status);
695 if (!VALID_STAT(smb_fname->st) &&
696 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
697 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
698 smb_fname_str_dbg(smb_fname),
700 reply_nterror(req, map_nt_error_from_unix(errno));
704 mode = fdos_mode(smb_fname->fsp);
705 size = smb_fname->st.st_ex_size;
708 struct timespec write_time_ts;
709 struct file_id fileid;
711 ZERO_STRUCT(write_time_ts);
712 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
713 get_file_infos(fileid, 0, NULL, &write_time_ts);
714 if (!is_omit_timespec(&write_time_ts)) {
715 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
719 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
720 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
725 reply_outbuf(req, 10, 0);
727 SSVAL(req->outbuf,smb_vwv0,mode);
728 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
729 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
731 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
733 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
735 if (get_Protocol() >= PROTOCOL_NT1) {
736 SSVAL(req->outbuf, smb_flg2,
737 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
740 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
741 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
744 TALLOC_FREE(smb_fname);
746 END_PROFILE(SMBgetatr);
750 /****************************************************************************
752 ****************************************************************************/
754 void reply_setatr(struct smb_request *req)
756 struct smb_file_time ft;
757 connection_struct *conn = req->conn;
758 struct smb_filename *smb_fname = NULL;
764 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
765 TALLOC_CTX *ctx = talloc_tos();
767 START_PROFILE(SMBsetatr);
768 init_smb_file_time(&ft);
771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
775 p = (const char *)req->buf + 1;
776 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
777 if (!NT_STATUS_IS_OK(status)) {
778 reply_nterror(req, status);
782 status = filename_convert(ctx,
788 if (!NT_STATUS_IS_OK(status)) {
789 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
790 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
794 reply_nterror(req, status);
798 if (ISDOT(smb_fname->base_name)) {
800 * Not sure here is the right place to catch this
801 * condition. Might be moved to somewhere else later -- vl
803 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
807 if (smb_fname->fsp == NULL) {
808 /* Can't set access rights on a symlink. */
809 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
813 mode = SVAL(req->vwv+0, 0);
814 mtime = srv_make_unix_date3(req->vwv+1);
816 if (mode != FILE_ATTRIBUTE_NORMAL) {
817 if (VALID_STAT_OF_DIR(smb_fname->st))
818 mode |= FILE_ATTRIBUTE_DIRECTORY;
820 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
822 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
825 FILE_WRITE_ATTRIBUTES);
826 if (!NT_STATUS_IS_OK(status)) {
827 reply_nterror(req, status);
831 if (file_set_dosmode(conn, smb_fname, mode, NULL,
833 reply_nterror(req, map_nt_error_from_unix(errno));
838 ft.mtime = time_t_to_full_timespec(mtime);
840 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
841 if (!NT_STATUS_IS_OK(status)) {
842 reply_nterror(req, status);
846 reply_outbuf(req, 0, 0);
848 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
851 TALLOC_FREE(smb_fname);
852 END_PROFILE(SMBsetatr);
856 /****************************************************************************
858 ****************************************************************************/
860 void reply_dskattr(struct smb_request *req)
862 connection_struct *conn = req->conn;
864 uint64_t dfree,dsize,bsize;
865 struct smb_filename smb_fname;
866 START_PROFILE(SMBdskattr);
868 ZERO_STRUCT(smb_fname);
869 smb_fname.base_name = discard_const_p(char, ".");
871 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
872 reply_nterror(req, map_nt_error_from_unix(errno));
873 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
874 END_PROFILE(SMBdskattr);
878 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
879 if (ret == (uint64_t)-1) {
880 reply_nterror(req, map_nt_error_from_unix(errno));
881 END_PROFILE(SMBdskattr);
886 * Force max to fit in 16 bit fields.
888 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
892 if (bsize > (WORDMAX*512)) {
893 bsize = (WORDMAX*512);
902 reply_outbuf(req, 5, 0);
904 if (get_Protocol() <= PROTOCOL_LANMAN2) {
905 double total_space, free_space;
906 /* we need to scale this to a number that DOS6 can handle. We
907 use floating point so we can handle large drives on systems
908 that don't have 64 bit integers
910 we end up displaying a maximum of 2G to DOS systems
912 total_space = dsize * (double)bsize;
913 free_space = dfree * (double)bsize;
915 dsize = (uint64_t)((total_space+63*512) / (64*512));
916 dfree = (uint64_t)((free_space+63*512) / (64*512));
918 if (dsize > 0xFFFF) dsize = 0xFFFF;
919 if (dfree > 0xFFFF) dfree = 0xFFFF;
921 SSVAL(req->outbuf,smb_vwv0,dsize);
922 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
923 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
924 SSVAL(req->outbuf,smb_vwv3,dfree);
926 SSVAL(req->outbuf,smb_vwv0,dsize);
927 SSVAL(req->outbuf,smb_vwv1,bsize/512);
928 SSVAL(req->outbuf,smb_vwv2,512);
929 SSVAL(req->outbuf,smb_vwv3,dfree);
932 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
934 END_PROFILE(SMBdskattr);
938 /****************************************************************************
940 ****************************************************************************/
942 static bool make_dir_struct(TALLOC_CTX *ctx,
952 char *mask2 = talloc_strdup(ctx, mask);
958 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
962 memset(buf+1,' ',11);
963 if ((p = strchr_m(mask2,'.')) != NULL) {
965 push_ascii(buf+1,mask2,8, 0);
966 push_ascii(buf+9,p+1,3, 0);
969 push_ascii(buf+1,mask2,11, 0);
972 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
974 srv_put_dos_date(buf,22,date);
975 SSVAL(buf,26,size & 0xFFFF);
976 SSVAL(buf,28,(size >> 16)&0xFFFF);
977 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
978 Strange, but verified on W2K3. Needed for OS/2. JRA. */
979 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
980 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
984 /****************************************************************************
986 Can be called from SMBsearch, SMBffirst or SMBfunique.
987 ****************************************************************************/
989 void reply_search(struct smb_request *req)
991 connection_struct *conn = req->conn;
994 char *directory = NULL;
995 struct smb_filename *smb_fname = NULL;
999 struct timespec date;
1001 unsigned int numentries = 0;
1002 unsigned int maxentries = 0;
1003 bool finished = False;
1008 bool check_descend = False;
1009 bool expect_close = False;
1011 bool mask_contains_wcard = False;
1012 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1013 TALLOC_CTX *ctx = talloc_tos();
1014 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1015 struct smbXsrv_connection *xconn = req->xconn;
1016 struct smbd_server_connection *sconn = req->sconn;
1017 files_struct *fsp = NULL;
1018 const struct loadparm_substitution *lp_sub =
1019 loadparm_s3_global_substitution();
1021 START_PROFILE(SMBsearch);
1024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1028 if (req->posix_pathnames) {
1029 reply_unknown_new(req, req->cmd);
1033 /* If we were called as SMBffirst then we must expect close. */
1034 if(req->cmd == SMBffirst) {
1035 expect_close = True;
1038 reply_outbuf(req, 1, 3);
1039 maxentries = SVAL(req->vwv+0, 0);
1040 dirtype = SVAL(req->vwv+1, 0);
1041 p = (const char *)req->buf + 1;
1042 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1044 if (!NT_STATUS_IS_OK(nt_status)) {
1045 reply_nterror(req, nt_status);
1049 if (smbreq_bufrem(req, p) < 3) {
1050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1055 status_len = SVAL(p, 0);
1058 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1060 if (status_len == 0) {
1061 const char *dirpath;
1062 struct smb_filename *smb_dname = NULL;
1063 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1065 nt_status = filename_convert_smb1_search_path(ctx,
1072 if (!NT_STATUS_IS_OK(nt_status)) {
1073 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1074 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1075 ERRSRV, ERRbadpath);
1078 reply_nterror(req, nt_status);
1082 memset((char *)status,'\0',21);
1083 SCVAL(status,0,(dirtype & 0x1F));
1086 * Open an fsp on this directory for the dptr.
1088 nt_status = SMB_VFS_CREATE_FILE(
1091 smb_dname, /* dname */
1092 FILE_LIST_DIRECTORY, /* access_mask */
1094 FILE_SHARE_WRITE, /* share_access */
1095 FILE_OPEN, /* create_disposition*/
1096 FILE_DIRECTORY_FILE, /* create_options */
1097 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1098 NO_OPLOCK, /* oplock_request */
1100 0, /* allocation_size */
1101 0, /* private_flags */
1106 NULL, /* in_context */
1107 NULL);/* out_context */
1109 if (!NT_STATUS_IS_OK(nt_status)) {
1110 DBG_ERR("failed to open directory %s\n",
1111 smb_fname_str_dbg(smb_dname));
1112 reply_nterror(req, nt_status);
1116 nt_status = dptr_create(conn,
1126 TALLOC_FREE(smb_dname);
1128 if (!NT_STATUS_IS_OK(nt_status)) {
1130 * Use NULL here for the first parameter (req)
1131 * as this is not a client visible handle so
1132 * can'tbe part of an SMB1 chain.
1134 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1135 reply_nterror(req, nt_status);
1139 dptr_num = dptr_dnum(fsp->dptr);
1140 dirpath = dptr_path(sconn, dptr_num);
1141 directory = talloc_strdup(ctx, dirpath);
1143 reply_nterror(req, NT_STATUS_NO_MEMORY);
1149 const char *dirpath;
1151 if (smbreq_bufrem(req, p) < 21) {
1152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1156 memcpy(status,p,21);
1157 status_dirtype = CVAL(status,0) & 0x1F;
1158 if (status_dirtype != (dirtype & 0x1F)) {
1159 dirtype = status_dirtype;
1162 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1166 dirpath = dptr_path(sconn, dptr_num);
1167 directory = talloc_strdup(ctx, dirpath);
1169 reply_nterror(req, NT_STATUS_NO_MEMORY);
1173 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1177 dirtype = dptr_attr(sconn, dptr_num);
1180 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1182 DEBUG(4,("dptr_num is %d\n",dptr_num));
1184 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1185 char buf[DIR_STRUCT_SIZE];
1186 memcpy(buf,status,21);
1187 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1188 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1189 reply_nterror(req, NT_STATUS_NO_MEMORY);
1192 dptr_fill(sconn, buf+12,dptr_num);
1193 if (dptr_zero(buf+12) && (status_len==0)) {
1198 if (message_push_blob(&req->outbuf,
1199 data_blob_const(buf, sizeof(buf)))
1201 reply_nterror(req, NT_STATUS_NO_MEMORY);
1206 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1207 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1209 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1211 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1212 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1213 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1214 check_descend = True;
1217 for (i=numentries;(i<maxentries) && !finished;i++) {
1218 finished = !get_dir_entry(ctx,
1229 char buf[DIR_STRUCT_SIZE];
1230 memcpy(buf,status,21);
1231 if (!make_dir_struct(ctx,
1237 convert_timespec_to_time_t(date),
1238 !allow_long_path_components)) {
1239 reply_nterror(req, NT_STATUS_NO_MEMORY);
1242 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1245 if (message_push_blob(&req->outbuf,
1246 data_blob_const(buf, sizeof(buf)))
1248 reply_nterror(req, NT_STATUS_NO_MEMORY);
1258 /* If we were called as SMBffirst with smb_search_id == NULL
1259 and no entries were found then return error and close fsp->dptr
1262 if (numentries == 0) {
1265 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1267 } else if(expect_close && status_len == 0) {
1268 /* Close the dptr - we know it's gone */
1271 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1275 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1276 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1278 /* fsp may have been closed above. */
1280 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1284 if ((numentries == 0) && !mask_contains_wcard) {
1285 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1289 SSVAL(req->outbuf,smb_vwv0,numentries);
1290 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1291 SCVAL(smb_buf(req->outbuf),0,5);
1292 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1294 /* The replies here are never long name. */
1295 SSVAL(req->outbuf, smb_flg2,
1296 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1297 if (!allow_long_path_components) {
1298 SSVAL(req->outbuf, smb_flg2,
1299 SVAL(req->outbuf, smb_flg2)
1300 & (~FLAGS2_LONG_PATH_COMPONENTS));
1303 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1304 SSVAL(req->outbuf, smb_flg2,
1305 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1307 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1308 smb_fn_name(req->cmd),
1315 TALLOC_FREE(directory);
1317 TALLOC_FREE(smb_fname);
1318 END_PROFILE(SMBsearch);
1322 /****************************************************************************
1323 Reply to a fclose (stop directory search).
1324 ****************************************************************************/
1326 void reply_fclose(struct smb_request *req)
1334 TALLOC_CTX *ctx = talloc_tos();
1335 struct smbd_server_connection *sconn = req->sconn;
1336 files_struct *fsp = NULL;
1338 START_PROFILE(SMBfclose);
1340 if (req->posix_pathnames) {
1341 reply_unknown_new(req, req->cmd);
1342 END_PROFILE(SMBfclose);
1346 p = (const char *)req->buf + 1;
1347 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1349 if (!NT_STATUS_IS_OK(err)) {
1350 reply_nterror(req, err);
1351 END_PROFILE(SMBfclose);
1355 if (smbreq_bufrem(req, p) < 3) {
1356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1357 END_PROFILE(SMBfclose);
1362 status_len = SVAL(p,0);
1365 if (status_len == 0) {
1366 reply_force_doserror(req, ERRSRV, ERRsrverror);
1367 END_PROFILE(SMBfclose);
1371 if (smbreq_bufrem(req, p) < 21) {
1372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1373 END_PROFILE(SMBfclose);
1377 memcpy(status,p,21);
1379 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1381 /* Close the file - we know it's gone */
1382 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1386 reply_outbuf(req, 1, 0);
1387 SSVAL(req->outbuf,smb_vwv0,0);
1389 DEBUG(3,("search close\n"));
1391 END_PROFILE(SMBfclose);
1395 /****************************************************************************
1397 ****************************************************************************/
1399 void reply_open(struct smb_request *req)
1401 connection_struct *conn = req->conn;
1402 struct smb_filename *smb_fname = NULL;
1412 uint32_t access_mask;
1413 uint32_t share_mode;
1414 uint32_t create_disposition;
1415 uint32_t create_options = 0;
1416 uint32_t private_flags = 0;
1419 TALLOC_CTX *ctx = talloc_tos();
1421 START_PROFILE(SMBopen);
1424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1428 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1429 deny_mode = SVAL(req->vwv+0, 0);
1430 dos_attr = SVAL(req->vwv+1, 0);
1432 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1433 STR_TERMINATE, &status);
1434 if (!NT_STATUS_IS_OK(status)) {
1435 reply_nterror(req, status);
1439 if (!map_open_params_to_ntcreate(fname, deny_mode,
1440 OPENX_FILE_EXISTS_OPEN, &access_mask,
1441 &share_mode, &create_disposition,
1442 &create_options, &private_flags)) {
1443 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1447 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1449 status = filename_convert(ctx,
1455 if (!NT_STATUS_IS_OK(status)) {
1456 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1457 reply_botherror(req,
1458 NT_STATUS_PATH_NOT_COVERED,
1459 ERRSRV, ERRbadpath);
1462 reply_nterror(req, status);
1466 status = SMB_VFS_CREATE_FILE(
1469 smb_fname, /* fname */
1470 access_mask, /* access_mask */
1471 share_mode, /* share_access */
1472 create_disposition, /* create_disposition*/
1473 create_options, /* create_options */
1474 dos_attr, /* file_attributes */
1475 oplock_request, /* oplock_request */
1477 0, /* allocation_size */
1483 NULL, NULL); /* create context */
1485 if (!NT_STATUS_IS_OK(status)) {
1486 if (open_was_deferred(req->xconn, req->mid)) {
1487 /* We have re-scheduled this call. */
1491 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1492 reply_openerror(req, status);
1496 fsp = fcb_or_dos_open(
1503 bool ok = defer_smb1_sharing_violation(req);
1507 reply_openerror(req, status);
1512 /* Ensure we're pointing at the correct stat struct. */
1513 TALLOC_FREE(smb_fname);
1514 smb_fname = fsp->fsp_name;
1516 size = smb_fname->st.st_ex_size;
1517 fattr = fdos_mode(fsp);
1519 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1521 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1522 DEBUG(3,("attempt to open a directory %s\n",
1524 close_file_free(req, &fsp, ERROR_CLOSE);
1525 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1526 ERRDOS, ERRnoaccess);
1530 reply_outbuf(req, 7, 0);
1531 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1532 SSVAL(req->outbuf,smb_vwv1,fattr);
1533 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1534 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1536 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1538 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1539 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1541 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1542 SCVAL(req->outbuf,smb_flg,
1543 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1546 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1547 SCVAL(req->outbuf,smb_flg,
1548 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1551 END_PROFILE(SMBopen);
1555 /****************************************************************************
1556 Reply to an open and X.
1557 ****************************************************************************/
1559 void reply_open_and_X(struct smb_request *req)
1561 connection_struct *conn = req->conn;
1562 struct smb_filename *smb_fname = NULL;
1564 uint16_t open_flags;
1567 /* Breakout the oplock request bits so we can set the
1568 reply bits separately. */
1569 int ex_oplock_request;
1570 int core_oplock_request;
1573 int smb_sattr = SVAL(req->vwv+4, 0);
1574 uint32_t smb_time = make_unix_date3(req->vwv+6);
1582 uint64_t allocation_size;
1583 ssize_t retval = -1;
1584 uint32_t access_mask;
1585 uint32_t share_mode;
1586 uint32_t create_disposition;
1587 uint32_t create_options = 0;
1588 uint32_t private_flags = 0;
1590 TALLOC_CTX *ctx = talloc_tos();
1592 START_PROFILE(SMBopenX);
1594 if (req->wct < 15) {
1595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1599 open_flags = SVAL(req->vwv+2, 0);
1600 deny_mode = SVAL(req->vwv+3, 0);
1601 smb_attr = SVAL(req->vwv+5, 0);
1602 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1603 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1604 oplock_request = ex_oplock_request | core_oplock_request;
1605 smb_ofun = SVAL(req->vwv+8, 0);
1606 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1608 /* If it's an IPC, pass off the pipe handler. */
1610 if (lp_nt_pipe_support()) {
1611 reply_open_pipe_and_X(conn, req);
1613 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1618 /* XXXX we need to handle passed times, sattr and flags */
1619 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1620 STR_TERMINATE, &status);
1621 if (!NT_STATUS_IS_OK(status)) {
1622 reply_nterror(req, status);
1626 if (!map_open_params_to_ntcreate(fname, deny_mode,
1628 &access_mask, &share_mode,
1629 &create_disposition,
1632 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1636 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1638 status = filename_convert(ctx,
1644 if (!NT_STATUS_IS_OK(status)) {
1645 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1646 reply_botherror(req,
1647 NT_STATUS_PATH_NOT_COVERED,
1648 ERRSRV, ERRbadpath);
1651 reply_nterror(req, status);
1655 status = SMB_VFS_CREATE_FILE(
1658 smb_fname, /* fname */
1659 access_mask, /* access_mask */
1660 share_mode, /* share_access */
1661 create_disposition, /* create_disposition*/
1662 create_options, /* create_options */
1663 smb_attr, /* file_attributes */
1664 oplock_request, /* oplock_request */
1666 0, /* allocation_size */
1671 &smb_action, /* pinfo */
1672 NULL, NULL); /* create context */
1674 if (!NT_STATUS_IS_OK(status)) {
1675 if (open_was_deferred(req->xconn, req->mid)) {
1676 /* We have re-scheduled this call. */
1680 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1681 reply_openerror(req, status);
1685 fsp = fcb_or_dos_open(
1692 bool ok = defer_smb1_sharing_violation(req);
1696 reply_openerror(req, status);
1701 smb_action = FILE_WAS_OPENED;
1704 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1705 if the file is truncated or created. */
1706 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1707 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1708 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1709 close_file_free(req, &fsp, ERROR_CLOSE);
1710 reply_nterror(req, NT_STATUS_DISK_FULL);
1713 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1715 close_file_free(req, &fsp, ERROR_CLOSE);
1716 reply_nterror(req, NT_STATUS_DISK_FULL);
1719 status = vfs_stat_fsp(fsp);
1720 if (!NT_STATUS_IS_OK(status)) {
1721 close_file_free(req, &fsp, ERROR_CLOSE);
1722 reply_nterror(req, status);
1727 fattr = fdos_mode(fsp);
1728 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1729 close_file_free(req, &fsp, ERROR_CLOSE);
1730 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1733 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
1735 /* If the caller set the extended oplock request bit
1736 and we granted one (by whatever means) - set the
1737 correct bit for extended oplock reply.
1740 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1741 smb_action |= EXTENDED_OPLOCK_GRANTED;
1744 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1745 smb_action |= EXTENDED_OPLOCK_GRANTED;
1748 /* If the caller set the core oplock request bit
1749 and we granted one (by whatever means) - set the
1750 correct bit for core oplock reply.
1753 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1754 reply_outbuf(req, 19, 0);
1756 reply_outbuf(req, 15, 0);
1759 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1760 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1762 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1763 SCVAL(req->outbuf, smb_flg,
1764 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1767 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1768 SCVAL(req->outbuf, smb_flg,
1769 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1772 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1773 SSVAL(req->outbuf,smb_vwv3,fattr);
1774 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1775 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1777 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1779 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
1780 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1781 SSVAL(req->outbuf,smb_vwv11,smb_action);
1783 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1784 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
1788 TALLOC_FREE(smb_fname);
1789 END_PROFILE(SMBopenX);
1793 /****************************************************************************
1794 Reply to a SMBulogoffX.
1795 ****************************************************************************/
1797 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1798 struct smbXsrv_session *session);
1799 static void reply_ulogoffX_done(struct tevent_req *req);
1801 void reply_ulogoffX(struct smb_request *smb1req)
1803 struct timeval now = timeval_current();
1804 struct smbXsrv_session *session = NULL;
1805 struct tevent_req *req;
1809 * Don't setup the profile charge here, take
1810 * it in reply_ulogoffX_done(). Not strictly correct
1811 * but better than the other SMB1 async
1812 * code that double-charges at the moment.
1815 status = smb1srv_session_lookup(smb1req->xconn,
1817 timeval_to_nttime(&now),
1819 if (!NT_STATUS_IS_OK(status)) {
1820 /* Not going async, profile here. */
1821 START_PROFILE(SMBulogoffX);
1822 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
1823 (unsigned long long)smb1req->vuid);
1825 smb1req->vuid = UID_FIELD_INVALID;
1826 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
1827 END_PROFILE(SMBulogoffX);
1831 req = reply_ulogoffX_send(smb1req, session);
1833 /* Not going async, profile here. */
1834 START_PROFILE(SMBulogoffX);
1835 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
1836 END_PROFILE(SMBulogoffX);
1840 /* We're async. This will complete later. */
1841 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
1845 struct reply_ulogoffX_state {
1846 struct tevent_queue *wait_queue;
1847 struct smbXsrv_session *session;
1850 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
1852 /****************************************************************************
1853 Async SMB1 ulogoffX.
1854 Note, on failure here we deallocate and return NULL to allow the caller to
1855 SMB1 return an error of ERRnomem immediately.
1856 ****************************************************************************/
1858 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1859 struct smbXsrv_session *session)
1861 struct tevent_req *req;
1862 struct reply_ulogoffX_state *state;
1863 struct tevent_req *subreq;
1865 struct smbd_server_connection *sconn = session->client->sconn;
1866 uint64_t vuid = session->global->session_wire_id;
1868 req = tevent_req_create(smb1req, &state,
1869 struct reply_ulogoffX_state);
1873 state->wait_queue = tevent_queue_create(state,
1874 "reply_ulogoffX_wait_queue");
1875 if (tevent_req_nomem(state->wait_queue, req)) {
1879 state->session = session;
1882 * Make sure that no new request will be able to use this session.
1883 * This ensures that once all outstanding fsp->aio_requests
1884 * on this session are done, we are safe to close it.
1886 session->status = NT_STATUS_USER_SESSION_DELETED;
1888 for (fsp = sconn->files; fsp; fsp = fsp->next) {
1889 if (fsp->vuid != vuid) {
1893 * Flag the file as close in progress.
1894 * This will prevent any more IO being
1897 fsp->fsp_flags.closing = true;
1899 if (fsp->num_aio_requests > 0) {
1901 * Now wait until all aio requests on this fsp are
1904 * We don't set a callback, as we just want to block the
1905 * wait queue and the talloc_free() of fsp->aio_request
1906 * will remove the item from the wait queue.
1908 subreq = tevent_queue_wait_send(fsp->aio_requests,
1911 if (tevent_req_nomem(subreq, req)) {
1919 * Now we add our own waiter to the end of the queue,
1920 * this way we get notified when all pending requests are finished
1921 * and reply to the outstanding SMB1 request.
1923 subreq = tevent_queue_wait_send(state,
1926 if (tevent_req_nomem(subreq, req)) {
1932 * We're really going async - move the SMB1 request from
1933 * a talloc stackframe above us to the sconn talloc-context.
1934 * We need this to stick around until the wait_done
1935 * callback is invoked.
1937 smb1req = talloc_move(sconn, &smb1req);
1939 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
1944 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
1946 struct tevent_req *req = tevent_req_callback_data(
1947 subreq, struct tevent_req);
1949 tevent_queue_wait_recv(subreq);
1950 TALLOC_FREE(subreq);
1951 tevent_req_done(req);
1954 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
1956 return tevent_req_simple_recv_ntstatus(req);
1959 static void reply_ulogoffX_done(struct tevent_req *req)
1961 struct smb_request *smb1req = tevent_req_callback_data(
1962 req, struct smb_request);
1963 struct reply_ulogoffX_state *state = tevent_req_data(req,
1964 struct reply_ulogoffX_state);
1965 struct smbXsrv_session *session = state->session;
1969 * Take the profile charge here. Not strictly
1970 * correct but better than the other SMB1 async
1971 * code that double-charges at the moment.
1973 START_PROFILE(SMBulogoffX);
1975 status = reply_ulogoffX_recv(req);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 TALLOC_FREE(smb1req);
1979 END_PROFILE(SMBulogoffX);
1980 exit_server(__location__ ": reply_ulogoffX_recv failed");
1984 status = smbXsrv_session_logoff(session);
1985 if (!NT_STATUS_IS_OK(status)) {
1986 TALLOC_FREE(smb1req);
1987 END_PROFILE(SMBulogoffX);
1988 exit_server(__location__ ": smbXsrv_session_logoff failed");
1992 TALLOC_FREE(session);
1994 reply_outbuf(smb1req, 2, 0);
1995 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1996 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
1998 DBG_NOTICE("ulogoffX vuid=%llu\n",
1999 (unsigned long long)smb1req->vuid);
2001 smb1req->vuid = UID_FIELD_INVALID;
2003 * The following call is needed to push the
2004 * reply data back out the socket after async
2005 * return. Plus it frees smb1req.
2007 smb_request_done(smb1req);
2008 END_PROFILE(SMBulogoffX);
2011 /****************************************************************************
2012 Reply to a mknew or a create.
2013 ****************************************************************************/
2015 void reply_mknew(struct smb_request *req)
2017 connection_struct *conn = req->conn;
2018 struct smb_filename *smb_fname = NULL;
2021 struct smb_file_time ft;
2023 int oplock_request = 0;
2025 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2026 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2027 uint32_t create_disposition;
2028 uint32_t create_options = 0;
2030 TALLOC_CTX *ctx = talloc_tos();
2032 START_PROFILE(SMBcreate);
2033 init_smb_file_time(&ft);
2036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 fattr = SVAL(req->vwv+0, 0);
2041 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2043 if (req->cmd == SMBmknew) {
2044 /* We should fail if file exists. */
2045 create_disposition = FILE_CREATE;
2047 /* Create if file doesn't exist, truncate if it does. */
2048 create_disposition = FILE_OVERWRITE_IF;
2052 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2054 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2055 STR_TERMINATE, &status);
2056 if (!NT_STATUS_IS_OK(status)) {
2057 reply_nterror(req, status);
2061 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2062 status = filename_convert(ctx,
2068 if (!NT_STATUS_IS_OK(status)) {
2069 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2070 reply_botherror(req,
2071 NT_STATUS_PATH_NOT_COVERED,
2072 ERRSRV, ERRbadpath);
2075 reply_nterror(req, status);
2079 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2080 DEBUG(0,("Attempt to create file (%s) with volid set - "
2081 "please report this\n",
2082 smb_fname_str_dbg(smb_fname)));
2085 status = SMB_VFS_CREATE_FILE(
2088 smb_fname, /* fname */
2089 access_mask, /* access_mask */
2090 share_mode, /* share_access */
2091 create_disposition, /* create_disposition*/
2092 create_options, /* create_options */
2093 fattr, /* file_attributes */
2094 oplock_request, /* oplock_request */
2096 0, /* allocation_size */
2097 0, /* private_flags */
2102 NULL, NULL); /* create context */
2104 if (!NT_STATUS_IS_OK(status)) {
2105 if (open_was_deferred(req->xconn, req->mid)) {
2106 /* We have re-scheduled this call. */
2109 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2110 bool ok = defer_smb1_sharing_violation(req);
2115 reply_openerror(req, status);
2119 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2120 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2121 if (!NT_STATUS_IS_OK(status)) {
2122 END_PROFILE(SMBcreate);
2126 reply_outbuf(req, 1, 0);
2127 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2129 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2130 SCVAL(req->outbuf,smb_flg,
2131 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2134 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2135 SCVAL(req->outbuf,smb_flg,
2136 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2139 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2140 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2141 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2142 (unsigned int)fattr));
2145 TALLOC_FREE(smb_fname);
2146 END_PROFILE(SMBcreate);
2150 /****************************************************************************
2151 Reply to a create temporary file.
2152 ****************************************************************************/
2154 void reply_ctemp(struct smb_request *req)
2156 connection_struct *conn = req->conn;
2157 struct smb_filename *smb_fname = NULL;
2158 char *wire_name = NULL;
2167 TALLOC_CTX *ctx = talloc_tos();
2169 START_PROFILE(SMBctemp);
2172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2176 fattr = SVAL(req->vwv+0, 0);
2177 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2179 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2180 STR_TERMINATE, &status);
2181 if (!NT_STATUS_IS_OK(status)) {
2182 reply_nterror(req, status);
2186 for (i = 0; i < 10; i++) {
2188 fname = talloc_asprintf(ctx,
2191 generate_random_str_list(ctx, 5, "0123456789"));
2193 fname = talloc_asprintf(ctx,
2195 generate_random_str_list(ctx, 5, "0123456789"));
2199 reply_nterror(req, NT_STATUS_NO_MEMORY);
2203 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2204 status = filename_convert(ctx, conn,
2209 if (!NT_STATUS_IS_OK(status)) {
2210 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2211 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2212 ERRSRV, ERRbadpath);
2215 reply_nterror(req, status);
2219 /* Create the file. */
2220 status = SMB_VFS_CREATE_FILE(
2223 smb_fname, /* fname */
2224 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2225 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2226 FILE_CREATE, /* create_disposition*/
2227 0, /* create_options */
2228 fattr, /* file_attributes */
2229 oplock_request, /* oplock_request */
2231 0, /* allocation_size */
2232 0, /* private_flags */
2237 NULL, NULL); /* create context */
2239 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2241 TALLOC_FREE(smb_fname);
2245 if (!NT_STATUS_IS_OK(status)) {
2246 if (open_was_deferred(req->xconn, req->mid)) {
2247 /* We have re-scheduled this call. */
2250 if (NT_STATUS_EQUAL(
2251 status, NT_STATUS_SHARING_VIOLATION)) {
2252 bool ok = defer_smb1_sharing_violation(req);
2257 reply_openerror(req, status);
2265 /* Collision after 10 times... */
2266 reply_nterror(req, status);
2270 reply_outbuf(req, 1, 0);
2271 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2273 /* the returned filename is relative to the directory */
2274 s = strrchr_m(fsp->fsp_name->base_name, '/');
2276 s = fsp->fsp_name->base_name;
2282 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2283 thing in the byte section. JRA */
2284 SSVALS(p, 0, -1); /* what is this? not in spec */
2286 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2288 reply_nterror(req, NT_STATUS_NO_MEMORY);
2292 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2293 SCVAL(req->outbuf, smb_flg,
2294 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2297 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2298 SCVAL(req->outbuf, smb_flg,
2299 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2302 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2303 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2304 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2306 TALLOC_FREE(smb_fname);
2307 TALLOC_FREE(wire_name);
2308 END_PROFILE(SMBctemp);
2312 /*******************************************************************
2313 Check if a user is allowed to rename a file.
2314 ********************************************************************/
2316 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2319 if (!CAN_WRITE(conn)) {
2320 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2323 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2324 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2325 /* Only bother to read the DOS attribute if we might deny the
2326 rename on the grounds of attribute mismatch. */
2327 uint32_t fmode = fdos_mode(fsp);
2328 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2329 return NT_STATUS_NO_SUCH_FILE;
2333 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2334 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2335 return NT_STATUS_OK;
2338 /* If no pathnames are open below this
2339 directory, allow the rename. */
2341 if (lp_strict_rename(SNUM(conn))) {
2343 * Strict rename, check open file db.
2345 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2346 return NT_STATUS_ACCESS_DENIED;
2348 } else if (file_find_subpath(fsp)) {
2350 * No strict rename, just look in local process.
2352 return NT_STATUS_ACCESS_DENIED;
2354 return NT_STATUS_OK;
2357 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2358 return NT_STATUS_OK;
2361 return NT_STATUS_ACCESS_DENIED;
2364 /*******************************************************************
2365 * unlink a file with all relevant access checks
2366 *******************************************************************/
2368 NTSTATUS unlink_internals(connection_struct *conn,
2369 struct smb_request *req,
2371 struct smb_filename *smb_fname)
2375 uint32_t dirtype_orig = dirtype;
2378 struct smb2_create_blobs *posx = NULL;
2381 dirtype = FILE_ATTRIBUTE_NORMAL;
2384 DBG_DEBUG("%s, dirtype = %d\n",
2385 smb_fname_str_dbg(smb_fname),
2388 if (!CAN_WRITE(conn)) {
2389 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2392 ret = vfs_stat(conn, smb_fname);
2394 return map_nt_error_from_unix(errno);
2397 fattr = fdos_mode(smb_fname->fsp);
2399 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2400 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2403 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2405 return NT_STATUS_NO_SUCH_FILE;
2408 if (!dir_check_ftype(fattr, dirtype)) {
2409 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2410 return NT_STATUS_FILE_IS_A_DIRECTORY;
2412 return NT_STATUS_NO_SUCH_FILE;
2415 if (dirtype_orig & 0x8000) {
2416 /* These will never be set for POSIX. */
2417 return NT_STATUS_NO_SUCH_FILE;
2421 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2422 return NT_STATUS_FILE_IS_A_DIRECTORY;
2425 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2426 return NT_STATUS_NO_SUCH_FILE;
2429 if (dirtype & 0xFF00) {
2430 /* These will never be set for POSIX. */
2431 return NT_STATUS_NO_SUCH_FILE;
2436 return NT_STATUS_NO_SUCH_FILE;
2439 /* Can't delete a directory. */
2440 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2441 return NT_STATUS_FILE_IS_A_DIRECTORY;
2446 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2447 return NT_STATUS_OBJECT_NAME_INVALID;
2448 #endif /* JRATEST */
2450 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
2451 status = make_smb2_posix_create_ctx(
2452 talloc_tos(), &posx, 0777);
2453 if (!NT_STATUS_IS_OK(status)) {
2454 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2460 /* On open checks the open itself will check the share mode, so
2461 don't do it here as we'll get it wrong. */
2463 status = SMB_VFS_CREATE_FILE
2466 smb_fname, /* fname */
2467 DELETE_ACCESS, /* access_mask */
2468 FILE_SHARE_NONE, /* share_access */
2469 FILE_OPEN, /* create_disposition*/
2470 FILE_NON_DIRECTORY_FILE, /* create_options */
2471 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2472 0, /* oplock_request */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2480 posx, /* in_context_blobs */
2481 NULL); /* out_context_blobs */
2485 if (!NT_STATUS_IS_OK(status)) {
2486 DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n",
2491 status = can_set_delete_on_close(fsp, fattr);
2492 if (!NT_STATUS_IS_OK(status)) {
2493 DBG_DEBUG("can_set_delete_on_close for file %s - "
2495 smb_fname_str_dbg(smb_fname),
2497 close_file_free(req, &fsp, NORMAL_CLOSE);
2501 /* The set is across all open files on this dev/inode pair. */
2502 if (!set_delete_on_close(fsp, True,
2503 conn->session_info->security_token,
2504 conn->session_info->unix_token)) {
2505 close_file_free(req, &fsp, NORMAL_CLOSE);
2506 return NT_STATUS_ACCESS_DENIED;
2509 return close_file_free(req, &fsp, NORMAL_CLOSE);
2512 /****************************************************************************
2514 ****************************************************************************/
2516 void reply_unlink(struct smb_request *req)
2518 connection_struct *conn = req->conn;
2520 struct smb_filename *smb_fname = NULL;
2523 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2524 TALLOC_CTX *ctx = talloc_tos();
2526 START_PROFILE(SMBunlink);
2529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2533 dirtype = SVAL(req->vwv+0, 0);
2535 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2536 STR_TERMINATE, &status);
2537 if (!NT_STATUS_IS_OK(status)) {
2538 reply_nterror(req, status);
2542 status = filename_convert(ctx, conn,
2547 if (!NT_STATUS_IS_OK(status)) {
2548 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2549 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2550 ERRSRV, ERRbadpath);
2553 reply_nterror(req, status);
2557 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2559 status = unlink_internals(conn, req, dirtype, smb_fname);
2560 if (!NT_STATUS_IS_OK(status)) {
2561 if (open_was_deferred(req->xconn, req->mid)) {
2562 /* We have re-scheduled this call. */
2565 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2566 bool ok = defer_smb1_sharing_violation(req);
2571 reply_nterror(req, status);
2575 reply_outbuf(req, 0, 0);
2577 TALLOC_FREE(smb_fname);
2578 END_PROFILE(SMBunlink);
2582 /****************************************************************************
2584 ****************************************************************************/
2586 static void fail_readraw(void)
2588 const char *errstr = talloc_asprintf(talloc_tos(),
2589 "FAIL ! reply_readbraw: socket write fail (%s)",
2594 exit_server_cleanly(errstr);
2597 /****************************************************************************
2598 Fake (read/write) sendfile. Returns -1 on read or write fail.
2599 ****************************************************************************/
2601 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
2602 off_t startpos, size_t nread)
2605 size_t tosend = nread;
2612 bufsize = MIN(nread, 65536);
2614 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2618 while (tosend > 0) {
2622 cur_read = MIN(tosend, bufsize);
2623 ret = read_file(fsp,buf,startpos,cur_read);
2629 /* If we had a short read, fill with zeros. */
2630 if (ret < cur_read) {
2631 memset(buf + ret, '\0', cur_read - ret);
2634 ret = write_data(xconn->transport.sock, buf, cur_read);
2635 if (ret != cur_read) {
2636 int saved_errno = errno;
2638 * Try and give an error message saying what
2641 DEBUG(0, ("write_data failed for client %s. "
2643 smbXsrv_connection_dbg(xconn),
2644 strerror(saved_errno)));
2646 errno = saved_errno;
2650 startpos += cur_read;
2654 return (ssize_t)nread;
2657 /****************************************************************************
2658 Deal with the case of sendfile reading less bytes from the file than
2659 requested. Fill with zeros (all we can do). Returns 0 on success
2660 ****************************************************************************/
2662 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
2668 #define SHORT_SEND_BUFSIZE 1024
2669 if (nread < headersize) {
2670 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2671 "header for file %s (%s). Terminating\n",
2672 fsp_str_dbg(fsp), strerror(errno)));
2676 nread -= headersize;
2678 if (nread < smb_maxcnt) {
2679 char buf[SHORT_SEND_BUFSIZE] = { 0 };
2681 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2682 "with zeros !\n", fsp_str_dbg(fsp)));
2684 while (nread < smb_maxcnt) {
2686 * We asked for the real file size and told sendfile
2687 * to not go beyond the end of the file. But it can
2688 * happen that in between our fstat call and the
2689 * sendfile call the file was truncated. This is very
2690 * bad because we have already announced the larger
2691 * number of bytes to the client.
2693 * The best we can do now is to send 0-bytes, just as
2694 * a read from a hole in a sparse file would do.
2696 * This should happen rarely enough that I don't care
2697 * about efficiency here :-)
2702 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2703 ret = write_data(xconn->transport.sock, buf, to_write);
2704 if (ret != to_write) {
2705 int saved_errno = errno;
2707 * Try and give an error message saying what
2710 DEBUG(0, ("write_data failed for client %s. "
2712 smbXsrv_connection_dbg(xconn),
2713 strerror(saved_errno)));
2714 errno = saved_errno;
2724 /****************************************************************************
2725 Return a readbraw error (4 bytes of zero).
2726 ****************************************************************************/
2728 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2734 smbd_lock_socket(xconn);
2735 if (write_data(xconn->transport.sock,header,4) != 4) {
2736 int saved_errno = errno;
2738 * Try and give an error message saying what
2741 DEBUG(0, ("write_data failed for client %s. "
2743 smbXsrv_connection_dbg(xconn),
2744 strerror(saved_errno)));
2745 errno = saved_errno;
2749 smbd_unlock_socket(xconn);
2752 /*******************************************************************
2753 Ensure we don't use sendfile if server smb signing is active.
2754 ********************************************************************/
2756 static bool lp_use_sendfile(int snum, struct smb1_signing_state *signing_state)
2758 bool sign_active = false;
2760 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2761 if (get_Protocol() < PROTOCOL_NT1) {
2764 if (signing_state) {
2765 sign_active = smb1_signing_is_active(signing_state);
2767 return (lp__use_sendfile(snum) &&
2768 (get_remote_arch() != RA_WIN95) &&
2771 /****************************************************************************
2772 Use sendfile in readbraw.
2773 ****************************************************************************/
2775 static void send_file_readbraw(connection_struct *conn,
2776 struct smb_request *req,
2782 struct smbXsrv_connection *xconn = req->xconn;
2783 char *outbuf = NULL;
2787 * We can only use sendfile on a non-chained packet
2788 * but we can use on a non-oplocked file. tridge proved this
2789 * on a train in Germany :-). JRA.
2790 * reply_readbraw has already checked the length.
2793 if ( !req_is_in_chain(req) &&
2795 !fsp_is_alternate_stream(fsp) &&
2796 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
2797 ssize_t sendfile_read = -1;
2799 DATA_BLOB header_blob;
2801 _smb_setlen(header,nread);
2802 header_blob = data_blob_const(header, 4);
2804 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2805 &header_blob, startpos,
2807 if (sendfile_read == -1) {
2808 /* Returning ENOSYS means no data at all was sent.
2809 * Do this as a normal read. */
2810 if (errno == ENOSYS) {
2811 goto normal_readbraw;
2815 * Special hack for broken Linux with no working sendfile. If we
2816 * return EINTR we sent the header but not the rest of the data.
2817 * Fake this up by doing read/write calls.
2819 if (errno == EINTR) {
2820 /* Ensure we don't do this again. */
2821 set_use_sendfile(SNUM(conn), False);
2822 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2824 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2825 DEBUG(0,("send_file_readbraw: "
2826 "fake_sendfile failed for "
2830 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2835 DEBUG(0,("send_file_readbraw: sendfile failed for "
2836 "file %s (%s). Terminating\n",
2837 fsp_str_dbg(fsp), strerror(errno)));
2838 exit_server_cleanly("send_file_readbraw sendfile failed");
2839 } else if (sendfile_read == 0) {
2841 * Some sendfile implementations return 0 to indicate
2842 * that there was a short read, but nothing was
2843 * actually written to the socket. In this case,
2844 * fallback to the normal read path so the header gets
2845 * the correct byte count.
2847 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2848 "bytes falling back to the normal read: "
2849 "%s\n", fsp_str_dbg(fsp)));
2850 goto normal_readbraw;
2853 /* Deal with possible short send. */
2854 if (sendfile_read != 4+nread) {
2855 ret = sendfile_short_send(xconn, fsp,
2856 sendfile_read, 4, nread);
2866 outbuf = talloc_array(NULL, char, nread+4);
2868 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2869 (unsigned)(nread+4)));
2870 reply_readbraw_error(xconn);
2875 ret = read_file(fsp,outbuf+4,startpos,nread);
2876 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2885 _smb_setlen(outbuf,ret);
2886 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2887 int saved_errno = errno;
2889 * Try and give an error message saying what
2892 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2893 smbXsrv_connection_dbg(xconn),
2894 strerror(saved_errno)));
2895 errno = saved_errno;
2900 TALLOC_FREE(outbuf);
2903 /****************************************************************************
2904 Reply to a readbraw (core+ protocol).
2905 ****************************************************************************/
2907 void reply_readbraw(struct smb_request *req)
2909 connection_struct *conn = req->conn;
2910 struct smbXsrv_connection *xconn = req->xconn;
2911 ssize_t maxcount,mincount;
2915 struct lock_struct lock;
2919 START_PROFILE(SMBreadbraw);
2921 if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
2922 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2923 "raw reads/writes are disallowed.");
2927 reply_readbraw_error(xconn);
2928 END_PROFILE(SMBreadbraw);
2932 if (xconn->smb1.echo_handler.trusted_fde) {
2933 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
2934 "'async smb echo handler = yes'\n"));
2935 reply_readbraw_error(xconn);
2936 END_PROFILE(SMBreadbraw);
2941 * Special check if an oplock break has been issued
2942 * and the readraw request croses on the wire, we must
2943 * return a zero length response here.
2946 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2949 * We have to do a check_fsp by hand here, as
2950 * we must always return 4 zero bytes on error,
2956 conn != fsp->conn ||
2957 req->vuid != fsp->vuid ||
2958 fsp->fsp_flags.is_directory ||
2959 fsp_get_io_fd(fsp) == -1)
2962 * fsp could be NULL here so use the value from the packet. JRA.
2964 DEBUG(3,("reply_readbraw: fnum %d not valid "
2966 (int)SVAL(req->vwv+0, 0)));
2967 reply_readbraw_error(xconn);
2968 END_PROFILE(SMBreadbraw);
2972 /* Do a "by hand" version of CHECK_READ. */
2973 if (!(fsp->fsp_flags.can_read ||
2974 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2975 (fsp->access_mask & FILE_EXECUTE)))) {
2976 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2977 (int)SVAL(req->vwv+0, 0)));
2978 reply_readbraw_error(xconn);
2979 END_PROFILE(SMBreadbraw);
2983 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2984 if(req->wct == 10) {
2986 * This is a large offset (64 bit) read.
2989 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
2992 DEBUG(0,("reply_readbraw: negative 64 bit "
2993 "readraw offset (%.0f) !\n",
2994 (double)startpos ));
2995 reply_readbraw_error(xconn);
2996 END_PROFILE(SMBreadbraw);
3001 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3002 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3004 /* ensure we don't overrun the packet size */
3005 maxcount = MIN(65535,maxcount);
3007 init_strict_lock_struct(fsp,
3008 (uint64_t)req->smbpid,
3012 lp_posix_cifsu_locktype(fsp),
3015 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3016 reply_readbraw_error(xconn);
3017 END_PROFILE(SMBreadbraw);
3021 status = vfs_stat_fsp(fsp);
3022 if (NT_STATUS_IS_OK(status)) {
3023 size = fsp->fsp_name->st.st_ex_size;
3026 if (startpos >= size) {
3029 nread = MIN(maxcount,(size - startpos));
3032 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3033 if (nread < mincount)
3037 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3038 "min=%lu nread=%lu\n",
3039 fsp_fnum_dbg(fsp), (double)startpos,
3040 (unsigned long)maxcount,
3041 (unsigned long)mincount,
3042 (unsigned long)nread ) );
3044 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3046 DEBUG(5,("reply_readbraw finished\n"));
3048 END_PROFILE(SMBreadbraw);
3053 #define DBGC_CLASS DBGC_LOCKING
3055 /****************************************************************************
3056 Reply to a lockread (core+ protocol).
3057 ****************************************************************************/
3059 static void reply_lockread_locked(struct tevent_req *subreq);
3061 void reply_lockread(struct smb_request *req)
3063 struct tevent_req *subreq = NULL;
3064 connection_struct *conn = req->conn;
3066 struct smbd_lock_element *lck = NULL;
3068 START_PROFILE(SMBlockread);
3071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3072 END_PROFILE(SMBlockread);
3076 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3078 if (!check_fsp(conn, req, fsp)) {
3079 END_PROFILE(SMBlockread);
3083 if (!CHECK_READ(fsp,req)) {
3084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3085 END_PROFILE(SMBlockread);
3089 lck = talloc(req, struct smbd_lock_element);
3091 reply_nterror(req, NT_STATUS_NO_MEMORY);
3092 END_PROFILE(SMBlockread);
3097 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3098 * protocol request that predates the read/write lock concept.
3099 * Thus instead of asking for a read lock here we need to ask
3100 * for a write lock. JRA.
3101 * Note that the requested lock size is unaffected by max_send.
3104 *lck = (struct smbd_lock_element) {
3105 .req_guid = smbd_request_guid(req, 0),
3106 .smblctx = req->smbpid,
3107 .brltype = WRITE_LOCK,
3108 .lock_flav = WINDOWS_LOCK,
3109 .count = SVAL(req->vwv+1, 0),
3110 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3113 subreq = smbd_smb1_do_locks_send(
3119 false, /* large_offset */
3122 if (subreq == NULL) {
3123 reply_nterror(req, NT_STATUS_NO_MEMORY);
3124 END_PROFILE(SMBlockread);
3127 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3128 END_PROFILE(SMBlockread);
3131 static void reply_lockread_locked(struct tevent_req *subreq)
3133 struct smb_request *req = NULL;
3139 size_t numtoread, maxtoread;
3140 struct files_struct *fsp = NULL;
3143 START_PROFILE(SMBlockread);
3145 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3148 status = smbd_smb1_do_locks_recv(subreq);
3149 TALLOC_FREE(subreq);
3151 if (!NT_STATUS_IS_OK(status)) {
3152 reply_nterror(req, status);
3156 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3158 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3162 numtoread = SVAL(req->vwv+1, 0);
3163 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3166 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3168 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3170 if (numtoread > maxtoread) {
3171 DBG_WARNING("requested read size (%zu) is greater than "
3172 "maximum allowed (%zu/%d). "
3173 "Returning short read of maximum allowed for "
3174 "compatibility with Windows 2000.\n",
3177 req->xconn->smb1.sessions.max_send);
3178 numtoread = maxtoread;
3181 reply_outbuf(req, 5, numtoread + 3);
3183 data = smb_buf(req->outbuf) + 3;
3185 nread = read_file(fsp,data,startpos,numtoread);
3188 reply_nterror(req, map_nt_error_from_unix(errno));
3192 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3194 SSVAL(req->outbuf,smb_vwv0,nread);
3195 SSVAL(req->outbuf,smb_vwv5,nread+3);
3196 p = smb_buf(req->outbuf);
3197 SCVAL(p,0,0); /* pad byte. */
3200 DEBUG(3,("lockread %s num=%d nread=%d\n",
3201 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3204 ok = srv_send_smb(req->xconn,
3205 (char *)req->outbuf,
3208 IS_CONN_ENCRYPTED(req->conn),
3211 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
3214 END_PROFILE(SMBlockread);
3219 #define DBGC_CLASS DBGC_ALL
3221 /****************************************************************************
3223 ****************************************************************************/
3225 void reply_read(struct smb_request *req)
3227 connection_struct *conn = req->conn;
3234 struct lock_struct lock;
3235 struct smbXsrv_connection *xconn = req->xconn;
3237 START_PROFILE(SMBread);
3240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3241 END_PROFILE(SMBread);
3245 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3247 if (!check_fsp(conn, req, fsp)) {
3248 END_PROFILE(SMBread);
3252 if (!CHECK_READ(fsp,req)) {
3253 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3254 END_PROFILE(SMBread);
3258 numtoread = SVAL(req->vwv+1, 0);
3259 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3262 * The requested read size cannot be greater than max_send. JRA.
3264 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3266 if (numtoread > maxtoread) {
3267 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3268 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3269 (unsigned int)numtoread, (unsigned int)maxtoread,
3270 (unsigned int)xconn->smb1.sessions.max_send));
3271 numtoread = maxtoread;
3274 reply_outbuf(req, 5, numtoread+3);
3276 data = smb_buf(req->outbuf) + 3;
3278 init_strict_lock_struct(fsp,
3279 (uint64_t)req->smbpid,
3281 (uint64_t)numtoread,
3283 lp_posix_cifsu_locktype(fsp),
3286 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3287 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3288 END_PROFILE(SMBread);
3293 nread = read_file(fsp,data,startpos,numtoread);
3296 reply_nterror(req, map_nt_error_from_unix(errno));
3300 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3302 SSVAL(req->outbuf,smb_vwv0,nread);
3303 SSVAL(req->outbuf,smb_vwv5,nread+3);
3304 SCVAL(smb_buf(req->outbuf),0,1);
3305 SSVAL(smb_buf(req->outbuf),1,nread);
3307 DEBUG(3, ("read %s num=%d nread=%d\n",
3308 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3311 END_PROFILE(SMBread);
3315 /****************************************************************************
3317 ****************************************************************************/
3319 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3323 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3326 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3328 SCVAL(outbuf,smb_vwv0,0xFF);
3329 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3330 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3331 SSVAL(outbuf,smb_vwv6,
3332 (smb_wct - 4) /* offset from smb header to wct */
3333 + 1 /* the wct field */
3334 + 12 * sizeof(uint16_t) /* vwv */
3335 + 2 /* the buflen field */
3336 + 1); /* padding byte */
3337 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3338 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3339 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3340 _smb_setlen_large(outbuf,
3341 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3345 /****************************************************************************
3346 Reply to a read and X - possibly using sendfile.
3347 ****************************************************************************/
3349 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3350 files_struct *fsp, off_t startpos,
3353 struct smbXsrv_connection *xconn = req->xconn;
3355 struct lock_struct lock;
3356 int saved_errno = 0;
3359 init_strict_lock_struct(fsp,
3360 (uint64_t)req->smbpid,
3362 (uint64_t)smb_maxcnt,
3364 lp_posix_cifsu_locktype(fsp),
3367 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3368 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3373 * We can only use sendfile on a non-chained packet
3374 * but we can use on a non-oplocked file. tridge proved this
3375 * on a train in Germany :-). JRA.
3378 if (!req_is_in_chain(req) &&
3380 !fsp_is_alternate_stream(fsp) &&
3381 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3382 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3385 status = vfs_stat_fsp(fsp);
3386 if (!NT_STATUS_IS_OK(status)) {
3387 reply_nterror(req, status);
3391 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3392 (startpos > fsp->fsp_name->st.st_ex_size) ||
3393 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3395 * We already know that we would do a short read, so don't
3396 * try the sendfile() path.
3398 goto nosendfile_read;
3402 * Set up the packet header before send. We
3403 * assume here the sendfile will work (get the
3404 * correct amount of data).
3407 header = data_blob_const(headerbuf, sizeof(headerbuf));
3409 construct_reply_common_req(req, (char *)headerbuf);
3410 setup_readX_header((char *)headerbuf, smb_maxcnt);
3412 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3413 startpos, smb_maxcnt);
3415 saved_errno = errno;
3417 /* Returning ENOSYS means no data at all was sent.
3418 Do this as a normal read. */
3419 if (errno == ENOSYS) {
3424 * Special hack for broken Linux with no working sendfile. If we
3425 * return EINTR we sent the header but not the rest of the data.
3426 * Fake this up by doing read/write calls.
3429 if (errno == EINTR) {
3430 /* Ensure we don't do this again. */
3431 set_use_sendfile(SNUM(conn), False);
3432 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3433 nread = fake_sendfile(xconn, fsp, startpos,
3436 saved_errno = errno;
3437 DEBUG(0,("send_file_readX: "
3438 "fake_sendfile failed for "
3439 "file %s (%s) for client %s. "
3442 smbXsrv_connection_dbg(xconn),
3443 strerror(saved_errno)));
3444 errno = saved_errno;
3445 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3447 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3448 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3449 /* No outbuf here means successful sendfile. */
3453 DEBUG(0,("send_file_readX: sendfile failed for file "
3454 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3456 exit_server_cleanly("send_file_readX sendfile failed");
3457 } else if (nread == 0) {
3459 * Some sendfile implementations return 0 to indicate
3460 * that there was a short read, but nothing was
3461 * actually written to the socket. In this case,
3462 * fallback to the normal read path so the header gets
3463 * the correct byte count.
3465 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3466 "falling back to the normal read: %s\n",
3471 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3472 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3474 /* Deal with possible short send. */
3475 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3478 ret = sendfile_short_send(xconn, fsp, nread,
3479 sizeof(headerbuf), smb_maxcnt);
3482 r = "send_file_readX: sendfile_short_send failed";
3483 DEBUG(0,("%s for file %s (%s).\n",
3484 r, fsp_str_dbg(fsp), strerror(errno)));
3485 exit_server_cleanly(r);
3488 /* No outbuf here means successful sendfile. */
3489 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3490 SMB_PERFCOUNT_END(&req->pcd);
3496 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3497 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3500 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3501 (startpos > fsp->fsp_name->st.st_ex_size) ||
3502 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3504 * We already know that we would do a short
3505 * read, so don't try the sendfile() path.
3507 goto nosendfile_read;
3510 construct_reply_common_req(req, (char *)headerbuf);
3511 setup_readX_header((char *)headerbuf, smb_maxcnt);
3513 /* Send out the header. */
3514 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3516 if (ret != sizeof(headerbuf)) {
3517 saved_errno = errno;
3519 * Try and give an error message saying what
3522 DEBUG(0,("send_file_readX: write_data failed for file "
3523 "%s (%s) for client %s. Terminating\n",
3525 smbXsrv_connection_dbg(xconn),
3526 strerror(saved_errno)));
3527 errno = saved_errno;
3528 exit_server_cleanly("send_file_readX sendfile failed");
3530 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3532 saved_errno = errno;
3533 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3534 "%s (%s) for client %s. Terminating\n",
3536 smbXsrv_connection_dbg(xconn),
3537 strerror(saved_errno)));
3538 errno = saved_errno;
3539 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3546 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3547 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3548 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3550 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3551 startpos, smb_maxcnt);
3552 saved_errno = errno;
3555 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3559 setup_readX_header((char *)req->outbuf, nread);
3561 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3562 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3566 TALLOC_FREE(req->outbuf);
3570 /****************************************************************************
3571 Work out how much space we have for a read return.
3572 ****************************************************************************/
3574 static size_t calc_max_read_pdu(const struct smb_request *req)
3576 struct smbXsrv_connection *xconn = req->xconn;
3578 if (xconn->protocol < PROTOCOL_NT1) {
3579 return xconn->smb1.sessions.max_send;
3582 if (!lp_large_readwrite()) {
3583 return xconn->smb1.sessions.max_send;
3586 if (req_is_in_chain(req)) {
3587 return xconn->smb1.sessions.max_send;
3590 if (req->encrypted) {
3592 * Don't take encrypted traffic up to the
3593 * limit. There are padding considerations
3594 * that make that tricky.
3596 return xconn->smb1.sessions.max_send;
3599 if (smb1_srv_is_signing_active(xconn)) {
3603 if (!lp_smb1_unix_extensions()) {
3608 * We can do ultra-large POSIX reads.
3613 /****************************************************************************
3614 Calculate how big a read can be. Copes with all clients. It's always
3615 safe to return a short read - Windows does this.
3616 ****************************************************************************/
3618 static size_t calc_read_size(const struct smb_request *req,
3622 struct smbXsrv_connection *xconn = req->xconn;
3623 size_t max_pdu = calc_max_read_pdu(req);
3624 size_t total_size = 0;
3625 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3626 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3629 * Windows explicitly ignores upper size of 0xFFFF.
3630 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3631 * We must do the same as these will never fit even in
3632 * an extended size NetBIOS packet.
3634 if (upper_size == 0xFFFF) {
3638 if (xconn->protocol < PROTOCOL_NT1) {
3642 total_size = ((upper_size<<16) | lower_size);
3645 * LARGE_READX test shows it's always safe to return
3646 * a short read. Windows does so.
3648 return MIN(total_size, max_len);
3651 /****************************************************************************
3652 Reply to a read and X.
3653 ****************************************************************************/
3655 void reply_read_and_X(struct smb_request *req)
3657 connection_struct *conn = req->conn;
3662 bool big_readX = False;
3664 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3667 START_PROFILE(SMBreadX);
3669 if ((req->wct != 10) && (req->wct != 12)) {
3670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3674 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3675 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3676 smb_maxcnt = SVAL(req->vwv+5, 0);
3678 /* If it's an IPC, pass off the pipe handler. */
3680 reply_pipe_read_and_X(req);
3681 END_PROFILE(SMBreadX);
3685 if (!check_fsp(conn, req, fsp)) {
3686 END_PROFILE(SMBreadX);
3690 if (!CHECK_READ(fsp,req)) {
3691 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3692 END_PROFILE(SMBreadX);
3696 upper_size = SVAL(req->vwv+7, 0);
3697 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3698 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3700 * This is a heuristic to avoid keeping large
3701 * outgoing buffers around over long-lived aio
3707 if (req->wct == 12) {
3709 * This is a large offset (64 bit) read.
3711 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3716 NTSTATUS status = schedule_aio_read_and_X(conn,
3721 if (NT_STATUS_IS_OK(status)) {
3722 /* Read scheduled - we're done. */
3725 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3726 /* Real error - report to client. */
3727 END_PROFILE(SMBreadX);
3728 reply_nterror(req, status);
3731 /* NT_STATUS_RETRY - fall back to sync read. */
3734 smbd_lock_socket(req->xconn);
3735 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3736 smbd_unlock_socket(req->xconn);
3739 END_PROFILE(SMBreadX);
3743 /****************************************************************************
3744 Error replies to writebraw must have smb_wct == 1. Fix this up.
3745 ****************************************************************************/
3747 void error_to_writebrawerr(struct smb_request *req)
3749 uint8_t *old_outbuf = req->outbuf;
3751 reply_outbuf(req, 1, 0);
3753 memcpy(req->outbuf, old_outbuf, smb_size);
3754 TALLOC_FREE(old_outbuf);
3757 /****************************************************************************
3758 Read 4 bytes of a smb packet and return the smb length of the packet.
3759 Store the result in the buffer. This version of the function will
3760 never return a session keepalive (length of zero).
3761 Timeout is in milliseconds.
3762 ****************************************************************************/
3764 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3767 uint8_t msgtype = NBSSkeepalive;
3769 while (msgtype == NBSSkeepalive) {
3772 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3774 if (!NT_STATUS_IS_OK(status)) {
3775 char addr[INET6_ADDRSTRLEN];
3776 /* Try and give an error message
3777 * saying what client failed. */
3778 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3779 "client %s read error = %s.\n",
3780 get_peer_addr(fd,addr,sizeof(addr)),
3781 nt_errstr(status)));
3785 msgtype = CVAL(inbuf, 0);
3788 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3789 (unsigned long)len));
3791 return NT_STATUS_OK;
3794 /****************************************************************************
3795 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3796 ****************************************************************************/
3798 void reply_writebraw(struct smb_request *req)
3800 connection_struct *conn = req->conn;
3801 struct smbXsrv_connection *xconn = req->xconn;
3804 ssize_t total_written=0;
3805 size_t numtowrite=0;
3808 const char *data=NULL;
3811 struct lock_struct lock;
3814 START_PROFILE(SMBwritebraw);
3817 * If we ever reply with an error, it must have the SMB command
3818 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3821 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3823 if (smb1_srv_is_signing_active(xconn)) {
3824 END_PROFILE(SMBwritebraw);
3825 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3826 "raw reads/writes are disallowed.");
3829 if (req->wct < 12) {
3830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3831 error_to_writebrawerr(req);
3832 END_PROFILE(SMBwritebraw);
3836 if (xconn->smb1.echo_handler.trusted_fde) {
3837 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3838 "'async smb echo handler = yes'\n"));
3839 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3840 error_to_writebrawerr(req);
3841 END_PROFILE(SMBwritebraw);
3845 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3846 if (!check_fsp(conn, req, fsp)) {
3847 error_to_writebrawerr(req);
3848 END_PROFILE(SMBwritebraw);
3852 if (!CHECK_WRITE(fsp)) {
3853 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3854 error_to_writebrawerr(req);
3855 END_PROFILE(SMBwritebraw);
3859 tcount = IVAL(req->vwv+1, 0);
3860 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3861 write_through = BITSETW(req->vwv+7,0);
3863 /* We have to deal with slightly different formats depending
3864 on whether we are using the core+ or lanman1.0 protocol */
3866 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3867 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3868 data = smb_buf_const(req->inbuf);
3870 numtowrite = SVAL(req->vwv+10, 0);
3871 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3874 /* Ensure we don't write bytes past the end of this packet. */
3876 * This already protects us against CVE-2017-12163.
3878 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3880 error_to_writebrawerr(req);
3881 END_PROFILE(SMBwritebraw);
3885 if (!fsp->print_file) {
3886 init_strict_lock_struct(fsp,
3887 (uint64_t)req->smbpid,
3891 lp_posix_cifsu_locktype(fsp),
3894 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3895 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3896 error_to_writebrawerr(req);
3897 END_PROFILE(SMBwritebraw);
3903 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3906 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3907 "wrote=%d sync=%d\n",
3908 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3909 (int)nwritten, (int)write_through));
3911 if (nwritten < (ssize_t)numtowrite) {
3912 reply_nterror(req, NT_STATUS_DISK_FULL);
3913 error_to_writebrawerr(req);
3917 total_written = nwritten;
3919 /* Allocate a buffer of 64k + length. */
3920 buf = talloc_array(NULL, char, 65540);
3922 reply_nterror(req, NT_STATUS_NO_MEMORY);
3923 error_to_writebrawerr(req);
3927 /* Return a SMBwritebraw message to the redirector to tell
3928 * it to send more bytes */
3930 memcpy(buf, req->inbuf, smb_size);
3931 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3932 SCVAL(buf,smb_com,SMBwritebraw);
3933 SSVALS(buf,smb_vwv0,0xFFFF);
3935 if (!srv_send_smb(req->xconn,
3937 false, 0, /* no signing */
3938 IS_CONN_ENCRYPTED(conn),
3940 exit_server_cleanly("reply_writebraw: srv_send_smb "
3944 /* Now read the raw data into the buffer and write it */
3945 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
3947 if (!NT_STATUS_IS_OK(status)) {
3948 exit_server_cleanly("secondary writebraw failed");
3951 /* Set up outbuf to return the correct size */
3952 reply_outbuf(req, 1, 0);
3954 if (numtowrite != 0) {
3956 if (numtowrite > 0xFFFF) {
3957 DEBUG(0,("reply_writebraw: Oversize secondary write "
3958 "raw requested (%u). Terminating\n",
3959 (unsigned int)numtowrite ));
3960 exit_server_cleanly("secondary writebraw failed");
3963 if (tcount > nwritten+numtowrite) {
3964 DEBUG(3,("reply_writebraw: Client overestimated the "
3966 (int)tcount,(int)nwritten,(int)numtowrite));
3969 status = read_data_ntstatus(xconn->transport.sock, buf+4,
3972 if (!NT_STATUS_IS_OK(status)) {
3973 /* Try and give an error message
3974 * saying what client failed. */
3975 DEBUG(0, ("reply_writebraw: Oversize secondary write "
3976 "raw read failed (%s) for client %s. "
3977 "Terminating\n", nt_errstr(status),
3978 smbXsrv_connection_dbg(xconn)));
3979 exit_server_cleanly("secondary writebraw failed");
3983 * We are not vulnerable to CVE-2017-12163
3984 * here as we are guaranteed to have numtowrite
3985 * bytes available - we just read from the client.
3987 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3988 if (nwritten == -1) {
3990 reply_nterror(req, map_nt_error_from_unix(errno));
3991 error_to_writebrawerr(req);
3995 if (nwritten < (ssize_t)numtowrite) {
3996 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3997 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4001 total_written += nwritten;
4006 SSVAL(req->outbuf,smb_vwv0,total_written);
4008 status = sync_file(conn, fsp, write_through);
4009 if (!NT_STATUS_IS_OK(status)) {
4010 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4011 fsp_str_dbg(fsp), nt_errstr(status)));
4012 reply_nterror(req, status);
4013 error_to_writebrawerr(req);
4017 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4019 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4020 (int)total_written));
4022 /* We won't return a status if write through is not selected - this
4023 * follows what WfWg does */
4024 END_PROFILE(SMBwritebraw);
4026 if (!write_through && total_written==tcount) {
4028 #if RABBIT_PELLET_FIX
4030 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4031 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4034 if (!send_keepalive(xconn->transport.sock)) {
4035 exit_server_cleanly("reply_writebraw: send of "
4036 "keepalive failed");
4039 TALLOC_FREE(req->outbuf);
4044 END_PROFILE(SMBwritebraw);
4049 #define DBGC_CLASS DBGC_LOCKING
4051 /****************************************************************************
4052 Reply to a writeunlock (core+).
4053 ****************************************************************************/
4055 void reply_writeunlock(struct smb_request *req)
4057 connection_struct *conn = req->conn;
4058 ssize_t nwritten = -1;
4063 NTSTATUS status = NT_STATUS_OK;
4065 struct lock_struct lock;
4066 int saved_errno = 0;
4068 START_PROFILE(SMBwriteunlock);
4071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4072 END_PROFILE(SMBwriteunlock);
4076 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4078 if (!check_fsp(conn, req, fsp)) {
4079 END_PROFILE(SMBwriteunlock);
4083 if (!CHECK_WRITE(fsp)) {
4084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4085 END_PROFILE(SMBwriteunlock);
4089 numtowrite = SVAL(req->vwv+1, 0);
4090 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4091 data = (const char *)req->buf + 3;
4094 * Ensure client isn't asking us to write more than
4095 * they sent. CVE-2017-12163.
4097 remaining = smbreq_bufrem(req, data);
4098 if (numtowrite > remaining) {
4099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4100 END_PROFILE(SMBwriteunlock);
4104 if (!fsp->print_file && numtowrite > 0) {
4105 init_strict_lock_struct(fsp,
4106 (uint64_t)req->smbpid,
4108 (uint64_t)numtowrite,
4110 lp_posix_cifsu_locktype(fsp),
4113 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4114 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4115 END_PROFILE(SMBwriteunlock);
4120 /* The special X/Open SMB protocol handling of
4121 zero length writes is *NOT* done for
4123 if(numtowrite == 0) {
4126 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4127 saved_errno = errno;
4130 status = sync_file(conn, fsp, False /* write through */);
4131 if (!NT_STATUS_IS_OK(status)) {
4132 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4133 fsp_str_dbg(fsp), nt_errstr(status)));
4134 reply_nterror(req, status);
4139 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4143 if((nwritten < numtowrite) && (numtowrite != 0)) {
4144 reply_nterror(req, NT_STATUS_DISK_FULL);
4148 if (numtowrite && !fsp->print_file) {
4149 struct smbd_lock_element l = {
4150 .req_guid = smbd_request_guid(req, 0),
4151 .smblctx = req->smbpid,
4152 .brltype = UNLOCK_LOCK,
4153 .lock_flav = WINDOWS_LOCK,
4155 .count = numtowrite,
4157 status = smbd_do_unlocking(req, fsp, 1, &l);
4158 if (NT_STATUS_V(status)) {
4159 reply_nterror(req, status);
4164 reply_outbuf(req, 1, 0);
4166 SSVAL(req->outbuf,smb_vwv0,nwritten);
4168 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4169 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4172 END_PROFILE(SMBwriteunlock);
4177 #define DBGC_CLASS DBGC_ALL
4179 /****************************************************************************
4181 ****************************************************************************/
4183 void reply_write(struct smb_request *req)
4185 connection_struct *conn = req->conn;
4188 ssize_t nwritten = -1;
4192 struct lock_struct lock;
4194 int saved_errno = 0;
4196 START_PROFILE(SMBwrite);
4199 END_PROFILE(SMBwrite);
4200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4204 /* If it's an IPC, pass off the pipe handler. */
4206 reply_pipe_write(req);
4207 END_PROFILE(SMBwrite);
4211 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4213 if (!check_fsp(conn, req, fsp)) {
4214 END_PROFILE(SMBwrite);
4218 if (!CHECK_WRITE(fsp)) {
4219 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4220 END_PROFILE(SMBwrite);
4224 numtowrite = SVAL(req->vwv+1, 0);
4225 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4226 data = (const char *)req->buf + 3;
4229 * Ensure client isn't asking us to write more than
4230 * they sent. CVE-2017-12163.
4232 remaining = smbreq_bufrem(req, data);
4233 if (numtowrite > remaining) {
4234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4235 END_PROFILE(SMBwrite);
4239 if (!fsp->print_file) {
4240 init_strict_lock_struct(fsp,
4241 (uint64_t)req->smbpid,
4243 (uint64_t)numtowrite,
4245 lp_posix_cifsu_locktype(fsp),
4248 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4249 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4250 END_PROFILE(SMBwrite);
4256 * X/Open SMB protocol says that if smb_vwv1 is
4257 * zero then the file size should be extended or
4258 * truncated to the size given in smb_vwv[2-3].
4261 if(numtowrite == 0) {
4263 * This is actually an allocate call, and set EOF. JRA.
4265 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4267 reply_nterror(req, NT_STATUS_DISK_FULL);
4270 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4272 reply_nterror(req, NT_STATUS_DISK_FULL);
4275 trigger_write_time_update_immediate(fsp);
4277 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4280 status = sync_file(conn, fsp, False);
4281 if (!NT_STATUS_IS_OK(status)) {
4282 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4283 fsp_str_dbg(fsp), nt_errstr(status)));
4284 reply_nterror(req, status);
4289 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4293 if((nwritten == 0) && (numtowrite != 0)) {
4294 reply_nterror(req, NT_STATUS_DISK_FULL);
4298 reply_outbuf(req, 1, 0);
4300 SSVAL(req->outbuf,smb_vwv0,nwritten);
4302 if (nwritten < (ssize_t)numtowrite) {
4303 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4304 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4307 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4310 END_PROFILE(SMBwrite);
4314 /****************************************************************************
4315 Ensure a buffer is a valid writeX for recvfile purposes.
4316 ****************************************************************************/
4318 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4319 (2*14) + /* word count (including bcc) */ \
4322 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4323 const uint8_t *inbuf)
4326 unsigned int doff = 0;
4327 size_t len = smb_len_large(inbuf);
4329 struct smbXsrv_open *op = NULL;
4330 struct files_struct *fsp = NULL;
4333 if (is_encrypted_packet(inbuf)) {
4334 /* Can't do this on encrypted
4339 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4343 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4344 CVAL(inbuf,smb_wct) != 14) {
4345 DEBUG(10,("is_valid_writeX_buffer: chained or "
4346 "invalid word length.\n"));
4350 fnum = SVAL(inbuf, smb_vwv2);
4351 status = smb1srv_open_lookup(xconn,
4355 if (!NT_STATUS_IS_OK(status)) {
4356 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4361 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4364 if (fsp->conn == NULL) {
4365 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4369 if (IS_IPC(fsp->conn)) {
4370 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4373 if (IS_PRINT(fsp->conn)) {
4374 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4377 if (fsp_is_alternate_stream(fsp)) {
4378 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4381 doff = SVAL(inbuf,smb_vwv11);
4383 numtowrite = SVAL(inbuf,smb_vwv10);
4385 if (len > doff && len - doff > 0xFFFF) {
4386 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4389 if (numtowrite == 0) {
4390 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4394 /* Ensure the sizes match up. */
4395 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4396 /* no pad byte...old smbclient :-( */
4397 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4399 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4403 if (len - doff != numtowrite) {
4404 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4405 "len = %u, doff = %u, numtowrite = %u\n",
4408 (unsigned int)numtowrite ));
4412 DEBUG(10,("is_valid_writeX_buffer: true "
4413 "len = %u, doff = %u, numtowrite = %u\n",
4416 (unsigned int)numtowrite ));
4421 /****************************************************************************
4422 Reply to a write and X.
4423 ****************************************************************************/
4425 void reply_write_and_X(struct smb_request *req)
4427 connection_struct *conn = req->conn;
4428 struct smbXsrv_connection *xconn = req->xconn;
4430 struct lock_struct lock;
4435 unsigned int smb_doff;
4436 unsigned int smblen;
4439 int saved_errno = 0;
4441 START_PROFILE(SMBwriteX);
4443 if ((req->wct != 12) && (req->wct != 14)) {
4444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4448 numtowrite = SVAL(req->vwv+10, 0);
4449 smb_doff = SVAL(req->vwv+11, 0);
4450 smblen = smb_len(req->inbuf);
4452 if (req->unread_bytes > 0xFFFF ||
4453 (smblen > smb_doff &&
4454 smblen - smb_doff > 0xFFFF)) {
4455 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4458 if (req->unread_bytes) {
4459 /* Can't do a recvfile write on IPC$ */
4461 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4464 if (numtowrite != req->unread_bytes) {
4465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4470 * This already protects us against CVE-2017-12163.
4472 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4473 smb_doff + numtowrite > smblen) {
4474 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4479 /* If it's an IPC, pass off the pipe handler. */
4481 if (req->unread_bytes) {
4482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4485 reply_pipe_write_and_X(req);
4489 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4490 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4491 write_through = BITSETW(req->vwv+7,0);
4493 if (!check_fsp(conn, req, fsp)) {
4497 if (!CHECK_WRITE(fsp)) {
4498 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4502 data = smb_base(req->inbuf) + smb_doff;
4504 if(req->wct == 14) {
4506 * This is a large offset (64 bit) write.
4508 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4512 /* X/Open SMB protocol says that, unlike SMBwrite
4513 if the length is zero then NO truncation is
4514 done, just a write of zero. To truncate a file,
4517 if(numtowrite == 0) {
4520 if (req->unread_bytes == 0) {
4521 status = schedule_aio_write_and_X(conn,
4528 if (NT_STATUS_IS_OK(status)) {
4529 /* write scheduled - we're done. */
4532 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4533 /* Real error - report to client. */
4534 reply_nterror(req, status);
4537 /* NT_STATUS_RETRY - fall through to sync write. */
4540 init_strict_lock_struct(fsp,
4541 (uint64_t)req->smbpid,
4543 (uint64_t)numtowrite,
4545 lp_posix_cifsu_locktype(fsp),
4548 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4549 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4553 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4554 saved_errno = errno;
4558 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4562 if((nwritten == 0) && (numtowrite != 0)) {
4563 reply_nterror(req, NT_STATUS_DISK_FULL);
4567 reply_outbuf(req, 6, 0);
4568 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4569 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4570 SSVAL(req->outbuf,smb_vwv2,nwritten);
4571 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4573 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4574 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4576 status = sync_file(conn, fsp, write_through);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4579 fsp_str_dbg(fsp), nt_errstr(status)));
4580 reply_nterror(req, status);
4584 END_PROFILE(SMBwriteX);
4588 if (req->unread_bytes) {
4589 /* writeX failed. drain socket. */
4590 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4591 req->unread_bytes) {
4592 smb_panic("failed to drain pending bytes");
4594 req->unread_bytes = 0;
4597 END_PROFILE(SMBwriteX);
4601 /****************************************************************************
4603 ****************************************************************************/
4605 void reply_lseek(struct smb_request *req)
4607 connection_struct *conn = req->conn;
4614 START_PROFILE(SMBlseek);
4617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4618 END_PROFILE(SMBlseek);
4622 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4624 if (!check_fsp(conn, req, fsp)) {
4628 mode = SVAL(req->vwv+1, 0) & 3;
4629 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4630 startpos = (off_t)IVALS(req->vwv+2, 0);
4639 res = fh_get_pos(fsp->fh) + startpos;
4650 if (umode == SEEK_END) {
4651 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4652 if(errno == EINVAL) {
4653 off_t current_pos = startpos;
4655 status = vfs_stat_fsp(fsp);
4656 if (!NT_STATUS_IS_OK(status)) {
4657 reply_nterror(req, status);
4658 END_PROFILE(SMBlseek);
4662 current_pos += fsp->fsp_name->st.st_ex_size;
4664 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4669 reply_nterror(req, map_nt_error_from_unix(errno));
4670 END_PROFILE(SMBlseek);
4675 fh_set_pos(fsp->fh, res);
4677 reply_outbuf(req, 2, 0);
4678 SIVAL(req->outbuf,smb_vwv0,res);
4680 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4681 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4683 END_PROFILE(SMBlseek);
4687 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4690 connection_struct *conn = talloc_get_type_abort(
4691 private_data, connection_struct);
4693 if (conn != fsp->conn) {
4696 if (fsp_get_io_fd(fsp) == -1) {
4699 sync_file(conn, fsp, True /* write through */);
4701 if (fsp->fsp_flags.modified) {
4702 trigger_write_time_update_immediate(fsp);
4708 /****************************************************************************
4710 ****************************************************************************/
4712 void reply_flush(struct smb_request *req)
4714 connection_struct *conn = req->conn;
4718 START_PROFILE(SMBflush);
4721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4725 fnum = SVAL(req->vwv+0, 0);
4726 fsp = file_fsp(req, fnum);
4728 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4733 files_forall(req->sconn, file_sync_one_fn, conn);
4735 NTSTATUS status = sync_file(conn, fsp, True);
4736 if (!NT_STATUS_IS_OK(status)) {
4737 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4738 fsp_str_dbg(fsp), nt_errstr(status)));
4739 reply_nterror(req, status);
4740 END_PROFILE(SMBflush);
4743 if (fsp->fsp_flags.modified) {
4744 trigger_write_time_update_immediate(fsp);
4748 reply_outbuf(req, 0, 0);
4750 DEBUG(3,("flush\n"));
4751 END_PROFILE(SMBflush);
4755 /****************************************************************************
4757 conn POINTER CAN BE NULL HERE !
4758 ****************************************************************************/
4760 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4761 static void reply_exit_done(struct tevent_req *req);
4763 void reply_exit(struct smb_request *smb1req)
4765 struct tevent_req *req;
4768 * Don't setup the profile charge here, take
4769 * it in reply_exit_done(). Not strictly correct
4770 * but better than the other SMB1 async
4771 * code that double-charges at the moment.
4773 req = reply_exit_send(smb1req);
4775 /* Not going async, profile here. */
4776 START_PROFILE(SMBexit);
4777 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4778 END_PROFILE(SMBexit);
4782 /* We're async. This will complete later. */
4783 tevent_req_set_callback(req, reply_exit_done, smb1req);
4787 struct reply_exit_state {
4788 struct tevent_queue *wait_queue;
4791 static void reply_exit_wait_done(struct tevent_req *subreq);
4793 /****************************************************************************
4795 Note, on failure here we deallocate and return NULL to allow the caller to
4796 SMB1 return an error of ERRnomem immediately.
4797 ****************************************************************************/
4799 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4801 struct tevent_req *req;
4802 struct reply_exit_state *state;
4803 struct tevent_req *subreq;
4805 struct smbd_server_connection *sconn = smb1req->sconn;
4807 req = tevent_req_create(smb1req, &state,
4808 struct reply_exit_state);
4812 state->wait_queue = tevent_queue_create(state,
4813 "reply_exit_wait_queue");
4814 if (tevent_req_nomem(state->wait_queue, req)) {
4819 for (fsp = sconn->files; fsp; fsp = fsp->next) {
4820 if (fsp->file_pid != smb1req->smbpid) {
4823 if (fsp->vuid != smb1req->vuid) {
4827 * Flag the file as close in progress.
4828 * This will prevent any more IO being
4831 fsp->fsp_flags.closing = true;
4833 if (fsp->num_aio_requests > 0) {
4835 * Now wait until all aio requests on this fsp are
4838 * We don't set a callback, as we just want to block the
4839 * wait queue and the talloc_free() of fsp->aio_request
4840 * will remove the item from the wait queue.
4842 subreq = tevent_queue_wait_send(fsp->aio_requests,
4845 if (tevent_req_nomem(subreq, req)) {
4853 * Now we add our own waiter to the end of the queue,
4854 * this way we get notified when all pending requests are finished
4855 * and reply to the outstanding SMB1 request.
4857 subreq = tevent_queue_wait_send(state,
4860 if (tevent_req_nomem(subreq, req)) {
4866 * We're really going async - move the SMB1 request from
4867 * a talloc stackframe above us to the conn talloc-context.
4868 * We need this to stick around until the wait_done
4869 * callback is invoked.
4871 smb1req = talloc_move(sconn, &smb1req);
4873 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4878 static void reply_exit_wait_done(struct tevent_req *subreq)
4880 struct tevent_req *req = tevent_req_callback_data(
4881 subreq, struct tevent_req);
4883 tevent_queue_wait_recv(subreq);
4884 TALLOC_FREE(subreq);
4885 tevent_req_done(req);
4888 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4890 return tevent_req_simple_recv_ntstatus(req);
4893 static void reply_exit_done(struct tevent_req *req)
4895 struct smb_request *smb1req = tevent_req_callback_data(
4896 req, struct smb_request);
4897 struct smbd_server_connection *sconn = smb1req->sconn;
4898 struct smbXsrv_connection *xconn = smb1req->xconn;
4899 NTTIME now = timeval_to_nttime(&smb1req->request_time);
4900 struct smbXsrv_session *session = NULL;
4901 files_struct *fsp, *next;
4905 * Take the profile charge here. Not strictly
4906 * correct but better than the other SMB1 async
4907 * code that double-charges at the moment.
4909 START_PROFILE(SMBexit);
4911 status = reply_exit_recv(req);
4913 if (!NT_STATUS_IS_OK(status)) {
4914 TALLOC_FREE(smb1req);
4915 END_PROFILE(SMBexit);
4916 exit_server(__location__ ": reply_exit_recv failed");
4921 * Ensure the session is still valid.
4923 status = smb1srv_session_lookup(xconn,
4927 if (!NT_STATUS_IS_OK(status)) {
4928 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4929 smb_request_done(smb1req);
4930 END_PROFILE(SMBexit);
4934 * Ensure the vuid is still valid - no one
4935 * called reply_ulogoffX() in the meantime.
4936 * reply_exit() doesn't have AS_USER set, so
4937 * use set_current_user_info() directly.
4938 * This is the same logic as in switch_message().
4940 if (session->global->auth_session_info != NULL) {
4941 set_current_user_info(
4942 session->global->auth_session_info->unix_info->sanitized_username,
4943 session->global->auth_session_info->unix_info->unix_name,
4944 session->global->auth_session_info->info->domain_name);
4947 /* No more aio - do the actual closes. */
4948 for (fsp = sconn->files; fsp; fsp = next) {
4952 if (fsp->file_pid != smb1req->smbpid) {
4955 if (fsp->vuid != smb1req->vuid) {
4958 if (!fsp->fsp_flags.closing) {
4963 * reply_exit() has the DO_CHDIR flag set.
4965 ok = chdir_current_service(fsp->conn);
4967 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4968 smb_request_done(smb1req);
4969 END_PROFILE(SMBexit);
4971 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
4974 reply_outbuf(smb1req, 0, 0);
4976 * The following call is needed to push the
4977 * reply data back out the socket after async
4978 * return. Plus it frees smb1req.
4980 smb_request_done(smb1req);
4981 DBG_INFO("reply_exit complete\n");
4982 END_PROFILE(SMBexit);
4986 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
4988 static void reply_close_done(struct tevent_req *req);
4990 void reply_close(struct smb_request *smb1req)
4992 connection_struct *conn = smb1req->conn;
4993 NTSTATUS status = NT_STATUS_OK;
4994 files_struct *fsp = NULL;
4995 START_PROFILE(SMBclose);
4997 if (smb1req->wct < 3) {
4998 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
4999 END_PROFILE(SMBclose);
5003 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5006 * We can only use check_fsp if we know it's not a directory.
5009 if (!check_fsp_open(conn, smb1req, fsp)) {
5010 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5011 END_PROFILE(SMBclose);
5015 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5016 fsp->fsp_flags.is_directory ?
5017 "directory" : "file",
5018 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5019 conn->num_files_open);
5021 if (!fsp->fsp_flags.is_directory) {
5025 * Take care of any time sent in the close.
5028 t = srv_make_unix_date3(smb1req->vwv+1);
5029 set_close_write_time(fsp, time_t_to_full_timespec(t));
5032 if (fsp->num_aio_requests != 0) {
5033 struct tevent_req *req;
5035 req = reply_close_send(smb1req, fsp);
5037 status = NT_STATUS_NO_MEMORY;
5040 /* We're async. This will complete later. */
5041 tevent_req_set_callback(req, reply_close_done, smb1req);
5042 END_PROFILE(SMBclose);
5047 * close_file_free() returns the unix errno if an error was detected on
5048 * close - normally this is due to a disk full error. If not then it
5049 * was probably an I/O error.
5052 status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
5054 if (!NT_STATUS_IS_OK(status)) {
5055 reply_nterror(smb1req, status);
5056 END_PROFILE(SMBclose);
5060 reply_outbuf(smb1req, 0, 0);
5061 END_PROFILE(SMBclose);
5065 struct reply_close_state {
5067 struct tevent_queue *wait_queue;
5070 static void reply_close_wait_done(struct tevent_req *subreq);
5072 /****************************************************************************
5074 Note, on failure here we deallocate and return NULL to allow the caller to
5075 SMB1 return an error of ERRnomem immediately.
5076 ****************************************************************************/
5078 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5081 struct tevent_req *req;
5082 struct reply_close_state *state;
5083 struct tevent_req *subreq;
5084 struct smbd_server_connection *sconn = smb1req->sconn;
5086 req = tevent_req_create(smb1req, &state,
5087 struct reply_close_state);
5091 state->wait_queue = tevent_queue_create(state,
5092 "reply_close_wait_queue");
5093 if (tevent_req_nomem(state->wait_queue, req)) {
5099 * Flag the file as close in progress.
5100 * This will prevent any more IO being
5103 fsp->fsp_flags.closing = true;
5106 * Now wait until all aio requests on this fsp are
5109 * We don't set a callback, as we just want to block the
5110 * wait queue and the talloc_free() of fsp->aio_request
5111 * will remove the item from the wait queue.
5113 subreq = tevent_queue_wait_send(fsp->aio_requests,
5116 if (tevent_req_nomem(subreq, req)) {
5122 * Now we add our own waiter to the end of the queue,
5123 * this way we get notified when all pending requests are finished
5124 * and reply to the outstanding SMB1 request.
5126 subreq = tevent_queue_wait_send(state,
5129 if (tevent_req_nomem(subreq, req)) {
5135 * We're really going async - move the SMB1 request from
5136 * a talloc stackframe above us to the conn talloc-context.
5137 * We need this to stick around until the wait_done
5138 * callback is invoked.
5140 smb1req = talloc_move(sconn, &smb1req);
5142 tevent_req_set_callback(subreq, reply_close_wait_done, req);
5147 static void reply_close_wait_done(struct tevent_req *subreq)
5149 struct tevent_req *req = tevent_req_callback_data(
5150 subreq, struct tevent_req);
5152 tevent_queue_wait_recv(subreq);
5153 TALLOC_FREE(subreq);
5154 tevent_req_done(req);
5157 static NTSTATUS reply_close_recv(struct tevent_req *req)
5159 return tevent_req_simple_recv_ntstatus(req);
5162 static void reply_close_done(struct tevent_req *req)
5164 struct smb_request *smb1req = tevent_req_callback_data(
5165 req, struct smb_request);
5166 struct reply_close_state *state = tevent_req_data(req,
5167 struct reply_close_state);
5170 status = reply_close_recv(req);
5172 if (!NT_STATUS_IS_OK(status)) {
5173 TALLOC_FREE(smb1req);
5174 exit_server(__location__ ": reply_close_recv failed");
5178 status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
5179 if (NT_STATUS_IS_OK(status)) {
5180 reply_outbuf(smb1req, 0, 0);
5182 reply_nterror(smb1req, status);
5185 * The following call is needed to push the
5186 * reply data back out the socket after async
5187 * return. Plus it frees smb1req.
5189 smb_request_done(smb1req);
5192 /****************************************************************************
5193 Reply to a writeclose (Core+ protocol).
5194 ****************************************************************************/
5196 void reply_writeclose(struct smb_request *req)
5198 connection_struct *conn = req->conn;
5201 ssize_t nwritten = -1;
5202 NTSTATUS close_status = NT_STATUS_OK;
5205 struct timespec mtime;
5207 struct lock_struct lock;
5209 START_PROFILE(SMBwriteclose);
5212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5213 END_PROFILE(SMBwriteclose);
5217 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5219 if (!check_fsp(conn, req, fsp)) {
5220 END_PROFILE(SMBwriteclose);
5223 if (!CHECK_WRITE(fsp)) {
5224 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5225 END_PROFILE(SMBwriteclose);
5229 numtowrite = SVAL(req->vwv+1, 0);
5230 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5231 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5232 data = (const char *)req->buf + 1;
5235 * Ensure client isn't asking us to write more than
5236 * they sent. CVE-2017-12163.
5238 remaining = smbreq_bufrem(req, data);
5239 if (numtowrite > remaining) {
5240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5241 END_PROFILE(SMBwriteclose);
5245 if (fsp->print_file == NULL) {
5246 init_strict_lock_struct(fsp,
5247 (uint64_t)req->smbpid,
5249 (uint64_t)numtowrite,
5251 lp_posix_cifsu_locktype(fsp),
5254 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5255 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5256 END_PROFILE(SMBwriteclose);
5261 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5263 set_close_write_time(fsp, mtime);
5266 * More insanity. W2K only closes the file if writelen > 0.
5270 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5271 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5272 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5275 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5276 "file %s\n", fsp_str_dbg(fsp)));
5277 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5280 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5281 reply_nterror(req, NT_STATUS_DISK_FULL);
5285 if(!NT_STATUS_IS_OK(close_status)) {
5286 reply_nterror(req, close_status);
5290 reply_outbuf(req, 1, 0);
5292 SSVAL(req->outbuf,smb_vwv0,nwritten);
5296 END_PROFILE(SMBwriteclose);
5301 #define DBGC_CLASS DBGC_LOCKING
5303 /****************************************************************************
5305 ****************************************************************************/
5307 static void reply_lock_done(struct tevent_req *subreq);
5309 void reply_lock(struct smb_request *req)
5311 struct tevent_req *subreq = NULL;
5312 connection_struct *conn = req->conn;
5314 struct smbd_lock_element *lck = NULL;
5316 START_PROFILE(SMBlock);
5319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5320 END_PROFILE(SMBlock);
5324 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5326 if (!check_fsp(conn, req, fsp)) {
5327 END_PROFILE(SMBlock);
5331 lck = talloc(req, struct smbd_lock_element);
5333 reply_nterror(req, NT_STATUS_NO_MEMORY);
5334 END_PROFILE(SMBlock);
5338 *lck = (struct smbd_lock_element) {
5339 .req_guid = smbd_request_guid(req, 0),
5340 .smblctx = req->smbpid,
5341 .brltype = WRITE_LOCK,
5342 .lock_flav = WINDOWS_LOCK,
5343 .count = IVAL(req->vwv+1, 0),
5344 .offset = IVAL(req->vwv+3, 0),
5347 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5353 subreq = smbd_smb1_do_locks_send(
5359 false, /* large_offset */
5362 if (subreq == NULL) {
5363 reply_nterror(req, NT_STATUS_NO_MEMORY);
5364 END_PROFILE(SMBlock);
5367 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5368 END_PROFILE(SMBlock);
5371 static void reply_lock_done(struct tevent_req *subreq)
5373 struct smb_request *req = NULL;
5377 START_PROFILE(SMBlock);
5379 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5382 status = smbd_smb1_do_locks_recv(subreq);
5383 TALLOC_FREE(subreq);
5385 if (NT_STATUS_IS_OK(status)) {
5386 reply_outbuf(req, 0, 0);
5388 reply_nterror(req, status);
5391 ok = srv_send_smb(req->xconn,
5392 (char *)req->outbuf,
5395 IS_CONN_ENCRYPTED(req->conn),
5398 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5401 END_PROFILE(SMBlock);
5404 /****************************************************************************
5406 ****************************************************************************/
5408 void reply_unlock(struct smb_request *req)
5410 connection_struct *conn = req->conn;
5413 struct smbd_lock_element lck;
5415 START_PROFILE(SMBunlock);
5418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5419 END_PROFILE(SMBunlock);
5423 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5425 if (!check_fsp(conn, req, fsp)) {
5426 END_PROFILE(SMBunlock);
5430 lck = (struct smbd_lock_element) {
5431 .req_guid = smbd_request_guid(req, 0),
5432 .smblctx = req->smbpid,
5433 .brltype = UNLOCK_LOCK,
5434 .lock_flav = WINDOWS_LOCK,
5435 .offset = IVAL(req->vwv+3, 0),
5436 .count = IVAL(req->vwv+1, 0),
5439 status = smbd_do_unlocking(req, fsp, 1, &lck);
5441 if (!NT_STATUS_IS_OK(status)) {
5442 reply_nterror(req, status);
5443 END_PROFILE(SMBunlock);
5447 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5453 reply_outbuf(req, 0, 0);
5455 END_PROFILE(SMBunlock);
5460 #define DBGC_CLASS DBGC_ALL
5462 /****************************************************************************
5464 conn POINTER CAN BE NULL HERE !
5465 ****************************************************************************/
5467 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5468 static void reply_tdis_done(struct tevent_req *req);
5470 void reply_tdis(struct smb_request *smb1req)
5472 connection_struct *conn = smb1req->conn;
5473 struct tevent_req *req;
5476 * Don't setup the profile charge here, take
5477 * it in reply_tdis_done(). Not strictly correct
5478 * but better than the other SMB1 async
5479 * code that double-charges at the moment.
5483 /* Not going async, profile here. */
5484 START_PROFILE(SMBtdis);
5485 DBG_INFO("Invalid connection in tdis\n");
5486 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5487 END_PROFILE(SMBtdis);
5491 req = reply_tdis_send(smb1req);
5493 /* Not going async, profile here. */
5494 START_PROFILE(SMBtdis);
5495 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5496 END_PROFILE(SMBtdis);
5499 /* We're async. This will complete later. */
5500 tevent_req_set_callback(req, reply_tdis_done, smb1req);
5504 struct reply_tdis_state {
5505 struct tevent_queue *wait_queue;
5508 static void reply_tdis_wait_done(struct tevent_req *subreq);
5510 /****************************************************************************
5512 Note, on failure here we deallocate and return NULL to allow the caller to
5513 SMB1 return an error of ERRnomem immediately.
5514 ****************************************************************************/
5516 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5518 struct tevent_req *req;
5519 struct reply_tdis_state *state;
5520 struct tevent_req *subreq;
5521 connection_struct *conn = smb1req->conn;
5524 req = tevent_req_create(smb1req, &state,
5525 struct reply_tdis_state);
5529 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5530 if (tevent_req_nomem(state->wait_queue, req)) {
5536 * Make sure that no new request will be able to use this tcon.
5537 * This ensures that once all outstanding fsp->aio_requests
5538 * on this tcon are done, we are safe to close it.
5540 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5542 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5543 if (fsp->conn != conn) {
5547 * Flag the file as close in progress.
5548 * This will prevent any more IO being
5549 * done on it. Not strictly needed, but
5550 * doesn't hurt to flag it as closing.
5552 fsp->fsp_flags.closing = true;
5554 if (fsp->num_aio_requests > 0) {
5556 * Now wait until all aio requests on this fsp are
5559 * We don't set a callback, as we just want to block the
5560 * wait queue and the talloc_free() of fsp->aio_request
5561 * will remove the item from the wait queue.
5563 subreq = tevent_queue_wait_send(fsp->aio_requests,
5564 conn->sconn->ev_ctx,
5566 if (tevent_req_nomem(subreq, req)) {
5574 * Now we add our own waiter to the end of the queue,
5575 * this way we get notified when all pending requests are finished
5576 * and reply to the outstanding SMB1 request.
5578 subreq = tevent_queue_wait_send(state,
5579 conn->sconn->ev_ctx,
5581 if (tevent_req_nomem(subreq, req)) {
5587 * We're really going async - move the SMB1 request from
5588 * a talloc stackframe above us to the sconn talloc-context.
5589 * We need this to stick around until the wait_done
5590 * callback is invoked.
5592 smb1req = talloc_move(smb1req->sconn, &smb1req);
5594 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5599 static void reply_tdis_wait_done(struct tevent_req *subreq)
5601 struct tevent_req *req = tevent_req_callback_data(
5602 subreq, struct tevent_req);
5604 tevent_queue_wait_recv(subreq);
5605 TALLOC_FREE(subreq);
5606 tevent_req_done(req);
5609 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5611 return tevent_req_simple_recv_ntstatus(req);
5614 static void reply_tdis_done(struct tevent_req *req)
5616 struct smb_request *smb1req = tevent_req_callback_data(
5617 req, struct smb_request);
5619 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5623 * Take the profile charge here. Not strictly
5624 * correct but better than the other SMB1 async
5625 * code that double-charges at the moment.
5627 START_PROFILE(SMBtdis);
5629 status = reply_tdis_recv(req);
5631 if (!NT_STATUS_IS_OK(status)) {
5632 TALLOC_FREE(smb1req);
5633 END_PROFILE(SMBtdis);
5634 exit_server(__location__ ": reply_tdis_recv failed");
5639 * As we've been awoken, we may have changed
5640 * directory in the meantime.
5641 * reply_tdis() has the DO_CHDIR flag set.
5643 ok = chdir_current_service(smb1req->conn);
5645 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5646 smb_request_done(smb1req);
5647 END_PROFILE(SMBtdis);
5650 status = smbXsrv_tcon_disconnect(tcon,
5652 if (!NT_STATUS_IS_OK(status)) {
5653 TALLOC_FREE(smb1req);
5654 END_PROFILE(SMBtdis);
5655 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5659 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5660 smb1req->conn = NULL;
5664 reply_outbuf(smb1req, 0, 0);
5666 * The following call is needed to push the
5667 * reply data back out the socket after async
5668 * return. Plus it frees smb1req.
5670 smb_request_done(smb1req);
5671 END_PROFILE(SMBtdis);
5674 /****************************************************************************
5676 conn POINTER CAN BE NULL HERE !
5677 ****************************************************************************/
5679 void reply_echo(struct smb_request *req)
5681 connection_struct *conn = req->conn;
5682 struct smb_perfcount_data local_pcd;
5683 struct smb_perfcount_data *cur_pcd;
5687 START_PROFILE(SMBecho);
5689 smb_init_perfcount_data(&local_pcd);
5692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5693 END_PROFILE(SMBecho);
5697 smb_reverb = SVAL(req->vwv+0, 0);
5699 reply_outbuf(req, 1, req->buflen);
5701 /* copy any incoming data back out */
5702 if (req->buflen > 0) {
5703 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5706 if (smb_reverb > 100) {
5707 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5711 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5713 /* this makes sure we catch the request pcd */
5714 if (seq_num == smb_reverb) {
5715 cur_pcd = &req->pcd;
5717 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5718 cur_pcd = &local_pcd;
5721 SSVAL(req->outbuf,smb_vwv0,seq_num);
5723 show_msg((char *)req->outbuf);
5724 if (!srv_send_smb(req->xconn,
5725 (char *)req->outbuf,
5726 true, req->seqnum+1,
5727 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5729 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5732 DEBUG(3,("echo %d times\n", smb_reverb));
5734 TALLOC_FREE(req->outbuf);
5736 END_PROFILE(SMBecho);
5740 /****************************************************************************
5741 Reply to a printopen.
5742 ****************************************************************************/
5744 void reply_printopen(struct smb_request *req)
5746 connection_struct *conn = req->conn;
5750 START_PROFILE(SMBsplopen);
5753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5754 END_PROFILE(SMBsplopen);
5758 if (!CAN_PRINT(conn)) {
5759 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5760 END_PROFILE(SMBsplopen);
5764 status = file_new(req, conn, &fsp);
5765 if(!NT_STATUS_IS_OK(status)) {
5766 reply_nterror(req, status);
5767 END_PROFILE(SMBsplopen);
5771 /* Open for exclusive use, write only. */
5772 status = print_spool_open(fsp, NULL, req->vuid);
5774 if (!NT_STATUS_IS_OK(status)) {
5775 file_free(req, fsp);
5776 reply_nterror(req, status);
5777 END_PROFILE(SMBsplopen);
5781 reply_outbuf(req, 1, 0);
5782 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5784 DEBUG(3,("openprint fd=%d %s\n",
5785 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5787 END_PROFILE(SMBsplopen);
5791 /****************************************************************************
5792 Reply to a printclose.
5793 ****************************************************************************/
5795 void reply_printclose(struct smb_request *req)
5797 connection_struct *conn = req->conn;
5801 START_PROFILE(SMBsplclose);
5804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5805 END_PROFILE(SMBsplclose);
5809 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5811 if (!check_fsp(conn, req, fsp)) {
5812 END_PROFILE(SMBsplclose);
5816 if (!CAN_PRINT(conn)) {
5817 reply_force_doserror(req, ERRSRV, ERRerror);
5818 END_PROFILE(SMBsplclose);
5822 DEBUG(3,("printclose fd=%d %s\n",
5823 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5825 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5827 if(!NT_STATUS_IS_OK(status)) {
5828 reply_nterror(req, status);
5829 END_PROFILE(SMBsplclose);
5833 reply_outbuf(req, 0, 0);
5835 END_PROFILE(SMBsplclose);
5839 /****************************************************************************
5840 Reply to a printqueue.
5841 ****************************************************************************/
5843 void reply_printqueue(struct smb_request *req)
5845 const struct loadparm_substitution *lp_sub =
5846 loadparm_s3_global_substitution();
5847 connection_struct *conn = req->conn;
5851 START_PROFILE(SMBsplretq);
5854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5855 END_PROFILE(SMBsplretq);
5859 max_count = SVAL(req->vwv+0, 0);
5860 start_index = SVAL(req->vwv+1, 0);
5862 /* we used to allow the client to get the cnum wrong, but that
5863 is really quite gross and only worked when there was only
5864 one printer - I think we should now only accept it if they
5865 get it right (tridge) */
5866 if (!CAN_PRINT(conn)) {
5867 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5868 END_PROFILE(SMBsplretq);
5872 reply_outbuf(req, 2, 3);
5873 SSVAL(req->outbuf,smb_vwv0,0);
5874 SSVAL(req->outbuf,smb_vwv1,0);
5875 SCVAL(smb_buf(req->outbuf),0,1);
5876 SSVAL(smb_buf(req->outbuf),1,0);
5878 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5879 start_index, max_count));
5882 TALLOC_CTX *mem_ctx = talloc_tos();
5885 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5886 struct rpc_pipe_client *cli = NULL;
5887 struct dcerpc_binding_handle *b = NULL;
5888 struct policy_handle handle;
5889 struct spoolss_DevmodeContainer devmode_ctr;
5890 union spoolss_JobInfo *info;
5892 uint32_t num_to_get;
5896 ZERO_STRUCT(handle);
5898 status = rpc_pipe_open_interface(mem_ctx,
5901 conn->sconn->remote_address,
5902 conn->sconn->local_address,
5903 conn->sconn->msg_ctx,
5905 if (!NT_STATUS_IS_OK(status)) {
5906 DEBUG(0, ("reply_printqueue: "
5907 "could not connect to spoolss: %s\n",
5908 nt_errstr(status)));
5909 reply_nterror(req, status);
5912 b = cli->binding_handle;
5914 ZERO_STRUCT(devmode_ctr);
5916 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5919 SEC_FLAG_MAXIMUM_ALLOWED,
5922 if (!NT_STATUS_IS_OK(status)) {
5923 reply_nterror(req, status);
5926 if (!W_ERROR_IS_OK(werr)) {
5927 reply_nterror(req, werror_to_ntstatus(werr));
5931 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5939 if (!W_ERROR_IS_OK(werr)) {
5940 reply_nterror(req, werror_to_ntstatus(werr));
5944 if (max_count > 0) {
5945 first = start_index;
5947 first = start_index + max_count + 1;
5950 if (first >= count) {
5953 num_to_get = first + MIN(ABS(max_count), count - first);
5956 for (i = first; i < num_to_get; i++) {
5959 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5962 uint16_t qrapjobid = pjobid_to_rap(sharename,
5963 info[i].info2.job_id);
5965 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5971 srv_put_dos_date2(p, 0, qtime);
5972 SCVAL(p, 4, qstatus);
5973 SSVAL(p, 5, qrapjobid);
5974 SIVAL(p, 7, info[i].info2.size);
5976 status = srvstr_push(blob, req->flags2, p+12,
5977 info[i].info2.notify_name, 16, STR_ASCII, &len);
5978 if (!NT_STATUS_IS_OK(status)) {
5979 reply_nterror(req, status);
5982 if (message_push_blob(
5985 blob, sizeof(blob))) == -1) {
5986 reply_nterror(req, NT_STATUS_NO_MEMORY);
5992 SSVAL(req->outbuf,smb_vwv0,count);
5993 SSVAL(req->outbuf,smb_vwv1,
5994 (max_count>0?first+count:first-1));
5995 SCVAL(smb_buf(req->outbuf),0,1);
5996 SSVAL(smb_buf(req->outbuf),1,28*count);
6000 DEBUG(3, ("%u entries returned in queue\n",
6004 if (b && is_valid_policy_hnd(&handle)) {
6005 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6010 END_PROFILE(SMBsplretq);
6014 /****************************************************************************
6015 Reply to a printwrite.
6016 ****************************************************************************/
6018 void reply_printwrite(struct smb_request *req)
6020 connection_struct *conn = req->conn;
6025 START_PROFILE(SMBsplwr);
6028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6029 END_PROFILE(SMBsplwr);
6033 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6035 if (!check_fsp(conn, req, fsp)) {
6036 END_PROFILE(SMBsplwr);
6040 if (!fsp->print_file) {
6041 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6042 END_PROFILE(SMBsplwr);
6046 if (!CHECK_WRITE(fsp)) {
6047 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6048 END_PROFILE(SMBsplwr);
6052 numtowrite = SVAL(req->buf, 1);
6055 * This already protects us against CVE-2017-12163.
6057 if (req->buflen < numtowrite + 3) {
6058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6059 END_PROFILE(SMBsplwr);
6063 data = (const char *)req->buf + 3;
6065 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6066 reply_nterror(req, map_nt_error_from_unix(errno));
6067 END_PROFILE(SMBsplwr);
6071 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6073 reply_outbuf(req, 0, 0);
6075 END_PROFILE(SMBsplwr);
6079 /****************************************************************************
6081 ****************************************************************************/
6083 void reply_mkdir(struct smb_request *req)
6085 connection_struct *conn = req->conn;
6086 struct smb_filename *smb_dname = NULL;
6087 char *directory = NULL;
6090 TALLOC_CTX *ctx = talloc_tos();
6092 START_PROFILE(SMBmkdir);
6094 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6095 STR_TERMINATE, &status);
6096 if (!NT_STATUS_IS_OK(status)) {
6097 reply_nterror(req, status);
6101 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6102 status = filename_convert(ctx, conn,
6107 if (!NT_STATUS_IS_OK(status)) {
6108 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6109 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6110 ERRSRV, ERRbadpath);
6113 reply_nterror(req, status);
6117 status = create_directory(conn, req, smb_dname);
6119 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6121 if (!NT_STATUS_IS_OK(status)) {
6123 if (!use_nt_status()
6124 && NT_STATUS_EQUAL(status,
6125 NT_STATUS_OBJECT_NAME_COLLISION)) {
6127 * Yes, in the DOS error code case we get a
6128 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6129 * samba4 torture test.
6131 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6134 reply_nterror(req, status);
6138 reply_outbuf(req, 0, 0);
6140 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6142 TALLOC_FREE(smb_dname);
6143 END_PROFILE(SMBmkdir);
6147 /****************************************************************************
6149 ****************************************************************************/
6151 void reply_rmdir(struct smb_request *req)
6153 connection_struct *conn = req->conn;
6154 struct smb_filename *smb_dname = NULL;
6155 char *directory = NULL;
6157 TALLOC_CTX *ctx = talloc_tos();
6158 files_struct *fsp = NULL;
6160 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6162 START_PROFILE(SMBrmdir);
6164 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6165 STR_TERMINATE, &status);
6166 if (!NT_STATUS_IS_OK(status)) {
6167 reply_nterror(req, status);
6171 status = filename_convert(ctx, conn,
6176 if (!NT_STATUS_IS_OK(status)) {
6177 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6178 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6179 ERRSRV, ERRbadpath);
6182 reply_nterror(req, status);
6186 status = SMB_VFS_CREATE_FILE(
6189 smb_dname, /* fname */
6190 DELETE_ACCESS, /* access_mask */
6191 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6193 FILE_OPEN, /* create_disposition*/
6194 FILE_DIRECTORY_FILE, /* create_options */
6195 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6196 0, /* oplock_request */
6198 0, /* allocation_size */
6199 0, /* private_flags */
6204 NULL, NULL); /* create context */
6206 if (!NT_STATUS_IS_OK(status)) {
6207 if (open_was_deferred(req->xconn, req->mid)) {
6208 /* We have re-scheduled this call. */
6211 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6212 bool ok = defer_smb1_sharing_violation(req);
6217 reply_nterror(req, status);
6221 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6222 if (!NT_STATUS_IS_OK(status)) {
6223 close_file_free(req, &fsp, ERROR_CLOSE);
6224 reply_nterror(req, status);
6228 if (!set_delete_on_close(fsp, true,
6229 conn->session_info->security_token,
6230 conn->session_info->unix_token)) {
6231 close_file_free(req, &fsp, ERROR_CLOSE);
6232 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6236 status = close_file_free(req, &fsp, NORMAL_CLOSE);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 reply_nterror(req, status);
6240 reply_outbuf(req, 0, 0);
6243 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6245 TALLOC_FREE(smb_dname);
6246 END_PROFILE(SMBrmdir);
6250 /****************************************************************************
6251 Ensure open files have their names updated. Updated to notify other smbd's
6253 ****************************************************************************/
6255 static void rename_open_files(connection_struct *conn,
6256 struct share_mode_lock *lck,
6258 uint32_t orig_name_hash,
6259 const struct smb_filename *smb_fname_dst)
6262 bool did_rename = False;
6264 uint32_t new_name_hash = 0;
6266 for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
6267 fsp = file_find_di_next(fsp, false)) {
6268 SMB_STRUCT_STAT fsp_orig_sbuf;
6269 struct file_id_buf idbuf;
6270 /* fsp_name is a relative path under the fsp. To change this for other
6271 sharepaths we need to manipulate relative paths. */
6272 /* TODO - create the absolute path and manipulate the newname
6273 relative to the sharepath. */
6274 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6277 if (fsp->name_hash != orig_name_hash) {
6280 DBG_DEBUG("renaming file %s "
6281 "(file_id %s) from %s -> %s\n",
6283 file_id_str_buf(fsp->file_id, &idbuf),
6285 smb_fname_str_dbg(smb_fname_dst));
6288 * The incoming smb_fname_dst here has an
6289 * invalid stat struct (it must not have
6290 * existed for the rename to succeed).
6291 * Preserve the existing stat from the
6292 * open fsp after fsp_set_smb_fname()
6293 * overwrites with the invalid stat.
6295 * We will do an fstat before returning
6296 * any of this metadata to the client anyway.
6298 fsp_orig_sbuf = fsp->fsp_name->st;
6299 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6300 if (NT_STATUS_IS_OK(status)) {
6302 new_name_hash = fsp->name_hash;
6303 /* Restore existing stat. */
6304 fsp->fsp_name->st = fsp_orig_sbuf;
6309 struct file_id_buf idbuf;
6310 DBG_DEBUG("no open files on file_id %s "
6312 file_id_str_buf(id, &idbuf),
6313 smb_fname_str_dbg(smb_fname_dst));
6316 /* Send messages to all smbd's (not ourself) that the name has changed. */
6317 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6318 orig_name_hash, new_name_hash,
6323 /****************************************************************************
6324 We need to check if the source path is a parent directory of the destination
6325 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6326 refuse the rename with a sharing violation. Under UNIX the above call can
6327 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6328 probably need to check that the client is a Windows one before disallowing
6329 this as a UNIX client (one with UNIX extensions) can know the source is a
6330 symlink and make this decision intelligently. Found by an excellent bug
6331 report from <AndyLiebman@aol.com>.
6332 ****************************************************************************/
6334 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6335 const struct smb_filename *smb_fname_dst)
6337 const char *psrc = smb_fname_src->base_name;
6338 const char *pdst = smb_fname_dst->base_name;
6341 if (psrc[0] == '.' && psrc[1] == '/') {
6344 if (pdst[0] == '.' && pdst[1] == '/') {
6347 if ((slen = strlen(psrc)) > strlen(pdst)) {
6350 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6354 * Do the notify calls from a rename
6357 static void notify_rename(connection_struct *conn, bool is_dir,
6358 const struct smb_filename *smb_fname_src,
6359 const struct smb_filename *smb_fname_dst)
6361 char *parent_dir_src = NULL;
6362 char *parent_dir_dst = NULL;
6365 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6366 : FILE_NOTIFY_CHANGE_FILE_NAME;
6368 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6369 &parent_dir_src, NULL) ||
6370 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6371 &parent_dir_dst, NULL)) {
6375 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6376 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6377 smb_fname_src->base_name);
6378 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6379 smb_fname_dst->base_name);
6382 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6383 smb_fname_src->base_name);
6384 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6385 smb_fname_dst->base_name);
6388 /* this is a strange one. w2k3 gives an additional event for
6389 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6390 files, but not directories */
6392 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6393 FILE_NOTIFY_CHANGE_ATTRIBUTES
6394 |FILE_NOTIFY_CHANGE_CREATION,
6395 smb_fname_dst->base_name);
6398 TALLOC_FREE(parent_dir_src);
6399 TALLOC_FREE(parent_dir_dst);
6402 /****************************************************************************
6403 Returns an error if the parent directory for a filename is open in an
6405 ****************************************************************************/
6407 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6408 const struct smb_filename *smb_fname_dst_in)
6410 struct smb_filename *smb_fname_parent = NULL;
6412 files_struct *fsp = NULL;
6416 status = SMB_VFS_PARENT_PATHNAME(conn,
6421 if (!NT_STATUS_IS_OK(status)) {
6425 ret = vfs_stat(conn, smb_fname_parent);
6427 return map_nt_error_from_unix(errno);
6431 * We're only checking on this smbd here, mostly good
6432 * enough.. and will pass tests.
6435 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
6436 for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
6437 fsp = file_find_di_next(fsp, true)) {
6438 if (fsp->access_mask & DELETE_ACCESS) {
6439 return NT_STATUS_SHARING_VIOLATION;
6442 return NT_STATUS_OK;
6445 /****************************************************************************
6446 Rename an open file - given an fsp.
6447 ****************************************************************************/
6449 NTSTATUS rename_internals_fsp(connection_struct *conn,
6451 struct smb_filename *smb_fname_dst_in,
6452 const char *dst_original_lcomp,
6454 bool replace_if_exists)
6456 TALLOC_CTX *ctx = talloc_tos();
6457 struct smb_filename *parent_dir_fname_dst = NULL;
6458 struct smb_filename *parent_dir_fname_dst_atname = NULL;
6459 struct smb_filename *parent_dir_fname_src = NULL;
6460 struct smb_filename *parent_dir_fname_src_atname = NULL;
6461 struct smb_filename *smb_fname_dst = NULL;
6462 NTSTATUS status = NT_STATUS_OK;
6463 struct share_mode_lock *lck = NULL;
6464 uint32_t access_mask = SEC_DIR_ADD_FILE;
6465 bool dst_exists, old_is_stream, new_is_stream;
6467 bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
6468 true : conn->case_sensitive;
6469 bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
6470 true : conn->case_preserve;
6472 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6473 if (!NT_STATUS_IS_OK(status)) {
6477 if (file_has_open_streams(fsp)) {
6478 return NT_STATUS_ACCESS_DENIED;
6481 /* Make a copy of the dst smb_fname structs */
6483 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6484 if (smb_fname_dst == NULL) {
6485 status = NT_STATUS_NO_MEMORY;
6490 * Check for special case with case preserving and not
6491 * case sensitive. If the new last component differs from the original
6492 * last component only by case, then we should allow
6493 * the rename (user is trying to change the case of the
6496 if (!case_sensitive && case_preserve &&
6497 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6498 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6499 char *fname_dst_parent = NULL;
6500 const char *fname_dst_lcomp = NULL;
6501 char *orig_lcomp_path = NULL;
6502 char *orig_lcomp_stream = NULL;
6506 * Split off the last component of the processed
6507 * destination name. We will compare this to
6508 * the split components of dst_original_lcomp.
6510 if (!parent_dirname(ctx,
6511 smb_fname_dst->base_name,
6513 &fname_dst_lcomp)) {
6514 status = NT_STATUS_NO_MEMORY;
6519 * The dst_original_lcomp component contains
6520 * the last_component of the path + stream
6521 * name (if a stream exists).
6523 * Split off the stream name so we
6524 * can check them separately.
6527 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6528 /* POSIX - no stream component. */
6529 orig_lcomp_path = talloc_strdup(ctx,
6530 dst_original_lcomp);
6531 if (orig_lcomp_path == NULL) {
6535 ok = split_stream_filename(ctx,
6538 &orig_lcomp_stream);
6542 TALLOC_FREE(fname_dst_parent);
6543 status = NT_STATUS_NO_MEMORY;
6547 /* If the base names only differ by case, use original. */
6548 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6551 * Replace the modified last component with the
6554 if (!ISDOT(fname_dst_parent)) {
6555 tmp = talloc_asprintf(smb_fname_dst,
6560 tmp = talloc_strdup(smb_fname_dst,
6564 status = NT_STATUS_NO_MEMORY;
6565 TALLOC_FREE(fname_dst_parent);
6566 TALLOC_FREE(orig_lcomp_path);
6567 TALLOC_FREE(orig_lcomp_stream);
6570 TALLOC_FREE(smb_fname_dst->base_name);
6571 smb_fname_dst->base_name = tmp;
6574 /* If the stream_names only differ by case, use original. */
6575 if(!strcsequal(smb_fname_dst->stream_name,
6576 orig_lcomp_stream)) {
6577 /* Use the original stream. */
6578 char *tmp = talloc_strdup(smb_fname_dst,
6581 status = NT_STATUS_NO_MEMORY;
6582 TALLOC_FREE(fname_dst_parent);
6583 TALLOC_FREE(orig_lcomp_path);
6584 TALLOC_FREE(orig_lcomp_stream);
6587 TALLOC_FREE(smb_fname_dst->stream_name);
6588 smb_fname_dst->stream_name = tmp;
6590 TALLOC_FREE(fname_dst_parent);
6591 TALLOC_FREE(orig_lcomp_path);
6592 TALLOC_FREE(orig_lcomp_stream);
6596 * If the src and dest names are identical - including case,
6597 * don't do the rename, just return success.
6600 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6601 strcsequal(fsp->fsp_name->stream_name,
6602 smb_fname_dst->stream_name)) {
6603 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6604 "- returning success\n",
6605 smb_fname_str_dbg(smb_fname_dst)));
6606 status = NT_STATUS_OK;
6610 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6611 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6613 /* Return the correct error code if both names aren't streams. */
6614 if (!old_is_stream && new_is_stream) {
6615 status = NT_STATUS_OBJECT_NAME_INVALID;
6619 if (old_is_stream && !new_is_stream) {
6620 status = NT_STATUS_INVALID_PARAMETER;
6624 dst_exists = vfs_stat(conn, smb_fname_dst) == 0;
6626 if(!replace_if_exists && dst_exists) {
6627 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6628 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6629 smb_fname_str_dbg(smb_fname_dst)));
6630 status = NT_STATUS_OBJECT_NAME_COLLISION;
6635 * Drop the pathref fsp on the destination otherwise we trip upon in in
6636 * the below check for open files check.
6638 if (smb_fname_dst_in->fsp != NULL) {
6639 fd_close(smb_fname_dst_in->fsp);
6640 file_free(NULL, smb_fname_dst_in->fsp);
6641 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
6645 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6646 &smb_fname_dst->st);
6647 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6649 /* The file can be open when renaming a stream */
6650 if (dst_fsp && !new_is_stream) {
6651 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6652 status = NT_STATUS_ACCESS_DENIED;
6657 /* Ensure we have a valid stat struct for the source. */
6658 status = vfs_stat_fsp(fsp);
6659 if (!NT_STATUS_IS_OK(status)) {
6663 status = can_rename(conn, fsp, attrs);
6665 if (!NT_STATUS_IS_OK(status)) {
6666 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6667 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6668 smb_fname_str_dbg(smb_fname_dst)));
6669 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6670 status = NT_STATUS_ACCESS_DENIED;
6674 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6675 status = NT_STATUS_ACCESS_DENIED;
6679 /* Do we have rights to move into the destination ? */
6680 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6681 /* We're moving a directory. */
6682 access_mask = SEC_DIR_ADD_SUBDIR;
6686 * Get a pathref on the destination parent directory, so
6687 * we can call check_parent_access_fsp().
6689 status = parent_pathref(ctx,
6692 &parent_dir_fname_dst,
6693 &parent_dir_fname_dst_atname);
6694 if (!NT_STATUS_IS_OK(status)) {
6698 status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
6700 if (!NT_STATUS_IS_OK(status)) {
6701 DBG_INFO("check_parent_access_fsp on "
6702 "dst %s returned %s\n",
6703 smb_fname_str_dbg(smb_fname_dst),
6709 * If the target existed, make sure the destination
6710 * atname has the same stat struct.
6712 parent_dir_fname_dst_atname->st = smb_fname_dst->st;
6715 * It's very common that source and
6716 * destination directories are the same.
6717 * Optimize by not opening the
6718 * second parent_pathref if we know
6722 status = SMB_VFS_PARENT_PATHNAME(conn,
6725 &parent_dir_fname_src,
6726 &parent_dir_fname_src_atname);
6727 if (!NT_STATUS_IS_OK(status)) {
6732 * We do a case-sensitive string comparison. We want to be *sure*
6733 * this is the same path. The worst that can happen if
6734 * the case doesn't match is we lose out on the optimization,
6735 * the code still works.
6737 * We can ignore twrp fields here. Rename is not allowed on
6738 * shadow copy handles.
6741 if (strcmp(parent_dir_fname_src->base_name,
6742 parent_dir_fname_dst->base_name) == 0) {
6744 * parent directory is the same for source
6747 /* Reparent the src_atname to the parent_dir_dest fname. */
6748 parent_dir_fname_src_atname = talloc_move(
6749 parent_dir_fname_dst,
6750 &parent_dir_fname_src_atname);
6751 /* Free the unneeded duplicate parent name. */
6752 TALLOC_FREE(parent_dir_fname_src);
6754 * And make the source parent name a copy of the
6755 * destination parent name.
6757 parent_dir_fname_src = parent_dir_fname_dst;
6760 * source and destination parent directories are
6763 * Get a pathref on the source parent directory, so
6764 * we can do a relative rename.
6766 TALLOC_FREE(parent_dir_fname_src);
6767 status = parent_pathref(ctx,
6770 &parent_dir_fname_src,
6771 &parent_dir_fname_src_atname);
6772 if (!NT_STATUS_IS_OK(status)) {
6778 * Some modules depend on the source smb_fname having a valid stat.
6779 * The parent_dir_fname_src_atname is the relative name of the
6780 * currently open file, so just copy the stat from the open fsp.
6782 parent_dir_fname_src_atname->st = fsp->fsp_name->st;
6784 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6787 * We have the file open ourselves, so not being able to get the
6788 * corresponding share mode lock is a fatal error.
6791 SMB_ASSERT(lck != NULL);
6793 ret = SMB_VFS_RENAMEAT(conn,
6794 parent_dir_fname_src->fsp,
6795 parent_dir_fname_src_atname,
6796 parent_dir_fname_dst->fsp,
6797 parent_dir_fname_dst_atname);
6799 uint32_t create_options = fh_get_private_options(fsp->fh);
6801 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6802 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6803 smb_fname_str_dbg(smb_fname_dst)));
6806 fsp->fsp_flags.is_directory,
6810 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6813 if (!fsp->fsp_flags.is_directory &&
6814 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6815 (lp_map_archive(SNUM(conn)) ||
6816 lp_store_dos_attributes(SNUM(conn))))
6819 * We must set the archive bit on the newly renamed
6822 status = vfs_stat_fsp(fsp);
6823 if (NT_STATUS_IS_OK(status)) {
6824 uint32_t old_dosmode;
6825 old_dosmode = fdos_mode(fsp);
6827 * We can use fsp->fsp_name here as it has
6828 * already been changed to the new name.
6830 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
6831 file_set_dosmode(conn,
6833 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6840 * A rename acts as a new file create w.r.t. allowing an initial delete
6841 * on close, probably because in Windows there is a new handle to the
6842 * new file. If initial delete on close was requested but not
6843 * originally set, we need to set it here. This is probably not 100% correct,
6844 * but will work for the CIFSFS client which in non-posix mode
6845 * depends on these semantics. JRA.
6848 if (create_options & FILE_DELETE_ON_CLOSE) {
6849 status = can_set_delete_on_close(fsp, 0);
6851 if (NT_STATUS_IS_OK(status)) {
6852 /* Note that here we set the *initial* delete on close flag,
6853 * not the regular one. The magic gets handled in close. */
6854 fsp->fsp_flags.initial_delete_on_close = true;
6858 status = NT_STATUS_OK;
6864 if (errno == ENOTDIR || errno == EISDIR) {
6865 status = NT_STATUS_OBJECT_NAME_COLLISION;
6867 status = map_nt_error_from_unix(errno);
6870 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6871 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6872 smb_fname_str_dbg(smb_fname_dst)));
6877 * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
6878 * See the optimization for same source and destination directory
6879 * above. Only free one in that case.
6881 if (parent_dir_fname_src != parent_dir_fname_dst) {
6882 TALLOC_FREE(parent_dir_fname_src);
6884 TALLOC_FREE(parent_dir_fname_dst);
6885 TALLOC_FREE(smb_fname_dst);
6890 /****************************************************************************
6891 The guts of the rename command, split out so it may be called by the NT SMB
6893 ****************************************************************************/
6895 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6896 connection_struct *conn,
6897 struct smb_request *req,
6898 struct smb_filename *smb_fname_src,
6899 struct smb_filename *smb_fname_dst,
6900 const char *dst_original_lcomp,
6902 bool replace_if_exists,
6903 uint32_t access_mask)
6905 NTSTATUS status = NT_STATUS_OK;
6906 int create_options = 0;
6907 struct smb2_create_blobs *posx = NULL;
6908 struct files_struct *fsp = NULL;
6909 bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
6910 bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
6911 bool case_preserve = posix_pathname ? true : conn->case_preserve;
6912 bool short_case_preserve = posix_pathname ? true :
6913 conn->short_case_preserve;
6915 if (posix_pathname) {
6916 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
6917 if (!NT_STATUS_IS_OK(status)) {
6918 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6924 DBG_NOTICE("case_sensitive = %d, "
6925 "case_preserve = %d, short case preserve = %d, "
6926 "directory = %s, newname = %s, "
6927 "last_component_dest = %s\n",
6928 case_sensitive, case_preserve,
6929 short_case_preserve,
6930 smb_fname_str_dbg(smb_fname_src),
6931 smb_fname_str_dbg(smb_fname_dst),
6932 dst_original_lcomp);
6934 ZERO_STRUCT(smb_fname_src->st);
6936 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
6937 if (!NT_STATUS_IS_OK(status)) {
6938 if (!NT_STATUS_EQUAL(status,
6939 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6943 * Possible symlink src.
6945 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
6948 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
6953 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6954 create_options |= FILE_DIRECTORY_FILE;
6957 status = SMB_VFS_CREATE_FILE(
6960 smb_fname_src, /* fname */
6961 access_mask, /* access_mask */
6962 (FILE_SHARE_READ | /* share_access */
6964 FILE_OPEN, /* create_disposition*/
6965 create_options, /* create_options */
6966 0, /* file_attributes */
6967 0, /* oplock_request */
6969 0, /* allocation_size */
6970 0, /* private_flags */
6975 posx, /* in_context_blobs */
6976 NULL); /* out_context_blobs */
6978 if (!NT_STATUS_IS_OK(status)) {
6979 DBG_NOTICE("Could not open rename source %s: %s\n",
6980 smb_fname_str_dbg(smb_fname_src),
6985 status = rename_internals_fsp(conn,
6992 close_file_free(req, &fsp, NORMAL_CLOSE);
6994 DBG_NOTICE("Error %s rename %s -> %s\n",
6995 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6996 smb_fname_str_dbg(smb_fname_dst));
7003 /****************************************************************************
7005 ****************************************************************************/
7007 void reply_mv(struct smb_request *req)
7009 connection_struct *conn = req->conn;
7011 char *newname = NULL;
7015 TALLOC_CTX *ctx = talloc_tos();
7016 struct smb_filename *smb_fname_src = NULL;
7017 struct smb_filename *smb_fname_dst = NULL;
7018 const char *dst_original_lcomp = NULL;
7019 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
7020 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
7021 bool stream_rename = false;
7023 START_PROFILE(SMBmv);
7026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7030 attrs = SVAL(req->vwv+0, 0);
7032 p = (const char *)req->buf + 1;
7033 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
7035 if (!NT_STATUS_IS_OK(status)) {
7036 reply_nterror(req, status);
7040 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
7042 if (!NT_STATUS_IS_OK(status)) {
7043 reply_nterror(req, status);
7047 if (!req->posix_pathnames) {
7048 /* The newname must begin with a ':' if the
7049 name contains a ':'. */
7050 if (strchr_m(name, ':')) {
7051 if (newname[0] != ':') {
7052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7055 stream_rename = true;
7059 status = filename_convert(ctx,
7066 if (!NT_STATUS_IS_OK(status)) {
7067 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7068 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7069 ERRSRV, ERRbadpath);
7072 reply_nterror(req, status);
7076 status = filename_convert(ctx,
7083 if (!NT_STATUS_IS_OK(status)) {
7084 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7085 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7086 ERRSRV, ERRbadpath);
7089 reply_nterror(req, status);
7093 /* Get the last component of the destination for rename_internals(). */
7094 dst_original_lcomp = get_original_lcomp(ctx,
7098 if (dst_original_lcomp == NULL) {
7099 reply_nterror(req, NT_STATUS_NO_MEMORY);
7103 if (stream_rename) {
7104 /* smb_fname_dst->base_name must be the same as
7105 smb_fname_src->base_name. */
7106 TALLOC_FREE(smb_fname_dst->base_name);
7107 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7108 smb_fname_src->base_name);
7109 if (!smb_fname_dst->base_name) {
7110 reply_nterror(req, NT_STATUS_NO_MEMORY);
7115 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7116 smb_fname_str_dbg(smb_fname_dst)));
7118 status = rename_internals(ctx,
7127 if (!NT_STATUS_IS_OK(status)) {
7128 if (open_was_deferred(req->xconn, req->mid)) {
7129 /* We have re-scheduled this call. */
7132 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7133 bool ok = defer_smb1_sharing_violation(req);
7138 reply_nterror(req, status);
7142 reply_outbuf(req, 0, 0);
7144 TALLOC_FREE(smb_fname_src);
7145 TALLOC_FREE(smb_fname_dst);
7150 /*******************************************************************
7151 Copy a file as part of a reply_copy.
7152 ******************************************************************/
7155 * TODO: check error codes on all callers
7158 NTSTATUS copy_file(TALLOC_CTX *ctx,
7159 connection_struct *conn,
7160 struct smb_filename *smb_fname_src,
7161 struct smb_filename *smb_fname_dst,
7164 bool target_is_directory)
7166 struct smb_filename *smb_fname_dst_tmp = NULL;
7168 files_struct *fsp1,*fsp2;
7170 uint32_t new_create_disposition;
7174 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7175 if (smb_fname_dst_tmp == NULL) {
7176 return NT_STATUS_NO_MEMORY;
7180 * If the target is a directory, extract the last component from the
7181 * src filename and append it to the dst filename
7183 if (target_is_directory) {
7186 /* dest/target can't be a stream if it's a directory. */
7187 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7189 p = strrchr_m(smb_fname_src->base_name,'/');
7193 p = smb_fname_src->base_name;
7195 smb_fname_dst_tmp->base_name =
7196 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7198 if (!smb_fname_dst_tmp->base_name) {
7199 status = NT_STATUS_NO_MEMORY;
7204 status = vfs_file_exist(conn, smb_fname_src);
7205 if (!NT_STATUS_IS_OK(status)) {
7209 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
7210 if (!NT_STATUS_IS_OK(status)) {
7214 if (!target_is_directory && count) {
7215 new_create_disposition = FILE_OPEN;
7217 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7220 &new_create_disposition,
7223 status = NT_STATUS_INVALID_PARAMETER;
7228 /* Open the src file for reading. */
7229 status = SMB_VFS_CREATE_FILE(
7232 smb_fname_src, /* fname */
7233 FILE_GENERIC_READ, /* access_mask */
7234 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7235 FILE_OPEN, /* create_disposition*/
7236 0, /* create_options */
7237 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7238 INTERNAL_OPEN_ONLY, /* oplock_request */
7240 0, /* allocation_size */
7241 0, /* private_flags */
7246 NULL, NULL); /* create context */
7248 if (!NT_STATUS_IS_OK(status)) {
7252 dosattrs = fdos_mode(fsp1);
7254 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7255 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7258 status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
7259 if (!NT_STATUS_IS_OK(status) &&
7260 !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
7265 /* Open the dst file for writing. */
7266 status = SMB_VFS_CREATE_FILE(
7269 smb_fname_dst, /* fname */
7270 FILE_GENERIC_WRITE, /* access_mask */
7271 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7272 new_create_disposition, /* create_disposition*/
7273 0, /* create_options */
7274 dosattrs, /* file_attributes */
7275 INTERNAL_OPEN_ONLY, /* oplock_request */
7277 0, /* allocation_size */
7278 0, /* private_flags */
7283 NULL, NULL); /* create context */
7285 if (!NT_STATUS_IS_OK(status)) {
7286 close_file_free(NULL, &fsp1, ERROR_CLOSE);
7290 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7291 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7293 DEBUG(0, ("error - vfs lseek returned error %s\n",
7295 status = map_nt_error_from_unix(errno);
7296 close_file_free(NULL, &fsp1, ERROR_CLOSE);
7297 close_file_free(NULL, &fsp2, ERROR_CLOSE);
7302 /* Do the actual copy. */
7303 if (smb_fname_src->st.st_ex_size) {
7304 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7309 close_file_free(NULL, &fsp1, NORMAL_CLOSE);
7311 /* Ensure the modtime is set correctly on the destination file. */
7312 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7315 * As we are opening fsp1 read-only we only expect
7316 * an error on close on fsp2 if we are out of space.
7317 * Thus we don't look at the error return from the
7320 status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
7322 if (!NT_STATUS_IS_OK(status)) {
7326 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7327 status = NT_STATUS_DISK_FULL;
7331 status = NT_STATUS_OK;
7334 TALLOC_FREE(smb_fname_dst_tmp);
7338 /****************************************************************************
7339 Reply to a file copy.
7343 This command was introduced in the LAN Manager 1.0 dialect
7344 It was rendered obsolete in the NT LAN Manager dialect.
7345 This command was used to perform server-side file copies, but
7346 is no longer used. Clients SHOULD
7347 NOT send requests using this command code.
7348 Servers receiving requests with this command code
7349 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
7350 ****************************************************************************/
7352 void reply_copy(struct smb_request *req)
7354 START_PROFILE(SMBcopy);
7355 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
7356 END_PROFILE(SMBcopy);
7361 #define DBGC_CLASS DBGC_LOCKING
7363 /****************************************************************************
7364 Get a lock pid, dealing with large count requests.
7365 ****************************************************************************/
7367 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7368 bool large_file_format)
7370 if(!large_file_format)
7371 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7373 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7376 /****************************************************************************
7377 Get a lock count, dealing with large count requests.
7378 ****************************************************************************/
7380 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7381 bool large_file_format)
7385 if(!large_file_format) {
7386 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7389 * No BVAL, this is reversed!
7391 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7392 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7398 /****************************************************************************
7399 Get a lock offset, dealing with large offset requests.
7400 ****************************************************************************/
7402 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7403 bool large_file_format)
7405 uint64_t offset = 0;
7407 if(!large_file_format) {
7408 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7411 * No BVAL, this is reversed!
7413 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7414 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7420 struct smbd_do_unlocking_state {
7421 struct files_struct *fsp;
7422 uint16_t num_ulocks;
7423 struct smbd_lock_element *ulocks;
7427 static void smbd_do_unlocking_fn(
7430 bool *pmodified_dependent,
7433 struct smbd_do_unlocking_state *state = private_data;
7434 struct files_struct *fsp = state->fsp;
7437 for (i = 0; i < state->num_ulocks; i++) {
7438 struct smbd_lock_element *e = &state->ulocks[i];
7440 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
7441 "pid %"PRIu64", file %s\n",
7447 if (e->brltype != UNLOCK_LOCK) {
7448 /* this can only happen with SMB2 */
7449 state->status = NT_STATUS_INVALID_PARAMETER;
7453 state->status = do_unlock(
7454 fsp, e->smblctx, e->count, e->offset, e->lock_flav);
7456 DBG_DEBUG("do_unlock returned %s\n",
7457 nt_errstr(state->status));
7459 if (!NT_STATUS_IS_OK(state->status)) {
7464 *pmodified_dependent = true;
7467 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7469 uint16_t num_ulocks,
7470 struct smbd_lock_element *ulocks)
7472 struct smbd_do_unlocking_state state = {
7474 .num_ulocks = num_ulocks,
7479 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
7481 status = share_mode_do_locked(
7482 fsp->file_id, smbd_do_unlocking_fn, &state);
7484 if (!NT_STATUS_IS_OK(status)) {
7485 DBG_DEBUG("share_mode_do_locked failed: %s\n",
7489 if (!NT_STATUS_IS_OK(state.status)) {
7490 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
7492 return state.status;
7495 return NT_STATUS_OK;
7498 /****************************************************************************
7499 Reply to a lockingX request.
7500 ****************************************************************************/
7502 static void reply_lockingx_done(struct tevent_req *subreq);
7504 void reply_lockingX(struct smb_request *req)
7506 connection_struct *conn = req->conn;
7508 unsigned char locktype;
7509 enum brl_type brltype;
7510 unsigned char oplocklevel;
7511 uint16_t num_ulocks;
7513 int32_t lock_timeout;
7515 const uint8_t *data;
7516 bool large_file_format;
7517 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7518 struct smbd_lock_element *locks = NULL;
7519 struct tevent_req *subreq = NULL;
7521 START_PROFILE(SMBlockingX);
7524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7525 END_PROFILE(SMBlockingX);
7529 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7530 locktype = CVAL(req->vwv+3, 0);
7531 oplocklevel = CVAL(req->vwv+3, 1);
7532 num_ulocks = SVAL(req->vwv+6, 0);
7533 num_locks = SVAL(req->vwv+7, 0);
7534 lock_timeout = IVAL(req->vwv+4, 0);
7535 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7537 if (!check_fsp(conn, req, fsp)) {
7538 END_PROFILE(SMBlockingX);
7544 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7545 /* we don't support these - and CANCEL_LOCK makes w2k
7546 and XP reboot so I don't really want to be
7547 compatible! (tridge) */
7548 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7549 END_PROFILE(SMBlockingX);
7553 /* Check if this is an oplock break on a file
7554 we have granted an oplock on.
7556 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7557 /* Client can insist on breaking to none. */
7558 bool break_to_none = (oplocklevel == 0);
7561 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7562 "for %s\n", (unsigned int)oplocklevel,
7563 fsp_fnum_dbg(fsp)));
7566 * Make sure we have granted an exclusive or batch oplock on
7570 if (fsp->oplock_type == 0) {
7572 /* The Samba4 nbench simulator doesn't understand
7573 the difference between break to level2 and break
7574 to none from level2 - it sends oplock break
7575 replies in both cases. Don't keep logging an error
7576 message here - just ignore it. JRA. */
7578 DEBUG(5,("reply_lockingX: Error : oplock break from "
7579 "client for %s (oplock=%d) and no "
7580 "oplock granted on this file (%s).\n",
7581 fsp_fnum_dbg(fsp), fsp->oplock_type,
7584 /* if this is a pure oplock break request then don't
7586 if (num_locks == 0 && num_ulocks == 0) {
7587 END_PROFILE(SMBlockingX);
7591 END_PROFILE(SMBlockingX);
7592 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7596 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7598 result = remove_oplock(fsp);
7600 result = downgrade_oplock(fsp);
7604 DEBUG(0, ("reply_lockingX: error in removing "
7605 "oplock on file %s\n", fsp_str_dbg(fsp)));
7606 /* Hmmm. Is this panic justified? */
7607 smb_panic("internal tdb error");
7610 /* if this is a pure oplock break request then don't send a
7612 if (num_locks == 0 && num_ulocks == 0) {
7613 /* Sanity check - ensure a pure oplock break is not a
7615 if (CVAL(req->vwv+0, 0) != 0xff) {
7616 DEBUG(0,("reply_lockingX: Error : pure oplock "
7617 "break is a chained %d request !\n",
7618 (unsigned int)CVAL(req->vwv+0, 0)));
7620 END_PROFILE(SMBlockingX);
7626 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7628 END_PROFILE(SMBlockingX);
7632 if (num_ulocks != 0) {
7633 struct smbd_lock_element *ulocks = NULL;
7636 ulocks = talloc_array(
7637 req, struct smbd_lock_element, num_ulocks);
7638 if (ulocks == NULL) {
7639 reply_nterror(req, NT_STATUS_NO_MEMORY);
7640 END_PROFILE(SMBlockingX);
7645 * Data now points at the beginning of the list of
7646 * smb_unlkrng structs
7648 for (i = 0; i < num_ulocks; i++) {
7649 ulocks[i].req_guid = smbd_request_guid(req,
7651 ulocks[i].smblctx = get_lock_pid(
7652 data, i, large_file_format);
7653 ulocks[i].count = get_lock_count(
7654 data, i, large_file_format);
7655 ulocks[i].offset = get_lock_offset(
7656 data, i, large_file_format);
7657 ulocks[i].brltype = UNLOCK_LOCK;
7658 ulocks[i].lock_flav = WINDOWS_LOCK;
7662 * Unlock cancels pending locks
7665 ok = smbd_smb1_brl_finish_by_lock(
7671 reply_outbuf(req, 2, 0);
7672 SSVAL(req->outbuf, smb_vwv0, 0xff);
7673 SSVAL(req->outbuf, smb_vwv1, 0);
7674 END_PROFILE(SMBlockingX);
7678 status = smbd_do_unlocking(
7679 req, fsp, num_ulocks, ulocks);
7680 TALLOC_FREE(ulocks);
7681 if (!NT_STATUS_IS_OK(status)) {
7682 END_PROFILE(SMBlockingX);
7683 reply_nterror(req, status);
7688 /* Now do any requested locks */
7689 data += ((large_file_format ? 20 : 10)*num_ulocks);
7691 /* Data now points at the beginning of the list
7692 of smb_lkrng structs */
7694 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7695 brltype = READ_LOCK;
7697 brltype = WRITE_LOCK;
7700 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7701 if (locks == NULL) {
7702 reply_nterror(req, NT_STATUS_NO_MEMORY);
7703 END_PROFILE(SMBlockingX);
7707 for (i = 0; i < num_locks; i++) {
7708 locks[i].req_guid = smbd_request_guid(req, i),
7709 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7710 locks[i].count = get_lock_count(data, i, large_file_format);
7711 locks[i].offset = get_lock_offset(data, i, large_file_format);
7712 locks[i].brltype = brltype;
7713 locks[i].lock_flav = WINDOWS_LOCK;
7716 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7720 if (num_locks == 0) {
7721 /* See smbtorture3 lock11 test */
7722 reply_outbuf(req, 2, 0);
7723 /* andx chain ends */
7724 SSVAL(req->outbuf, smb_vwv0, 0xff);
7725 SSVAL(req->outbuf, smb_vwv1, 0);
7726 END_PROFILE(SMBlockingX);
7730 ok = smbd_smb1_brl_finish_by_lock(
7733 locks[0], /* Windows only cancels the first lock */
7734 NT_STATUS_FILE_LOCK_CONFLICT);
7737 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
7738 END_PROFILE(SMBlockingX);
7742 reply_outbuf(req, 2, 0);
7743 SSVAL(req->outbuf, smb_vwv0, 0xff);
7744 SSVAL(req->outbuf, smb_vwv1, 0);
7745 END_PROFILE(SMBlockingX);
7749 subreq = smbd_smb1_do_locks_send(
7758 if (subreq == NULL) {
7759 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760 END_PROFILE(SMBlockingX);
7763 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
7764 END_PROFILE(SMBlockingX);
7767 static void reply_lockingx_done(struct tevent_req *subreq)
7769 struct smb_request *req = NULL;
7773 START_PROFILE(SMBlockingX);
7775 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7778 status = smbd_smb1_do_locks_recv(subreq);
7779 TALLOC_FREE(subreq);
7781 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
7783 if (NT_STATUS_IS_OK(status)) {
7784 reply_outbuf(req, 2, 0);
7785 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7786 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7788 reply_nterror(req, status);
7791 ok = srv_send_smb(req->xconn,
7792 (char *)req->outbuf,
7795 IS_CONN_ENCRYPTED(req->conn),
7798 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
7801 END_PROFILE(SMBlockingX);
7805 #define DBGC_CLASS DBGC_ALL
7807 /****************************************************************************
7808 Reply to a SMBreadbmpx (read block multiplex) request.
7809 Always reply with an error, if someone has a platform really needs this,
7810 please contact vl@samba.org
7811 ****************************************************************************/
7813 void reply_readbmpx(struct smb_request *req)
7815 START_PROFILE(SMBreadBmpx);
7816 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7817 END_PROFILE(SMBreadBmpx);
7821 /****************************************************************************
7822 Reply to a SMBreadbs (read block multiplex secondary) request.
7823 Always reply with an error, if someone has a platform really needs this,
7824 please contact vl@samba.org
7825 ****************************************************************************/
7827 void reply_readbs(struct smb_request *req)
7829 START_PROFILE(SMBreadBs);
7830 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7831 END_PROFILE(SMBreadBs);
7835 /****************************************************************************
7836 Reply to a SMBsetattrE.
7837 ****************************************************************************/
7839 void reply_setattrE(struct smb_request *req)
7841 connection_struct *conn = req->conn;
7842 struct smb_file_time ft;
7846 START_PROFILE(SMBsetattrE);
7847 init_smb_file_time(&ft);
7850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7856 if(!fsp || (fsp->conn != conn)) {
7857 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7862 * Convert the DOS times into unix times.
7865 ft.atime = time_t_to_full_timespec(
7866 srv_make_unix_date2(req->vwv+3));
7867 ft.mtime = time_t_to_full_timespec(
7868 srv_make_unix_date2(req->vwv+5));
7869 ft.create_time = time_t_to_full_timespec(
7870 srv_make_unix_date2(req->vwv+1));
7872 reply_outbuf(req, 0, 0);
7875 * Patch from Ray Frush <frush@engr.colostate.edu>
7876 * Sometimes times are sent as zero - ignore them.
7879 /* Ensure we have a valid stat struct for the source. */
7880 status = vfs_stat_fsp(fsp);
7881 if (!NT_STATUS_IS_OK(status)) {
7882 reply_nterror(req, status);
7886 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7887 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7891 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7892 if (!NT_STATUS_IS_OK(status)) {
7893 reply_nterror(req, status);
7897 if (fsp->fsp_flags.modified) {
7898 trigger_write_time_update_immediate(fsp);
7901 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
7904 (unsigned int)ft.atime.tv_sec,
7905 (unsigned int)ft.mtime.tv_sec,
7906 (unsigned int)ft.create_time.tv_sec
7909 END_PROFILE(SMBsetattrE);
7914 /* Back from the dead for OS/2..... JRA. */
7916 /****************************************************************************
7917 Reply to a SMBwritebmpx (write block multiplex primary) request.
7918 Always reply with an error, if someone has a platform really needs this,
7919 please contact vl@samba.org
7920 ****************************************************************************/
7922 void reply_writebmpx(struct smb_request *req)
7924 START_PROFILE(SMBwriteBmpx);
7925 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7926 END_PROFILE(SMBwriteBmpx);
7930 /****************************************************************************
7931 Reply to a SMBwritebs (write block multiplex secondary) request.
7932 Always reply with an error, if someone has a platform really needs this,
7933 please contact vl@samba.org
7934 ****************************************************************************/
7936 void reply_writebs(struct smb_request *req)
7938 START_PROFILE(SMBwriteBs);
7939 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7940 END_PROFILE(SMBwriteBs);
7944 /****************************************************************************
7945 Reply to a SMBgetattrE.
7946 ****************************************************************************/
7948 void reply_getattrE(struct smb_request *req)
7950 connection_struct *conn = req->conn;
7953 struct timespec create_ts;
7956 START_PROFILE(SMBgetattrE);
7959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7960 END_PROFILE(SMBgetattrE);
7964 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7966 if(!fsp || (fsp->conn != conn)) {
7967 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7968 END_PROFILE(SMBgetattrE);
7972 /* Do an fstat on this file */
7973 status = vfs_stat_fsp(fsp);
7974 if (!NT_STATUS_IS_OK(status)) {
7975 reply_nterror(req, status);
7976 END_PROFILE(SMBgetattrE);
7980 mode = fdos_mode(fsp);
7983 * Convert the times into dos times. Set create
7984 * date to be last modify date as UNIX doesn't save
7988 reply_outbuf(req, 11, 0);
7990 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7991 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7992 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7993 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7994 /* Should we check pending modtime here ? JRA */
7995 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7996 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7998 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7999 SIVAL(req->outbuf, smb_vwv6, 0);
8000 SIVAL(req->outbuf, smb_vwv8, 0);
8002 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8003 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8004 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8006 SSVAL(req->outbuf,smb_vwv10, mode);
8008 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8010 END_PROFILE(SMBgetattrE);