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 "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
53 #include "source3/lib/substitute.h"
54 #include "source3/smbd/dir.h"
56 /****************************************************************************
57 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
58 ****************************************************************************/
60 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
63 if ((fsp == NULL) || (conn == NULL)) {
64 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
67 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
68 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
74 /****************************************************************************
75 SMB1 version of smb2_strip_dfs_path()
76 Differs from SMB2 in that all Windows path separator '\' characters
77 have already been converted to '/' by check_path_syntax().
78 ****************************************************************************/
80 NTSTATUS smb1_strip_dfs_path(TALLOC_CTX *mem_ctx,
84 uint32_t ucf_flags = *_ucf_flags;
85 char *path = *in_path;
86 char *return_path = NULL;
88 if (!(ucf_flags & UCF_DFS_PATHNAME)) {
92 /* Strip any leading '/' characters - MacOSX client behavior. */
93 while (*path == '/') {
97 /* We should now be pointing at the server name. Go past it. */
100 /* End of complete path. Exit OK. */
104 /* End of server name. Go past and break. */
108 path++; /* Continue looking for end of server name or string. */
111 /* We should now be pointing at the share name. Go past it. */
114 /* End of complete path. Exit OK. */
118 /* End of share name. Go past and break. */
123 /* Only invalid character in sharename. */
124 return NT_STATUS_OBJECT_NAME_INVALID;
126 path++; /* Continue looking for end of share name or string. */
130 /* path now points at the start of the real filename (if any). */
131 /* Duplicate it first. */
132 return_path = talloc_strdup(mem_ctx, path);
133 if (return_path == NULL) {
134 return NT_STATUS_NO_MEMORY;
137 /* Now we can free the original (path points to part of this). */
138 TALLOC_FREE(*in_path);
140 *in_path = return_path;
141 ucf_flags &= ~UCF_DFS_PATHNAME;
142 *_ucf_flags = ucf_flags;
146 /****************************************************************************
147 Check if we have a correct fsp pointing to a file.
148 ****************************************************************************/
150 bool check_fsp(connection_struct *conn, struct smb_request *req,
153 if (!check_fsp_open(conn, req, fsp)) {
156 if (fsp->fsp_flags.is_directory) {
157 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
160 if (fsp_get_pathref_fd(fsp) == -1) {
161 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
164 fsp->num_smb_operations++;
168 /****************************************************************************
170 conn POINTER CAN BE NULL HERE !
171 ****************************************************************************/
173 void reply_tcon(struct smb_request *req)
175 connection_struct *conn = req->conn;
177 char *service_buf = NULL;
178 char *password = NULL;
184 TALLOC_CTX *ctx = talloc_tos();
185 struct smbXsrv_connection *xconn = req->xconn;
186 NTTIME now = timeval_to_nttime(&req->request_time);
188 START_PROFILE(SMBtcon);
190 if (req->buflen < 4) {
191 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
192 END_PROFILE(SMBtcon);
197 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
199 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
201 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
204 if (service_buf == NULL || password == NULL || dev == NULL) {
205 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
206 END_PROFILE(SMBtcon);
209 p2 = strrchr_m(service_buf,'\\');
213 service = service_buf;
216 conn = make_connection(req, now, service, dev,
217 req->vuid,&nt_status);
221 reply_nterror(req, nt_status);
222 END_PROFILE(SMBtcon);
226 reply_smb1_outbuf(req, 2, 0);
227 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
228 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
229 SSVAL(req->outbuf,smb_tid,conn->cnum);
231 DEBUG(3,("tcon service=%s cnum=%d\n",
232 service, conn->cnum));
234 END_PROFILE(SMBtcon);
238 /****************************************************************************
239 Reply to a tcon and X.
240 conn POINTER CAN BE NULL HERE !
241 ****************************************************************************/
243 void reply_tcon_and_X(struct smb_request *req)
245 const struct loadparm_substitution *lp_sub =
246 loadparm_s3_global_substitution();
247 connection_struct *conn = req->conn;
248 const char *service = NULL;
249 TALLOC_CTX *ctx = talloc_tos();
250 /* what the client thinks the device is */
251 char *client_devicetype = NULL;
252 /* what the server tells the client the share represents */
253 const char *server_devicetype;
260 struct smbXsrv_session *session = NULL;
261 NTTIME now = timeval_to_nttime(&req->request_time);
262 bool session_key_updated = false;
263 uint16_t optional_support = 0;
264 struct smbXsrv_connection *xconn = req->xconn;
266 START_PROFILE(SMBtconX);
269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
270 END_PROFILE(SMBtconX);
274 passlen = SVAL(req->vwv+3, 0);
275 tcon_flags = SVAL(req->vwv+2, 0);
277 /* we might have to close an old one */
278 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
279 struct smbXsrv_tcon *tcon;
287 * TODO: cancel all outstanding requests on the tcon
289 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
290 if (!NT_STATUS_IS_OK(status)) {
291 DEBUG(0, ("reply_tcon_and_X: "
292 "smbXsrv_tcon_disconnect() failed: %s\n",
295 * If we hit this case, there is something completely
296 * wrong, so we better disconnect the transport connection.
298 END_PROFILE(SMBtconX);
299 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
305 * This tree id is gone. Make sure we can't re-use it
311 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
312 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
313 END_PROFILE(SMBtconX);
317 if (xconn->smb1.negprot.encrypted_passwords) {
318 p = req->buf + passlen;
320 p = req->buf + passlen + 1;
323 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
327 END_PROFILE(SMBtconX);
332 * the service name can be either: \\server\share
333 * or share directly like on the DELL PowerVault 705
336 q = strchr_m(path+2,'\\');
338 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
339 END_PROFILE(SMBtconX);
347 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
348 &client_devicetype, p,
349 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
351 if (client_devicetype == NULL) {
352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
353 END_PROFILE(SMBtconX);
357 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
359 nt_status = smb1srv_session_lookup(xconn,
360 req->vuid, now, &session);
361 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
362 reply_force_doserror(req, ERRSRV, ERRbaduid);
363 END_PROFILE(SMBtconX);
366 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
367 reply_nterror(req, nt_status);
368 END_PROFILE(SMBtconX);
371 if (!NT_STATUS_IS_OK(nt_status)) {
372 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
373 END_PROFILE(SMBtconX);
377 if (session->global->auth_session_info == NULL) {
378 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
379 END_PROFILE(SMBtconX);
384 * If there is no application key defined yet
387 * This means we setup the application key on the
388 * first tcon that happens via the given session.
390 * Once the application key is defined, it does not
393 if (session->global->application_key_blob.length == 0 &&
394 smb2_signing_key_valid(session->global->signing_key))
396 struct smbXsrv_session *x = session;
397 struct auth_session_info *session_info =
398 session->global->auth_session_info;
399 uint8_t session_key[16];
401 ZERO_STRUCT(session_key);
402 memcpy(session_key, x->global->signing_key->blob.data,
403 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
406 * The application key is truncated/padded to 16 bytes
408 x->global->application_key_blob = data_blob_talloc(x->global,
410 sizeof(session_key));
411 ZERO_STRUCT(session_key);
412 if (x->global->application_key_blob.data == NULL) {
413 reply_nterror(req, NT_STATUS_NO_MEMORY);
414 END_PROFILE(SMBtconX);
417 talloc_keep_secret(x->global->application_key_blob.data);
419 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
422 status = smb1_key_derivation(x->global->application_key_blob.data,
423 x->global->application_key_blob.length,
424 x->global->application_key_blob.data);
425 if (!NT_STATUS_IS_OK(status)) {
426 DBG_ERR("smb1_key_derivation failed: %s\n",
428 END_PROFILE(SMBtconX);
431 optional_support |= SMB_EXTENDED_SIGNATURES;
435 * Place the application key into the session_info
437 data_blob_clear_free(&session_info->session_key);
438 session_info->session_key = data_blob_dup_talloc(session_info,
439 x->global->application_key_blob);
440 if (session_info->session_key.data == NULL) {
441 data_blob_clear_free(&x->global->application_key_blob);
442 reply_nterror(req, NT_STATUS_NO_MEMORY);
443 END_PROFILE(SMBtconX);
446 talloc_keep_secret(session_info->session_key.data);
447 session_key_updated = true;
450 conn = make_connection(req, now, service, client_devicetype,
451 req->vuid, &nt_status);
455 if (session_key_updated) {
456 struct smbXsrv_session *x = session;
457 struct auth_session_info *session_info =
458 session->global->auth_session_info;
459 data_blob_clear_free(&x->global->application_key_blob);
460 data_blob_clear_free(&session_info->session_key);
462 reply_nterror(req, nt_status);
463 END_PROFILE(SMBtconX);
468 server_devicetype = "IPC";
469 else if ( IS_PRINT(conn) )
470 server_devicetype = "LPT1:";
472 server_devicetype = "A:";
474 if (xconn->protocol < PROTOCOL_NT1) {
475 reply_smb1_outbuf(req, 2, 0);
476 if (message_push_string(&req->outbuf, server_devicetype,
477 STR_TERMINATE|STR_ASCII) == -1) {
478 reply_nterror(req, NT_STATUS_NO_MEMORY);
479 END_PROFILE(SMBtconX);
483 /* NT sets the fstype of IPC$ to the null string */
484 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
486 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
487 /* Return permissions. */
491 reply_smb1_outbuf(req, 7, 0);
494 perm1 = FILE_ALL_ACCESS;
495 perm2 = FILE_ALL_ACCESS;
497 perm1 = conn->share_access;
500 SIVAL(req->outbuf, smb_vwv3, perm1);
501 SIVAL(req->outbuf, smb_vwv5, perm2);
503 reply_smb1_outbuf(req, 3, 0);
506 if ((message_push_string(&req->outbuf, server_devicetype,
507 STR_TERMINATE|STR_ASCII) == -1)
508 || (message_push_string(&req->outbuf, fstype,
509 STR_TERMINATE) == -1)) {
510 reply_nterror(req, NT_STATUS_NO_MEMORY);
511 END_PROFILE(SMBtconX);
515 /* what does setting this bit do? It is set by NT4 and
516 may affect the ability to autorun mounted cdroms */
517 optional_support |= SMB_SUPPORT_SEARCH_BITS;
519 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
521 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
522 DEBUG(2,("Serving %s as a Dfs root\n",
523 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
524 optional_support |= SMB_SHARE_IN_DFS;
527 SSVAL(req->outbuf, smb_vwv2, optional_support);
530 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
531 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
533 DEBUG(3,("tconX service=%s \n",
536 /* set the incoming and outgoing tid to the just created one */
537 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
538 SSVAL(req->outbuf,smb_tid,conn->cnum);
540 END_PROFILE(SMBtconX);
542 req->tid = conn->cnum;
545 /****************************************************************************
546 Reply to an unknown type.
547 ****************************************************************************/
549 void reply_unknown_new(struct smb_request *req, uint8_t type)
551 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
552 smb_fn_name(type), type, type));
553 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
557 /****************************************************************************
559 conn POINTER CAN BE NULL HERE !
560 ****************************************************************************/
562 void reply_ioctl(struct smb_request *req)
564 const struct loadparm_substitution *lp_sub =
565 loadparm_s3_global_substitution();
566 connection_struct *conn = req->conn;
573 START_PROFILE(SMBioctl);
576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
577 END_PROFILE(SMBioctl);
581 device = SVAL(req->vwv+1, 0);
582 function = SVAL(req->vwv+2, 0);
583 ioctl_code = (device << 16) + function;
585 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
587 switch (ioctl_code) {
588 case IOCTL_QUERY_JOB_INFO:
592 reply_force_doserror(req, ERRSRV, ERRnosupport);
593 END_PROFILE(SMBioctl);
597 reply_smb1_outbuf(req, 8, replysize+1);
598 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
599 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
600 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
601 p = smb_buf(req->outbuf);
602 memset(p, '\0', replysize+1); /* valgrind-safe. */
603 p += 1; /* Allow for alignment */
605 switch (ioctl_code) {
606 case IOCTL_QUERY_JOB_INFO:
610 files_struct *fsp = file_fsp(
611 req, SVAL(req->vwv+0, 0));
613 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
614 END_PROFILE(SMBioctl);
618 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
620 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
621 lp_netbios_name(), 15,
622 STR_TERMINATE|STR_ASCII, &len);
623 if (!NT_STATUS_IS_OK(status)) {
624 reply_nterror(req, status);
625 END_PROFILE(SMBioctl);
629 status = srvstr_push((char *)req->outbuf, req->flags2,
631 lp_servicename(talloc_tos(),
634 13, STR_TERMINATE|STR_ASCII, &len);
635 if (!NT_STATUS_IS_OK(status)) {
636 reply_nterror(req, status);
637 END_PROFILE(SMBioctl);
647 END_PROFILE(SMBioctl);
651 /****************************************************************************
652 Strange checkpath NTSTATUS mapping.
653 ****************************************************************************/
655 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
657 /* Strange DOS error code semantics only for checkpath... */
658 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
659 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
660 /* We need to map to ERRbadpath */
661 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
667 /****************************************************************************
668 Reply to a checkpath.
669 ****************************************************************************/
671 void reply_checkpath(struct smb_request *req)
673 connection_struct *conn = req->conn;
674 struct smb_filename *smb_fname = NULL;
677 struct files_struct *dirfsp = NULL;
678 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
680 TALLOC_CTX *ctx = talloc_tos();
682 START_PROFILE(SMBcheckpath);
684 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
685 STR_TERMINATE, &status);
687 if (!NT_STATUS_IS_OK(status)) {
688 status = map_checkpath_error(req->flags2, status);
689 reply_nterror(req, status);
690 END_PROFILE(SMBcheckpath);
694 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
696 if (ucf_flags & UCF_GMT_PATHNAME) {
697 extract_snapshot_token(name, &twrp);
699 status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
700 if (!NT_STATUS_IS_OK(status)) {
701 reply_nterror(req, status);
705 status = filename_convert_dirfsp(ctx,
712 if (!NT_STATUS_IS_OK(status)) {
713 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
714 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
716 END_PROFILE(SMBcheckpath);
722 if (!VALID_STAT(smb_fname->st) &&
723 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
724 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
725 smb_fname_str_dbg(smb_fname), strerror(errno)));
726 status = map_nt_error_from_unix(errno);
730 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
731 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
736 reply_smb1_outbuf(req, 0, 0);
739 /* We special case this - as when a Windows machine
740 is parsing a path is steps through the components
741 one at a time - if a component fails it expects
742 ERRbadpath, not ERRbadfile.
744 status = map_checkpath_error(req->flags2, status);
745 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
747 * Windows returns different error codes if
748 * the parent directory is valid but not the
749 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
750 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
751 * if the path is invalid.
753 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
758 reply_nterror(req, status);
761 TALLOC_FREE(smb_fname);
762 END_PROFILE(SMBcheckpath);
766 /****************************************************************************
768 ****************************************************************************/
770 void reply_getatr(struct smb_request *req)
772 struct smbXsrv_connection *xconn = req->xconn;
773 connection_struct *conn = req->conn;
774 struct smb_filename *smb_fname = NULL;
781 TALLOC_CTX *ctx = talloc_tos();
783 START_PROFILE(SMBgetatr);
785 p = (const char *)req->buf + 1;
786 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
787 if (!NT_STATUS_IS_OK(status)) {
788 reply_nterror(req, status);
793 * dos sometimes asks for a stat of "" - it returns a "hidden
794 * directory" under WfWg - weird!
796 if (*fname == '\0') {
797 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
798 if (!CAN_WRITE(conn)) {
799 mode |= FILE_ATTRIBUTE_READONLY;
804 struct files_struct *dirfsp = NULL;
805 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
809 if (ucf_flags & UCF_GMT_PATHNAME) {
810 extract_snapshot_token(fname, &twrp);
812 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
813 if (!NT_STATUS_IS_OK(status)) {
814 reply_nterror(req, status);
817 status = filename_convert_dirfsp(ctx,
824 if (!NT_STATUS_IS_OK(status)) {
825 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
826 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
830 reply_nterror(req, status);
833 if (!VALID_STAT(smb_fname->st) &&
834 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
835 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
836 smb_fname_str_dbg(smb_fname),
838 reply_nterror(req, map_nt_error_from_unix(errno));
842 mode = fdos_mode(smb_fname->fsp);
843 size = smb_fname->st.st_ex_size;
845 ask_sharemode = fsp_search_ask_sharemode(smb_fname->fsp);
847 struct timespec write_time_ts;
848 struct file_id fileid;
850 ZERO_STRUCT(write_time_ts);
851 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
852 get_file_infos(fileid, 0, NULL, &write_time_ts);
853 if (!is_omit_timespec(&write_time_ts)) {
854 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
858 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
859 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
864 reply_smb1_outbuf(req, 10, 0);
866 SSVAL(req->outbuf,smb_vwv0,mode);
867 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
868 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
870 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
872 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
874 if (xconn->protocol >= PROTOCOL_NT1) {
875 SSVAL(req->outbuf, smb_flg2,
876 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
879 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
880 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
883 TALLOC_FREE(smb_fname);
885 END_PROFILE(SMBgetatr);
889 /****************************************************************************
891 ****************************************************************************/
893 void reply_setatr(struct smb_request *req)
895 struct smb_file_time ft;
896 connection_struct *conn = req->conn;
897 struct smb_filename *smb_fname = NULL;
898 struct files_struct *dirfsp = NULL;
904 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
906 TALLOC_CTX *ctx = talloc_tos();
908 START_PROFILE(SMBsetatr);
909 init_smb_file_time(&ft);
912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
916 p = (const char *)req->buf + 1;
917 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
918 if (!NT_STATUS_IS_OK(status)) {
919 reply_nterror(req, status);
923 if (ucf_flags & UCF_GMT_PATHNAME) {
924 extract_snapshot_token(fname, &twrp);
926 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
927 if (!NT_STATUS_IS_OK(status)) {
928 reply_nterror(req, status);
931 status = filename_convert_dirfsp(ctx,
938 if (!NT_STATUS_IS_OK(status)) {
939 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
940 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
944 reply_nterror(req, status);
948 if (ISDOT(smb_fname->base_name)) {
950 * Not sure here is the right place to catch this
951 * condition. Might be moved to somewhere else later -- vl
953 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
957 if (smb_fname->fsp == NULL) {
958 /* Can't set access rights on a symlink. */
959 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
963 mode = SVAL(req->vwv+0, 0);
964 mtime = srv_make_unix_date3(req->vwv+1);
966 if (mode != FILE_ATTRIBUTE_NORMAL) {
967 if (VALID_STAT_OF_DIR(smb_fname->st))
968 mode |= FILE_ATTRIBUTE_DIRECTORY;
970 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
972 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
975 FILE_WRITE_ATTRIBUTES);
976 if (!NT_STATUS_IS_OK(status)) {
977 reply_nterror(req, status);
981 if (file_set_dosmode(conn, smb_fname, mode, NULL,
983 reply_nterror(req, map_nt_error_from_unix(errno));
988 ft.mtime = time_t_to_full_timespec(mtime);
990 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
991 if (!NT_STATUS_IS_OK(status)) {
992 reply_nterror(req, status);
996 reply_smb1_outbuf(req, 0, 0);
998 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1001 TALLOC_FREE(smb_fname);
1002 END_PROFILE(SMBsetatr);
1006 /****************************************************************************
1008 ****************************************************************************/
1010 void reply_dskattr(struct smb_request *req)
1012 struct smbXsrv_connection *xconn = req->xconn;
1013 connection_struct *conn = req->conn;
1015 uint64_t dfree,dsize,bsize;
1016 struct smb_filename smb_fname;
1017 START_PROFILE(SMBdskattr);
1019 ZERO_STRUCT(smb_fname);
1020 smb_fname.base_name = discard_const_p(char, ".");
1022 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1023 reply_nterror(req, map_nt_error_from_unix(errno));
1024 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1025 END_PROFILE(SMBdskattr);
1029 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1030 if (ret == (uint64_t)-1) {
1031 reply_nterror(req, map_nt_error_from_unix(errno));
1032 END_PROFILE(SMBdskattr);
1037 * Force max to fit in 16 bit fields.
1039 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1043 if (bsize > (WORDMAX*512)) {
1044 bsize = (WORDMAX*512);
1045 if (dsize > WORDMAX)
1047 if (dfree > WORDMAX)
1053 reply_smb1_outbuf(req, 5, 0);
1055 if (xconn->protocol <= PROTOCOL_LANMAN2) {
1056 double total_space, free_space;
1057 /* we need to scale this to a number that DOS6 can handle. We
1058 use floating point so we can handle large drives on systems
1059 that don't have 64 bit integers
1061 we end up displaying a maximum of 2G to DOS systems
1063 total_space = dsize * (double)bsize;
1064 free_space = dfree * (double)bsize;
1066 dsize = (uint64_t)((total_space+63*512) / (64*512));
1067 dfree = (uint64_t)((free_space+63*512) / (64*512));
1069 if (dsize > 0xFFFF) dsize = 0xFFFF;
1070 if (dfree > 0xFFFF) dfree = 0xFFFF;
1072 SSVAL(req->outbuf,smb_vwv0,dsize);
1073 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1074 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1075 SSVAL(req->outbuf,smb_vwv3,dfree);
1077 SSVAL(req->outbuf,smb_vwv0,dsize);
1078 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1079 SSVAL(req->outbuf,smb_vwv2,512);
1080 SSVAL(req->outbuf,smb_vwv3,dfree);
1083 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1085 END_PROFILE(SMBdskattr);
1089 /****************************************************************************
1091 ****************************************************************************/
1093 static void make_dir_struct(TALLOC_CTX *ctx,
1104 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1108 memset(buf+1,' ',11);
1109 if ((p = strchr_m(mask, '.')) != NULL) {
1110 char name[p - mask + 1];
1111 strlcpy(name, mask, sizeof(name));
1112 push_ascii(buf + 1, name, 8, 0);
1113 push_ascii(buf+9,p+1,3, 0);
1115 push_ascii(buf + 1, mask, 11, 0);
1118 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1120 srv_put_dos_date(buf,22,date);
1121 SSVAL(buf,26,size & 0xFFFF);
1122 SSVAL(buf,28,(size >> 16)&0xFFFF);
1123 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1124 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1125 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1126 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1129 /*******************************************************************
1130 A wrapper that handles case sensitivity and the special handling
1132 *******************************************************************/
1134 static bool mask_match_search(const char *string,
1135 const char *pattern,
1136 bool is_case_sensitive)
1138 if (ISDOTDOT(string)) {
1141 if (ISDOT(pattern)) {
1145 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1148 static bool mangle_mask_match(connection_struct *conn,
1149 const char *filename,
1154 if (!name_to_8_3(filename, mname, False, conn->params)) {
1157 return mask_match_search(mname, mask, False);
1160 /****************************************************************************
1161 Get an 8.3 directory entry.
1162 ****************************************************************************/
1164 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1170 connection_struct *conn = (connection_struct *)private_data;
1172 if ((strcmp(mask, "*.*") == 0) ||
1173 mask_match_search(dname, mask, false) ||
1174 mangle_mask_match(conn, dname, mask)) {
1178 * Ensure we can push the original name as UCS2. If
1179 * not, then just don't return this name.
1183 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1184 uint8_t *tmp = talloc_array(talloc_tos(), uint8_t, len);
1186 status = srvstr_push(NULL,
1187 FLAGS2_UNICODE_STRINGS,
1196 if (!NT_STATUS_IS_OK(status)) {
1200 if (!mangle_is_8_3(dname, false, conn->params)) {
1202 name_to_8_3(dname, mname, false, conn->params);
1211 *_fname = talloc_strdup(ctx, fname);
1212 if (*_fname == NULL) {
1222 static bool get_dir_entry(TALLOC_CTX *ctx,
1223 connection_struct *conn,
1224 struct dptr_struct *dirptr,
1230 struct timespec *_date,
1235 struct smb_filename *smb_fname = NULL;
1240 ok = smbd_dirptr_get_entry(ctx,
1247 smbd_dirptr_8_3_match_fn,
1255 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1256 /* hide reparse points from ancient clients */
1258 TALLOC_FREE(smb_fname);
1262 *_fname = talloc_move(ctx, &fname);
1263 *_size = smb_fname->st.st_ex_size;
1265 *_date = smb_fname->st.st_ex_mtime;
1266 TALLOC_FREE(smb_fname);
1270 /****************************************************************************
1272 Can be called from SMBsearch, SMBffirst or SMBfunique.
1273 ****************************************************************************/
1275 void reply_search(struct smb_request *req)
1277 connection_struct *conn = req->conn;
1280 char *directory = NULL;
1281 struct smb_filename *smb_fname = NULL;
1285 struct timespec date;
1287 unsigned int numentries = 0;
1288 unsigned int maxentries = 0;
1289 bool finished = False;
1294 bool check_descend = False;
1295 bool expect_close = False;
1297 bool mask_contains_wcard = False;
1298 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1299 TALLOC_CTX *ctx = talloc_tos();
1300 struct smbXsrv_connection *xconn = req->xconn;
1301 struct smbd_server_connection *sconn = req->sconn;
1302 files_struct *fsp = NULL;
1303 const struct loadparm_substitution *lp_sub =
1304 loadparm_s3_global_substitution();
1306 START_PROFILE(SMBsearch);
1309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1313 if (req->posix_pathnames) {
1314 reply_unknown_new(req, req->cmd);
1318 /* If we were called as SMBffirst then we must expect close. */
1319 if(req->cmd == SMBffirst) {
1320 expect_close = True;
1323 reply_smb1_outbuf(req, 1, 3);
1324 maxentries = SVAL(req->vwv+0, 0);
1325 dirtype = SVAL(req->vwv+1, 0);
1326 p = (const char *)req->buf + 1;
1327 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1329 if (!NT_STATUS_IS_OK(nt_status)) {
1330 reply_nterror(req, nt_status);
1334 if (smbreq_bufrem(req, p) < 3) {
1335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1340 status_len = SVAL(p, 0);
1343 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1345 if (status_len == 0) {
1346 const char *dirpath;
1347 struct files_struct *dirfsp = NULL;
1348 struct smb_filename *smb_dname = NULL;
1349 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1351 nt_status = smb1_strip_dfs_path(ctx, &ucf_flags, &path);
1352 if (!NT_STATUS_IS_OK(nt_status)) {
1353 reply_nterror(req, nt_status);
1357 nt_status = filename_convert_smb1_search_path(ctx,
1365 if (!NT_STATUS_IS_OK(nt_status)) {
1366 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1367 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1368 ERRSRV, ERRbadpath);
1371 reply_nterror(req, nt_status);
1375 memset((char *)status,'\0',21);
1376 SCVAL(status,0,(dirtype & 0x1F));
1379 * Open an fsp on this directory for the dptr.
1381 nt_status = SMB_VFS_CREATE_FILE(
1384 dirfsp, /* dirfsp */
1385 smb_dname, /* dname */
1386 FILE_LIST_DIRECTORY, /* access_mask */
1388 FILE_SHARE_WRITE, /* share_access */
1389 FILE_OPEN, /* create_disposition*/
1390 FILE_DIRECTORY_FILE, /* create_options */
1391 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1392 NO_OPLOCK, /* oplock_request */
1394 0, /* allocation_size */
1395 0, /* private_flags */
1400 NULL, /* in_context */
1401 NULL);/* out_context */
1403 if (!NT_STATUS_IS_OK(nt_status)) {
1404 DBG_ERR("failed to open directory %s\n",
1405 smb_fname_str_dbg(smb_dname));
1406 reply_nterror(req, nt_status);
1410 nt_status = dptr_create(conn,
1418 TALLOC_FREE(smb_dname);
1420 if (!NT_STATUS_IS_OK(nt_status)) {
1422 * Use NULL here for the first parameter (req)
1423 * as this is not a client visible handle so
1424 * can't be part of an SMB1 chain.
1426 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1427 reply_nterror(req, nt_status);
1431 dptr_num = dptr_dnum(fsp->dptr);
1432 dirpath = dptr_path(sconn, dptr_num);
1433 directory = talloc_strdup(ctx, dirpath);
1435 reply_nterror(req, NT_STATUS_NO_MEMORY);
1441 const char *dirpath;
1442 unsigned int dptr_filenum;
1443 uint32_t resume_key_index;
1445 if (smbreq_bufrem(req, p) < 21) {
1446 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1450 memcpy(status,p,21);
1451 status_dirtype = CVAL(status,0) & 0x1F;
1452 if (status_dirtype != (dirtype & 0x1F)) {
1453 dirtype = status_dirtype;
1456 dptr_num = CVAL(status, 12);
1457 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1462 resume_key_index = PULL_LE_U32(status, 13);
1463 dptr_filenum = dptr_FileNumber(fsp->dptr);
1465 if (resume_key_index > dptr_filenum) {
1467 * Haven't seen this resume key yet. Just stop
1473 if (resume_key_index < dptr_filenum) {
1475 * The resume key was not the last one we
1476 * sent, rewind and skip to what the client
1479 dptr_RewindDir(fsp->dptr);
1481 dptr_filenum = dptr_FileNumber(fsp->dptr);
1482 SMB_ASSERT(dptr_filenum == 0);
1484 while (dptr_filenum < resume_key_index) {
1485 bool ok = get_dir_entry(
1489 dptr_wcard(sconn, dptr_num),
1502 dptr_filenum = dptr_FileNumber(fsp->dptr);
1506 dirpath = dptr_path(sconn, dptr_num);
1507 directory = talloc_strdup(ctx, dirpath);
1509 reply_nterror(req, NT_STATUS_NO_MEMORY);
1513 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1517 dirtype = dptr_attr(sconn, dptr_num);
1520 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1522 DEBUG(4,("dptr_num is %d\n",dptr_num));
1524 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1525 char buf[DIR_STRUCT_SIZE];
1526 memcpy(buf,status,21);
1527 make_dir_struct(ctx,
1530 volume_label(ctx, SNUM(conn)),
1532 FILE_ATTRIBUTE_VOLUME,
1534 !allow_long_path_components);
1535 SCVAL(buf, 12, dptr_num);
1537 if (message_push_blob(&req->outbuf,
1538 data_blob_const(buf, sizeof(buf)))
1540 reply_nterror(req, NT_STATUS_NO_MEMORY);
1545 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1546 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1549 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1551 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1552 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1553 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1554 check_descend = True;
1557 ask_sharemode = fsp_search_ask_sharemode(fsp);
1559 for (i=numentries;(i<maxentries) && !finished;i++) {
1560 finished = !get_dir_entry(ctx,
1572 char buf[DIR_STRUCT_SIZE];
1573 memcpy(buf,status,21);
1581 convert_timespec_to_time_t(date),
1582 !allow_long_path_components);
1583 SCVAL(buf, 12, dptr_num);
1586 dptr_FileNumber(fsp->dptr));
1587 if (message_push_blob(&req->outbuf,
1588 data_blob_const(buf, sizeof(buf)))
1590 reply_nterror(req, NT_STATUS_NO_MEMORY);
1601 /* If we were called as SMBffirst with smb_search_id == NULL
1602 and no entries were found then return error and close fsp->dptr
1605 if (numentries == 0) {
1608 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1610 } else if(expect_close && status_len == 0) {
1611 /* Close the dptr - we know it's gone */
1614 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1618 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1619 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1621 /* fsp may have been closed above. */
1623 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1627 if ((numentries == 0) && !mask_contains_wcard) {
1628 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1632 SSVAL(req->outbuf,smb_vwv0,numentries);
1633 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1634 SCVAL(smb_buf(req->outbuf),0,5);
1635 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1637 /* The replies here are never long name. */
1638 SSVAL(req->outbuf, smb_flg2,
1639 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1640 if (!allow_long_path_components) {
1641 SSVAL(req->outbuf, smb_flg2,
1642 SVAL(req->outbuf, smb_flg2)
1643 & (~FLAGS2_LONG_PATH_COMPONENTS));
1646 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1647 SSVAL(req->outbuf, smb_flg2,
1648 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1650 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1651 smb_fn_name(req->cmd),
1658 TALLOC_FREE(directory);
1660 TALLOC_FREE(smb_fname);
1661 END_PROFILE(SMBsearch);
1665 /****************************************************************************
1666 Reply to a fclose (stop directory search).
1667 ****************************************************************************/
1669 void reply_fclose(struct smb_request *req)
1676 TALLOC_CTX *ctx = talloc_tos();
1677 struct smbd_server_connection *sconn = req->sconn;
1678 files_struct *fsp = NULL;
1680 START_PROFILE(SMBfclose);
1682 if (req->posix_pathnames) {
1683 reply_unknown_new(req, req->cmd);
1684 END_PROFILE(SMBfclose);
1688 p = (const char *)req->buf + 1;
1689 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1691 if (!NT_STATUS_IS_OK(err)) {
1692 reply_nterror(req, err);
1693 END_PROFILE(SMBfclose);
1697 if (smbreq_bufrem(req, p) < 3) {
1698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1699 END_PROFILE(SMBfclose);
1704 status_len = SVAL(p,0);
1707 if (status_len == 0) {
1708 reply_force_doserror(req, ERRSRV, ERRsrverror);
1709 END_PROFILE(SMBfclose);
1713 if (smbreq_bufrem(req, p) < 21) {
1714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1715 END_PROFILE(SMBfclose);
1719 dptr_num = CVAL(p, 12);
1721 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1723 /* Close the file - we know it's gone */
1724 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1728 reply_smb1_outbuf(req, 1, 0);
1729 SSVAL(req->outbuf,smb_vwv0,0);
1731 DEBUG(3,("search close\n"));
1733 END_PROFILE(SMBfclose);
1737 /****************************************************************************
1739 ****************************************************************************/
1741 void reply_open(struct smb_request *req)
1743 connection_struct *conn = req->conn;
1744 struct smb_filename *smb_fname = NULL;
1750 struct files_struct *dirfsp = NULL;
1755 uint32_t access_mask;
1756 uint32_t share_mode;
1757 uint32_t create_disposition;
1758 uint32_t create_options = 0;
1759 uint32_t private_flags = 0;
1763 TALLOC_CTX *ctx = talloc_tos();
1765 START_PROFILE(SMBopen);
1768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1772 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1773 deny_mode = SVAL(req->vwv+0, 0);
1774 dos_attr = SVAL(req->vwv+1, 0);
1776 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1777 STR_TERMINATE, &status);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 reply_nterror(req, status);
1783 if (!map_open_params_to_ntcreate(fname, deny_mode,
1784 OPENX_FILE_EXISTS_OPEN, &access_mask,
1785 &share_mode, &create_disposition,
1786 &create_options, &private_flags)) {
1787 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1791 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1793 if (ucf_flags & UCF_GMT_PATHNAME) {
1794 extract_snapshot_token(fname, &twrp);
1796 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 reply_nterror(req, status);
1801 status = filename_convert_dirfsp(ctx,
1808 if (!NT_STATUS_IS_OK(status)) {
1809 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1810 reply_botherror(req,
1811 NT_STATUS_PATH_NOT_COVERED,
1812 ERRSRV, ERRbadpath);
1815 reply_nterror(req, status);
1819 status = SMB_VFS_CREATE_FILE(
1822 dirfsp, /* dirfsp */
1823 smb_fname, /* fname */
1824 access_mask, /* access_mask */
1825 share_mode, /* share_access */
1826 create_disposition, /* create_disposition*/
1827 create_options, /* create_options */
1828 dos_attr, /* file_attributes */
1829 oplock_request, /* oplock_request */
1831 0, /* allocation_size */
1837 NULL, NULL); /* create context */
1839 if (!NT_STATUS_IS_OK(status)) {
1840 if (open_was_deferred(req->xconn, req->mid)) {
1841 /* We have re-scheduled this call. */
1845 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1846 reply_openerror(req, status);
1850 fsp = fcb_or_dos_open(
1857 bool ok = defer_smb1_sharing_violation(req);
1861 reply_openerror(req, status);
1866 /* Ensure we're pointing at the correct stat struct. */
1867 TALLOC_FREE(smb_fname);
1868 smb_fname = fsp->fsp_name;
1870 size = smb_fname->st.st_ex_size;
1871 fattr = fdos_mode(fsp);
1873 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1875 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1876 DEBUG(3,("attempt to open a directory %s\n",
1878 close_file_free(req, &fsp, ERROR_CLOSE);
1879 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1880 ERRDOS, ERRnoaccess);
1884 reply_smb1_outbuf(req, 7, 0);
1885 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1886 SSVAL(req->outbuf,smb_vwv1,fattr);
1887 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1888 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1890 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1892 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1893 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1895 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1896 SCVAL(req->outbuf,smb_flg,
1897 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1900 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1901 SCVAL(req->outbuf,smb_flg,
1902 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1905 END_PROFILE(SMBopen);
1909 /****************************************************************************
1910 Reply to an open and X.
1911 ****************************************************************************/
1913 void reply_open_and_X(struct smb_request *req)
1915 connection_struct *conn = req->conn;
1916 struct smb_filename *smb_fname = NULL;
1918 uint16_t open_flags;
1921 /* Breakout the oplock request bits so we can set the
1922 reply bits separately. */
1923 int ex_oplock_request;
1924 int core_oplock_request;
1927 int smb_sattr = SVAL(req->vwv+4, 0);
1928 uint32_t smb_time = make_unix_date3(req->vwv+6);
1934 struct files_struct *dirfsp = NULL;
1937 uint64_t allocation_size;
1938 ssize_t retval = -1;
1939 uint32_t access_mask;
1940 uint32_t share_mode;
1941 uint32_t create_disposition;
1942 uint32_t create_options = 0;
1943 uint32_t private_flags = 0;
1946 TALLOC_CTX *ctx = talloc_tos();
1948 START_PROFILE(SMBopenX);
1950 if (req->wct < 15) {
1951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1955 open_flags = SVAL(req->vwv+2, 0);
1956 deny_mode = SVAL(req->vwv+3, 0);
1957 smb_attr = SVAL(req->vwv+5, 0);
1958 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1959 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1960 oplock_request = ex_oplock_request | core_oplock_request;
1961 smb_ofun = SVAL(req->vwv+8, 0);
1962 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1964 /* If it's an IPC, pass off the pipe handler. */
1966 if (lp_nt_pipe_support()) {
1967 reply_open_pipe_and_X(conn, req);
1969 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1974 /* XXXX we need to handle passed times, sattr and flags */
1975 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1976 STR_TERMINATE, &status);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 reply_nterror(req, status);
1982 if (!map_open_params_to_ntcreate(fname, deny_mode,
1984 &access_mask, &share_mode,
1985 &create_disposition,
1988 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1992 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1994 if (ucf_flags & UCF_GMT_PATHNAME) {
1995 extract_snapshot_token(fname, &twrp);
1997 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1998 if (!NT_STATUS_IS_OK(status)) {
1999 reply_nterror(req, status);
2003 status = filename_convert_dirfsp(ctx,
2010 if (!NT_STATUS_IS_OK(status)) {
2011 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2012 reply_botherror(req,
2013 NT_STATUS_PATH_NOT_COVERED,
2014 ERRSRV, ERRbadpath);
2017 reply_nterror(req, status);
2021 status = SMB_VFS_CREATE_FILE(
2024 dirfsp, /* dirfsp */
2025 smb_fname, /* fname */
2026 access_mask, /* access_mask */
2027 share_mode, /* share_access */
2028 create_disposition, /* create_disposition*/
2029 create_options, /* create_options */
2030 smb_attr, /* file_attributes */
2031 oplock_request, /* oplock_request */
2033 0, /* allocation_size */
2038 &smb_action, /* pinfo */
2039 NULL, NULL); /* create context */
2041 if (!NT_STATUS_IS_OK(status)) {
2042 if (open_was_deferred(req->xconn, req->mid)) {
2043 /* We have re-scheduled this call. */
2047 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2048 reply_openerror(req, status);
2052 fsp = fcb_or_dos_open(
2059 bool ok = defer_smb1_sharing_violation(req);
2063 reply_openerror(req, status);
2068 smb_action = FILE_WAS_OPENED;
2071 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2072 if the file is truncated or created. */
2073 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2074 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2075 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2076 close_file_free(req, &fsp, ERROR_CLOSE);
2077 reply_nterror(req, NT_STATUS_DISK_FULL);
2080 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2082 close_file_free(req, &fsp, ERROR_CLOSE);
2083 reply_nterror(req, NT_STATUS_DISK_FULL);
2086 status = vfs_stat_fsp(fsp);
2087 if (!NT_STATUS_IS_OK(status)) {
2088 close_file_free(req, &fsp, ERROR_CLOSE);
2089 reply_nterror(req, status);
2094 fattr = fdos_mode(fsp);
2095 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2096 close_file_free(req, &fsp, ERROR_CLOSE);
2097 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2100 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2102 /* If the caller set the extended oplock request bit
2103 and we granted one (by whatever means) - set the
2104 correct bit for extended oplock reply.
2107 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2108 smb_action |= EXTENDED_OPLOCK_GRANTED;
2111 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2112 smb_action |= EXTENDED_OPLOCK_GRANTED;
2115 /* If the caller set the core oplock request bit
2116 and we granted one (by whatever means) - set the
2117 correct bit for core oplock reply.
2120 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2121 reply_smb1_outbuf(req, 19, 0);
2123 reply_smb1_outbuf(req, 15, 0);
2126 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2127 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2129 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2130 SCVAL(req->outbuf, smb_flg,
2131 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2134 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2135 SCVAL(req->outbuf, smb_flg,
2136 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2139 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2140 SSVAL(req->outbuf,smb_vwv3,fattr);
2141 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2142 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2144 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2146 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2147 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2148 SSVAL(req->outbuf,smb_vwv11,smb_action);
2150 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2151 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2155 TALLOC_FREE(smb_fname);
2156 END_PROFILE(SMBopenX);
2160 /****************************************************************************
2161 Reply to a SMBulogoffX.
2162 ****************************************************************************/
2164 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2165 struct smbXsrv_session *session);
2166 static void reply_ulogoffX_done(struct tevent_req *req);
2168 void reply_ulogoffX(struct smb_request *smb1req)
2170 struct timeval now = timeval_current();
2171 struct smbXsrv_session *session = NULL;
2172 struct tevent_req *req;
2176 * Don't setup the profile charge here, take
2177 * it in reply_ulogoffX_done(). Not strictly correct
2178 * but better than the other SMB1 async
2179 * code that double-charges at the moment.
2182 status = smb1srv_session_lookup(smb1req->xconn,
2184 timeval_to_nttime(&now),
2186 if (!NT_STATUS_IS_OK(status)) {
2187 /* Not going async, profile here. */
2188 START_PROFILE(SMBulogoffX);
2189 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2190 (unsigned long long)smb1req->vuid);
2192 smb1req->vuid = UID_FIELD_INVALID;
2193 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2194 END_PROFILE(SMBulogoffX);
2198 req = reply_ulogoffX_send(smb1req, session);
2200 /* Not going async, profile here. */
2201 START_PROFILE(SMBulogoffX);
2202 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2203 END_PROFILE(SMBulogoffX);
2207 /* We're async. This will complete later. */
2208 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2212 struct reply_ulogoffX_state {
2213 struct tevent_queue *wait_queue;
2214 struct smbXsrv_session *session;
2217 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2219 /****************************************************************************
2220 Async SMB1 ulogoffX.
2221 Note, on failure here we deallocate and return NULL to allow the caller to
2222 SMB1 return an error of ERRnomem immediately.
2223 ****************************************************************************/
2225 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2226 struct smbXsrv_session *session)
2228 struct tevent_req *req;
2229 struct reply_ulogoffX_state *state;
2230 struct tevent_req *subreq;
2232 struct smbd_server_connection *sconn = session->client->sconn;
2233 uint64_t vuid = session->global->session_wire_id;
2235 req = tevent_req_create(smb1req, &state,
2236 struct reply_ulogoffX_state);
2240 state->wait_queue = tevent_queue_create(state,
2241 "reply_ulogoffX_wait_queue");
2242 if (tevent_req_nomem(state->wait_queue, req)) {
2246 state->session = session;
2249 * Make sure that no new request will be able to use this session.
2250 * This ensures that once all outstanding fsp->aio_requests
2251 * on this session are done, we are safe to close it.
2253 session->status = NT_STATUS_USER_SESSION_DELETED;
2255 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2256 if (fsp->vuid != vuid) {
2260 * Flag the file as close in progress.
2261 * This will prevent any more IO being
2264 fsp->fsp_flags.closing = true;
2266 if (fsp->num_aio_requests > 0) {
2268 * Now wait until all aio requests on this fsp are
2271 * We don't set a callback, as we just want to block the
2272 * wait queue and the talloc_free() of fsp->aio_request
2273 * will remove the item from the wait queue.
2275 subreq = tevent_queue_wait_send(fsp->aio_requests,
2278 if (tevent_req_nomem(subreq, req)) {
2286 * Now we add our own waiter to the end of the queue,
2287 * this way we get notified when all pending requests are finished
2288 * and reply to the outstanding SMB1 request.
2290 subreq = tevent_queue_wait_send(state,
2293 if (tevent_req_nomem(subreq, req)) {
2299 * We're really going async - move the SMB1 request from
2300 * a talloc stackframe above us to the sconn talloc-context.
2301 * We need this to stick around until the wait_done
2302 * callback is invoked.
2304 smb1req = talloc_move(sconn, &smb1req);
2306 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2311 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2313 struct tevent_req *req = tevent_req_callback_data(
2314 subreq, struct tevent_req);
2316 tevent_queue_wait_recv(subreq);
2317 TALLOC_FREE(subreq);
2318 tevent_req_done(req);
2321 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2323 return tevent_req_simple_recv_ntstatus(req);
2326 static void reply_ulogoffX_done(struct tevent_req *req)
2328 struct smb_request *smb1req = tevent_req_callback_data(
2329 req, struct smb_request);
2330 struct reply_ulogoffX_state *state = tevent_req_data(req,
2331 struct reply_ulogoffX_state);
2332 struct smbXsrv_session *session = state->session;
2336 * Take the profile charge here. Not strictly
2337 * correct but better than the other SMB1 async
2338 * code that double-charges at the moment.
2340 START_PROFILE(SMBulogoffX);
2342 status = reply_ulogoffX_recv(req);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 TALLOC_FREE(smb1req);
2346 END_PROFILE(SMBulogoffX);
2347 exit_server(__location__ ": reply_ulogoffX_recv failed");
2351 status = smbXsrv_session_logoff(session);
2352 if (!NT_STATUS_IS_OK(status)) {
2353 TALLOC_FREE(smb1req);
2354 END_PROFILE(SMBulogoffX);
2355 exit_server(__location__ ": smbXsrv_session_logoff failed");
2359 TALLOC_FREE(session);
2361 reply_smb1_outbuf(smb1req, 2, 0);
2362 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2363 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2365 DBG_NOTICE("ulogoffX vuid=%llu\n",
2366 (unsigned long long)smb1req->vuid);
2368 smb1req->vuid = UID_FIELD_INVALID;
2370 * The following call is needed to push the
2371 * reply data back out the socket after async
2372 * return. Plus it frees smb1req.
2374 smb_request_done(smb1req);
2375 END_PROFILE(SMBulogoffX);
2378 /****************************************************************************
2379 Reply to a mknew or a create.
2380 ****************************************************************************/
2382 void reply_mknew(struct smb_request *req)
2384 connection_struct *conn = req->conn;
2385 struct smb_filename *smb_fname = NULL;
2388 struct smb_file_time ft;
2389 struct files_struct *dirfsp = NULL;
2391 int oplock_request = 0;
2393 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2394 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2395 uint32_t create_disposition;
2396 uint32_t create_options = 0;
2399 TALLOC_CTX *ctx = talloc_tos();
2401 START_PROFILE(SMBcreate);
2402 init_smb_file_time(&ft);
2405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2409 fattr = SVAL(req->vwv+0, 0);
2410 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2412 if (req->cmd == SMBmknew) {
2413 /* We should fail if file exists. */
2414 create_disposition = FILE_CREATE;
2416 /* Create if file doesn't exist, truncate if it does. */
2417 create_disposition = FILE_OVERWRITE_IF;
2421 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2423 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2424 STR_TERMINATE, &status);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 reply_nterror(req, status);
2430 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2431 if (ucf_flags & UCF_GMT_PATHNAME) {
2432 extract_snapshot_token(fname, &twrp);
2434 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2435 if (!NT_STATUS_IS_OK(status)) {
2436 reply_nterror(req, status);
2440 status = filename_convert_dirfsp(ctx,
2447 if (!NT_STATUS_IS_OK(status)) {
2448 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2449 reply_botherror(req,
2450 NT_STATUS_PATH_NOT_COVERED,
2451 ERRSRV, ERRbadpath);
2454 reply_nterror(req, status);
2458 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2459 DEBUG(0,("Attempt to create file (%s) with volid set - "
2460 "please report this\n",
2461 smb_fname_str_dbg(smb_fname)));
2464 status = SMB_VFS_CREATE_FILE(
2467 dirfsp, /* dirfsp */
2468 smb_fname, /* fname */
2469 access_mask, /* access_mask */
2470 share_mode, /* share_access */
2471 create_disposition, /* create_disposition*/
2472 create_options, /* create_options */
2473 fattr, /* file_attributes */
2474 oplock_request, /* oplock_request */
2476 0, /* allocation_size */
2477 0, /* private_flags */
2482 NULL, NULL); /* create context */
2484 if (!NT_STATUS_IS_OK(status)) {
2485 if (open_was_deferred(req->xconn, req->mid)) {
2486 /* We have re-scheduled this call. */
2489 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2490 bool ok = defer_smb1_sharing_violation(req);
2495 reply_openerror(req, status);
2499 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2500 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 END_PROFILE(SMBcreate);
2506 reply_smb1_outbuf(req, 1, 0);
2507 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2509 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2510 SCVAL(req->outbuf,smb_flg,
2511 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2514 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2515 SCVAL(req->outbuf,smb_flg,
2516 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2519 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2520 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2521 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2522 (unsigned int)fattr));
2525 TALLOC_FREE(smb_fname);
2526 END_PROFILE(SMBcreate);
2530 /****************************************************************************
2531 Reply to a create temporary file.
2532 ****************************************************************************/
2534 void reply_ctemp(struct smb_request *req)
2536 connection_struct *conn = req->conn;
2537 struct smb_filename *smb_fname = NULL;
2538 char *wire_name = NULL;
2541 struct files_struct *dirfsp = NULL;
2549 TALLOC_CTX *ctx = talloc_tos();
2551 START_PROFILE(SMBctemp);
2554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2558 fattr = SVAL(req->vwv+0, 0);
2559 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2561 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2562 STR_TERMINATE, &status);
2563 if (!NT_STATUS_IS_OK(status)) {
2564 reply_nterror(req, status);
2568 for (i = 0; i < 10; i++) {
2570 fname = talloc_asprintf(ctx,
2573 generate_random_str_list(ctx, 5, "0123456789"));
2575 fname = talloc_asprintf(ctx,
2577 generate_random_str_list(ctx, 5, "0123456789"));
2581 reply_nterror(req, NT_STATUS_NO_MEMORY);
2585 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2586 if (ucf_flags & UCF_GMT_PATHNAME) {
2587 extract_snapshot_token(fname, &twrp);
2589 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2590 if (!NT_STATUS_IS_OK(status)) {
2591 reply_nterror(req, status);
2595 status = filename_convert_dirfsp(ctx,
2602 if (!NT_STATUS_IS_OK(status)) {
2603 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2604 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2605 ERRSRV, ERRbadpath);
2608 reply_nterror(req, status);
2612 /* Create the file. */
2613 status = SMB_VFS_CREATE_FILE(
2616 dirfsp, /* dirfsp */
2617 smb_fname, /* fname */
2618 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2619 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2620 FILE_CREATE, /* create_disposition*/
2621 0, /* create_options */
2622 fattr, /* file_attributes */
2623 oplock_request, /* oplock_request */
2625 0, /* allocation_size */
2626 0, /* private_flags */
2631 NULL, NULL); /* create context */
2633 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2635 TALLOC_FREE(dirfsp);
2636 TALLOC_FREE(smb_fname);
2640 if (!NT_STATUS_IS_OK(status)) {
2641 if (open_was_deferred(req->xconn, req->mid)) {
2642 /* We have re-scheduled this call. */
2645 if (NT_STATUS_EQUAL(
2646 status, NT_STATUS_SHARING_VIOLATION)) {
2647 bool ok = defer_smb1_sharing_violation(req);
2652 reply_openerror(req, status);
2660 /* Collision after 10 times... */
2661 reply_nterror(req, status);
2665 reply_smb1_outbuf(req, 1, 0);
2666 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2668 /* the returned filename is relative to the directory */
2669 s = strrchr_m(fsp->fsp_name->base_name, '/');
2671 s = fsp->fsp_name->base_name;
2677 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2678 thing in the byte section. JRA */
2679 SSVALS(p, 0, -1); /* what is this? not in spec */
2681 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2683 reply_nterror(req, NT_STATUS_NO_MEMORY);
2687 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2688 SCVAL(req->outbuf, smb_flg,
2689 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2692 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2693 SCVAL(req->outbuf, smb_flg,
2694 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2697 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2698 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2699 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2701 TALLOC_FREE(smb_fname);
2702 TALLOC_FREE(wire_name);
2703 END_PROFILE(SMBctemp);
2707 /****************************************************************************
2709 ****************************************************************************/
2711 void reply_unlink(struct smb_request *req)
2713 connection_struct *conn = req->conn;
2715 struct files_struct *dirfsp = NULL;
2716 struct smb_filename *smb_fname = NULL;
2719 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2721 TALLOC_CTX *ctx = talloc_tos();
2723 START_PROFILE(SMBunlink);
2726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2730 dirtype = SVAL(req->vwv+0, 0);
2732 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2733 STR_TERMINATE, &status);
2734 if (!NT_STATUS_IS_OK(status)) {
2735 reply_nterror(req, status);
2739 if (ucf_flags & UCF_GMT_PATHNAME) {
2740 extract_snapshot_token(name, &twrp);
2742 status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
2743 if (!NT_STATUS_IS_OK(status)) {
2744 reply_nterror(req, status);
2747 status = filename_convert_dirfsp(ctx,
2750 ucf_flags | UCF_LCOMP_LNK_OK,
2754 if (!NT_STATUS_IS_OK(status)) {
2755 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2756 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2757 ERRSRV, ERRbadpath);
2760 reply_nterror(req, status);
2764 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2766 status = unlink_internals(conn, req, dirtype, dirfsp, smb_fname);
2767 if (!NT_STATUS_IS_OK(status)) {
2768 if (open_was_deferred(req->xconn, req->mid)) {
2769 /* We have re-scheduled this call. */
2772 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2773 bool ok = defer_smb1_sharing_violation(req);
2778 reply_nterror(req, status);
2782 reply_smb1_outbuf(req, 0, 0);
2784 TALLOC_FREE(smb_fname);
2785 END_PROFILE(SMBunlink);
2789 /****************************************************************************
2791 ****************************************************************************/
2793 static void fail_readraw(void)
2795 const char *errstr = talloc_asprintf(talloc_tos(),
2796 "FAIL ! reply_readbraw: socket write fail (%s)",
2801 exit_server_cleanly(errstr);
2804 /****************************************************************************
2805 Return a readbraw error (4 bytes of zero).
2806 ****************************************************************************/
2808 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2814 smbd_lock_socket(xconn);
2815 if (write_data(xconn->transport.sock,header,4) != 4) {
2816 int saved_errno = errno;
2818 * Try and give an error message saying what
2821 DEBUG(0, ("write_data failed for client %s. "
2823 smbXsrv_connection_dbg(xconn),
2824 strerror(saved_errno)));
2825 errno = saved_errno;
2829 smbd_unlock_socket(xconn);
2832 /*******************************************************************
2833 Ensure we don't use sendfile if server smb signing is active.
2834 ********************************************************************/
2836 static bool lp_use_sendfile(struct smbXsrv_connection *xconn,
2838 struct smb1_signing_state *signing_state)
2840 bool sign_active = false;
2842 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2843 if (xconn->protocol < PROTOCOL_NT1) {
2846 if (signing_state) {
2847 sign_active = smb1_signing_is_active(signing_state);
2849 return (lp__use_sendfile(snum) &&
2850 (get_remote_arch() != RA_WIN95) &&
2853 /****************************************************************************
2854 Use sendfile in readbraw.
2855 ****************************************************************************/
2857 static void send_file_readbraw(connection_struct *conn,
2858 struct smb_request *req,
2864 struct smbXsrv_connection *xconn = req->xconn;
2865 char *outbuf = NULL;
2869 * We can only use sendfile on a non-chained packet
2870 * but we can use on a non-oplocked file. tridge proved this
2871 * on a train in Germany :-). JRA.
2872 * reply_readbraw has already checked the length.
2875 if ( !req_is_in_chain(req) &&
2877 !fsp_is_alternate_stream(fsp) &&
2878 lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
2879 ssize_t sendfile_read = -1;
2881 DATA_BLOB header_blob;
2883 _smb_setlen(header,nread);
2884 header_blob = data_blob_const(header, 4);
2886 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2887 &header_blob, startpos,
2889 if (sendfile_read == -1) {
2890 /* Returning ENOSYS means no data at all was sent.
2891 * Do this as a normal read. */
2892 if (errno == ENOSYS) {
2893 goto normal_readbraw;
2897 * Special hack for broken Linux with no working sendfile. If we
2898 * return EINTR we sent the header but not the rest of the data.
2899 * Fake this up by doing read/write calls.
2901 if (errno == EINTR) {
2902 /* Ensure we don't do this again. */
2903 set_use_sendfile(SNUM(conn), False);
2904 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2906 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2907 DEBUG(0,("send_file_readbraw: "
2908 "fake_sendfile failed for "
2912 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2917 DEBUG(0,("send_file_readbraw: sendfile failed for "
2918 "file %s (%s). Terminating\n",
2919 fsp_str_dbg(fsp), strerror(errno)));
2920 exit_server_cleanly("send_file_readbraw sendfile failed");
2921 } else if (sendfile_read == 0) {
2923 * Some sendfile implementations return 0 to indicate
2924 * that there was a short read, but nothing was
2925 * actually written to the socket. In this case,
2926 * fallback to the normal read path so the header gets
2927 * the correct byte count.
2929 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2930 "bytes falling back to the normal read: "
2931 "%s\n", fsp_str_dbg(fsp)));
2932 goto normal_readbraw;
2935 /* Deal with possible short send. */
2936 if (sendfile_read != 4+nread) {
2937 ret = sendfile_short_send(xconn, fsp,
2938 sendfile_read, 4, nread);
2948 outbuf = talloc_array(NULL, char, nread+4);
2950 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2951 (unsigned)(nread+4)));
2952 reply_readbraw_error(xconn);
2957 ret = read_file(fsp,outbuf+4,startpos,nread);
2958 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2967 _smb_setlen(outbuf,ret);
2968 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2969 int saved_errno = errno;
2971 * Try and give an error message saying what
2974 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2975 smbXsrv_connection_dbg(xconn),
2976 strerror(saved_errno)));
2977 errno = saved_errno;
2982 TALLOC_FREE(outbuf);
2985 /****************************************************************************
2986 Reply to a readbraw (core+ protocol).
2987 ****************************************************************************/
2989 void reply_readbraw(struct smb_request *req)
2991 connection_struct *conn = req->conn;
2992 struct smbXsrv_connection *xconn = req->xconn;
2993 ssize_t maxcount,mincount;
2997 struct lock_struct lock;
3001 START_PROFILE(SMBreadbraw);
3003 if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
3004 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3005 "raw reads/writes are disallowed.");
3009 reply_readbraw_error(xconn);
3010 END_PROFILE(SMBreadbraw);
3014 if (xconn->smb1.echo_handler.trusted_fde) {
3015 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3016 "'async smb echo handler = yes'\n"));
3017 reply_readbraw_error(xconn);
3018 END_PROFILE(SMBreadbraw);
3023 * Special check if an oplock break has been issued
3024 * and the readraw request croses on the wire, we must
3025 * return a zero length response here.
3028 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3031 * We have to do a check_fsp by hand here, as
3032 * we must always return 4 zero bytes on error,
3038 conn != fsp->conn ||
3039 req->vuid != fsp->vuid ||
3040 fsp->fsp_flags.is_directory ||
3041 fsp_get_io_fd(fsp) == -1)
3044 * fsp could be NULL here so use the value from the packet. JRA.
3046 DEBUG(3,("reply_readbraw: fnum %d not valid "
3048 (int)SVAL(req->vwv+0, 0)));
3049 reply_readbraw_error(xconn);
3050 END_PROFILE(SMBreadbraw);
3054 /* Do a "by hand" version of CHECK_READ. */
3055 if (!(fsp->fsp_flags.can_read ||
3056 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3057 (fsp->access_mask & FILE_EXECUTE)))) {
3058 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3059 (int)SVAL(req->vwv+0, 0)));
3060 reply_readbraw_error(xconn);
3061 END_PROFILE(SMBreadbraw);
3065 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3066 if(req->wct == 10) {
3068 * This is a large offset (64 bit) read.
3071 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3074 DEBUG(0,("reply_readbraw: negative 64 bit "
3075 "readraw offset (%.0f) !\n",
3076 (double)startpos ));
3077 reply_readbraw_error(xconn);
3078 END_PROFILE(SMBreadbraw);
3083 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3084 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3086 /* ensure we don't overrun the packet size */
3087 maxcount = MIN(65535,maxcount);
3089 init_strict_lock_struct(fsp,
3090 (uint64_t)req->smbpid,
3094 lp_posix_cifsu_locktype(fsp),
3097 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3098 reply_readbraw_error(xconn);
3099 END_PROFILE(SMBreadbraw);
3103 status = vfs_stat_fsp(fsp);
3104 if (NT_STATUS_IS_OK(status)) {
3105 size = fsp->fsp_name->st.st_ex_size;
3108 if (startpos >= size) {
3111 nread = MIN(maxcount,(size - startpos));
3114 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3115 if (nread < mincount)
3119 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3120 "min=%lu nread=%lu\n",
3121 fsp_fnum_dbg(fsp), (double)startpos,
3122 (unsigned long)maxcount,
3123 (unsigned long)mincount,
3124 (unsigned long)nread ) );
3126 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3128 DEBUG(5,("reply_readbraw finished\n"));
3130 END_PROFILE(SMBreadbraw);
3135 #define DBGC_CLASS DBGC_LOCKING
3137 /****************************************************************************
3138 Reply to a lockread (core+ protocol).
3139 ****************************************************************************/
3141 static void reply_lockread_locked(struct tevent_req *subreq);
3143 void reply_lockread(struct smb_request *req)
3145 struct tevent_req *subreq = NULL;
3146 connection_struct *conn = req->conn;
3148 struct smbd_lock_element *lck = NULL;
3150 START_PROFILE(SMBlockread);
3153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3154 END_PROFILE(SMBlockread);
3158 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3160 if (!check_fsp(conn, req, fsp)) {
3161 END_PROFILE(SMBlockread);
3165 if (!CHECK_READ(fsp,req)) {
3166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3167 END_PROFILE(SMBlockread);
3171 lck = talloc(req, struct smbd_lock_element);
3173 reply_nterror(req, NT_STATUS_NO_MEMORY);
3174 END_PROFILE(SMBlockread);
3179 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3180 * protocol request that predates the read/write lock concept.
3181 * Thus instead of asking for a read lock here we need to ask
3182 * for a write lock. JRA.
3183 * Note that the requested lock size is unaffected by max_send.
3186 *lck = (struct smbd_lock_element) {
3187 .req_guid = smbd_request_guid(req, 0),
3188 .smblctx = req->smbpid,
3189 .brltype = WRITE_LOCK,
3190 .lock_flav = WINDOWS_LOCK,
3191 .count = SVAL(req->vwv+1, 0),
3192 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3195 subreq = smbd_smb1_do_locks_send(
3201 false, /* large_offset */
3204 if (subreq == NULL) {
3205 reply_nterror(req, NT_STATUS_NO_MEMORY);
3206 END_PROFILE(SMBlockread);
3209 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3210 END_PROFILE(SMBlockread);
3213 static void reply_lockread_locked(struct tevent_req *subreq)
3215 struct smb_request *req = NULL;
3221 size_t numtoread, maxtoread;
3222 struct files_struct *fsp = NULL;
3225 START_PROFILE(SMBlockread);
3227 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3230 status = smbd_smb1_do_locks_recv(subreq);
3231 TALLOC_FREE(subreq);
3233 if (!NT_STATUS_IS_OK(status)) {
3234 reply_nterror(req, status);
3238 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3240 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3244 numtoread = SVAL(req->vwv+1, 0);
3245 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3248 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3250 maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3252 if (numtoread > maxtoread) {
3253 DBG_WARNING("requested read size (%zu) is greater than "
3254 "maximum allowed (%zu/%d). "
3255 "Returning short read of maximum allowed for "
3256 "compatibility with Windows 2000.\n",
3259 req->xconn->smb1.sessions.max_send);
3260 numtoread = maxtoread;
3263 reply_smb1_outbuf(req, 5, numtoread + 3);
3265 data = smb_buf(req->outbuf) + 3;
3267 nread = read_file(fsp,data,startpos,numtoread);
3270 reply_nterror(req, map_nt_error_from_unix(errno));
3274 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3276 SSVAL(req->outbuf,smb_vwv0,nread);
3277 SSVAL(req->outbuf,smb_vwv5,nread+3);
3278 p = smb_buf(req->outbuf);
3279 SCVAL(p,0,0); /* pad byte. */
3282 DEBUG(3,("lockread %s num=%d nread=%d\n",
3283 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3286 ok = smb1_srv_send(req->xconn,
3287 (char *)req->outbuf,
3290 IS_CONN_ENCRYPTED(req->conn));
3292 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
3295 END_PROFILE(SMBlockread);
3300 #define DBGC_CLASS DBGC_ALL
3302 /****************************************************************************
3304 ****************************************************************************/
3306 void reply_read(struct smb_request *req)
3308 connection_struct *conn = req->conn;
3315 struct lock_struct lock;
3316 struct smbXsrv_connection *xconn = req->xconn;
3318 START_PROFILE(SMBread);
3321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3322 END_PROFILE(SMBread);
3326 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3328 if (!check_fsp(conn, req, fsp)) {
3329 END_PROFILE(SMBread);
3333 if (!CHECK_READ(fsp,req)) {
3334 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3335 END_PROFILE(SMBread);
3339 numtoread = SVAL(req->vwv+1, 0);
3340 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3343 * The requested read size cannot be greater than max_send. JRA.
3345 maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3347 if (numtoread > maxtoread) {
3348 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3349 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3350 (unsigned int)numtoread, (unsigned int)maxtoread,
3351 (unsigned int)xconn->smb1.sessions.max_send));
3352 numtoread = maxtoread;
3355 reply_smb1_outbuf(req, 5, numtoread+3);
3357 data = smb_buf(req->outbuf) + 3;
3359 init_strict_lock_struct(fsp,
3360 (uint64_t)req->smbpid,
3362 (uint64_t)numtoread,
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);
3369 END_PROFILE(SMBread);
3374 nread = read_file(fsp,data,startpos,numtoread);
3377 reply_nterror(req, map_nt_error_from_unix(errno));
3381 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3383 SSVAL(req->outbuf,smb_vwv0,nread);
3384 SSVAL(req->outbuf,smb_vwv5,nread+3);
3385 SCVAL(smb_buf(req->outbuf),0,1);
3386 SSVAL(smb_buf(req->outbuf),1,nread);
3388 DEBUG(3, ("read %s num=%d nread=%d\n",
3389 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3392 END_PROFILE(SMBread);
3396 /****************************************************************************
3398 ****************************************************************************/
3400 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3404 outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3407 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3409 SCVAL(outbuf,smb_vwv0,0xFF);
3410 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3411 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3412 SSVAL(outbuf,smb_vwv6,
3413 (smb_wct - 4) /* offset from smb header to wct */
3414 + 1 /* the wct field */
3415 + 12 * sizeof(uint16_t) /* vwv */
3416 + 2 /* the buflen field */
3417 + 1); /* padding byte */
3418 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3419 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3420 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3421 _smb_setlen_large(outbuf,
3422 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3426 /****************************************************************************
3427 Reply to a read and X - possibly using sendfile.
3428 ****************************************************************************/
3430 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3431 files_struct *fsp, off_t startpos,
3434 struct smbXsrv_connection *xconn = req->xconn;
3436 struct lock_struct lock;
3437 int saved_errno = 0;
3440 init_strict_lock_struct(fsp,
3441 (uint64_t)req->smbpid,
3443 (uint64_t)smb_maxcnt,
3445 lp_posix_cifsu_locktype(fsp),
3448 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3449 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3454 * We can only use sendfile on a non-chained packet
3455 * but we can use on a non-oplocked file. tridge proved this
3456 * on a train in Germany :-). JRA.
3459 if (!req_is_in_chain(req) &&
3461 !fsp_is_alternate_stream(fsp) &&
3462 lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
3463 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3466 status = vfs_stat_fsp(fsp);
3467 if (!NT_STATUS_IS_OK(status)) {
3468 reply_nterror(req, status);
3472 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3473 (startpos > fsp->fsp_name->st.st_ex_size) ||
3474 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3476 * We already know that we would do a short read, so don't
3477 * try the sendfile() path.
3479 goto nosendfile_read;
3483 * Set up the packet header before send. We
3484 * assume here the sendfile will work (get the
3485 * correct amount of data).
3488 header = data_blob_const(headerbuf, sizeof(headerbuf));
3490 construct_smb1_reply_common_req(req, (char *)headerbuf);
3491 setup_readX_header((char *)headerbuf, smb_maxcnt);
3493 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3494 startpos, smb_maxcnt);
3496 saved_errno = errno;
3498 /* Returning ENOSYS means no data at all was sent.
3499 Do this as a normal read. */
3500 if (errno == ENOSYS) {
3505 * Special hack for broken Linux with no working sendfile. If we
3506 * return EINTR we sent the header but not the rest of the data.
3507 * Fake this up by doing read/write calls.
3510 if (errno == EINTR) {
3511 /* Ensure we don't do this again. */
3512 set_use_sendfile(SNUM(conn), False);
3513 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3514 nread = fake_sendfile(xconn, fsp, startpos,
3517 saved_errno = errno;
3518 DEBUG(0,("send_file_readX: "
3519 "fake_sendfile failed for "
3520 "file %s (%s) for client %s. "
3523 smbXsrv_connection_dbg(xconn),
3524 strerror(saved_errno)));
3525 errno = saved_errno;
3526 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3528 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3529 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3530 /* No outbuf here means successful sendfile. */
3534 DEBUG(0,("send_file_readX: sendfile failed for file "
3535 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3537 exit_server_cleanly("send_file_readX sendfile failed");
3538 } else if (nread == 0) {
3540 * Some sendfile implementations return 0 to indicate
3541 * that there was a short read, but nothing was
3542 * actually written to the socket. In this case,
3543 * fallback to the normal read path so the header gets
3544 * the correct byte count.
3546 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3547 "falling back to the normal read: %s\n",
3552 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3553 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3555 /* Deal with possible short send. */
3556 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3559 ret = sendfile_short_send(xconn, fsp, nread,
3560 sizeof(headerbuf), smb_maxcnt);
3563 r = "send_file_readX: sendfile_short_send failed";
3564 DEBUG(0,("%s for file %s (%s).\n",
3565 r, fsp_str_dbg(fsp), strerror(errno)));
3566 exit_server_cleanly(r);
3569 /* No outbuf here means successful sendfile. */
3575 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3576 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3579 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3580 (startpos > fsp->fsp_name->st.st_ex_size) ||
3581 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3583 * We already know that we would do a short
3584 * read, so don't try the sendfile() path.
3586 goto nosendfile_read;
3589 construct_smb1_reply_common_req(req, (char *)headerbuf);
3590 setup_readX_header((char *)headerbuf, smb_maxcnt);
3592 /* Send out the header. */
3593 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3595 if (ret != sizeof(headerbuf)) {
3596 saved_errno = errno;
3598 * Try and give an error message saying what
3601 DEBUG(0,("send_file_readX: write_data failed for file "
3602 "%s (%s) for client %s. Terminating\n",
3604 smbXsrv_connection_dbg(xconn),
3605 strerror(saved_errno)));
3606 errno = saved_errno;
3607 exit_server_cleanly("send_file_readX sendfile failed");
3609 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3611 saved_errno = errno;
3612 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3613 "%s (%s) for client %s. Terminating\n",
3615 smbXsrv_connection_dbg(xconn),
3616 strerror(saved_errno)));
3617 errno = saved_errno;
3618 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3625 reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3626 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3627 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3629 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3630 startpos, smb_maxcnt);
3631 saved_errno = errno;
3634 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3638 setup_readX_header((char *)req->outbuf, nread);
3640 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3641 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3645 TALLOC_FREE(req->outbuf);
3649 /****************************************************************************
3650 Work out how much space we have for a read return.
3651 ****************************************************************************/
3653 static size_t calc_max_read_pdu(const struct smb_request *req)
3655 struct smbXsrv_connection *xconn = req->xconn;
3657 if (xconn->protocol < PROTOCOL_NT1) {
3658 return xconn->smb1.sessions.max_send;
3661 if (!lp_large_readwrite()) {
3662 return xconn->smb1.sessions.max_send;
3665 if (req_is_in_chain(req)) {
3666 return xconn->smb1.sessions.max_send;
3669 if (req->encrypted) {
3671 * Don't take encrypted traffic up to the
3672 * limit. There are padding considerations
3673 * that make that tricky.
3675 return xconn->smb1.sessions.max_send;
3678 if (smb1_srv_is_signing_active(xconn)) {
3682 if (!lp_smb1_unix_extensions()) {
3687 * We can do ultra-large POSIX reads.
3692 /****************************************************************************
3693 Calculate how big a read can be. Copes with all clients. It's always
3694 safe to return a short read - Windows does this.
3695 ****************************************************************************/
3697 static size_t calc_read_size(const struct smb_request *req,
3701 struct smbXsrv_connection *xconn = req->xconn;
3702 size_t max_pdu = calc_max_read_pdu(req);
3703 size_t total_size = 0;
3704 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3705 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3708 * Windows explicitly ignores upper size of 0xFFFF.
3709 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3710 * We must do the same as these will never fit even in
3711 * an extended size NetBIOS packet.
3713 if (upper_size == 0xFFFF) {
3717 if (xconn->protocol < PROTOCOL_NT1) {
3721 total_size = ((upper_size<<16) | lower_size);
3724 * LARGE_READX test shows it's always safe to return
3725 * a short read. Windows does so.
3727 return MIN(total_size, max_len);
3730 /****************************************************************************
3731 Reply to a read and X.
3732 ****************************************************************************/
3734 void reply_read_and_X(struct smb_request *req)
3736 connection_struct *conn = req->conn;
3741 bool big_readX = False;
3743 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3746 START_PROFILE(SMBreadX);
3748 if ((req->wct != 10) && (req->wct != 12)) {
3749 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3753 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3754 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3755 smb_maxcnt = SVAL(req->vwv+5, 0);
3757 /* If it's an IPC, pass off the pipe handler. */
3759 reply_pipe_read_and_X(req);
3760 END_PROFILE(SMBreadX);
3764 if (!check_fsp(conn, req, fsp)) {
3765 END_PROFILE(SMBreadX);
3769 if (!CHECK_READ(fsp,req)) {
3770 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3771 END_PROFILE(SMBreadX);
3775 upper_size = SVAL(req->vwv+7, 0);
3776 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3777 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3779 * This is a heuristic to avoid keeping large
3780 * outgoing buffers around over long-lived aio
3786 if (req->wct == 12) {
3788 * This is a large offset (64 bit) read.
3790 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3795 NTSTATUS status = schedule_aio_read_and_X(conn,
3800 if (NT_STATUS_IS_OK(status)) {
3801 /* Read scheduled - we're done. */
3804 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3805 /* Real error - report to client. */
3806 END_PROFILE(SMBreadX);
3807 reply_nterror(req, status);
3810 /* NT_STATUS_RETRY - fall back to sync read. */
3813 smbd_lock_socket(req->xconn);
3814 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3815 smbd_unlock_socket(req->xconn);
3818 END_PROFILE(SMBreadX);
3822 /****************************************************************************
3823 Error replies to writebraw must have smb_wct == 1. Fix this up.
3824 ****************************************************************************/
3826 void error_to_writebrawerr(struct smb_request *req)
3828 uint8_t *old_outbuf = req->outbuf;
3830 reply_smb1_outbuf(req, 1, 0);
3832 memcpy(req->outbuf, old_outbuf, smb_size);
3833 TALLOC_FREE(old_outbuf);
3836 /****************************************************************************
3837 Read 4 bytes of a smb packet and return the smb length of the packet.
3838 Store the result in the buffer. This version of the function will
3839 never return a session keepalive (length of zero).
3840 Timeout is in milliseconds.
3841 ****************************************************************************/
3843 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3846 uint8_t msgtype = NBSSkeepalive;
3848 while (msgtype == NBSSkeepalive) {
3851 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3853 if (!NT_STATUS_IS_OK(status)) {
3854 char addr[INET6_ADDRSTRLEN];
3855 /* Try and give an error message
3856 * saying what client failed. */
3857 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3858 "client %s read error = %s.\n",
3859 get_peer_addr(fd,addr,sizeof(addr)),
3860 nt_errstr(status)));
3864 msgtype = CVAL(inbuf, 0);
3867 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3868 (unsigned long)len));
3870 return NT_STATUS_OK;
3873 /****************************************************************************
3874 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3875 ****************************************************************************/
3877 void reply_writebraw(struct smb_request *req)
3879 connection_struct *conn = req->conn;
3880 struct smbXsrv_connection *xconn = req->xconn;
3883 ssize_t total_written=0;
3884 size_t numtowrite=0;
3887 const char *data=NULL;
3890 struct lock_struct lock;
3893 START_PROFILE(SMBwritebraw);
3896 * If we ever reply with an error, it must have the SMB command
3897 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3900 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3902 if (smb1_srv_is_signing_active(xconn)) {
3903 END_PROFILE(SMBwritebraw);
3904 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3905 "raw reads/writes are disallowed.");
3908 if (req->wct < 12) {
3909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3910 error_to_writebrawerr(req);
3911 END_PROFILE(SMBwritebraw);
3915 if (xconn->smb1.echo_handler.trusted_fde) {
3916 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3917 "'async smb echo handler = yes'\n"));
3918 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3919 error_to_writebrawerr(req);
3920 END_PROFILE(SMBwritebraw);
3924 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3925 if (!check_fsp(conn, req, fsp)) {
3926 error_to_writebrawerr(req);
3927 END_PROFILE(SMBwritebraw);
3931 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
3932 if (!NT_STATUS_IS_OK(status)) {
3933 reply_nterror(req, status);
3934 error_to_writebrawerr(req);
3935 END_PROFILE(SMBwritebraw);
3939 tcount = IVAL(req->vwv+1, 0);
3940 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3941 write_through = BITSETW(req->vwv+7,0);
3943 /* We have to deal with slightly different formats depending
3944 on whether we are using the core+ or lanman1.0 protocol */
3946 if(xconn->protocol <= PROTOCOL_COREPLUS) {
3947 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3948 data = smb_buf_const(req->inbuf);
3950 numtowrite = SVAL(req->vwv+10, 0);
3951 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3954 /* Ensure we don't write bytes past the end of this packet. */
3956 * This already protects us against CVE-2017-12163.
3958 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3960 error_to_writebrawerr(req);
3961 END_PROFILE(SMBwritebraw);
3965 if (!fsp->print_file) {
3966 init_strict_lock_struct(fsp,
3967 (uint64_t)req->smbpid,
3971 lp_posix_cifsu_locktype(fsp),
3974 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3975 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3976 error_to_writebrawerr(req);
3977 END_PROFILE(SMBwritebraw);
3983 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3986 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3987 "wrote=%d sync=%d\n",
3988 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3989 (int)nwritten, (int)write_through));
3991 if (nwritten < (ssize_t)numtowrite) {
3992 reply_nterror(req, NT_STATUS_DISK_FULL);
3993 error_to_writebrawerr(req);
3997 total_written = nwritten;
3999 /* Allocate a buffer of 64k + length. */
4000 buf = talloc_array(NULL, char, 65540);
4002 reply_nterror(req, NT_STATUS_NO_MEMORY);
4003 error_to_writebrawerr(req);
4007 /* Return a SMBwritebraw message to the redirector to tell
4008 * it to send more bytes */
4010 memcpy(buf, req->inbuf, smb_size);
4011 srv_smb1_set_message(buf,xconn->protocol>PROTOCOL_COREPLUS?1:0,0,True);
4012 SCVAL(buf,smb_com,SMBwritebraw);
4013 SSVALS(buf,smb_vwv0,0xFFFF);
4015 if (!smb1_srv_send(req->xconn,
4019 IS_CONN_ENCRYPTED(conn))) {
4020 exit_server_cleanly("reply_writebraw: smb1_srv_send "
4024 /* Now read the raw data into the buffer and write it */
4025 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4027 if (!NT_STATUS_IS_OK(status)) {
4028 exit_server_cleanly("secondary writebraw failed");
4031 /* Set up outbuf to return the correct size */
4032 reply_smb1_outbuf(req, 1, 0);
4034 if (numtowrite != 0) {
4036 if (numtowrite > 0xFFFF) {
4037 DEBUG(0,("reply_writebraw: Oversize secondary write "
4038 "raw requested (%u). Terminating\n",
4039 (unsigned int)numtowrite ));
4040 exit_server_cleanly("secondary writebraw failed");
4043 if (tcount > nwritten+numtowrite) {
4044 DEBUG(3,("reply_writebraw: Client overestimated the "
4046 (int)tcount,(int)nwritten,(int)numtowrite));
4049 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4052 if (!NT_STATUS_IS_OK(status)) {
4053 /* Try and give an error message
4054 * saying what client failed. */
4055 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4056 "raw read failed (%s) for client %s. "
4057 "Terminating\n", nt_errstr(status),
4058 smbXsrv_connection_dbg(xconn)));
4059 exit_server_cleanly("secondary writebraw failed");
4063 * We are not vulnerable to CVE-2017-12163
4064 * here as we are guaranteed to have numtowrite
4065 * bytes available - we just read from the client.
4067 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4068 if (nwritten == -1) {
4070 reply_nterror(req, map_nt_error_from_unix(errno));
4071 error_to_writebrawerr(req);
4075 if (nwritten < (ssize_t)numtowrite) {
4076 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4077 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4081 total_written += nwritten;
4086 SSVAL(req->outbuf,smb_vwv0,total_written);
4088 status = sync_file(conn, fsp, write_through);
4089 if (!NT_STATUS_IS_OK(status)) {
4090 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4091 fsp_str_dbg(fsp), nt_errstr(status)));
4092 reply_nterror(req, status);
4093 error_to_writebrawerr(req);
4097 DEBUG(3,("reply_writebraw: secondary write %s start=%.0f num=%d "
4099 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4100 (int)total_written));
4102 /* We won't return a status if write through is not selected - this
4103 * follows what WfWg does */
4104 END_PROFILE(SMBwritebraw);
4106 if (!write_through && total_written==tcount) {
4108 #if RABBIT_PELLET_FIX
4110 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4111 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4114 if (!send_keepalive(xconn->transport.sock)) {
4115 exit_server_cleanly("reply_writebraw: send of "
4116 "keepalive failed");
4119 TALLOC_FREE(req->outbuf);
4124 END_PROFILE(SMBwritebraw);
4129 #define DBGC_CLASS DBGC_LOCKING
4131 /****************************************************************************
4132 Reply to a writeunlock (core+).
4133 ****************************************************************************/
4135 void reply_writeunlock(struct smb_request *req)
4137 connection_struct *conn = req->conn;
4138 ssize_t nwritten = -1;
4143 NTSTATUS status = NT_STATUS_OK;
4145 struct lock_struct lock;
4146 int saved_errno = 0;
4148 START_PROFILE(SMBwriteunlock);
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4152 END_PROFILE(SMBwriteunlock);
4156 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4158 if (!check_fsp(conn, req, fsp)) {
4159 END_PROFILE(SMBwriteunlock);
4163 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4164 if (!NT_STATUS_IS_OK(status)) {
4165 reply_nterror(req, status);
4166 END_PROFILE(SMBwriteunlock);
4170 numtowrite = SVAL(req->vwv+1, 0);
4171 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4172 data = (const char *)req->buf + 3;
4175 * Ensure client isn't asking us to write more than
4176 * they sent. CVE-2017-12163.
4178 remaining = smbreq_bufrem(req, data);
4179 if (numtowrite > remaining) {
4180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4181 END_PROFILE(SMBwriteunlock);
4185 if (!fsp->print_file && numtowrite > 0) {
4186 init_strict_lock_struct(fsp,
4187 (uint64_t)req->smbpid,
4189 (uint64_t)numtowrite,
4191 lp_posix_cifsu_locktype(fsp),
4194 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4195 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4196 END_PROFILE(SMBwriteunlock);
4201 /* The special X/Open SMB protocol handling of
4202 zero length writes is *NOT* done for
4204 if(numtowrite == 0) {
4207 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4208 saved_errno = errno;
4211 status = sync_file(conn, fsp, False /* write through */);
4212 if (!NT_STATUS_IS_OK(status)) {
4213 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4214 fsp_str_dbg(fsp), nt_errstr(status)));
4215 reply_nterror(req, status);
4220 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4224 if((nwritten < numtowrite) && (numtowrite != 0)) {
4225 reply_nterror(req, NT_STATUS_DISK_FULL);
4229 if (numtowrite && !fsp->print_file) {
4230 struct smbd_lock_element l = {
4231 .req_guid = smbd_request_guid(req, 0),
4232 .smblctx = req->smbpid,
4233 .brltype = UNLOCK_LOCK,
4234 .lock_flav = WINDOWS_LOCK,
4236 .count = numtowrite,
4238 status = smbd_do_unlocking(req, fsp, 1, &l);
4239 if (NT_STATUS_V(status)) {
4240 reply_nterror(req, status);
4245 reply_smb1_outbuf(req, 1, 0);
4247 SSVAL(req->outbuf,smb_vwv0,nwritten);
4249 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4250 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4253 END_PROFILE(SMBwriteunlock);
4258 #define DBGC_CLASS DBGC_ALL
4260 /****************************************************************************
4262 ****************************************************************************/
4264 void reply_write(struct smb_request *req)
4266 connection_struct *conn = req->conn;
4269 ssize_t nwritten = -1;
4273 struct lock_struct lock;
4275 int saved_errno = 0;
4277 START_PROFILE(SMBwrite);
4280 END_PROFILE(SMBwrite);
4281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4285 /* If it's an IPC, pass off the pipe handler. */
4287 reply_pipe_write(req);
4288 END_PROFILE(SMBwrite);
4292 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4294 if (!check_fsp(conn, req, fsp)) {
4295 END_PROFILE(SMBwrite);
4299 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4300 if (!NT_STATUS_IS_OK(status)) {
4301 reply_nterror(req, status);
4302 END_PROFILE(SMBwrite);
4306 numtowrite = SVAL(req->vwv+1, 0);
4307 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4308 data = (const char *)req->buf + 3;
4311 * Ensure client isn't asking us to write more than
4312 * they sent. CVE-2017-12163.
4314 remaining = smbreq_bufrem(req, data);
4315 if (numtowrite > remaining) {
4316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4317 END_PROFILE(SMBwrite);
4321 if (!fsp->print_file) {
4322 init_strict_lock_struct(fsp,
4323 (uint64_t)req->smbpid,
4325 (uint64_t)numtowrite,
4327 lp_posix_cifsu_locktype(fsp),
4330 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4331 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4332 END_PROFILE(SMBwrite);
4338 * X/Open SMB protocol says that if smb_vwv1 is
4339 * zero then the file size should be extended or
4340 * truncated to the size given in smb_vwv[2-3].
4343 if(numtowrite == 0) {
4345 * This is actually an allocate call, and set EOF. JRA.
4347 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4349 reply_nterror(req, NT_STATUS_DISK_FULL);
4352 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4354 reply_nterror(req, NT_STATUS_DISK_FULL);
4357 trigger_write_time_update_immediate(fsp);
4359 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4362 status = sync_file(conn, fsp, False);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4365 fsp_str_dbg(fsp), nt_errstr(status)));
4366 reply_nterror(req, status);
4371 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4375 if((nwritten == 0) && (numtowrite != 0)) {
4376 reply_nterror(req, NT_STATUS_DISK_FULL);
4380 reply_smb1_outbuf(req, 1, 0);
4382 SSVAL(req->outbuf,smb_vwv0,nwritten);
4384 if (nwritten < (ssize_t)numtowrite) {
4385 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4386 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4389 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4392 END_PROFILE(SMBwrite);
4396 /****************************************************************************
4397 Ensure a buffer is a valid writeX for recvfile purposes.
4398 ****************************************************************************/
4400 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4401 (2*14) + /* word count (including bcc) */ \
4404 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4405 const uint8_t *inbuf)
4408 unsigned int doff = 0;
4409 size_t len = smb_len_large(inbuf);
4411 struct smbXsrv_open *op = NULL;
4412 struct files_struct *fsp = NULL;
4415 if (is_encrypted_packet(inbuf)) {
4416 /* Can't do this on encrypted
4421 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4425 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4426 CVAL(inbuf,smb_wct) != 14) {
4427 DEBUG(10,("is_valid_writeX_buffer: chained or "
4428 "invalid word length.\n"));
4432 fnum = SVAL(inbuf, smb_vwv2);
4433 status = smb1srv_open_lookup(xconn,
4437 if (!NT_STATUS_IS_OK(status)) {
4438 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4443 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4446 if (fsp->conn == NULL) {
4447 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4451 if (IS_IPC(fsp->conn)) {
4452 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4455 if (IS_PRINT(fsp->conn)) {
4456 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4459 if (fsp_is_alternate_stream(fsp)) {
4460 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4463 doff = SVAL(inbuf,smb_vwv11);
4465 numtowrite = SVAL(inbuf,smb_vwv10);
4467 if (len > doff && len - doff > 0xFFFF) {
4468 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4471 if (numtowrite == 0) {
4472 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4476 /* Ensure the sizes match up. */
4477 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4478 /* no pad byte...old smbclient :-( */
4479 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4481 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4485 if (len - doff != numtowrite) {
4486 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4487 "len = %u, doff = %u, numtowrite = %u\n",
4490 (unsigned int)numtowrite ));
4494 DEBUG(10,("is_valid_writeX_buffer: true "
4495 "len = %u, doff = %u, numtowrite = %u\n",
4498 (unsigned int)numtowrite ));
4503 /****************************************************************************
4504 Reply to a write and X.
4505 ****************************************************************************/
4507 void reply_write_and_X(struct smb_request *req)
4509 connection_struct *conn = req->conn;
4510 struct smbXsrv_connection *xconn = req->xconn;
4512 struct lock_struct lock;
4517 unsigned int smb_doff;
4518 unsigned int smblen;
4521 int saved_errno = 0;
4523 START_PROFILE(SMBwriteX);
4525 if ((req->wct != 12) && (req->wct != 14)) {
4526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4530 numtowrite = SVAL(req->vwv+10, 0);
4531 smb_doff = SVAL(req->vwv+11, 0);
4532 smblen = smb_len(req->inbuf);
4534 if (req->unread_bytes > 0xFFFF ||
4535 (smblen > smb_doff &&
4536 smblen - smb_doff > 0xFFFF)) {
4537 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4540 if (req->unread_bytes) {
4541 /* Can't do a recvfile write on IPC$ */
4543 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4546 if (numtowrite != req->unread_bytes) {
4547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4552 * This already protects us against CVE-2017-12163.
4554 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4555 smb_doff + numtowrite > smblen) {
4556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4561 /* If it's an IPC, pass off the pipe handler. */
4563 if (req->unread_bytes) {
4564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4567 reply_pipe_write_and_X(req);
4571 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4572 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4573 write_through = BITSETW(req->vwv+7,0);
4575 if (!check_fsp(conn, req, fsp)) {
4579 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4580 if (!NT_STATUS_IS_OK(status)) {
4581 reply_nterror(req, status);
4585 data = smb_base(req->inbuf) + smb_doff;
4587 if(req->wct == 14) {
4589 * This is a large offset (64 bit) write.
4591 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4595 /* X/Open SMB protocol says that, unlike SMBwrite
4596 if the length is zero then NO truncation is
4597 done, just a write of zero. To truncate a file,
4600 if(numtowrite == 0) {
4603 if (req->unread_bytes == 0) {
4604 status = schedule_aio_write_and_X(conn,
4611 if (NT_STATUS_IS_OK(status)) {
4612 /* write scheduled - we're done. */
4615 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4616 /* Real error - report to client. */
4617 reply_nterror(req, status);
4620 /* NT_STATUS_RETRY - fall through to sync write. */
4623 init_strict_lock_struct(fsp,
4624 (uint64_t)req->smbpid,
4626 (uint64_t)numtowrite,
4628 lp_posix_cifsu_locktype(fsp),
4631 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4632 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4636 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4637 saved_errno = errno;
4641 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4645 if((nwritten == 0) && (numtowrite != 0)) {
4646 reply_nterror(req, NT_STATUS_DISK_FULL);
4650 reply_smb1_outbuf(req, 6, 0);
4651 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4652 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4653 SSVAL(req->outbuf,smb_vwv2,nwritten);
4654 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4656 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4657 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4659 status = sync_file(conn, fsp, write_through);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4662 fsp_str_dbg(fsp), nt_errstr(status)));
4663 reply_nterror(req, status);
4667 END_PROFILE(SMBwriteX);
4671 if (req->unread_bytes) {
4672 /* writeX failed. drain socket. */
4673 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4674 req->unread_bytes) {
4675 smb_panic("failed to drain pending bytes");
4677 req->unread_bytes = 0;
4680 END_PROFILE(SMBwriteX);
4684 /****************************************************************************
4686 ****************************************************************************/
4688 void reply_lseek(struct smb_request *req)
4690 connection_struct *conn = req->conn;
4697 START_PROFILE(SMBlseek);
4700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4701 END_PROFILE(SMBlseek);
4705 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4707 if (!check_fsp(conn, req, fsp)) {
4711 mode = SVAL(req->vwv+1, 0) & 3;
4712 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4713 startpos = (off_t)IVALS(req->vwv+2, 0);
4722 res = fh_get_pos(fsp->fh) + startpos;
4733 if (umode == SEEK_END) {
4734 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4735 if(errno == EINVAL) {
4736 off_t current_pos = startpos;
4738 status = vfs_stat_fsp(fsp);
4739 if (!NT_STATUS_IS_OK(status)) {
4740 reply_nterror(req, status);
4741 END_PROFILE(SMBlseek);
4745 current_pos += fsp->fsp_name->st.st_ex_size;
4747 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4752 reply_nterror(req, map_nt_error_from_unix(errno));
4753 END_PROFILE(SMBlseek);
4758 fh_set_pos(fsp->fh, res);
4760 reply_smb1_outbuf(req, 2, 0);
4761 SIVAL(req->outbuf,smb_vwv0,res);
4763 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4764 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4766 END_PROFILE(SMBlseek);
4770 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4773 connection_struct *conn = talloc_get_type_abort(
4774 private_data, connection_struct);
4776 if (conn != fsp->conn) {
4779 if (fsp_get_io_fd(fsp) == -1) {
4782 sync_file(conn, fsp, True /* write through */);
4784 if (fsp->fsp_flags.modified) {
4785 trigger_write_time_update_immediate(fsp);
4791 /****************************************************************************
4793 ****************************************************************************/
4795 void reply_flush(struct smb_request *req)
4797 connection_struct *conn = req->conn;
4801 START_PROFILE(SMBflush);
4804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4808 fnum = SVAL(req->vwv+0, 0);
4809 fsp = file_fsp(req, fnum);
4811 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4816 files_forall(req->sconn, file_sync_one_fn, conn);
4818 NTSTATUS status = sync_file(conn, fsp, True);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4821 fsp_str_dbg(fsp), nt_errstr(status)));
4822 reply_nterror(req, status);
4823 END_PROFILE(SMBflush);
4826 if (fsp->fsp_flags.modified) {
4827 trigger_write_time_update_immediate(fsp);
4831 reply_smb1_outbuf(req, 0, 0);
4833 DEBUG(3,("flush\n"));
4834 END_PROFILE(SMBflush);
4838 /****************************************************************************
4840 conn POINTER CAN BE NULL HERE !
4841 ****************************************************************************/
4843 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4844 static void reply_exit_done(struct tevent_req *req);
4846 void reply_exit(struct smb_request *smb1req)
4848 struct tevent_req *req;
4851 * Don't setup the profile charge here, take
4852 * it in reply_exit_done(). Not strictly correct
4853 * but better than the other SMB1 async
4854 * code that double-charges at the moment.
4856 req = reply_exit_send(smb1req);
4858 /* Not going async, profile here. */
4859 START_PROFILE(SMBexit);
4860 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4861 END_PROFILE(SMBexit);
4865 /* We're async. This will complete later. */
4866 tevent_req_set_callback(req, reply_exit_done, smb1req);
4870 struct reply_exit_state {
4871 struct tevent_queue *wait_queue;
4874 static void reply_exit_wait_done(struct tevent_req *subreq);
4876 /****************************************************************************
4878 Note, on failure here we deallocate and return NULL to allow the caller to
4879 SMB1 return an error of ERRnomem immediately.
4880 ****************************************************************************/
4882 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4884 struct tevent_req *req;
4885 struct reply_exit_state *state;
4886 struct tevent_req *subreq;
4888 struct smbd_server_connection *sconn = smb1req->sconn;
4890 req = tevent_req_create(smb1req, &state,
4891 struct reply_exit_state);
4895 state->wait_queue = tevent_queue_create(state,
4896 "reply_exit_wait_queue");
4897 if (tevent_req_nomem(state->wait_queue, req)) {
4902 for (fsp = sconn->files; fsp; fsp = fsp->next) {
4903 if (fsp->file_pid != smb1req->smbpid) {
4906 if (fsp->vuid != smb1req->vuid) {
4910 * Flag the file as close in progress.
4911 * This will prevent any more IO being
4914 fsp->fsp_flags.closing = true;
4916 if (fsp->num_aio_requests > 0) {
4918 * Now wait until all aio requests on this fsp are
4921 * We don't set a callback, as we just want to block the
4922 * wait queue and the talloc_free() of fsp->aio_request
4923 * will remove the item from the wait queue.
4925 subreq = tevent_queue_wait_send(fsp->aio_requests,
4928 if (tevent_req_nomem(subreq, req)) {
4936 * Now we add our own waiter to the end of the queue,
4937 * this way we get notified when all pending requests are finished
4938 * and reply to the outstanding SMB1 request.
4940 subreq = tevent_queue_wait_send(state,
4943 if (tevent_req_nomem(subreq, req)) {
4949 * We're really going async - move the SMB1 request from
4950 * a talloc stackframe above us to the conn talloc-context.
4951 * We need this to stick around until the wait_done
4952 * callback is invoked.
4954 smb1req = talloc_move(sconn, &smb1req);
4956 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4961 static void reply_exit_wait_done(struct tevent_req *subreq)
4963 struct tevent_req *req = tevent_req_callback_data(
4964 subreq, struct tevent_req);
4966 tevent_queue_wait_recv(subreq);
4967 TALLOC_FREE(subreq);
4968 tevent_req_done(req);
4971 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4973 return tevent_req_simple_recv_ntstatus(req);
4976 static void reply_exit_done(struct tevent_req *req)
4978 struct smb_request *smb1req = tevent_req_callback_data(
4979 req, struct smb_request);
4980 struct smbd_server_connection *sconn = smb1req->sconn;
4981 struct smbXsrv_connection *xconn = smb1req->xconn;
4982 NTTIME now = timeval_to_nttime(&smb1req->request_time);
4983 struct smbXsrv_session *session = NULL;
4984 files_struct *fsp, *next;
4988 * Take the profile charge here. Not strictly
4989 * correct but better than the other SMB1 async
4990 * code that double-charges at the moment.
4992 START_PROFILE(SMBexit);
4994 status = reply_exit_recv(req);
4996 if (!NT_STATUS_IS_OK(status)) {
4997 TALLOC_FREE(smb1req);
4998 END_PROFILE(SMBexit);
4999 exit_server(__location__ ": reply_exit_recv failed");
5004 * Ensure the session is still valid.
5006 status = smb1srv_session_lookup(xconn,
5010 if (!NT_STATUS_IS_OK(status)) {
5011 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5012 smb_request_done(smb1req);
5013 END_PROFILE(SMBexit);
5018 * Ensure the vuid is still valid - no one
5019 * called reply_ulogoffX() in the meantime.
5020 * reply_exit() doesn't have AS_USER set, so
5021 * use set_current_user_info() directly.
5022 * This is the same logic as in switch_message().
5024 if (session->global->auth_session_info != NULL) {
5025 set_current_user_info(
5026 session->global->auth_session_info->unix_info->sanitized_username,
5027 session->global->auth_session_info->unix_info->unix_name,
5028 session->global->auth_session_info->info->domain_name);
5031 /* No more aio - do the actual closes. */
5032 for (fsp = sconn->files; fsp; fsp = next) {
5036 if (fsp->file_pid != smb1req->smbpid) {
5039 if (fsp->vuid != smb1req->vuid) {
5042 if (!fsp->fsp_flags.closing) {
5047 * reply_exit() has the DO_CHDIR flag set.
5049 ok = chdir_current_service(fsp->conn);
5051 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5052 smb_request_done(smb1req);
5053 END_PROFILE(SMBexit);
5056 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
5059 reply_smb1_outbuf(smb1req, 0, 0);
5061 * The following call is needed to push the
5062 * reply data back out the socket after async
5063 * return. Plus it frees smb1req.
5065 smb_request_done(smb1req);
5066 DBG_INFO("reply_exit complete\n");
5067 END_PROFILE(SMBexit);
5071 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5073 static void reply_close_done(struct tevent_req *req);
5075 void reply_close(struct smb_request *smb1req)
5077 connection_struct *conn = smb1req->conn;
5078 NTSTATUS status = NT_STATUS_OK;
5079 files_struct *fsp = NULL;
5080 START_PROFILE(SMBclose);
5082 if (smb1req->wct < 3) {
5083 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5084 END_PROFILE(SMBclose);
5088 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5091 * We can only use check_fsp if we know it's not a directory.
5094 if (!check_fsp_open(conn, smb1req, fsp)) {
5095 END_PROFILE(SMBclose);
5099 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5100 fsp->fsp_flags.is_directory ?
5101 "directory" : "file",
5102 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5103 conn->num_files_open);
5105 if (!fsp->fsp_flags.is_directory) {
5109 * Take care of any time sent in the close.
5112 t = srv_make_unix_date3(smb1req->vwv+1);
5113 set_close_write_time(fsp, time_t_to_full_timespec(t));
5116 if (fsp->num_aio_requests != 0) {
5117 struct tevent_req *req;
5119 req = reply_close_send(smb1req, fsp);
5121 status = NT_STATUS_NO_MEMORY;
5124 /* We're async. This will complete later. */
5125 tevent_req_set_callback(req, reply_close_done, smb1req);
5126 END_PROFILE(SMBclose);
5131 * close_file_free() returns the unix errno if an error was detected on
5132 * close - normally this is due to a disk full error. If not then it
5133 * was probably an I/O error.
5136 status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
5138 if (!NT_STATUS_IS_OK(status)) {
5139 reply_nterror(smb1req, status);
5140 END_PROFILE(SMBclose);
5144 reply_smb1_outbuf(smb1req, 0, 0);
5145 END_PROFILE(SMBclose);
5149 struct reply_close_state {
5151 struct tevent_queue *wait_queue;
5154 static void reply_close_wait_done(struct tevent_req *subreq);
5156 /****************************************************************************
5158 Note, on failure here we deallocate and return NULL to allow the caller to
5159 SMB1 return an error of ERRnomem immediately.
5160 ****************************************************************************/
5162 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5165 struct tevent_req *req;
5166 struct reply_close_state *state;
5167 struct tevent_req *subreq;
5168 struct smbd_server_connection *sconn = smb1req->sconn;
5170 req = tevent_req_create(smb1req, &state,
5171 struct reply_close_state);
5175 state->wait_queue = tevent_queue_create(state,
5176 "reply_close_wait_queue");
5177 if (tevent_req_nomem(state->wait_queue, req)) {
5183 * Flag the file as close in progress.
5184 * This will prevent any more IO being
5187 fsp->fsp_flags.closing = true;
5190 * Now wait until all aio requests on this fsp are
5193 * We don't set a callback, as we just want to block the
5194 * wait queue and the talloc_free() of fsp->aio_request
5195 * will remove the item from the wait queue.
5197 subreq = tevent_queue_wait_send(fsp->aio_requests,
5200 if (tevent_req_nomem(subreq, req)) {
5206 * Now we add our own waiter to the end of the queue,
5207 * this way we get notified when all pending requests are finished
5208 * and reply to the outstanding SMB1 request.
5210 subreq = tevent_queue_wait_send(state,
5213 if (tevent_req_nomem(subreq, req)) {
5219 * We're really going async - move the SMB1 request from
5220 * a talloc stackframe above us to the conn talloc-context.
5221 * We need this to stick around until the wait_done
5222 * callback is invoked.
5224 smb1req = talloc_move(sconn, &smb1req);
5226 tevent_req_set_callback(subreq, reply_close_wait_done, req);
5231 static void reply_close_wait_done(struct tevent_req *subreq)
5233 struct tevent_req *req = tevent_req_callback_data(
5234 subreq, struct tevent_req);
5236 tevent_queue_wait_recv(subreq);
5237 TALLOC_FREE(subreq);
5238 tevent_req_done(req);
5241 static NTSTATUS reply_close_recv(struct tevent_req *req)
5243 return tevent_req_simple_recv_ntstatus(req);
5246 static void reply_close_done(struct tevent_req *req)
5248 struct smb_request *smb1req = tevent_req_callback_data(
5249 req, struct smb_request);
5250 struct reply_close_state *state = tevent_req_data(req,
5251 struct reply_close_state);
5254 status = reply_close_recv(req);
5256 if (!NT_STATUS_IS_OK(status)) {
5257 TALLOC_FREE(smb1req);
5258 exit_server(__location__ ": reply_close_recv failed");
5262 status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
5263 if (NT_STATUS_IS_OK(status)) {
5264 reply_smb1_outbuf(smb1req, 0, 0);
5266 reply_nterror(smb1req, status);
5269 * The following call is needed to push the
5270 * reply data back out the socket after async
5271 * return. Plus it frees smb1req.
5273 smb_request_done(smb1req);
5276 /****************************************************************************
5277 Reply to a writeclose (Core+ protocol).
5278 ****************************************************************************/
5280 void reply_writeclose(struct smb_request *req)
5282 connection_struct *conn = req->conn;
5285 ssize_t nwritten = -1;
5286 NTSTATUS close_status = NT_STATUS_OK;
5289 struct timespec mtime;
5291 struct lock_struct lock;
5294 START_PROFILE(SMBwriteclose);
5297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5298 END_PROFILE(SMBwriteclose);
5302 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5304 if (!check_fsp(conn, req, fsp)) {
5305 END_PROFILE(SMBwriteclose);
5308 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
5309 if (!NT_STATUS_IS_OK(status)) {
5310 reply_nterror(req, status);
5311 END_PROFILE(SMBwriteclose);
5315 numtowrite = SVAL(req->vwv+1, 0);
5316 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5317 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5318 data = (const char *)req->buf + 1;
5321 * Ensure client isn't asking us to write more than
5322 * they sent. CVE-2017-12163.
5324 remaining = smbreq_bufrem(req, data);
5325 if (numtowrite > remaining) {
5326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5327 END_PROFILE(SMBwriteclose);
5331 if (fsp->print_file == NULL) {
5332 init_strict_lock_struct(fsp,
5333 (uint64_t)req->smbpid,
5335 (uint64_t)numtowrite,
5337 lp_posix_cifsu_locktype(fsp),
5340 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5341 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5342 END_PROFILE(SMBwriteclose);
5347 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5349 set_close_write_time(fsp, mtime);
5352 * More insanity. W2K only closes the file if writelen > 0.
5356 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5357 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5358 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5361 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5362 "file %s\n", fsp_str_dbg(fsp)));
5363 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5366 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5367 reply_nterror(req, NT_STATUS_DISK_FULL);
5371 if(!NT_STATUS_IS_OK(close_status)) {
5372 reply_nterror(req, close_status);
5376 reply_smb1_outbuf(req, 1, 0);
5378 SSVAL(req->outbuf,smb_vwv0,nwritten);
5382 END_PROFILE(SMBwriteclose);
5387 #define DBGC_CLASS DBGC_LOCKING
5389 /****************************************************************************
5391 ****************************************************************************/
5393 static void reply_lock_done(struct tevent_req *subreq);
5395 void reply_lock(struct smb_request *req)
5397 struct tevent_req *subreq = NULL;
5398 connection_struct *conn = req->conn;
5400 struct smbd_lock_element *lck = NULL;
5402 START_PROFILE(SMBlock);
5405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5406 END_PROFILE(SMBlock);
5410 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5412 if (!check_fsp(conn, req, fsp)) {
5413 END_PROFILE(SMBlock);
5417 lck = talloc(req, struct smbd_lock_element);
5419 reply_nterror(req, NT_STATUS_NO_MEMORY);
5420 END_PROFILE(SMBlock);
5424 *lck = (struct smbd_lock_element) {
5425 .req_guid = smbd_request_guid(req, 0),
5426 .smblctx = req->smbpid,
5427 .brltype = WRITE_LOCK,
5428 .lock_flav = WINDOWS_LOCK,
5429 .count = IVAL(req->vwv+1, 0),
5430 .offset = IVAL(req->vwv+3, 0),
5433 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5439 subreq = smbd_smb1_do_locks_send(
5445 false, /* large_offset */
5448 if (subreq == NULL) {
5449 reply_nterror(req, NT_STATUS_NO_MEMORY);
5450 END_PROFILE(SMBlock);
5453 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5454 END_PROFILE(SMBlock);
5457 static void reply_lock_done(struct tevent_req *subreq)
5459 struct smb_request *req = NULL;
5463 START_PROFILE(SMBlock);
5465 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5468 status = smbd_smb1_do_locks_recv(subreq);
5469 TALLOC_FREE(subreq);
5471 if (NT_STATUS_IS_OK(status)) {
5472 reply_smb1_outbuf(req, 0, 0);
5474 reply_nterror(req, status);
5477 ok = smb1_srv_send(req->xconn,
5478 (char *)req->outbuf,
5481 IS_CONN_ENCRYPTED(req->conn));
5483 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5486 END_PROFILE(SMBlock);
5489 /****************************************************************************
5491 ****************************************************************************/
5493 void reply_unlock(struct smb_request *req)
5495 connection_struct *conn = req->conn;
5498 struct smbd_lock_element lck;
5500 START_PROFILE(SMBunlock);
5503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5504 END_PROFILE(SMBunlock);
5508 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5510 if (!check_fsp(conn, req, fsp)) {
5511 END_PROFILE(SMBunlock);
5515 lck = (struct smbd_lock_element) {
5516 .req_guid = smbd_request_guid(req, 0),
5517 .smblctx = req->smbpid,
5518 .brltype = UNLOCK_LOCK,
5519 .lock_flav = WINDOWS_LOCK,
5520 .offset = IVAL(req->vwv+3, 0),
5521 .count = IVAL(req->vwv+1, 0),
5524 status = smbd_do_unlocking(req, fsp, 1, &lck);
5526 if (!NT_STATUS_IS_OK(status)) {
5527 reply_nterror(req, status);
5528 END_PROFILE(SMBunlock);
5532 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5538 reply_smb1_outbuf(req, 0, 0);
5540 END_PROFILE(SMBunlock);
5545 #define DBGC_CLASS DBGC_ALL
5547 /****************************************************************************
5549 conn POINTER CAN BE NULL HERE !
5550 ****************************************************************************/
5552 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5553 static void reply_tdis_done(struct tevent_req *req);
5555 void reply_tdis(struct smb_request *smb1req)
5557 connection_struct *conn = smb1req->conn;
5558 struct tevent_req *req;
5561 * Don't setup the profile charge here, take
5562 * it in reply_tdis_done(). Not strictly correct
5563 * but better than the other SMB1 async
5564 * code that double-charges at the moment.
5568 /* Not going async, profile here. */
5569 START_PROFILE(SMBtdis);
5570 DBG_INFO("Invalid connection in tdis\n");
5571 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5572 END_PROFILE(SMBtdis);
5576 req = reply_tdis_send(smb1req);
5578 /* Not going async, profile here. */
5579 START_PROFILE(SMBtdis);
5580 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5581 END_PROFILE(SMBtdis);
5584 /* We're async. This will complete later. */
5585 tevent_req_set_callback(req, reply_tdis_done, smb1req);
5589 struct reply_tdis_state {
5590 struct tevent_queue *wait_queue;
5593 static void reply_tdis_wait_done(struct tevent_req *subreq);
5595 /****************************************************************************
5597 Note, on failure here we deallocate and return NULL to allow the caller to
5598 SMB1 return an error of ERRnomem immediately.
5599 ****************************************************************************/
5601 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5603 struct tevent_req *req;
5604 struct reply_tdis_state *state;
5605 struct tevent_req *subreq;
5606 connection_struct *conn = smb1req->conn;
5609 req = tevent_req_create(smb1req, &state,
5610 struct reply_tdis_state);
5614 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5615 if (tevent_req_nomem(state->wait_queue, req)) {
5621 * Make sure that no new request will be able to use this tcon.
5622 * This ensures that once all outstanding fsp->aio_requests
5623 * on this tcon are done, we are safe to close it.
5625 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5627 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5628 if (fsp->conn != conn) {
5632 * Flag the file as close in progress.
5633 * This will prevent any more IO being
5634 * done on it. Not strictly needed, but
5635 * doesn't hurt to flag it as closing.
5637 fsp->fsp_flags.closing = true;
5639 if (fsp->num_aio_requests > 0) {
5641 * Now wait until all aio requests on this fsp are
5644 * We don't set a callback, as we just want to block the
5645 * wait queue and the talloc_free() of fsp->aio_request
5646 * will remove the item from the wait queue.
5648 subreq = tevent_queue_wait_send(fsp->aio_requests,
5649 conn->sconn->ev_ctx,
5651 if (tevent_req_nomem(subreq, req)) {
5659 * Now we add our own waiter to the end of the queue,
5660 * this way we get notified when all pending requests are finished
5661 * and reply to the outstanding SMB1 request.
5663 subreq = tevent_queue_wait_send(state,
5664 conn->sconn->ev_ctx,
5666 if (tevent_req_nomem(subreq, req)) {
5672 * We're really going async - move the SMB1 request from
5673 * a talloc stackframe above us to the sconn talloc-context.
5674 * We need this to stick around until the wait_done
5675 * callback is invoked.
5677 smb1req = talloc_move(smb1req->sconn, &smb1req);
5679 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5684 static void reply_tdis_wait_done(struct tevent_req *subreq)
5686 struct tevent_req *req = tevent_req_callback_data(
5687 subreq, struct tevent_req);
5689 tevent_queue_wait_recv(subreq);
5690 TALLOC_FREE(subreq);
5691 tevent_req_done(req);
5694 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5696 return tevent_req_simple_recv_ntstatus(req);
5699 static void reply_tdis_done(struct tevent_req *req)
5701 struct smb_request *smb1req = tevent_req_callback_data(
5702 req, struct smb_request);
5704 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5708 * Take the profile charge here. Not strictly
5709 * correct but better than the other SMB1 async
5710 * code that double-charges at the moment.
5712 START_PROFILE(SMBtdis);
5714 status = reply_tdis_recv(req);
5716 if (!NT_STATUS_IS_OK(status)) {
5717 TALLOC_FREE(smb1req);
5718 END_PROFILE(SMBtdis);
5719 exit_server(__location__ ": reply_tdis_recv failed");
5724 * As we've been awoken, we may have changed
5725 * directory in the meantime.
5726 * reply_tdis() has the DO_CHDIR flag set.
5728 ok = chdir_current_service(smb1req->conn);
5730 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5731 smb_request_done(smb1req);
5732 END_PROFILE(SMBtdis);
5735 status = smbXsrv_tcon_disconnect(tcon,
5737 if (!NT_STATUS_IS_OK(status)) {
5738 TALLOC_FREE(smb1req);
5739 END_PROFILE(SMBtdis);
5740 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5744 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5745 smb1req->conn = NULL;
5749 reply_smb1_outbuf(smb1req, 0, 0);
5751 * The following call is needed to push the
5752 * reply data back out the socket after async
5753 * return. Plus it frees smb1req.
5755 smb_request_done(smb1req);
5756 END_PROFILE(SMBtdis);
5759 /****************************************************************************
5761 conn POINTER CAN BE NULL HERE !
5762 ****************************************************************************/
5764 void reply_echo(struct smb_request *req)
5766 connection_struct *conn = req->conn;
5770 START_PROFILE(SMBecho);
5773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5774 END_PROFILE(SMBecho);
5778 smb_reverb = SVAL(req->vwv+0, 0);
5780 reply_smb1_outbuf(req, 1, req->buflen);
5782 /* copy any incoming data back out */
5783 if (req->buflen > 0) {
5784 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5787 if (smb_reverb > 100) {
5788 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5792 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5794 SSVAL(req->outbuf,smb_vwv0,seq_num);
5796 show_msg((char *)req->outbuf);
5797 if (!smb1_srv_send(req->xconn,
5798 (char *)req->outbuf,
5801 IS_CONN_ENCRYPTED(conn) || req->encrypted))
5802 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5805 DEBUG(3,("echo %d times\n", smb_reverb));
5807 TALLOC_FREE(req->outbuf);
5809 END_PROFILE(SMBecho);
5813 /****************************************************************************
5814 Reply to a printopen.
5815 ****************************************************************************/
5817 void reply_printopen(struct smb_request *req)
5819 connection_struct *conn = req->conn;
5823 START_PROFILE(SMBsplopen);
5826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5827 END_PROFILE(SMBsplopen);
5831 if (!CAN_PRINT(conn)) {
5832 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5833 END_PROFILE(SMBsplopen);
5837 status = file_new(req, conn, &fsp);
5838 if(!NT_STATUS_IS_OK(status)) {
5839 reply_nterror(req, status);
5840 END_PROFILE(SMBsplopen);
5844 /* Open for exclusive use, write only. */
5845 status = print_spool_open(fsp, NULL, req->vuid);
5847 if (!NT_STATUS_IS_OK(status)) {
5848 file_free(req, fsp);
5849 reply_nterror(req, status);
5850 END_PROFILE(SMBsplopen);
5854 reply_smb1_outbuf(req, 1, 0);
5855 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5857 DEBUG(3,("openprint fd=%d %s\n",
5858 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5860 END_PROFILE(SMBsplopen);
5864 /****************************************************************************
5865 Reply to a printclose.
5866 ****************************************************************************/
5868 void reply_printclose(struct smb_request *req)
5870 connection_struct *conn = req->conn;
5874 START_PROFILE(SMBsplclose);
5877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5878 END_PROFILE(SMBsplclose);
5882 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5884 if (!check_fsp(conn, req, fsp)) {
5885 END_PROFILE(SMBsplclose);
5889 if (!CAN_PRINT(conn)) {
5890 reply_force_doserror(req, ERRSRV, ERRerror);
5891 END_PROFILE(SMBsplclose);
5895 DEBUG(3,("printclose fd=%d %s\n",
5896 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5898 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5900 if(!NT_STATUS_IS_OK(status)) {
5901 reply_nterror(req, status);
5902 END_PROFILE(SMBsplclose);
5906 reply_smb1_outbuf(req, 0, 0);
5908 END_PROFILE(SMBsplclose);
5912 /****************************************************************************
5913 Reply to a printqueue.
5914 ****************************************************************************/
5916 void reply_printqueue(struct smb_request *req)
5918 const struct loadparm_substitution *lp_sub =
5919 loadparm_s3_global_substitution();
5920 connection_struct *conn = req->conn;
5924 START_PROFILE(SMBsplretq);
5927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5928 END_PROFILE(SMBsplretq);
5932 max_count = SVAL(req->vwv+0, 0);
5933 start_index = SVAL(req->vwv+1, 0);
5935 /* we used to allow the client to get the cnum wrong, but that
5936 is really quite gross and only worked when there was only
5937 one printer - I think we should now only accept it if they
5938 get it right (tridge) */
5939 if (!CAN_PRINT(conn)) {
5940 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5941 END_PROFILE(SMBsplretq);
5945 reply_smb1_outbuf(req, 2, 3);
5946 SSVAL(req->outbuf,smb_vwv0,0);
5947 SSVAL(req->outbuf,smb_vwv1,0);
5948 SCVAL(smb_buf(req->outbuf),0,1);
5949 SSVAL(smb_buf(req->outbuf),1,0);
5951 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5952 start_index, max_count));
5955 TALLOC_CTX *mem_ctx = talloc_tos();
5958 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5959 struct rpc_pipe_client *cli = NULL;
5960 struct dcerpc_binding_handle *b = NULL;
5961 struct policy_handle handle;
5962 struct spoolss_DevmodeContainer devmode_ctr;
5963 union spoolss_JobInfo *info;
5965 uint32_t num_to_get;
5969 ZERO_STRUCT(handle);
5971 status = rpc_pipe_open_interface(mem_ctx,
5974 conn->sconn->remote_address,
5975 conn->sconn->local_address,
5976 conn->sconn->msg_ctx,
5978 if (!NT_STATUS_IS_OK(status)) {
5979 DEBUG(0, ("reply_printqueue: "
5980 "could not connect to spoolss: %s\n",
5981 nt_errstr(status)));
5982 reply_nterror(req, status);
5985 b = cli->binding_handle;
5987 ZERO_STRUCT(devmode_ctr);
5989 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5992 SEC_FLAG_MAXIMUM_ALLOWED,
5995 if (!NT_STATUS_IS_OK(status)) {
5996 reply_nterror(req, status);
5999 if (!W_ERROR_IS_OK(werr)) {
6000 reply_nterror(req, werror_to_ntstatus(werr));
6004 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6012 if (!W_ERROR_IS_OK(werr)) {
6013 reply_nterror(req, werror_to_ntstatus(werr));
6017 if (max_count > 0) {
6018 first = start_index;
6020 first = start_index + max_count + 1;
6023 if (first >= count) {
6026 num_to_get = first + MIN(ABS(max_count), count - first);
6029 for (i = first; i < num_to_get; i++) {
6032 struct timespec qtime = {
6033 .tv_sec = spoolss_Time_to_time_t(
6034 &info[i].info2.submitted),
6038 uint16_t qrapjobid = pjobid_to_rap(sharename,
6039 info[i].info2.job_id);
6041 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6047 srv_put_dos_date2_ts(p, 0, qtime);
6048 SCVAL(p, 4, qstatus);
6049 SSVAL(p, 5, qrapjobid);
6050 SIVAL(p, 7, info[i].info2.size);
6052 status = srvstr_push(blob, req->flags2, p+12,
6053 info[i].info2.notify_name, 16, STR_ASCII, &len);
6054 if (!NT_STATUS_IS_OK(status)) {
6055 reply_nterror(req, status);
6058 if (message_push_blob(
6061 blob, sizeof(blob))) == -1) {
6062 reply_nterror(req, NT_STATUS_NO_MEMORY);
6068 SSVAL(req->outbuf,smb_vwv0,count);
6069 SSVAL(req->outbuf,smb_vwv1,
6070 (max_count>0?first+count:first-1));
6071 SCVAL(smb_buf(req->outbuf),0,1);
6072 SSVAL(smb_buf(req->outbuf),1,28*count);
6076 DEBUG(3, ("%u entries returned in queue\n",
6080 if (b && is_valid_policy_hnd(&handle)) {
6081 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6086 END_PROFILE(SMBsplretq);
6090 /****************************************************************************
6091 Reply to a printwrite.
6092 ****************************************************************************/
6094 void reply_printwrite(struct smb_request *req)
6096 connection_struct *conn = req->conn;
6102 START_PROFILE(SMBsplwr);
6105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6106 END_PROFILE(SMBsplwr);
6110 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6112 if (!check_fsp(conn, req, fsp)) {
6113 END_PROFILE(SMBsplwr);
6117 if (!fsp->print_file) {
6118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6119 END_PROFILE(SMBsplwr);
6123 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
6124 if (!NT_STATUS_IS_OK(status)) {
6125 reply_nterror(req, status);
6126 END_PROFILE(SMBsplwr);
6130 numtowrite = SVAL(req->buf, 1);
6133 * This already protects us against CVE-2017-12163.
6135 if (req->buflen < numtowrite + 3) {
6136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6137 END_PROFILE(SMBsplwr);
6141 data = (const char *)req->buf + 3;
6143 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6144 reply_nterror(req, map_nt_error_from_unix(errno));
6145 END_PROFILE(SMBsplwr);
6149 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6151 reply_smb1_outbuf(req, 0, 0);
6153 END_PROFILE(SMBsplwr);
6157 /****************************************************************************
6159 ****************************************************************************/
6161 void reply_mkdir(struct smb_request *req)
6163 connection_struct *conn = req->conn;
6164 struct files_struct *dirfsp = NULL;
6165 struct smb_filename *smb_dname = NULL;
6166 char *directory = NULL;
6170 TALLOC_CTX *ctx = talloc_tos();
6172 START_PROFILE(SMBmkdir);
6174 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6175 STR_TERMINATE, &status);
6176 if (!NT_STATUS_IS_OK(status)) {
6177 reply_nterror(req, status);
6181 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6182 if (ucf_flags & UCF_GMT_PATHNAME) {
6183 extract_snapshot_token(directory, &twrp);
6185 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6186 if (!NT_STATUS_IS_OK(status)) {
6187 reply_nterror(req, status);
6191 status = filename_convert_dirfsp(ctx,
6198 if (!NT_STATUS_IS_OK(status)) {
6199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6200 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6201 ERRSRV, ERRbadpath);
6204 reply_nterror(req, status);
6208 status = create_directory(conn, req, dirfsp, smb_dname);
6210 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6212 if (!NT_STATUS_IS_OK(status)) {
6214 if (!use_nt_status()
6215 && NT_STATUS_EQUAL(status,
6216 NT_STATUS_OBJECT_NAME_COLLISION)) {
6218 * Yes, in the DOS error code case we get a
6219 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6220 * samba4 torture test.
6222 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6225 reply_nterror(req, status);
6229 reply_smb1_outbuf(req, 0, 0);
6231 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6233 TALLOC_FREE(smb_dname);
6234 END_PROFILE(SMBmkdir);
6238 /****************************************************************************
6240 ****************************************************************************/
6242 void reply_rmdir(struct smb_request *req)
6244 connection_struct *conn = req->conn;
6245 struct smb_filename *smb_dname = NULL;
6246 char *directory = NULL;
6248 TALLOC_CTX *ctx = talloc_tos();
6249 struct files_struct *dirfsp = NULL;
6250 files_struct *fsp = NULL;
6253 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6255 START_PROFILE(SMBrmdir);
6257 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6258 STR_TERMINATE, &status);
6259 if (!NT_STATUS_IS_OK(status)) {
6260 reply_nterror(req, status);
6264 if (ucf_flags & UCF_GMT_PATHNAME) {
6265 extract_snapshot_token(directory, &twrp);
6267 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6268 if (!NT_STATUS_IS_OK(status)) {
6269 reply_nterror(req, status);
6273 status = filename_convert_dirfsp(ctx,
6280 if (!NT_STATUS_IS_OK(status)) {
6281 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6282 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6283 ERRSRV, ERRbadpath);
6286 reply_nterror(req, status);
6290 status = SMB_VFS_CREATE_FILE(
6293 dirfsp, /* dirfsp */
6294 smb_dname, /* fname */
6295 DELETE_ACCESS, /* access_mask */
6296 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6298 FILE_OPEN, /* create_disposition*/
6299 FILE_DIRECTORY_FILE |
6300 FILE_OPEN_REPARSE_POINT, /* create_options */
6301 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6302 0, /* oplock_request */
6304 0, /* allocation_size */
6305 0, /* private_flags */
6310 NULL, NULL); /* create context */
6312 if (!NT_STATUS_IS_OK(status)) {
6313 if (open_was_deferred(req->xconn, req->mid)) {
6314 /* We have re-scheduled this call. */
6317 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6318 bool ok = defer_smb1_sharing_violation(req);
6323 reply_nterror(req, status);
6327 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6328 if (!NT_STATUS_IS_OK(status)) {
6329 close_file_free(req, &fsp, ERROR_CLOSE);
6330 reply_nterror(req, status);
6334 if (!set_delete_on_close(fsp, true,
6335 conn->session_info->security_token,
6336 conn->session_info->unix_token)) {
6337 close_file_free(req, &fsp, ERROR_CLOSE);
6338 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6342 status = close_file_free(req, &fsp, NORMAL_CLOSE);
6343 if (!NT_STATUS_IS_OK(status)) {
6344 reply_nterror(req, status);
6346 reply_smb1_outbuf(req, 0, 0);
6349 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6351 TALLOC_FREE(smb_dname);
6352 END_PROFILE(SMBrmdir);
6356 /****************************************************************************
6358 ****************************************************************************/
6360 void reply_mv(struct smb_request *req)
6362 connection_struct *conn = req->conn;
6364 char *newname = NULL;
6368 TALLOC_CTX *ctx = talloc_tos();
6369 struct files_struct *src_dirfsp = NULL;
6370 struct smb_filename *smb_fname_src = NULL;
6371 struct files_struct *dst_dirfsp = NULL;
6372 struct smb_filename *smb_fname_dst = NULL;
6373 const char *dst_original_lcomp = NULL;
6374 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
6375 NTTIME src_twrp = 0;
6376 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
6377 NTTIME dst_twrp = 0;
6378 bool stream_rename = false;
6380 START_PROFILE(SMBmv);
6383 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6387 attrs = SVAL(req->vwv+0, 0);
6389 p = (const char *)req->buf + 1;
6390 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
6392 if (!NT_STATUS_IS_OK(status)) {
6393 reply_nterror(req, status);
6397 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
6399 if (!NT_STATUS_IS_OK(status)) {
6400 reply_nterror(req, status);
6404 if (!req->posix_pathnames) {
6405 /* The newname must begin with a ':' if the
6406 name contains a ':'. */
6407 if (strchr_m(name, ':')) {
6408 if (newname[0] != ':') {
6409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6412 stream_rename = true;
6416 if (src_ucf_flags & UCF_GMT_PATHNAME) {
6417 extract_snapshot_token(name, &src_twrp);
6419 status = smb1_strip_dfs_path(ctx, &src_ucf_flags, &name);
6420 if (!NT_STATUS_IS_OK(status)) {
6421 reply_nterror(req, status);
6424 status = filename_convert_dirfsp(ctx,
6432 if (!NT_STATUS_IS_OK(status)) {
6433 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6434 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6435 ERRSRV, ERRbadpath);
6438 reply_nterror(req, status);
6442 if (dst_ucf_flags & UCF_GMT_PATHNAME) {
6443 extract_snapshot_token(newname, &dst_twrp);
6445 status = smb1_strip_dfs_path(ctx, &dst_ucf_flags, &newname);
6446 if (!NT_STATUS_IS_OK(status)) {
6447 reply_nterror(req, status);
6450 status = filename_convert_dirfsp(ctx,
6458 if (!NT_STATUS_IS_OK(status)) {
6459 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6460 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6461 ERRSRV, ERRbadpath);
6464 reply_nterror(req, status);
6468 /* Get the last component of the destination for rename_internals(). */
6469 dst_original_lcomp = get_original_lcomp(ctx,
6473 if (dst_original_lcomp == NULL) {
6474 reply_nterror(req, NT_STATUS_NO_MEMORY);
6478 if (stream_rename) {
6479 /* smb_fname_dst->base_name must be the same as
6480 smb_fname_src->base_name. */
6481 TALLOC_FREE(smb_fname_dst->base_name);
6482 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6483 smb_fname_src->base_name);
6484 if (!smb_fname_dst->base_name) {
6485 reply_nterror(req, NT_STATUS_NO_MEMORY);
6490 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6491 smb_fname_str_dbg(smb_fname_dst)));
6493 status = rename_internals(ctx,
6496 src_dirfsp, /* src_dirfsp */
6503 if (!NT_STATUS_IS_OK(status)) {
6504 if (open_was_deferred(req->xconn, req->mid)) {
6505 /* We have re-scheduled this call. */
6508 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6509 bool ok = defer_smb1_sharing_violation(req);
6514 reply_nterror(req, status);
6518 reply_smb1_outbuf(req, 0, 0);
6520 TALLOC_FREE(smb_fname_src);
6521 TALLOC_FREE(smb_fname_dst);
6526 /****************************************************************************
6527 Reply to a file copy.
6531 This command was introduced in the LAN Manager 1.0 dialect
6532 It was rendered obsolete in the NT LAN Manager dialect.
6533 This command was used to perform server-side file copies, but
6534 is no longer used. Clients SHOULD
6535 NOT send requests using this command code.
6536 Servers receiving requests with this command code
6537 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6538 ****************************************************************************/
6540 void reply_copy(struct smb_request *req)
6542 START_PROFILE(SMBcopy);
6543 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
6544 END_PROFILE(SMBcopy);
6549 #define DBGC_CLASS DBGC_LOCKING
6551 /****************************************************************************
6552 Get a lock pid, dealing with large count requests.
6553 ****************************************************************************/
6555 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6556 bool large_file_format)
6558 if(!large_file_format)
6559 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6561 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6564 /****************************************************************************
6565 Get a lock count, dealing with large count requests.
6566 ****************************************************************************/
6568 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6569 bool large_file_format)
6573 if(!large_file_format) {
6574 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6577 * No BVAL, this is reversed!
6579 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6580 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6586 /****************************************************************************
6587 Reply to a lockingX request.
6588 ****************************************************************************/
6590 static void reply_lockingx_done(struct tevent_req *subreq);
6592 void reply_lockingX(struct smb_request *req)
6594 connection_struct *conn = req->conn;
6596 unsigned char locktype;
6597 enum brl_type brltype;
6598 unsigned char oplocklevel;
6599 uint16_t num_ulocks;
6601 int32_t lock_timeout;
6603 const uint8_t *data;
6604 bool large_file_format;
6605 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6606 struct smbd_lock_element *locks = NULL;
6607 struct tevent_req *subreq = NULL;
6609 START_PROFILE(SMBlockingX);
6612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6613 END_PROFILE(SMBlockingX);
6617 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6618 locktype = CVAL(req->vwv+3, 0);
6619 oplocklevel = CVAL(req->vwv+3, 1);
6620 num_ulocks = SVAL(req->vwv+6, 0);
6621 num_locks = SVAL(req->vwv+7, 0);
6622 lock_timeout = IVAL(req->vwv+4, 0);
6623 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
6625 if (!check_fsp(conn, req, fsp)) {
6626 END_PROFILE(SMBlockingX);
6632 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6633 /* we don't support these - and CANCEL_LOCK makes w2k
6634 and XP reboot so I don't really want to be
6635 compatible! (tridge) */
6636 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
6637 END_PROFILE(SMBlockingX);
6641 /* Check if this is an oplock break on a file
6642 we have granted an oplock on.
6644 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
6645 /* Client can insist on breaking to none. */
6646 bool break_to_none = (oplocklevel == 0);
6649 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6650 "for %s\n", (unsigned int)oplocklevel,
6651 fsp_fnum_dbg(fsp)));
6654 * Make sure we have granted an exclusive or batch oplock on
6658 if (fsp->oplock_type == 0) {
6660 /* The Samba4 nbench simulator doesn't understand
6661 the difference between break to level2 and break
6662 to none from level2 - it sends oplock break
6663 replies in both cases. Don't keep logging an error
6664 message here - just ignore it. JRA. */
6666 DEBUG(5,("reply_lockingX: Error : oplock break from "
6667 "client for %s (oplock=%d) and no "
6668 "oplock granted on this file (%s).\n",
6669 fsp_fnum_dbg(fsp), fsp->oplock_type,
6672 /* if this is a pure oplock break request then don't
6674 if (num_locks == 0 && num_ulocks == 0) {
6675 END_PROFILE(SMBlockingX);
6679 END_PROFILE(SMBlockingX);
6680 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6684 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6686 result = remove_oplock(fsp);
6688 result = downgrade_oplock(fsp);
6692 DEBUG(0, ("reply_lockingX: error in removing "
6693 "oplock on file %s\n", fsp_str_dbg(fsp)));
6694 /* Hmmm. Is this panic justified? */
6695 smb_panic("internal tdb error");
6698 /* if this is a pure oplock break request then don't send a
6700 if (num_locks == 0 && num_ulocks == 0) {
6701 /* Sanity check - ensure a pure oplock break is not a
6703 if (CVAL(req->vwv+0, 0) != 0xff) {
6704 DEBUG(0,("reply_lockingX: Error : pure oplock "
6705 "break is a chained %d request !\n",
6706 (unsigned int)CVAL(req->vwv+0, 0)));
6708 END_PROFILE(SMBlockingX);
6714 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6716 END_PROFILE(SMBlockingX);
6720 if (num_ulocks != 0) {
6721 struct smbd_lock_element *ulocks = NULL;
6724 ulocks = talloc_array(
6725 req, struct smbd_lock_element, num_ulocks);
6726 if (ulocks == NULL) {
6727 reply_nterror(req, NT_STATUS_NO_MEMORY);
6728 END_PROFILE(SMBlockingX);
6733 * Data now points at the beginning of the list of
6734 * smb_unlkrng structs
6736 for (i = 0; i < num_ulocks; i++) {
6737 ulocks[i].req_guid = smbd_request_guid(req,
6739 ulocks[i].smblctx = get_lock_pid(
6740 data, i, large_file_format);
6741 ulocks[i].count = get_lock_count(
6742 data, i, large_file_format);
6743 ulocks[i].offset = get_lock_offset(
6744 data, i, large_file_format);
6745 ulocks[i].brltype = UNLOCK_LOCK;
6746 ulocks[i].lock_flav = WINDOWS_LOCK;
6750 * Unlock cancels pending locks
6753 ok = smbd_smb1_brl_finish_by_lock(
6759 reply_smb1_outbuf(req, 2, 0);
6760 SSVAL(req->outbuf, smb_vwv0, 0xff);
6761 SSVAL(req->outbuf, smb_vwv1, 0);
6762 END_PROFILE(SMBlockingX);
6766 status = smbd_do_unlocking(
6767 req, fsp, num_ulocks, ulocks);
6768 TALLOC_FREE(ulocks);
6769 if (!NT_STATUS_IS_OK(status)) {
6770 END_PROFILE(SMBlockingX);
6771 reply_nterror(req, status);
6776 /* Now do any requested locks */
6777 data += ((large_file_format ? 20 : 10)*num_ulocks);
6779 /* Data now points at the beginning of the list
6780 of smb_lkrng structs */
6782 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
6783 brltype = READ_LOCK;
6785 brltype = WRITE_LOCK;
6788 locks = talloc_array(req, struct smbd_lock_element, num_locks);
6789 if (locks == NULL) {
6790 reply_nterror(req, NT_STATUS_NO_MEMORY);
6791 END_PROFILE(SMBlockingX);
6795 for (i = 0; i < num_locks; i++) {
6796 locks[i].req_guid = smbd_request_guid(req, i),
6797 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
6798 locks[i].count = get_lock_count(data, i, large_file_format);
6799 locks[i].offset = get_lock_offset(data, i, large_file_format);
6800 locks[i].brltype = brltype;
6801 locks[i].lock_flav = WINDOWS_LOCK;
6804 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6808 if (num_locks == 0) {
6809 /* See smbtorture3 lock11 test */
6810 reply_smb1_outbuf(req, 2, 0);
6811 /* andx chain ends */
6812 SSVAL(req->outbuf, smb_vwv0, 0xff);
6813 SSVAL(req->outbuf, smb_vwv1, 0);
6814 END_PROFILE(SMBlockingX);
6818 ok = smbd_smb1_brl_finish_by_lock(
6821 locks[0], /* Windows only cancels the first lock */
6822 NT_STATUS_FILE_LOCK_CONFLICT);
6825 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
6826 END_PROFILE(SMBlockingX);
6830 reply_smb1_outbuf(req, 2, 0);
6831 SSVAL(req->outbuf, smb_vwv0, 0xff);
6832 SSVAL(req->outbuf, smb_vwv1, 0);
6833 END_PROFILE(SMBlockingX);
6837 subreq = smbd_smb1_do_locks_send(
6846 if (subreq == NULL) {
6847 reply_nterror(req, NT_STATUS_NO_MEMORY);
6848 END_PROFILE(SMBlockingX);
6851 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
6852 END_PROFILE(SMBlockingX);
6855 static void reply_lockingx_done(struct tevent_req *subreq)
6857 struct smb_request *req = NULL;
6861 START_PROFILE(SMBlockingX);
6863 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6866 status = smbd_smb1_do_locks_recv(subreq);
6867 TALLOC_FREE(subreq);
6869 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
6871 if (NT_STATUS_IS_OK(status)) {
6872 reply_smb1_outbuf(req, 2, 0);
6873 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
6874 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
6876 reply_nterror(req, status);
6879 ok = smb1_srv_send(req->xconn,
6880 (char *)req->outbuf,
6883 IS_CONN_ENCRYPTED(req->conn));
6885 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6888 END_PROFILE(SMBlockingX);
6892 #define DBGC_CLASS DBGC_ALL
6894 /****************************************************************************
6895 Reply to a SMBreadbmpx (read block multiplex) request.
6896 Always reply with an error, if someone has a platform really needs this,
6897 please contact vl@samba.org
6898 ****************************************************************************/
6900 void reply_readbmpx(struct smb_request *req)
6902 START_PROFILE(SMBreadBmpx);
6903 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6904 END_PROFILE(SMBreadBmpx);
6908 /****************************************************************************
6909 Reply to a SMBreadbs (read block multiplex secondary) request.
6910 Always reply with an error, if someone has a platform really needs this,
6911 please contact vl@samba.org
6912 ****************************************************************************/
6914 void reply_readbs(struct smb_request *req)
6916 START_PROFILE(SMBreadBs);
6917 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6918 END_PROFILE(SMBreadBs);
6922 /****************************************************************************
6923 Reply to a SMBsetattrE.
6924 ****************************************************************************/
6926 void reply_setattrE(struct smb_request *req)
6928 connection_struct *conn = req->conn;
6929 struct smb_file_time ft;
6933 START_PROFILE(SMBsetattrE);
6934 init_smb_file_time(&ft);
6937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6941 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6943 if(!fsp || (fsp->conn != conn)) {
6944 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6949 * Convert the DOS times into unix times.
6952 ft.atime = time_t_to_full_timespec(
6953 srv_make_unix_date2(req->vwv+3));
6954 ft.mtime = time_t_to_full_timespec(
6955 srv_make_unix_date2(req->vwv+5));
6956 ft.create_time = time_t_to_full_timespec(
6957 srv_make_unix_date2(req->vwv+1));
6959 reply_smb1_outbuf(req, 0, 0);
6962 * Patch from Ray Frush <frush@engr.colostate.edu>
6963 * Sometimes times are sent as zero - ignore them.
6966 /* Ensure we have a valid stat struct for the source. */
6967 status = vfs_stat_fsp(fsp);
6968 if (!NT_STATUS_IS_OK(status)) {
6969 reply_nterror(req, status);
6973 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
6974 if (!NT_STATUS_IS_OK(status)) {
6975 reply_nterror(req, status);
6979 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
6980 if (!NT_STATUS_IS_OK(status)) {
6981 reply_nterror(req, status);
6985 if (fsp->fsp_flags.modified) {
6986 trigger_write_time_update_immediate(fsp);
6989 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6992 (unsigned int)ft.atime.tv_sec,
6993 (unsigned int)ft.mtime.tv_sec,
6994 (unsigned int)ft.create_time.tv_sec
6997 END_PROFILE(SMBsetattrE);
7002 /* Back from the dead for OS/2..... JRA. */
7004 /****************************************************************************
7005 Reply to a SMBwritebmpx (write block multiplex primary) request.
7006 Always reply with an error, if someone has a platform really needs this,
7007 please contact vl@samba.org
7008 ****************************************************************************/
7010 void reply_writebmpx(struct smb_request *req)
7012 START_PROFILE(SMBwriteBmpx);
7013 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7014 END_PROFILE(SMBwriteBmpx);
7018 /****************************************************************************
7019 Reply to a SMBwritebs (write block multiplex secondary) request.
7020 Always reply with an error, if someone has a platform really needs this,
7021 please contact vl@samba.org
7022 ****************************************************************************/
7024 void reply_writebs(struct smb_request *req)
7026 START_PROFILE(SMBwriteBs);
7027 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7028 END_PROFILE(SMBwriteBs);
7032 /****************************************************************************
7033 Reply to a SMBgetattrE.
7034 ****************************************************************************/
7036 void reply_getattrE(struct smb_request *req)
7038 connection_struct *conn = req->conn;
7041 struct timespec create_ts;
7044 START_PROFILE(SMBgetattrE);
7047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7048 END_PROFILE(SMBgetattrE);
7052 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7054 if(!fsp || (fsp->conn != conn)) {
7055 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7056 END_PROFILE(SMBgetattrE);
7060 /* Do an fstat on this file */
7061 status = vfs_stat_fsp(fsp);
7062 if (!NT_STATUS_IS_OK(status)) {
7063 reply_nterror(req, status);
7064 END_PROFILE(SMBgetattrE);
7068 mode = fdos_mode(fsp);
7071 * Convert the times into dos times. Set create
7072 * date to be last modify date as UNIX doesn't save
7076 reply_smb1_outbuf(req, 11, 0);
7078 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7079 srv_put_dos_date2_ts((char *)req->outbuf, smb_vwv0, create_ts);
7080 srv_put_dos_date2_ts((char *)req->outbuf,
7082 fsp->fsp_name->st.st_ex_atime);
7083 /* Should we check pending modtime here ? JRA */
7084 srv_put_dos_date2_ts((char *)req->outbuf,
7086 fsp->fsp_name->st.st_ex_mtime);
7088 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7089 SIVAL(req->outbuf, smb_vwv6, 0);
7090 SIVAL(req->outbuf, smb_vwv8, 0);
7092 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7093 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
7094 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7096 SSVAL(req->outbuf,smb_vwv10, mode);
7098 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
7100 END_PROFILE(SMBgetattrE);
7104 /****************************************************************************
7105 Reply to a SMBfindclose (stop trans2 directory search).
7106 ****************************************************************************/
7108 void reply_findclose(struct smb_request *req)
7111 struct smbd_server_connection *sconn = req->sconn;
7112 files_struct *fsp = NULL;
7114 START_PROFILE(SMBfindclose);
7117 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7118 END_PROFILE(SMBfindclose);
7122 dptr_num = SVALS(req->vwv+0, 0);
7124 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7127 * OS/2 seems to use -1 to indicate "close all directories"
7128 * This has to mean on this specific connection struct.
7130 if (dptr_num == -1) {
7131 dptr_closecnum(req->conn);
7133 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
7136 close_file_free(NULL, &fsp, NORMAL_CLOSE);
7140 reply_smb1_outbuf(req, 0, 0);
7142 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7144 END_PROFILE(SMBfindclose);
7148 /****************************************************************************
7149 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7150 ****************************************************************************/
7152 void reply_findnclose(struct smb_request *req)
7156 START_PROFILE(SMBfindnclose);
7159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7160 END_PROFILE(SMBfindnclose);
7164 dptr_num = SVAL(req->vwv+0, 0);
7166 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7168 /* We never give out valid handles for a
7169 findnotifyfirst - so any dptr_num is ok here.
7172 reply_smb1_outbuf(req, 0, 0);
7174 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7176 END_PROFILE(SMBfindnclose);