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"
55 /****************************************************************************
57 conn POINTER CAN BE NULL HERE !
58 ****************************************************************************/
60 void reply_tcon(struct smb_request *req)
62 connection_struct *conn = req->conn;
64 char *service_buf = NULL;
65 char *password = NULL;
71 TALLOC_CTX *ctx = talloc_tos();
72 struct smbXsrv_connection *xconn = req->xconn;
73 NTTIME now = timeval_to_nttime(&req->request_time);
75 START_PROFILE(SMBtcon);
77 if (req->buflen < 4) {
78 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
84 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
86 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
88 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
91 if (service_buf == NULL || password == NULL || dev == NULL) {
92 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
96 p2 = strrchr_m(service_buf,'\\');
100 service = service_buf;
103 conn = make_connection(req, now, service, dev,
104 req->vuid,&nt_status);
108 reply_nterror(req, nt_status);
109 END_PROFILE(SMBtcon);
113 reply_smb1_outbuf(req, 2, 0);
114 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
115 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
116 SSVAL(req->outbuf,smb_tid,conn->cnum);
118 DEBUG(3,("tcon service=%s cnum=%d\n",
119 service, conn->cnum));
121 END_PROFILE(SMBtcon);
125 /****************************************************************************
126 Reply to a tcon and X.
127 conn POINTER CAN BE NULL HERE !
128 ****************************************************************************/
130 void reply_tcon_and_X(struct smb_request *req)
132 const struct loadparm_substitution *lp_sub =
133 loadparm_s3_global_substitution();
134 connection_struct *conn = req->conn;
135 const char *service = NULL;
136 TALLOC_CTX *ctx = talloc_tos();
137 /* what the client thinks the device is */
138 char *client_devicetype = NULL;
139 /* what the server tells the client the share represents */
140 const char *server_devicetype;
147 struct smbXsrv_session *session = NULL;
148 NTTIME now = timeval_to_nttime(&req->request_time);
149 bool session_key_updated = false;
150 uint16_t optional_support = 0;
151 struct smbXsrv_connection *xconn = req->xconn;
153 START_PROFILE(SMBtconX);
156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
157 END_PROFILE(SMBtconX);
161 passlen = SVAL(req->vwv+3, 0);
162 tcon_flags = SVAL(req->vwv+2, 0);
164 /* we might have to close an old one */
165 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
166 struct smbXsrv_tcon *tcon;
174 * TODO: cancel all outstanding requests on the tcon
176 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
177 if (!NT_STATUS_IS_OK(status)) {
178 DEBUG(0, ("reply_tcon_and_X: "
179 "smbXsrv_tcon_disconnect() failed: %s\n",
182 * If we hit this case, there is something completely
183 * wrong, so we better disconnect the transport connection.
185 END_PROFILE(SMBtconX);
186 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
192 * This tree id is gone. Make sure we can't re-use it
198 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
199 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
200 END_PROFILE(SMBtconX);
204 if (xconn->smb1.negprot.encrypted_passwords) {
205 p = req->buf + passlen;
207 p = req->buf + passlen + 1;
210 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
214 END_PROFILE(SMBtconX);
219 * the service name can be either: \\server\share
220 * or share directly like on the DELL PowerVault 705
223 q = strchr_m(path+2,'\\');
225 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
226 END_PROFILE(SMBtconX);
234 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
235 &client_devicetype, p,
236 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
238 if (client_devicetype == NULL) {
239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
240 END_PROFILE(SMBtconX);
244 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
246 nt_status = smb1srv_session_lookup(xconn,
247 req->vuid, now, &session);
248 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
249 reply_force_doserror(req, ERRSRV, ERRbaduid);
250 END_PROFILE(SMBtconX);
253 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
254 reply_nterror(req, nt_status);
255 END_PROFILE(SMBtconX);
258 if (!NT_STATUS_IS_OK(nt_status)) {
259 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
260 END_PROFILE(SMBtconX);
264 if (session->global->auth_session_info == NULL) {
265 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
266 END_PROFILE(SMBtconX);
271 * If there is no application key defined yet
274 * This means we setup the application key on the
275 * first tcon that happens via the given session.
277 * Once the application key is defined, it does not
280 if (session->global->application_key_blob.length == 0 &&
281 smb2_signing_key_valid(session->global->signing_key))
283 struct smbXsrv_session *x = session;
284 struct auth_session_info *session_info =
285 session->global->auth_session_info;
286 uint8_t session_key[16];
288 ZERO_STRUCT(session_key);
289 memcpy(session_key, x->global->signing_key->blob.data,
290 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
293 * The application key is truncated/padded to 16 bytes
295 x->global->application_key_blob = data_blob_talloc(x->global,
297 sizeof(session_key));
298 ZERO_STRUCT(session_key);
299 if (x->global->application_key_blob.data == NULL) {
300 reply_nterror(req, NT_STATUS_NO_MEMORY);
301 END_PROFILE(SMBtconX);
304 talloc_keep_secret(x->global->application_key_blob.data);
306 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
309 status = smb1_key_derivation(x->global->application_key_blob.data,
310 x->global->application_key_blob.length,
311 x->global->application_key_blob.data);
312 if (!NT_STATUS_IS_OK(status)) {
313 DBG_ERR("smb1_key_derivation failed: %s\n",
315 END_PROFILE(SMBtconX);
318 optional_support |= SMB_EXTENDED_SIGNATURES;
322 * Place the application key into the session_info
324 data_blob_clear_free(&session_info->session_key);
325 session_info->session_key = data_blob_dup_talloc(session_info,
326 x->global->application_key_blob);
327 if (session_info->session_key.data == NULL) {
328 data_blob_clear_free(&x->global->application_key_blob);
329 reply_nterror(req, NT_STATUS_NO_MEMORY);
330 END_PROFILE(SMBtconX);
333 talloc_keep_secret(session_info->session_key.data);
334 session_key_updated = true;
337 conn = make_connection(req, now, service, client_devicetype,
338 req->vuid, &nt_status);
342 if (session_key_updated) {
343 struct smbXsrv_session *x = session;
344 struct auth_session_info *session_info =
345 session->global->auth_session_info;
346 data_blob_clear_free(&x->global->application_key_blob);
347 data_blob_clear_free(&session_info->session_key);
349 reply_nterror(req, nt_status);
350 END_PROFILE(SMBtconX);
355 server_devicetype = "IPC";
356 else if ( IS_PRINT(conn) )
357 server_devicetype = "LPT1:";
359 server_devicetype = "A:";
361 if (get_Protocol() < PROTOCOL_NT1) {
362 reply_smb1_outbuf(req, 2, 0);
363 if (message_push_string(&req->outbuf, server_devicetype,
364 STR_TERMINATE|STR_ASCII) == -1) {
365 reply_nterror(req, NT_STATUS_NO_MEMORY);
366 END_PROFILE(SMBtconX);
370 /* NT sets the fstype of IPC$ to the null string */
371 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
373 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
374 /* Return permissions. */
378 reply_smb1_outbuf(req, 7, 0);
381 perm1 = FILE_ALL_ACCESS;
382 perm2 = FILE_ALL_ACCESS;
384 perm1 = conn->share_access;
387 SIVAL(req->outbuf, smb_vwv3, perm1);
388 SIVAL(req->outbuf, smb_vwv5, perm2);
390 reply_smb1_outbuf(req, 3, 0);
393 if ((message_push_string(&req->outbuf, server_devicetype,
394 STR_TERMINATE|STR_ASCII) == -1)
395 || (message_push_string(&req->outbuf, fstype,
396 STR_TERMINATE) == -1)) {
397 reply_nterror(req, NT_STATUS_NO_MEMORY);
398 END_PROFILE(SMBtconX);
402 /* what does setting this bit do? It is set by NT4 and
403 may affect the ability to autorun mounted cdroms */
404 optional_support |= SMB_SUPPORT_SEARCH_BITS;
406 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
408 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
409 DEBUG(2,("Serving %s as a Dfs root\n",
410 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
411 optional_support |= SMB_SHARE_IN_DFS;
414 SSVAL(req->outbuf, smb_vwv2, optional_support);
417 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
418 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
420 DEBUG(3,("tconX service=%s \n",
423 /* set the incoming and outgoing tid to the just created one */
424 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
425 SSVAL(req->outbuf,smb_tid,conn->cnum);
427 END_PROFILE(SMBtconX);
429 req->tid = conn->cnum;
432 /****************************************************************************
433 Reply to an unknown type.
434 ****************************************************************************/
436 void reply_unknown_new(struct smb_request *req, uint8_t type)
438 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
439 smb_fn_name(type), type, type));
440 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
444 /****************************************************************************
446 conn POINTER CAN BE NULL HERE !
447 ****************************************************************************/
449 void reply_ioctl(struct smb_request *req)
451 const struct loadparm_substitution *lp_sub =
452 loadparm_s3_global_substitution();
453 connection_struct *conn = req->conn;
460 START_PROFILE(SMBioctl);
463 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
464 END_PROFILE(SMBioctl);
468 device = SVAL(req->vwv+1, 0);
469 function = SVAL(req->vwv+2, 0);
470 ioctl_code = (device << 16) + function;
472 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
474 switch (ioctl_code) {
475 case IOCTL_QUERY_JOB_INFO:
479 reply_force_doserror(req, ERRSRV, ERRnosupport);
480 END_PROFILE(SMBioctl);
484 reply_smb1_outbuf(req, 8, replysize+1);
485 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
486 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
487 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
488 p = smb_buf(req->outbuf);
489 memset(p, '\0', replysize+1); /* valgrind-safe. */
490 p += 1; /* Allow for alignment */
492 switch (ioctl_code) {
493 case IOCTL_QUERY_JOB_INFO:
497 files_struct *fsp = file_fsp(
498 req, SVAL(req->vwv+0, 0));
500 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
501 END_PROFILE(SMBioctl);
505 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
507 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
508 lp_netbios_name(), 15,
509 STR_TERMINATE|STR_ASCII, &len);
510 if (!NT_STATUS_IS_OK(status)) {
511 reply_nterror(req, status);
512 END_PROFILE(SMBioctl);
516 status = srvstr_push((char *)req->outbuf, req->flags2,
518 lp_servicename(talloc_tos(),
521 13, STR_TERMINATE|STR_ASCII, &len);
522 if (!NT_STATUS_IS_OK(status)) {
523 reply_nterror(req, status);
524 END_PROFILE(SMBioctl);
534 END_PROFILE(SMBioctl);
538 /****************************************************************************
539 Strange checkpath NTSTATUS mapping.
540 ****************************************************************************/
542 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
544 /* Strange DOS error code semantics only for checkpath... */
545 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
546 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
547 /* We need to map to ERRbadpath */
548 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
554 /****************************************************************************
555 Reply to a checkpath.
556 ****************************************************************************/
558 void reply_checkpath(struct smb_request *req)
560 connection_struct *conn = req->conn;
561 struct smb_filename *smb_fname = NULL;
564 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
565 TALLOC_CTX *ctx = talloc_tos();
567 START_PROFILE(SMBcheckpath);
569 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
570 STR_TERMINATE, &status);
572 if (!NT_STATUS_IS_OK(status)) {
573 status = map_checkpath_error(req->flags2, status);
574 reply_nterror(req, status);
575 END_PROFILE(SMBcheckpath);
579 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
581 status = filename_convert(ctx,
588 if (!NT_STATUS_IS_OK(status)) {
589 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
590 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
592 END_PROFILE(SMBcheckpath);
598 if (!VALID_STAT(smb_fname->st) &&
599 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
600 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
601 smb_fname_str_dbg(smb_fname), strerror(errno)));
602 status = map_nt_error_from_unix(errno);
606 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
607 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
612 reply_smb1_outbuf(req, 0, 0);
615 /* We special case this - as when a Windows machine
616 is parsing a path is steps through the components
617 one at a time - if a component fails it expects
618 ERRbadpath, not ERRbadfile.
620 status = map_checkpath_error(req->flags2, status);
621 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
623 * Windows returns different error codes if
624 * the parent directory is valid but not the
625 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
626 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
627 * if the path is invalid.
629 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
634 reply_nterror(req, status);
637 TALLOC_FREE(smb_fname);
638 END_PROFILE(SMBcheckpath);
642 /****************************************************************************
644 ****************************************************************************/
646 void reply_getatr(struct smb_request *req)
648 connection_struct *conn = req->conn;
649 struct smb_filename *smb_fname = NULL;
656 TALLOC_CTX *ctx = talloc_tos();
657 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
659 START_PROFILE(SMBgetatr);
661 p = (const char *)req->buf + 1;
662 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
663 if (!NT_STATUS_IS_OK(status)) {
664 reply_nterror(req, status);
669 * dos sometimes asks for a stat of "" - it returns a "hidden
670 * directory" under WfWg - weird!
672 if (*fname == '\0') {
673 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
674 if (!CAN_WRITE(conn)) {
675 mode |= FILE_ATTRIBUTE_READONLY;
680 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
681 status = filename_convert(ctx,
687 if (!NT_STATUS_IS_OK(status)) {
688 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
689 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
693 reply_nterror(req, status);
696 if (!VALID_STAT(smb_fname->st) &&
697 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
698 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
699 smb_fname_str_dbg(smb_fname),
701 reply_nterror(req, map_nt_error_from_unix(errno));
705 mode = fdos_mode(smb_fname->fsp);
706 size = smb_fname->st.st_ex_size;
709 struct timespec write_time_ts;
710 struct file_id fileid;
712 ZERO_STRUCT(write_time_ts);
713 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
714 get_file_infos(fileid, 0, NULL, &write_time_ts);
715 if (!is_omit_timespec(&write_time_ts)) {
716 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
720 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
721 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
726 reply_smb1_outbuf(req, 10, 0);
728 SSVAL(req->outbuf,smb_vwv0,mode);
729 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
730 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
732 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
734 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
736 if (get_Protocol() >= PROTOCOL_NT1) {
737 SSVAL(req->outbuf, smb_flg2,
738 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
741 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
742 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
745 TALLOC_FREE(smb_fname);
747 END_PROFILE(SMBgetatr);
751 /****************************************************************************
753 ****************************************************************************/
755 void reply_setatr(struct smb_request *req)
757 struct smb_file_time ft;
758 connection_struct *conn = req->conn;
759 struct smb_filename *smb_fname = NULL;
765 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
766 TALLOC_CTX *ctx = talloc_tos();
768 START_PROFILE(SMBsetatr);
769 init_smb_file_time(&ft);
772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
776 p = (const char *)req->buf + 1;
777 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
778 if (!NT_STATUS_IS_OK(status)) {
779 reply_nterror(req, status);
783 status = filename_convert(ctx,
789 if (!NT_STATUS_IS_OK(status)) {
790 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
791 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
795 reply_nterror(req, status);
799 if (ISDOT(smb_fname->base_name)) {
801 * Not sure here is the right place to catch this
802 * condition. Might be moved to somewhere else later -- vl
804 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
808 if (smb_fname->fsp == NULL) {
809 /* Can't set access rights on a symlink. */
810 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
814 mode = SVAL(req->vwv+0, 0);
815 mtime = srv_make_unix_date3(req->vwv+1);
817 if (mode != FILE_ATTRIBUTE_NORMAL) {
818 if (VALID_STAT_OF_DIR(smb_fname->st))
819 mode |= FILE_ATTRIBUTE_DIRECTORY;
821 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
823 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
826 FILE_WRITE_ATTRIBUTES);
827 if (!NT_STATUS_IS_OK(status)) {
828 reply_nterror(req, status);
832 if (file_set_dosmode(conn, smb_fname, mode, NULL,
834 reply_nterror(req, map_nt_error_from_unix(errno));
839 ft.mtime = time_t_to_full_timespec(mtime);
841 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
842 if (!NT_STATUS_IS_OK(status)) {
843 reply_nterror(req, status);
847 reply_smb1_outbuf(req, 0, 0);
849 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
852 TALLOC_FREE(smb_fname);
853 END_PROFILE(SMBsetatr);
857 /****************************************************************************
859 ****************************************************************************/
861 void reply_dskattr(struct smb_request *req)
863 connection_struct *conn = req->conn;
865 uint64_t dfree,dsize,bsize;
866 struct smb_filename smb_fname;
867 START_PROFILE(SMBdskattr);
869 ZERO_STRUCT(smb_fname);
870 smb_fname.base_name = discard_const_p(char, ".");
872 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
873 reply_nterror(req, map_nt_error_from_unix(errno));
874 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
875 END_PROFILE(SMBdskattr);
879 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
880 if (ret == (uint64_t)-1) {
881 reply_nterror(req, map_nt_error_from_unix(errno));
882 END_PROFILE(SMBdskattr);
887 * Force max to fit in 16 bit fields.
889 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
893 if (bsize > (WORDMAX*512)) {
894 bsize = (WORDMAX*512);
903 reply_smb1_outbuf(req, 5, 0);
905 if (get_Protocol() <= PROTOCOL_LANMAN2) {
906 double total_space, free_space;
907 /* we need to scale this to a number that DOS6 can handle. We
908 use floating point so we can handle large drives on systems
909 that don't have 64 bit integers
911 we end up displaying a maximum of 2G to DOS systems
913 total_space = dsize * (double)bsize;
914 free_space = dfree * (double)bsize;
916 dsize = (uint64_t)((total_space+63*512) / (64*512));
917 dfree = (uint64_t)((free_space+63*512) / (64*512));
919 if (dsize > 0xFFFF) dsize = 0xFFFF;
920 if (dfree > 0xFFFF) dfree = 0xFFFF;
922 SSVAL(req->outbuf,smb_vwv0,dsize);
923 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
924 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
925 SSVAL(req->outbuf,smb_vwv3,dfree);
927 SSVAL(req->outbuf,smb_vwv0,dsize);
928 SSVAL(req->outbuf,smb_vwv1,bsize/512);
929 SSVAL(req->outbuf,smb_vwv2,512);
930 SSVAL(req->outbuf,smb_vwv3,dfree);
933 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
935 END_PROFILE(SMBdskattr);
939 /****************************************************************************
941 ****************************************************************************/
943 static bool make_dir_struct(TALLOC_CTX *ctx,
953 char *mask2 = talloc_strdup(ctx, mask);
959 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
963 memset(buf+1,' ',11);
964 if ((p = strchr_m(mask2,'.')) != NULL) {
966 push_ascii(buf+1,mask2,8, 0);
967 push_ascii(buf+9,p+1,3, 0);
970 push_ascii(buf+1,mask2,11, 0);
973 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
975 srv_put_dos_date(buf,22,date);
976 SSVAL(buf,26,size & 0xFFFF);
977 SSVAL(buf,28,(size >> 16)&0xFFFF);
978 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
979 Strange, but verified on W2K3. Needed for OS/2. JRA. */
980 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
981 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
985 /****************************************************************************
987 Can be called from SMBsearch, SMBffirst or SMBfunique.
988 ****************************************************************************/
990 void reply_search(struct smb_request *req)
992 connection_struct *conn = req->conn;
995 char *directory = NULL;
996 struct smb_filename *smb_fname = NULL;
1000 struct timespec date;
1002 unsigned int numentries = 0;
1003 unsigned int maxentries = 0;
1004 bool finished = False;
1009 bool check_descend = False;
1010 bool expect_close = False;
1012 bool mask_contains_wcard = False;
1013 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1014 TALLOC_CTX *ctx = talloc_tos();
1015 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1016 struct smbXsrv_connection *xconn = req->xconn;
1017 struct smbd_server_connection *sconn = req->sconn;
1018 files_struct *fsp = NULL;
1019 const struct loadparm_substitution *lp_sub =
1020 loadparm_s3_global_substitution();
1022 START_PROFILE(SMBsearch);
1025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1029 if (req->posix_pathnames) {
1030 reply_unknown_new(req, req->cmd);
1034 /* If we were called as SMBffirst then we must expect close. */
1035 if(req->cmd == SMBffirst) {
1036 expect_close = True;
1039 reply_smb1_outbuf(req, 1, 3);
1040 maxentries = SVAL(req->vwv+0, 0);
1041 dirtype = SVAL(req->vwv+1, 0);
1042 p = (const char *)req->buf + 1;
1043 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1045 if (!NT_STATUS_IS_OK(nt_status)) {
1046 reply_nterror(req, nt_status);
1050 if (smbreq_bufrem(req, p) < 3) {
1051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1056 status_len = SVAL(p, 0);
1059 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1061 if (status_len == 0) {
1062 const char *dirpath;
1063 struct smb_filename *smb_dname = NULL;
1064 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1066 nt_status = filename_convert_smb1_search_path(ctx,
1073 if (!NT_STATUS_IS_OK(nt_status)) {
1074 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1075 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1076 ERRSRV, ERRbadpath);
1079 reply_nterror(req, nt_status);
1083 memset((char *)status,'\0',21);
1084 SCVAL(status,0,(dirtype & 0x1F));
1087 * Open an fsp on this directory for the dptr.
1089 nt_status = SMB_VFS_CREATE_FILE(
1093 smb_dname, /* dname */
1094 FILE_LIST_DIRECTORY, /* access_mask */
1096 FILE_SHARE_WRITE, /* share_access */
1097 FILE_OPEN, /* create_disposition*/
1098 FILE_DIRECTORY_FILE, /* create_options */
1099 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1100 NO_OPLOCK, /* oplock_request */
1102 0, /* allocation_size */
1103 0, /* private_flags */
1108 NULL, /* in_context */
1109 NULL);/* out_context */
1111 if (!NT_STATUS_IS_OK(nt_status)) {
1112 DBG_ERR("failed to open directory %s\n",
1113 smb_fname_str_dbg(smb_dname));
1114 reply_nterror(req, nt_status);
1118 nt_status = dptr_create(conn,
1128 TALLOC_FREE(smb_dname);
1130 if (!NT_STATUS_IS_OK(nt_status)) {
1132 * Use NULL here for the first parameter (req)
1133 * as this is not a client visible handle so
1134 * can'tbe part of an SMB1 chain.
1136 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1137 reply_nterror(req, nt_status);
1141 dptr_num = dptr_dnum(fsp->dptr);
1142 dirpath = dptr_path(sconn, dptr_num);
1143 directory = talloc_strdup(ctx, dirpath);
1145 reply_nterror(req, NT_STATUS_NO_MEMORY);
1151 const char *dirpath;
1153 if (smbreq_bufrem(req, p) < 21) {
1154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1158 memcpy(status,p,21);
1159 status_dirtype = CVAL(status,0) & 0x1F;
1160 if (status_dirtype != (dirtype & 0x1F)) {
1161 dirtype = status_dirtype;
1164 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1168 dirpath = dptr_path(sconn, dptr_num);
1169 directory = talloc_strdup(ctx, dirpath);
1171 reply_nterror(req, NT_STATUS_NO_MEMORY);
1175 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1179 dirtype = dptr_attr(sconn, dptr_num);
1182 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1184 DEBUG(4,("dptr_num is %d\n",dptr_num));
1186 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1187 char buf[DIR_STRUCT_SIZE];
1188 memcpy(buf,status,21);
1189 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1190 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1191 reply_nterror(req, NT_STATUS_NO_MEMORY);
1194 dptr_fill(sconn, buf+12,dptr_num);
1195 if (dptr_zero(buf+12) && (status_len==0)) {
1200 if (message_push_blob(&req->outbuf,
1201 data_blob_const(buf, sizeof(buf)))
1203 reply_nterror(req, NT_STATUS_NO_MEMORY);
1208 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1209 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1211 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1213 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1214 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1215 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1216 check_descend = True;
1219 for (i=numentries;(i<maxentries) && !finished;i++) {
1220 finished = !get_dir_entry(ctx,
1231 char buf[DIR_STRUCT_SIZE];
1232 memcpy(buf,status,21);
1233 if (!make_dir_struct(ctx,
1239 convert_timespec_to_time_t(date),
1240 !allow_long_path_components)) {
1241 reply_nterror(req, NT_STATUS_NO_MEMORY);
1244 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1247 if (message_push_blob(&req->outbuf,
1248 data_blob_const(buf, sizeof(buf)))
1250 reply_nterror(req, NT_STATUS_NO_MEMORY);
1260 /* If we were called as SMBffirst with smb_search_id == NULL
1261 and no entries were found then return error and close fsp->dptr
1264 if (numentries == 0) {
1267 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1269 } else if(expect_close && status_len == 0) {
1270 /* Close the dptr - we know it's gone */
1273 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1277 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1278 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1280 /* fsp may have been closed above. */
1282 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1286 if ((numentries == 0) && !mask_contains_wcard) {
1287 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1291 SSVAL(req->outbuf,smb_vwv0,numentries);
1292 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1293 SCVAL(smb_buf(req->outbuf),0,5);
1294 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1296 /* The replies here are never long name. */
1297 SSVAL(req->outbuf, smb_flg2,
1298 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1299 if (!allow_long_path_components) {
1300 SSVAL(req->outbuf, smb_flg2,
1301 SVAL(req->outbuf, smb_flg2)
1302 & (~FLAGS2_LONG_PATH_COMPONENTS));
1305 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1306 SSVAL(req->outbuf, smb_flg2,
1307 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1309 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1310 smb_fn_name(req->cmd),
1317 TALLOC_FREE(directory);
1319 TALLOC_FREE(smb_fname);
1320 END_PROFILE(SMBsearch);
1324 /****************************************************************************
1325 Reply to a fclose (stop directory search).
1326 ****************************************************************************/
1328 void reply_fclose(struct smb_request *req)
1336 TALLOC_CTX *ctx = talloc_tos();
1337 struct smbd_server_connection *sconn = req->sconn;
1338 files_struct *fsp = NULL;
1340 START_PROFILE(SMBfclose);
1342 if (req->posix_pathnames) {
1343 reply_unknown_new(req, req->cmd);
1344 END_PROFILE(SMBfclose);
1348 p = (const char *)req->buf + 1;
1349 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1351 if (!NT_STATUS_IS_OK(err)) {
1352 reply_nterror(req, err);
1353 END_PROFILE(SMBfclose);
1357 if (smbreq_bufrem(req, p) < 3) {
1358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1359 END_PROFILE(SMBfclose);
1364 status_len = SVAL(p,0);
1367 if (status_len == 0) {
1368 reply_force_doserror(req, ERRSRV, ERRsrverror);
1369 END_PROFILE(SMBfclose);
1373 if (smbreq_bufrem(req, p) < 21) {
1374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1375 END_PROFILE(SMBfclose);
1379 memcpy(status,p,21);
1381 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1383 /* Close the file - we know it's gone */
1384 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1388 reply_smb1_outbuf(req, 1, 0);
1389 SSVAL(req->outbuf,smb_vwv0,0);
1391 DEBUG(3,("search close\n"));
1393 END_PROFILE(SMBfclose);
1397 /****************************************************************************
1399 ****************************************************************************/
1401 void reply_open(struct smb_request *req)
1403 connection_struct *conn = req->conn;
1404 struct smb_filename *smb_fname = NULL;
1410 struct files_struct *dirfsp = NULL;
1415 uint32_t access_mask;
1416 uint32_t share_mode;
1417 uint32_t create_disposition;
1418 uint32_t create_options = 0;
1419 uint32_t private_flags = 0;
1423 TALLOC_CTX *ctx = talloc_tos();
1425 START_PROFILE(SMBopen);
1428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1432 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1433 deny_mode = SVAL(req->vwv+0, 0);
1434 dos_attr = SVAL(req->vwv+1, 0);
1436 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1437 STR_TERMINATE, &status);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 reply_nterror(req, status);
1443 if (!map_open_params_to_ntcreate(fname, deny_mode,
1444 OPENX_FILE_EXISTS_OPEN, &access_mask,
1445 &share_mode, &create_disposition,
1446 &create_options, &private_flags)) {
1447 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1451 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1453 if (ucf_flags & UCF_GMT_PATHNAME) {
1454 extract_snapshot_token(fname, &twrp);
1456 status = filename_convert_dirfsp(ctx,
1463 if (!NT_STATUS_IS_OK(status)) {
1464 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1465 reply_botherror(req,
1466 NT_STATUS_PATH_NOT_COVERED,
1467 ERRSRV, ERRbadpath);
1470 reply_nterror(req, status);
1474 status = SMB_VFS_CREATE_FILE(
1477 dirfsp, /* dirfsp */
1478 smb_fname, /* fname */
1479 access_mask, /* access_mask */
1480 share_mode, /* share_access */
1481 create_disposition, /* create_disposition*/
1482 create_options, /* create_options */
1483 dos_attr, /* file_attributes */
1484 oplock_request, /* oplock_request */
1486 0, /* allocation_size */
1492 NULL, NULL); /* create context */
1494 if (!NT_STATUS_IS_OK(status)) {
1495 if (open_was_deferred(req->xconn, req->mid)) {
1496 /* We have re-scheduled this call. */
1500 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1501 reply_openerror(req, status);
1505 fsp = fcb_or_dos_open(
1512 bool ok = defer_smb1_sharing_violation(req);
1516 reply_openerror(req, status);
1521 /* Ensure we're pointing at the correct stat struct. */
1522 TALLOC_FREE(smb_fname);
1523 smb_fname = fsp->fsp_name;
1525 size = smb_fname->st.st_ex_size;
1526 fattr = fdos_mode(fsp);
1528 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1530 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1531 DEBUG(3,("attempt to open a directory %s\n",
1533 close_file_free(req, &fsp, ERROR_CLOSE);
1534 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1535 ERRDOS, ERRnoaccess);
1539 reply_smb1_outbuf(req, 7, 0);
1540 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1541 SSVAL(req->outbuf,smb_vwv1,fattr);
1542 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1543 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1545 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1547 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1548 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1550 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1551 SCVAL(req->outbuf,smb_flg,
1552 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1555 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1556 SCVAL(req->outbuf,smb_flg,
1557 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1560 END_PROFILE(SMBopen);
1564 /****************************************************************************
1565 Reply to an open and X.
1566 ****************************************************************************/
1568 void reply_open_and_X(struct smb_request *req)
1570 connection_struct *conn = req->conn;
1571 struct smb_filename *smb_fname = NULL;
1573 uint16_t open_flags;
1576 /* Breakout the oplock request bits so we can set the
1577 reply bits separately. */
1578 int ex_oplock_request;
1579 int core_oplock_request;
1582 int smb_sattr = SVAL(req->vwv+4, 0);
1583 uint32_t smb_time = make_unix_date3(req->vwv+6);
1589 struct files_struct *dirfsp = NULL;
1592 uint64_t allocation_size;
1593 ssize_t retval = -1;
1594 uint32_t access_mask;
1595 uint32_t share_mode;
1596 uint32_t create_disposition;
1597 uint32_t create_options = 0;
1598 uint32_t private_flags = 0;
1601 TALLOC_CTX *ctx = talloc_tos();
1603 START_PROFILE(SMBopenX);
1605 if (req->wct < 15) {
1606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1610 open_flags = SVAL(req->vwv+2, 0);
1611 deny_mode = SVAL(req->vwv+3, 0);
1612 smb_attr = SVAL(req->vwv+5, 0);
1613 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1614 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1615 oplock_request = ex_oplock_request | core_oplock_request;
1616 smb_ofun = SVAL(req->vwv+8, 0);
1617 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1619 /* If it's an IPC, pass off the pipe handler. */
1621 if (lp_nt_pipe_support()) {
1622 reply_open_pipe_and_X(conn, req);
1624 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1629 /* XXXX we need to handle passed times, sattr and flags */
1630 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1631 STR_TERMINATE, &status);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 reply_nterror(req, status);
1637 if (!map_open_params_to_ntcreate(fname, deny_mode,
1639 &access_mask, &share_mode,
1640 &create_disposition,
1643 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1647 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1649 if (ucf_flags & UCF_GMT_PATHNAME) {
1650 extract_snapshot_token(fname, &twrp);
1653 status = filename_convert_dirfsp(ctx,
1660 if (!NT_STATUS_IS_OK(status)) {
1661 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1662 reply_botherror(req,
1663 NT_STATUS_PATH_NOT_COVERED,
1664 ERRSRV, ERRbadpath);
1667 reply_nterror(req, status);
1671 status = SMB_VFS_CREATE_FILE(
1674 dirfsp, /* dirfsp */
1675 smb_fname, /* fname */
1676 access_mask, /* access_mask */
1677 share_mode, /* share_access */
1678 create_disposition, /* create_disposition*/
1679 create_options, /* create_options */
1680 smb_attr, /* file_attributes */
1681 oplock_request, /* oplock_request */
1683 0, /* allocation_size */
1688 &smb_action, /* pinfo */
1689 NULL, NULL); /* create context */
1691 if (!NT_STATUS_IS_OK(status)) {
1692 if (open_was_deferred(req->xconn, req->mid)) {
1693 /* We have re-scheduled this call. */
1697 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1698 reply_openerror(req, status);
1702 fsp = fcb_or_dos_open(
1709 bool ok = defer_smb1_sharing_violation(req);
1713 reply_openerror(req, status);
1718 smb_action = FILE_WAS_OPENED;
1721 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1722 if the file is truncated or created. */
1723 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1724 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1725 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1726 close_file_free(req, &fsp, ERROR_CLOSE);
1727 reply_nterror(req, NT_STATUS_DISK_FULL);
1730 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1732 close_file_free(req, &fsp, ERROR_CLOSE);
1733 reply_nterror(req, NT_STATUS_DISK_FULL);
1736 status = vfs_stat_fsp(fsp);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 close_file_free(req, &fsp, ERROR_CLOSE);
1739 reply_nterror(req, status);
1744 fattr = fdos_mode(fsp);
1745 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1746 close_file_free(req, &fsp, ERROR_CLOSE);
1747 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1750 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
1752 /* If the caller set the extended oplock request bit
1753 and we granted one (by whatever means) - set the
1754 correct bit for extended oplock reply.
1757 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1758 smb_action |= EXTENDED_OPLOCK_GRANTED;
1761 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1762 smb_action |= EXTENDED_OPLOCK_GRANTED;
1765 /* If the caller set the core oplock request bit
1766 and we granted one (by whatever means) - set the
1767 correct bit for core oplock reply.
1770 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1771 reply_smb1_outbuf(req, 19, 0);
1773 reply_smb1_outbuf(req, 15, 0);
1776 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1777 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1779 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1780 SCVAL(req->outbuf, smb_flg,
1781 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1784 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1785 SCVAL(req->outbuf, smb_flg,
1786 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1789 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1790 SSVAL(req->outbuf,smb_vwv3,fattr);
1791 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1792 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1794 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1796 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
1797 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1798 SSVAL(req->outbuf,smb_vwv11,smb_action);
1800 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1801 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
1805 TALLOC_FREE(smb_fname);
1806 END_PROFILE(SMBopenX);
1810 /****************************************************************************
1811 Reply to a SMBulogoffX.
1812 ****************************************************************************/
1814 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1815 struct smbXsrv_session *session);
1816 static void reply_ulogoffX_done(struct tevent_req *req);
1818 void reply_ulogoffX(struct smb_request *smb1req)
1820 struct timeval now = timeval_current();
1821 struct smbXsrv_session *session = NULL;
1822 struct tevent_req *req;
1826 * Don't setup the profile charge here, take
1827 * it in reply_ulogoffX_done(). Not strictly correct
1828 * but better than the other SMB1 async
1829 * code that double-charges at the moment.
1832 status = smb1srv_session_lookup(smb1req->xconn,
1834 timeval_to_nttime(&now),
1836 if (!NT_STATUS_IS_OK(status)) {
1837 /* Not going async, profile here. */
1838 START_PROFILE(SMBulogoffX);
1839 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
1840 (unsigned long long)smb1req->vuid);
1842 smb1req->vuid = UID_FIELD_INVALID;
1843 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
1844 END_PROFILE(SMBulogoffX);
1848 req = reply_ulogoffX_send(smb1req, session);
1850 /* Not going async, profile here. */
1851 START_PROFILE(SMBulogoffX);
1852 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
1853 END_PROFILE(SMBulogoffX);
1857 /* We're async. This will complete later. */
1858 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
1862 struct reply_ulogoffX_state {
1863 struct tevent_queue *wait_queue;
1864 struct smbXsrv_session *session;
1867 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
1869 /****************************************************************************
1870 Async SMB1 ulogoffX.
1871 Note, on failure here we deallocate and return NULL to allow the caller to
1872 SMB1 return an error of ERRnomem immediately.
1873 ****************************************************************************/
1875 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1876 struct smbXsrv_session *session)
1878 struct tevent_req *req;
1879 struct reply_ulogoffX_state *state;
1880 struct tevent_req *subreq;
1882 struct smbd_server_connection *sconn = session->client->sconn;
1883 uint64_t vuid = session->global->session_wire_id;
1885 req = tevent_req_create(smb1req, &state,
1886 struct reply_ulogoffX_state);
1890 state->wait_queue = tevent_queue_create(state,
1891 "reply_ulogoffX_wait_queue");
1892 if (tevent_req_nomem(state->wait_queue, req)) {
1896 state->session = session;
1899 * Make sure that no new request will be able to use this session.
1900 * This ensures that once all outstanding fsp->aio_requests
1901 * on this session are done, we are safe to close it.
1903 session->status = NT_STATUS_USER_SESSION_DELETED;
1905 for (fsp = sconn->files; fsp; fsp = fsp->next) {
1906 if (fsp->vuid != vuid) {
1910 * Flag the file as close in progress.
1911 * This will prevent any more IO being
1914 fsp->fsp_flags.closing = true;
1916 if (fsp->num_aio_requests > 0) {
1918 * Now wait until all aio requests on this fsp are
1921 * We don't set a callback, as we just want to block the
1922 * wait queue and the talloc_free() of fsp->aio_request
1923 * will remove the item from the wait queue.
1925 subreq = tevent_queue_wait_send(fsp->aio_requests,
1928 if (tevent_req_nomem(subreq, req)) {
1936 * Now we add our own waiter to the end of the queue,
1937 * this way we get notified when all pending requests are finished
1938 * and reply to the outstanding SMB1 request.
1940 subreq = tevent_queue_wait_send(state,
1943 if (tevent_req_nomem(subreq, req)) {
1949 * We're really going async - move the SMB1 request from
1950 * a talloc stackframe above us to the sconn talloc-context.
1951 * We need this to stick around until the wait_done
1952 * callback is invoked.
1954 smb1req = talloc_move(sconn, &smb1req);
1956 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
1961 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
1963 struct tevent_req *req = tevent_req_callback_data(
1964 subreq, struct tevent_req);
1966 tevent_queue_wait_recv(subreq);
1967 TALLOC_FREE(subreq);
1968 tevent_req_done(req);
1971 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
1973 return tevent_req_simple_recv_ntstatus(req);
1976 static void reply_ulogoffX_done(struct tevent_req *req)
1978 struct smb_request *smb1req = tevent_req_callback_data(
1979 req, struct smb_request);
1980 struct reply_ulogoffX_state *state = tevent_req_data(req,
1981 struct reply_ulogoffX_state);
1982 struct smbXsrv_session *session = state->session;
1986 * Take the profile charge here. Not strictly
1987 * correct but better than the other SMB1 async
1988 * code that double-charges at the moment.
1990 START_PROFILE(SMBulogoffX);
1992 status = reply_ulogoffX_recv(req);
1994 if (!NT_STATUS_IS_OK(status)) {
1995 TALLOC_FREE(smb1req);
1996 END_PROFILE(SMBulogoffX);
1997 exit_server(__location__ ": reply_ulogoffX_recv failed");
2001 status = smbXsrv_session_logoff(session);
2002 if (!NT_STATUS_IS_OK(status)) {
2003 TALLOC_FREE(smb1req);
2004 END_PROFILE(SMBulogoffX);
2005 exit_server(__location__ ": smbXsrv_session_logoff failed");
2009 TALLOC_FREE(session);
2011 reply_smb1_outbuf(smb1req, 2, 0);
2012 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2013 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2015 DBG_NOTICE("ulogoffX vuid=%llu\n",
2016 (unsigned long long)smb1req->vuid);
2018 smb1req->vuid = UID_FIELD_INVALID;
2020 * The following call is needed to push the
2021 * reply data back out the socket after async
2022 * return. Plus it frees smb1req.
2024 smb_request_done(smb1req);
2025 END_PROFILE(SMBulogoffX);
2028 /****************************************************************************
2029 Reply to a mknew or a create.
2030 ****************************************************************************/
2032 void reply_mknew(struct smb_request *req)
2034 connection_struct *conn = req->conn;
2035 struct smb_filename *smb_fname = NULL;
2038 struct smb_file_time ft;
2039 struct files_struct *dirfsp = NULL;
2041 int oplock_request = 0;
2043 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2044 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2045 uint32_t create_disposition;
2046 uint32_t create_options = 0;
2049 TALLOC_CTX *ctx = talloc_tos();
2051 START_PROFILE(SMBcreate);
2052 init_smb_file_time(&ft);
2055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2059 fattr = SVAL(req->vwv+0, 0);
2060 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2062 if (req->cmd == SMBmknew) {
2063 /* We should fail if file exists. */
2064 create_disposition = FILE_CREATE;
2066 /* Create if file doesn't exist, truncate if it does. */
2067 create_disposition = FILE_OVERWRITE_IF;
2071 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2073 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2074 STR_TERMINATE, &status);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 reply_nterror(req, status);
2080 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2081 if (ucf_flags & UCF_GMT_PATHNAME) {
2082 extract_snapshot_token(fname, &twrp);
2085 status = filename_convert_dirfsp(ctx,
2092 if (!NT_STATUS_IS_OK(status)) {
2093 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2094 reply_botherror(req,
2095 NT_STATUS_PATH_NOT_COVERED,
2096 ERRSRV, ERRbadpath);
2099 reply_nterror(req, status);
2103 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2104 DEBUG(0,("Attempt to create file (%s) with volid set - "
2105 "please report this\n",
2106 smb_fname_str_dbg(smb_fname)));
2109 status = SMB_VFS_CREATE_FILE(
2112 dirfsp, /* dirfsp */
2113 smb_fname, /* fname */
2114 access_mask, /* access_mask */
2115 share_mode, /* share_access */
2116 create_disposition, /* create_disposition*/
2117 create_options, /* create_options */
2118 fattr, /* file_attributes */
2119 oplock_request, /* oplock_request */
2121 0, /* allocation_size */
2122 0, /* private_flags */
2127 NULL, NULL); /* create context */
2129 if (!NT_STATUS_IS_OK(status)) {
2130 if (open_was_deferred(req->xconn, req->mid)) {
2131 /* We have re-scheduled this call. */
2134 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2135 bool ok = defer_smb1_sharing_violation(req);
2140 reply_openerror(req, status);
2144 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2145 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2146 if (!NT_STATUS_IS_OK(status)) {
2147 END_PROFILE(SMBcreate);
2151 reply_smb1_outbuf(req, 1, 0);
2152 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2154 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2155 SCVAL(req->outbuf,smb_flg,
2156 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2159 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2160 SCVAL(req->outbuf,smb_flg,
2161 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2164 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2165 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2166 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2167 (unsigned int)fattr));
2170 TALLOC_FREE(smb_fname);
2171 END_PROFILE(SMBcreate);
2175 /****************************************************************************
2176 Reply to a create temporary file.
2177 ****************************************************************************/
2179 void reply_ctemp(struct smb_request *req)
2181 connection_struct *conn = req->conn;
2182 struct smb_filename *smb_fname = NULL;
2183 char *wire_name = NULL;
2186 struct files_struct *dirfsp = NULL;
2194 TALLOC_CTX *ctx = talloc_tos();
2196 START_PROFILE(SMBctemp);
2199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2203 fattr = SVAL(req->vwv+0, 0);
2204 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2206 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2207 STR_TERMINATE, &status);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 reply_nterror(req, status);
2213 for (i = 0; i < 10; i++) {
2215 fname = talloc_asprintf(ctx,
2218 generate_random_str_list(ctx, 5, "0123456789"));
2220 fname = talloc_asprintf(ctx,
2222 generate_random_str_list(ctx, 5, "0123456789"));
2226 reply_nterror(req, NT_STATUS_NO_MEMORY);
2230 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2231 if (ucf_flags & UCF_GMT_PATHNAME) {
2232 extract_snapshot_token(fname, &twrp);
2234 status = filename_convert_dirfsp(ctx,
2241 if (!NT_STATUS_IS_OK(status)) {
2242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2244 ERRSRV, ERRbadpath);
2247 reply_nterror(req, status);
2251 /* Create the file. */
2252 status = SMB_VFS_CREATE_FILE(
2255 dirfsp, /* dirfsp */
2256 smb_fname, /* fname */
2257 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2258 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2259 FILE_CREATE, /* create_disposition*/
2260 0, /* create_options */
2261 fattr, /* file_attributes */
2262 oplock_request, /* oplock_request */
2264 0, /* allocation_size */
2265 0, /* private_flags */
2270 NULL, NULL); /* create context */
2272 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2274 TALLOC_FREE(dirfsp);
2275 TALLOC_FREE(smb_fname);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 if (open_was_deferred(req->xconn, req->mid)) {
2281 /* We have re-scheduled this call. */
2284 if (NT_STATUS_EQUAL(
2285 status, NT_STATUS_SHARING_VIOLATION)) {
2286 bool ok = defer_smb1_sharing_violation(req);
2291 reply_openerror(req, status);
2299 /* Collision after 10 times... */
2300 reply_nterror(req, status);
2304 reply_smb1_outbuf(req, 1, 0);
2305 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2307 /* the returned filename is relative to the directory */
2308 s = strrchr_m(fsp->fsp_name->base_name, '/');
2310 s = fsp->fsp_name->base_name;
2316 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2317 thing in the byte section. JRA */
2318 SSVALS(p, 0, -1); /* what is this? not in spec */
2320 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2326 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2327 SCVAL(req->outbuf, smb_flg,
2328 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2331 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2332 SCVAL(req->outbuf, smb_flg,
2333 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2336 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2337 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2338 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2340 TALLOC_FREE(smb_fname);
2341 TALLOC_FREE(wire_name);
2342 END_PROFILE(SMBctemp);
2346 /****************************************************************************
2348 ****************************************************************************/
2350 void reply_unlink(struct smb_request *req)
2352 connection_struct *conn = req->conn;
2354 struct smb_filename *smb_fname = NULL;
2357 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2358 TALLOC_CTX *ctx = talloc_tos();
2360 START_PROFILE(SMBunlink);
2363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2367 dirtype = SVAL(req->vwv+0, 0);
2369 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2370 STR_TERMINATE, &status);
2371 if (!NT_STATUS_IS_OK(status)) {
2372 reply_nterror(req, status);
2376 status = filename_convert(ctx, conn,
2381 if (!NT_STATUS_IS_OK(status)) {
2382 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2383 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2384 ERRSRV, ERRbadpath);
2387 reply_nterror(req, status);
2391 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2393 status = unlink_internals(conn, req, dirtype, smb_fname);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 if (open_was_deferred(req->xconn, req->mid)) {
2396 /* We have re-scheduled this call. */
2399 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2400 bool ok = defer_smb1_sharing_violation(req);
2405 reply_nterror(req, status);
2409 reply_smb1_outbuf(req, 0, 0);
2411 TALLOC_FREE(smb_fname);
2412 END_PROFILE(SMBunlink);
2416 /****************************************************************************
2418 ****************************************************************************/
2420 static void fail_readraw(void)
2422 const char *errstr = talloc_asprintf(talloc_tos(),
2423 "FAIL ! reply_readbraw: socket write fail (%s)",
2428 exit_server_cleanly(errstr);
2431 /****************************************************************************
2432 Return a readbraw error (4 bytes of zero).
2433 ****************************************************************************/
2435 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2441 smbd_lock_socket(xconn);
2442 if (write_data(xconn->transport.sock,header,4) != 4) {
2443 int saved_errno = errno;
2445 * Try and give an error message saying what
2448 DEBUG(0, ("write_data failed for client %s. "
2450 smbXsrv_connection_dbg(xconn),
2451 strerror(saved_errno)));
2452 errno = saved_errno;
2456 smbd_unlock_socket(xconn);
2459 /*******************************************************************
2460 Ensure we don't use sendfile if server smb signing is active.
2461 ********************************************************************/
2463 static bool lp_use_sendfile(int snum, struct smb1_signing_state *signing_state)
2465 bool sign_active = false;
2467 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2468 if (get_Protocol() < PROTOCOL_NT1) {
2471 if (signing_state) {
2472 sign_active = smb1_signing_is_active(signing_state);
2474 return (lp__use_sendfile(snum) &&
2475 (get_remote_arch() != RA_WIN95) &&
2478 /****************************************************************************
2479 Use sendfile in readbraw.
2480 ****************************************************************************/
2482 static void send_file_readbraw(connection_struct *conn,
2483 struct smb_request *req,
2489 struct smbXsrv_connection *xconn = req->xconn;
2490 char *outbuf = NULL;
2494 * We can only use sendfile on a non-chained packet
2495 * but we can use on a non-oplocked file. tridge proved this
2496 * on a train in Germany :-). JRA.
2497 * reply_readbraw has already checked the length.
2500 if ( !req_is_in_chain(req) &&
2502 !fsp_is_alternate_stream(fsp) &&
2503 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
2504 ssize_t sendfile_read = -1;
2506 DATA_BLOB header_blob;
2508 _smb_setlen(header,nread);
2509 header_blob = data_blob_const(header, 4);
2511 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2512 &header_blob, startpos,
2514 if (sendfile_read == -1) {
2515 /* Returning ENOSYS means no data at all was sent.
2516 * Do this as a normal read. */
2517 if (errno == ENOSYS) {
2518 goto normal_readbraw;
2522 * Special hack for broken Linux with no working sendfile. If we
2523 * return EINTR we sent the header but not the rest of the data.
2524 * Fake this up by doing read/write calls.
2526 if (errno == EINTR) {
2527 /* Ensure we don't do this again. */
2528 set_use_sendfile(SNUM(conn), False);
2529 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2531 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2532 DEBUG(0,("send_file_readbraw: "
2533 "fake_sendfile failed for "
2537 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2542 DEBUG(0,("send_file_readbraw: sendfile failed for "
2543 "file %s (%s). Terminating\n",
2544 fsp_str_dbg(fsp), strerror(errno)));
2545 exit_server_cleanly("send_file_readbraw sendfile failed");
2546 } else if (sendfile_read == 0) {
2548 * Some sendfile implementations return 0 to indicate
2549 * that there was a short read, but nothing was
2550 * actually written to the socket. In this case,
2551 * fallback to the normal read path so the header gets
2552 * the correct byte count.
2554 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2555 "bytes falling back to the normal read: "
2556 "%s\n", fsp_str_dbg(fsp)));
2557 goto normal_readbraw;
2560 /* Deal with possible short send. */
2561 if (sendfile_read != 4+nread) {
2562 ret = sendfile_short_send(xconn, fsp,
2563 sendfile_read, 4, nread);
2573 outbuf = talloc_array(NULL, char, nread+4);
2575 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2576 (unsigned)(nread+4)));
2577 reply_readbraw_error(xconn);
2582 ret = read_file(fsp,outbuf+4,startpos,nread);
2583 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2592 _smb_setlen(outbuf,ret);
2593 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2594 int saved_errno = errno;
2596 * Try and give an error message saying what
2599 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2600 smbXsrv_connection_dbg(xconn),
2601 strerror(saved_errno)));
2602 errno = saved_errno;
2607 TALLOC_FREE(outbuf);
2610 /****************************************************************************
2611 Reply to a readbraw (core+ protocol).
2612 ****************************************************************************/
2614 void reply_readbraw(struct smb_request *req)
2616 connection_struct *conn = req->conn;
2617 struct smbXsrv_connection *xconn = req->xconn;
2618 ssize_t maxcount,mincount;
2622 struct lock_struct lock;
2626 START_PROFILE(SMBreadbraw);
2628 if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
2629 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2630 "raw reads/writes are disallowed.");
2634 reply_readbraw_error(xconn);
2635 END_PROFILE(SMBreadbraw);
2639 if (xconn->smb1.echo_handler.trusted_fde) {
2640 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
2641 "'async smb echo handler = yes'\n"));
2642 reply_readbraw_error(xconn);
2643 END_PROFILE(SMBreadbraw);
2648 * Special check if an oplock break has been issued
2649 * and the readraw request croses on the wire, we must
2650 * return a zero length response here.
2653 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2656 * We have to do a check_fsp by hand here, as
2657 * we must always return 4 zero bytes on error,
2663 conn != fsp->conn ||
2664 req->vuid != fsp->vuid ||
2665 fsp->fsp_flags.is_directory ||
2666 fsp_get_io_fd(fsp) == -1)
2669 * fsp could be NULL here so use the value from the packet. JRA.
2671 DEBUG(3,("reply_readbraw: fnum %d not valid "
2673 (int)SVAL(req->vwv+0, 0)));
2674 reply_readbraw_error(xconn);
2675 END_PROFILE(SMBreadbraw);
2679 /* Do a "by hand" version of CHECK_READ. */
2680 if (!(fsp->fsp_flags.can_read ||
2681 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2682 (fsp->access_mask & FILE_EXECUTE)))) {
2683 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2684 (int)SVAL(req->vwv+0, 0)));
2685 reply_readbraw_error(xconn);
2686 END_PROFILE(SMBreadbraw);
2690 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2691 if(req->wct == 10) {
2693 * This is a large offset (64 bit) read.
2696 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
2699 DEBUG(0,("reply_readbraw: negative 64 bit "
2700 "readraw offset (%.0f) !\n",
2701 (double)startpos ));
2702 reply_readbraw_error(xconn);
2703 END_PROFILE(SMBreadbraw);
2708 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2709 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2711 /* ensure we don't overrun the packet size */
2712 maxcount = MIN(65535,maxcount);
2714 init_strict_lock_struct(fsp,
2715 (uint64_t)req->smbpid,
2719 lp_posix_cifsu_locktype(fsp),
2722 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
2723 reply_readbraw_error(xconn);
2724 END_PROFILE(SMBreadbraw);
2728 status = vfs_stat_fsp(fsp);
2729 if (NT_STATUS_IS_OK(status)) {
2730 size = fsp->fsp_name->st.st_ex_size;
2733 if (startpos >= size) {
2736 nread = MIN(maxcount,(size - startpos));
2739 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2740 if (nread < mincount)
2744 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
2745 "min=%lu nread=%lu\n",
2746 fsp_fnum_dbg(fsp), (double)startpos,
2747 (unsigned long)maxcount,
2748 (unsigned long)mincount,
2749 (unsigned long)nread ) );
2751 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
2753 DEBUG(5,("reply_readbraw finished\n"));
2755 END_PROFILE(SMBreadbraw);
2760 #define DBGC_CLASS DBGC_LOCKING
2762 /****************************************************************************
2763 Reply to a lockread (core+ protocol).
2764 ****************************************************************************/
2766 static void reply_lockread_locked(struct tevent_req *subreq);
2768 void reply_lockread(struct smb_request *req)
2770 struct tevent_req *subreq = NULL;
2771 connection_struct *conn = req->conn;
2773 struct smbd_lock_element *lck = NULL;
2775 START_PROFILE(SMBlockread);
2778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2779 END_PROFILE(SMBlockread);
2783 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2785 if (!check_fsp(conn, req, fsp)) {
2786 END_PROFILE(SMBlockread);
2790 if (!CHECK_READ(fsp,req)) {
2791 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2792 END_PROFILE(SMBlockread);
2796 lck = talloc(req, struct smbd_lock_element);
2798 reply_nterror(req, NT_STATUS_NO_MEMORY);
2799 END_PROFILE(SMBlockread);
2804 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2805 * protocol request that predates the read/write lock concept.
2806 * Thus instead of asking for a read lock here we need to ask
2807 * for a write lock. JRA.
2808 * Note that the requested lock size is unaffected by max_send.
2811 *lck = (struct smbd_lock_element) {
2812 .req_guid = smbd_request_guid(req, 0),
2813 .smblctx = req->smbpid,
2814 .brltype = WRITE_LOCK,
2815 .lock_flav = WINDOWS_LOCK,
2816 .count = SVAL(req->vwv+1, 0),
2817 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
2820 subreq = smbd_smb1_do_locks_send(
2826 false, /* large_offset */
2829 if (subreq == NULL) {
2830 reply_nterror(req, NT_STATUS_NO_MEMORY);
2831 END_PROFILE(SMBlockread);
2834 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
2835 END_PROFILE(SMBlockread);
2838 static void reply_lockread_locked(struct tevent_req *subreq)
2840 struct smb_request *req = NULL;
2846 size_t numtoread, maxtoread;
2847 struct files_struct *fsp = NULL;
2850 START_PROFILE(SMBlockread);
2852 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
2855 status = smbd_smb1_do_locks_recv(subreq);
2856 TALLOC_FREE(subreq);
2858 if (!NT_STATUS_IS_OK(status)) {
2859 reply_nterror(req, status);
2863 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2865 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
2869 numtoread = SVAL(req->vwv+1, 0);
2870 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2873 * However the requested READ size IS affected by max_send. Insanity.... JRA.
2875 maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
2877 if (numtoread > maxtoread) {
2878 DBG_WARNING("requested read size (%zu) is greater than "
2879 "maximum allowed (%zu/%d). "
2880 "Returning short read of maximum allowed for "
2881 "compatibility with Windows 2000.\n",
2884 req->xconn->smb1.sessions.max_send);
2885 numtoread = maxtoread;
2888 reply_smb1_outbuf(req, 5, numtoread + 3);
2890 data = smb_buf(req->outbuf) + 3;
2892 nread = read_file(fsp,data,startpos,numtoread);
2895 reply_nterror(req, map_nt_error_from_unix(errno));
2899 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
2901 SSVAL(req->outbuf,smb_vwv0,nread);
2902 SSVAL(req->outbuf,smb_vwv5,nread+3);
2903 p = smb_buf(req->outbuf);
2904 SCVAL(p,0,0); /* pad byte. */
2907 DEBUG(3,("lockread %s num=%d nread=%d\n",
2908 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
2911 ok = smb1_srv_send(req->xconn,
2912 (char *)req->outbuf,
2915 IS_CONN_ENCRYPTED(req->conn),
2918 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
2921 END_PROFILE(SMBlockread);
2926 #define DBGC_CLASS DBGC_ALL
2928 /****************************************************************************
2930 ****************************************************************************/
2932 void reply_read(struct smb_request *req)
2934 connection_struct *conn = req->conn;
2941 struct lock_struct lock;
2942 struct smbXsrv_connection *xconn = req->xconn;
2944 START_PROFILE(SMBread);
2947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2948 END_PROFILE(SMBread);
2952 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2954 if (!check_fsp(conn, req, fsp)) {
2955 END_PROFILE(SMBread);
2959 if (!CHECK_READ(fsp,req)) {
2960 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2961 END_PROFILE(SMBread);
2965 numtoread = SVAL(req->vwv+1, 0);
2966 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2969 * The requested read size cannot be greater than max_send. JRA.
2971 maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
2973 if (numtoread > maxtoread) {
2974 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
2975 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2976 (unsigned int)numtoread, (unsigned int)maxtoread,
2977 (unsigned int)xconn->smb1.sessions.max_send));
2978 numtoread = maxtoread;
2981 reply_smb1_outbuf(req, 5, numtoread+3);
2983 data = smb_buf(req->outbuf) + 3;
2985 init_strict_lock_struct(fsp,
2986 (uint64_t)req->smbpid,
2988 (uint64_t)numtoread,
2990 lp_posix_cifsu_locktype(fsp),
2993 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
2994 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
2995 END_PROFILE(SMBread);
3000 nread = read_file(fsp,data,startpos,numtoread);
3003 reply_nterror(req, map_nt_error_from_unix(errno));
3007 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3009 SSVAL(req->outbuf,smb_vwv0,nread);
3010 SSVAL(req->outbuf,smb_vwv5,nread+3);
3011 SCVAL(smb_buf(req->outbuf),0,1);
3012 SSVAL(smb_buf(req->outbuf),1,nread);
3014 DEBUG(3, ("read %s num=%d nread=%d\n",
3015 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3018 END_PROFILE(SMBread);
3022 /****************************************************************************
3024 ****************************************************************************/
3026 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3030 outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3033 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3035 SCVAL(outbuf,smb_vwv0,0xFF);
3036 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3037 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3038 SSVAL(outbuf,smb_vwv6,
3039 (smb_wct - 4) /* offset from smb header to wct */
3040 + 1 /* the wct field */
3041 + 12 * sizeof(uint16_t) /* vwv */
3042 + 2 /* the buflen field */
3043 + 1); /* padding byte */
3044 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3045 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3046 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3047 _smb_setlen_large(outbuf,
3048 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3052 /****************************************************************************
3053 Reply to a read and X - possibly using sendfile.
3054 ****************************************************************************/
3056 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3057 files_struct *fsp, off_t startpos,
3060 struct smbXsrv_connection *xconn = req->xconn;
3062 struct lock_struct lock;
3063 int saved_errno = 0;
3066 init_strict_lock_struct(fsp,
3067 (uint64_t)req->smbpid,
3069 (uint64_t)smb_maxcnt,
3071 lp_posix_cifsu_locktype(fsp),
3074 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3075 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3080 * We can only use sendfile on a non-chained packet
3081 * but we can use on a non-oplocked file. tridge proved this
3082 * on a train in Germany :-). JRA.
3085 if (!req_is_in_chain(req) &&
3087 !fsp_is_alternate_stream(fsp) &&
3088 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3089 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3092 status = vfs_stat_fsp(fsp);
3093 if (!NT_STATUS_IS_OK(status)) {
3094 reply_nterror(req, status);
3098 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3099 (startpos > fsp->fsp_name->st.st_ex_size) ||
3100 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3102 * We already know that we would do a short read, so don't
3103 * try the sendfile() path.
3105 goto nosendfile_read;
3109 * Set up the packet header before send. We
3110 * assume here the sendfile will work (get the
3111 * correct amount of data).
3114 header = data_blob_const(headerbuf, sizeof(headerbuf));
3116 construct_smb1_reply_common_req(req, (char *)headerbuf);
3117 setup_readX_header((char *)headerbuf, smb_maxcnt);
3119 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3120 startpos, smb_maxcnt);
3122 saved_errno = errno;
3124 /* Returning ENOSYS means no data at all was sent.
3125 Do this as a normal read. */
3126 if (errno == ENOSYS) {
3131 * Special hack for broken Linux with no working sendfile. If we
3132 * return EINTR we sent the header but not the rest of the data.
3133 * Fake this up by doing read/write calls.
3136 if (errno == EINTR) {
3137 /* Ensure we don't do this again. */
3138 set_use_sendfile(SNUM(conn), False);
3139 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3140 nread = fake_sendfile(xconn, fsp, startpos,
3143 saved_errno = errno;
3144 DEBUG(0,("send_file_readX: "
3145 "fake_sendfile failed for "
3146 "file %s (%s) for client %s. "
3149 smbXsrv_connection_dbg(xconn),
3150 strerror(saved_errno)));
3151 errno = saved_errno;
3152 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3154 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3155 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3156 /* No outbuf here means successful sendfile. */
3160 DEBUG(0,("send_file_readX: sendfile failed for file "
3161 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3163 exit_server_cleanly("send_file_readX sendfile failed");
3164 } else if (nread == 0) {
3166 * Some sendfile implementations return 0 to indicate
3167 * that there was a short read, but nothing was
3168 * actually written to the socket. In this case,
3169 * fallback to the normal read path so the header gets
3170 * the correct byte count.
3172 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3173 "falling back to the normal read: %s\n",
3178 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3179 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3181 /* Deal with possible short send. */
3182 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3185 ret = sendfile_short_send(xconn, fsp, nread,
3186 sizeof(headerbuf), smb_maxcnt);
3189 r = "send_file_readX: sendfile_short_send failed";
3190 DEBUG(0,("%s for file %s (%s).\n",
3191 r, fsp_str_dbg(fsp), strerror(errno)));
3192 exit_server_cleanly(r);
3195 /* No outbuf here means successful sendfile. */
3196 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3197 SMB_PERFCOUNT_END(&req->pcd);
3203 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3204 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3207 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3208 (startpos > fsp->fsp_name->st.st_ex_size) ||
3209 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3211 * We already know that we would do a short
3212 * read, so don't try the sendfile() path.
3214 goto nosendfile_read;
3217 construct_smb1_reply_common_req(req, (char *)headerbuf);
3218 setup_readX_header((char *)headerbuf, smb_maxcnt);
3220 /* Send out the header. */
3221 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3223 if (ret != sizeof(headerbuf)) {
3224 saved_errno = errno;
3226 * Try and give an error message saying what
3229 DEBUG(0,("send_file_readX: write_data failed for file "
3230 "%s (%s) for client %s. Terminating\n",
3232 smbXsrv_connection_dbg(xconn),
3233 strerror(saved_errno)));
3234 errno = saved_errno;
3235 exit_server_cleanly("send_file_readX sendfile failed");
3237 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3239 saved_errno = errno;
3240 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3241 "%s (%s) for client %s. Terminating\n",
3243 smbXsrv_connection_dbg(xconn),
3244 strerror(saved_errno)));
3245 errno = saved_errno;
3246 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3253 reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3254 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3255 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3257 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3258 startpos, smb_maxcnt);
3259 saved_errno = errno;
3262 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3266 setup_readX_header((char *)req->outbuf, nread);
3268 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3269 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3273 TALLOC_FREE(req->outbuf);
3277 /****************************************************************************
3278 Work out how much space we have for a read return.
3279 ****************************************************************************/
3281 static size_t calc_max_read_pdu(const struct smb_request *req)
3283 struct smbXsrv_connection *xconn = req->xconn;
3285 if (xconn->protocol < PROTOCOL_NT1) {
3286 return xconn->smb1.sessions.max_send;
3289 if (!lp_large_readwrite()) {
3290 return xconn->smb1.sessions.max_send;
3293 if (req_is_in_chain(req)) {
3294 return xconn->smb1.sessions.max_send;
3297 if (req->encrypted) {
3299 * Don't take encrypted traffic up to the
3300 * limit. There are padding considerations
3301 * that make that tricky.
3303 return xconn->smb1.sessions.max_send;
3306 if (smb1_srv_is_signing_active(xconn)) {
3310 if (!lp_smb1_unix_extensions()) {
3315 * We can do ultra-large POSIX reads.
3320 /****************************************************************************
3321 Calculate how big a read can be. Copes with all clients. It's always
3322 safe to return a short read - Windows does this.
3323 ****************************************************************************/
3325 static size_t calc_read_size(const struct smb_request *req,
3329 struct smbXsrv_connection *xconn = req->xconn;
3330 size_t max_pdu = calc_max_read_pdu(req);
3331 size_t total_size = 0;
3332 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3333 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3336 * Windows explicitly ignores upper size of 0xFFFF.
3337 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3338 * We must do the same as these will never fit even in
3339 * an extended size NetBIOS packet.
3341 if (upper_size == 0xFFFF) {
3345 if (xconn->protocol < PROTOCOL_NT1) {
3349 total_size = ((upper_size<<16) | lower_size);
3352 * LARGE_READX test shows it's always safe to return
3353 * a short read. Windows does so.
3355 return MIN(total_size, max_len);
3358 /****************************************************************************
3359 Reply to a read and X.
3360 ****************************************************************************/
3362 void reply_read_and_X(struct smb_request *req)
3364 connection_struct *conn = req->conn;
3369 bool big_readX = False;
3371 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3374 START_PROFILE(SMBreadX);
3376 if ((req->wct != 10) && (req->wct != 12)) {
3377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3381 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3382 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3383 smb_maxcnt = SVAL(req->vwv+5, 0);
3385 /* If it's an IPC, pass off the pipe handler. */
3387 reply_pipe_read_and_X(req);
3388 END_PROFILE(SMBreadX);
3392 if (!check_fsp(conn, req, fsp)) {
3393 END_PROFILE(SMBreadX);
3397 if (!CHECK_READ(fsp,req)) {
3398 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3399 END_PROFILE(SMBreadX);
3403 upper_size = SVAL(req->vwv+7, 0);
3404 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3405 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3407 * This is a heuristic to avoid keeping large
3408 * outgoing buffers around over long-lived aio
3414 if (req->wct == 12) {
3416 * This is a large offset (64 bit) read.
3418 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3423 NTSTATUS status = schedule_aio_read_and_X(conn,
3428 if (NT_STATUS_IS_OK(status)) {
3429 /* Read scheduled - we're done. */
3432 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3433 /* Real error - report to client. */
3434 END_PROFILE(SMBreadX);
3435 reply_nterror(req, status);
3438 /* NT_STATUS_RETRY - fall back to sync read. */
3441 smbd_lock_socket(req->xconn);
3442 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3443 smbd_unlock_socket(req->xconn);
3446 END_PROFILE(SMBreadX);
3450 /****************************************************************************
3451 Error replies to writebraw must have smb_wct == 1. Fix this up.
3452 ****************************************************************************/
3454 void error_to_writebrawerr(struct smb_request *req)
3456 uint8_t *old_outbuf = req->outbuf;
3458 reply_smb1_outbuf(req, 1, 0);
3460 memcpy(req->outbuf, old_outbuf, smb_size);
3461 TALLOC_FREE(old_outbuf);
3464 /****************************************************************************
3465 Read 4 bytes of a smb packet and return the smb length of the packet.
3466 Store the result in the buffer. This version of the function will
3467 never return a session keepalive (length of zero).
3468 Timeout is in milliseconds.
3469 ****************************************************************************/
3471 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3474 uint8_t msgtype = NBSSkeepalive;
3476 while (msgtype == NBSSkeepalive) {
3479 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3481 if (!NT_STATUS_IS_OK(status)) {
3482 char addr[INET6_ADDRSTRLEN];
3483 /* Try and give an error message
3484 * saying what client failed. */
3485 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3486 "client %s read error = %s.\n",
3487 get_peer_addr(fd,addr,sizeof(addr)),
3488 nt_errstr(status)));
3492 msgtype = CVAL(inbuf, 0);
3495 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3496 (unsigned long)len));
3498 return NT_STATUS_OK;
3501 /****************************************************************************
3502 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3503 ****************************************************************************/
3505 void reply_writebraw(struct smb_request *req)
3507 connection_struct *conn = req->conn;
3508 struct smbXsrv_connection *xconn = req->xconn;
3511 ssize_t total_written=0;
3512 size_t numtowrite=0;
3515 const char *data=NULL;
3518 struct lock_struct lock;
3521 START_PROFILE(SMBwritebraw);
3524 * If we ever reply with an error, it must have the SMB command
3525 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3528 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3530 if (smb1_srv_is_signing_active(xconn)) {
3531 END_PROFILE(SMBwritebraw);
3532 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3533 "raw reads/writes are disallowed.");
3536 if (req->wct < 12) {
3537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3538 error_to_writebrawerr(req);
3539 END_PROFILE(SMBwritebraw);
3543 if (xconn->smb1.echo_handler.trusted_fde) {
3544 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3545 "'async smb echo handler = yes'\n"));
3546 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3547 error_to_writebrawerr(req);
3548 END_PROFILE(SMBwritebraw);
3552 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3553 if (!check_fsp(conn, req, fsp)) {
3554 error_to_writebrawerr(req);
3555 END_PROFILE(SMBwritebraw);
3559 if (!CHECK_WRITE(fsp)) {
3560 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3561 error_to_writebrawerr(req);
3562 END_PROFILE(SMBwritebraw);
3566 tcount = IVAL(req->vwv+1, 0);
3567 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3568 write_through = BITSETW(req->vwv+7,0);
3570 /* We have to deal with slightly different formats depending
3571 on whether we are using the core+ or lanman1.0 protocol */
3573 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3574 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3575 data = smb_buf_const(req->inbuf);
3577 numtowrite = SVAL(req->vwv+10, 0);
3578 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3581 /* Ensure we don't write bytes past the end of this packet. */
3583 * This already protects us against CVE-2017-12163.
3585 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3587 error_to_writebrawerr(req);
3588 END_PROFILE(SMBwritebraw);
3592 if (!fsp->print_file) {
3593 init_strict_lock_struct(fsp,
3594 (uint64_t)req->smbpid,
3598 lp_posix_cifsu_locktype(fsp),
3601 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3602 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3603 error_to_writebrawerr(req);
3604 END_PROFILE(SMBwritebraw);
3610 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3613 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3614 "wrote=%d sync=%d\n",
3615 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3616 (int)nwritten, (int)write_through));
3618 if (nwritten < (ssize_t)numtowrite) {
3619 reply_nterror(req, NT_STATUS_DISK_FULL);
3620 error_to_writebrawerr(req);
3624 total_written = nwritten;
3626 /* Allocate a buffer of 64k + length. */
3627 buf = talloc_array(NULL, char, 65540);
3629 reply_nterror(req, NT_STATUS_NO_MEMORY);
3630 error_to_writebrawerr(req);
3634 /* Return a SMBwritebraw message to the redirector to tell
3635 * it to send more bytes */
3637 memcpy(buf, req->inbuf, smb_size);
3638 srv_smb1_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3639 SCVAL(buf,smb_com,SMBwritebraw);
3640 SSVALS(buf,smb_vwv0,0xFFFF);
3642 if (!smb1_srv_send(req->xconn,
3644 false, 0, /* no signing */
3645 IS_CONN_ENCRYPTED(conn),
3647 exit_server_cleanly("reply_writebraw: smb1_srv_send "
3651 /* Now read the raw data into the buffer and write it */
3652 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
3654 if (!NT_STATUS_IS_OK(status)) {
3655 exit_server_cleanly("secondary writebraw failed");
3658 /* Set up outbuf to return the correct size */
3659 reply_smb1_outbuf(req, 1, 0);
3661 if (numtowrite != 0) {
3663 if (numtowrite > 0xFFFF) {
3664 DEBUG(0,("reply_writebraw: Oversize secondary write "
3665 "raw requested (%u). Terminating\n",
3666 (unsigned int)numtowrite ));
3667 exit_server_cleanly("secondary writebraw failed");
3670 if (tcount > nwritten+numtowrite) {
3671 DEBUG(3,("reply_writebraw: Client overestimated the "
3673 (int)tcount,(int)nwritten,(int)numtowrite));
3676 status = read_data_ntstatus(xconn->transport.sock, buf+4,
3679 if (!NT_STATUS_IS_OK(status)) {
3680 /* Try and give an error message
3681 * saying what client failed. */
3682 DEBUG(0, ("reply_writebraw: Oversize secondary write "
3683 "raw read failed (%s) for client %s. "
3684 "Terminating\n", nt_errstr(status),
3685 smbXsrv_connection_dbg(xconn)));
3686 exit_server_cleanly("secondary writebraw failed");
3690 * We are not vulnerable to CVE-2017-12163
3691 * here as we are guaranteed to have numtowrite
3692 * bytes available - we just read from the client.
3694 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3695 if (nwritten == -1) {
3697 reply_nterror(req, map_nt_error_from_unix(errno));
3698 error_to_writebrawerr(req);
3702 if (nwritten < (ssize_t)numtowrite) {
3703 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3704 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3708 total_written += nwritten;
3713 SSVAL(req->outbuf,smb_vwv0,total_written);
3715 status = sync_file(conn, fsp, write_through);
3716 if (!NT_STATUS_IS_OK(status)) {
3717 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3718 fsp_str_dbg(fsp), nt_errstr(status)));
3719 reply_nterror(req, status);
3720 error_to_writebrawerr(req);
3724 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
3726 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3727 (int)total_written));
3729 /* We won't return a status if write through is not selected - this
3730 * follows what WfWg does */
3731 END_PROFILE(SMBwritebraw);
3733 if (!write_through && total_written==tcount) {
3735 #if RABBIT_PELLET_FIX
3737 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3738 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
3741 if (!send_keepalive(xconn->transport.sock)) {
3742 exit_server_cleanly("reply_writebraw: send of "
3743 "keepalive failed");
3746 TALLOC_FREE(req->outbuf);
3751 END_PROFILE(SMBwritebraw);
3756 #define DBGC_CLASS DBGC_LOCKING
3758 /****************************************************************************
3759 Reply to a writeunlock (core+).
3760 ****************************************************************************/
3762 void reply_writeunlock(struct smb_request *req)
3764 connection_struct *conn = req->conn;
3765 ssize_t nwritten = -1;
3770 NTSTATUS status = NT_STATUS_OK;
3772 struct lock_struct lock;
3773 int saved_errno = 0;
3775 START_PROFILE(SMBwriteunlock);
3778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3779 END_PROFILE(SMBwriteunlock);
3783 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3785 if (!check_fsp(conn, req, fsp)) {
3786 END_PROFILE(SMBwriteunlock);
3790 if (!CHECK_WRITE(fsp)) {
3791 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3792 END_PROFILE(SMBwriteunlock);
3796 numtowrite = SVAL(req->vwv+1, 0);
3797 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3798 data = (const char *)req->buf + 3;
3801 * Ensure client isn't asking us to write more than
3802 * they sent. CVE-2017-12163.
3804 remaining = smbreq_bufrem(req, data);
3805 if (numtowrite > remaining) {
3806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3807 END_PROFILE(SMBwriteunlock);
3811 if (!fsp->print_file && numtowrite > 0) {
3812 init_strict_lock_struct(fsp,
3813 (uint64_t)req->smbpid,
3815 (uint64_t)numtowrite,
3817 lp_posix_cifsu_locktype(fsp),
3820 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3821 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3822 END_PROFILE(SMBwriteunlock);
3827 /* The special X/Open SMB protocol handling of
3828 zero length writes is *NOT* done for
3830 if(numtowrite == 0) {
3833 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3834 saved_errno = errno;
3837 status = sync_file(conn, fsp, False /* write through */);
3838 if (!NT_STATUS_IS_OK(status)) {
3839 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3840 fsp_str_dbg(fsp), nt_errstr(status)));
3841 reply_nterror(req, status);
3846 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3850 if((nwritten < numtowrite) && (numtowrite != 0)) {
3851 reply_nterror(req, NT_STATUS_DISK_FULL);
3855 if (numtowrite && !fsp->print_file) {
3856 struct smbd_lock_element l = {
3857 .req_guid = smbd_request_guid(req, 0),
3858 .smblctx = req->smbpid,
3859 .brltype = UNLOCK_LOCK,
3860 .lock_flav = WINDOWS_LOCK,
3862 .count = numtowrite,
3864 status = smbd_do_unlocking(req, fsp, 1, &l);
3865 if (NT_STATUS_V(status)) {
3866 reply_nterror(req, status);
3871 reply_smb1_outbuf(req, 1, 0);
3873 SSVAL(req->outbuf,smb_vwv0,nwritten);
3875 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
3876 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
3879 END_PROFILE(SMBwriteunlock);
3884 #define DBGC_CLASS DBGC_ALL
3886 /****************************************************************************
3888 ****************************************************************************/
3890 void reply_write(struct smb_request *req)
3892 connection_struct *conn = req->conn;
3895 ssize_t nwritten = -1;
3899 struct lock_struct lock;
3901 int saved_errno = 0;
3903 START_PROFILE(SMBwrite);
3906 END_PROFILE(SMBwrite);
3907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3911 /* If it's an IPC, pass off the pipe handler. */
3913 reply_pipe_write(req);
3914 END_PROFILE(SMBwrite);
3918 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3920 if (!check_fsp(conn, req, fsp)) {
3921 END_PROFILE(SMBwrite);
3925 if (!CHECK_WRITE(fsp)) {
3926 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3927 END_PROFILE(SMBwrite);
3931 numtowrite = SVAL(req->vwv+1, 0);
3932 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3933 data = (const char *)req->buf + 3;
3936 * Ensure client isn't asking us to write more than
3937 * they sent. CVE-2017-12163.
3939 remaining = smbreq_bufrem(req, data);
3940 if (numtowrite > remaining) {
3941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3942 END_PROFILE(SMBwrite);
3946 if (!fsp->print_file) {
3947 init_strict_lock_struct(fsp,
3948 (uint64_t)req->smbpid,
3950 (uint64_t)numtowrite,
3952 lp_posix_cifsu_locktype(fsp),
3955 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3956 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3957 END_PROFILE(SMBwrite);
3963 * X/Open SMB protocol says that if smb_vwv1 is
3964 * zero then the file size should be extended or
3965 * truncated to the size given in smb_vwv[2-3].
3968 if(numtowrite == 0) {
3970 * This is actually an allocate call, and set EOF. JRA.
3972 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
3974 reply_nterror(req, NT_STATUS_DISK_FULL);
3977 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
3979 reply_nterror(req, NT_STATUS_DISK_FULL);
3982 trigger_write_time_update_immediate(fsp);
3984 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3987 status = sync_file(conn, fsp, False);
3988 if (!NT_STATUS_IS_OK(status)) {
3989 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3990 fsp_str_dbg(fsp), nt_errstr(status)));
3991 reply_nterror(req, status);
3996 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4000 if((nwritten == 0) && (numtowrite != 0)) {
4001 reply_nterror(req, NT_STATUS_DISK_FULL);
4005 reply_smb1_outbuf(req, 1, 0);
4007 SSVAL(req->outbuf,smb_vwv0,nwritten);
4009 if (nwritten < (ssize_t)numtowrite) {
4010 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4011 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4014 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4017 END_PROFILE(SMBwrite);
4021 /****************************************************************************
4022 Ensure a buffer is a valid writeX for recvfile purposes.
4023 ****************************************************************************/
4025 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4026 (2*14) + /* word count (including bcc) */ \
4029 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4030 const uint8_t *inbuf)
4033 unsigned int doff = 0;
4034 size_t len = smb_len_large(inbuf);
4036 struct smbXsrv_open *op = NULL;
4037 struct files_struct *fsp = NULL;
4040 if (is_encrypted_packet(inbuf)) {
4041 /* Can't do this on encrypted
4046 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4050 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4051 CVAL(inbuf,smb_wct) != 14) {
4052 DEBUG(10,("is_valid_writeX_buffer: chained or "
4053 "invalid word length.\n"));
4057 fnum = SVAL(inbuf, smb_vwv2);
4058 status = smb1srv_open_lookup(xconn,
4062 if (!NT_STATUS_IS_OK(status)) {
4063 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4068 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4071 if (fsp->conn == NULL) {
4072 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4076 if (IS_IPC(fsp->conn)) {
4077 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4080 if (IS_PRINT(fsp->conn)) {
4081 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4084 if (fsp_is_alternate_stream(fsp)) {
4085 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4088 doff = SVAL(inbuf,smb_vwv11);
4090 numtowrite = SVAL(inbuf,smb_vwv10);
4092 if (len > doff && len - doff > 0xFFFF) {
4093 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4096 if (numtowrite == 0) {
4097 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4101 /* Ensure the sizes match up. */
4102 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4103 /* no pad byte...old smbclient :-( */
4104 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4106 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4110 if (len - doff != numtowrite) {
4111 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4112 "len = %u, doff = %u, numtowrite = %u\n",
4115 (unsigned int)numtowrite ));
4119 DEBUG(10,("is_valid_writeX_buffer: true "
4120 "len = %u, doff = %u, numtowrite = %u\n",
4123 (unsigned int)numtowrite ));
4128 /****************************************************************************
4129 Reply to a write and X.
4130 ****************************************************************************/
4132 void reply_write_and_X(struct smb_request *req)
4134 connection_struct *conn = req->conn;
4135 struct smbXsrv_connection *xconn = req->xconn;
4137 struct lock_struct lock;
4142 unsigned int smb_doff;
4143 unsigned int smblen;
4146 int saved_errno = 0;
4148 START_PROFILE(SMBwriteX);
4150 if ((req->wct != 12) && (req->wct != 14)) {
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4155 numtowrite = SVAL(req->vwv+10, 0);
4156 smb_doff = SVAL(req->vwv+11, 0);
4157 smblen = smb_len(req->inbuf);
4159 if (req->unread_bytes > 0xFFFF ||
4160 (smblen > smb_doff &&
4161 smblen - smb_doff > 0xFFFF)) {
4162 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4165 if (req->unread_bytes) {
4166 /* Can't do a recvfile write on IPC$ */
4168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4171 if (numtowrite != req->unread_bytes) {
4172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4177 * This already protects us against CVE-2017-12163.
4179 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4180 smb_doff + numtowrite > smblen) {
4181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4186 /* If it's an IPC, pass off the pipe handler. */
4188 if (req->unread_bytes) {
4189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4192 reply_pipe_write_and_X(req);
4196 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4197 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4198 write_through = BITSETW(req->vwv+7,0);
4200 if (!check_fsp(conn, req, fsp)) {
4204 if (!CHECK_WRITE(fsp)) {
4205 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4209 data = smb_base(req->inbuf) + smb_doff;
4211 if(req->wct == 14) {
4213 * This is a large offset (64 bit) write.
4215 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4219 /* X/Open SMB protocol says that, unlike SMBwrite
4220 if the length is zero then NO truncation is
4221 done, just a write of zero. To truncate a file,
4224 if(numtowrite == 0) {
4227 if (req->unread_bytes == 0) {
4228 status = schedule_aio_write_and_X(conn,
4235 if (NT_STATUS_IS_OK(status)) {
4236 /* write scheduled - we're done. */
4239 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4240 /* Real error - report to client. */
4241 reply_nterror(req, status);
4244 /* NT_STATUS_RETRY - fall through to sync write. */
4247 init_strict_lock_struct(fsp,
4248 (uint64_t)req->smbpid,
4250 (uint64_t)numtowrite,
4252 lp_posix_cifsu_locktype(fsp),
4255 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4256 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4260 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4261 saved_errno = errno;
4265 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4269 if((nwritten == 0) && (numtowrite != 0)) {
4270 reply_nterror(req, NT_STATUS_DISK_FULL);
4274 reply_smb1_outbuf(req, 6, 0);
4275 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4276 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4277 SSVAL(req->outbuf,smb_vwv2,nwritten);
4278 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4280 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4281 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4283 status = sync_file(conn, fsp, write_through);
4284 if (!NT_STATUS_IS_OK(status)) {
4285 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4286 fsp_str_dbg(fsp), nt_errstr(status)));
4287 reply_nterror(req, status);
4291 END_PROFILE(SMBwriteX);
4295 if (req->unread_bytes) {
4296 /* writeX failed. drain socket. */
4297 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4298 req->unread_bytes) {
4299 smb_panic("failed to drain pending bytes");
4301 req->unread_bytes = 0;
4304 END_PROFILE(SMBwriteX);
4308 /****************************************************************************
4310 ****************************************************************************/
4312 void reply_lseek(struct smb_request *req)
4314 connection_struct *conn = req->conn;
4321 START_PROFILE(SMBlseek);
4324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4325 END_PROFILE(SMBlseek);
4329 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4331 if (!check_fsp(conn, req, fsp)) {
4335 mode = SVAL(req->vwv+1, 0) & 3;
4336 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4337 startpos = (off_t)IVALS(req->vwv+2, 0);
4346 res = fh_get_pos(fsp->fh) + startpos;
4357 if (umode == SEEK_END) {
4358 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4359 if(errno == EINVAL) {
4360 off_t current_pos = startpos;
4362 status = vfs_stat_fsp(fsp);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 reply_nterror(req, status);
4365 END_PROFILE(SMBlseek);
4369 current_pos += fsp->fsp_name->st.st_ex_size;
4371 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4376 reply_nterror(req, map_nt_error_from_unix(errno));
4377 END_PROFILE(SMBlseek);
4382 fh_set_pos(fsp->fh, res);
4384 reply_smb1_outbuf(req, 2, 0);
4385 SIVAL(req->outbuf,smb_vwv0,res);
4387 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4388 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4390 END_PROFILE(SMBlseek);
4394 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4397 connection_struct *conn = talloc_get_type_abort(
4398 private_data, connection_struct);
4400 if (conn != fsp->conn) {
4403 if (fsp_get_io_fd(fsp) == -1) {
4406 sync_file(conn, fsp, True /* write through */);
4408 if (fsp->fsp_flags.modified) {
4409 trigger_write_time_update_immediate(fsp);
4415 /****************************************************************************
4417 ****************************************************************************/
4419 void reply_flush(struct smb_request *req)
4421 connection_struct *conn = req->conn;
4425 START_PROFILE(SMBflush);
4428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4432 fnum = SVAL(req->vwv+0, 0);
4433 fsp = file_fsp(req, fnum);
4435 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4440 files_forall(req->sconn, file_sync_one_fn, conn);
4442 NTSTATUS status = sync_file(conn, fsp, True);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4445 fsp_str_dbg(fsp), nt_errstr(status)));
4446 reply_nterror(req, status);
4447 END_PROFILE(SMBflush);
4450 if (fsp->fsp_flags.modified) {
4451 trigger_write_time_update_immediate(fsp);
4455 reply_smb1_outbuf(req, 0, 0);
4457 DEBUG(3,("flush\n"));
4458 END_PROFILE(SMBflush);
4462 /****************************************************************************
4464 conn POINTER CAN BE NULL HERE !
4465 ****************************************************************************/
4467 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4468 static void reply_exit_done(struct tevent_req *req);
4470 void reply_exit(struct smb_request *smb1req)
4472 struct tevent_req *req;
4475 * Don't setup the profile charge here, take
4476 * it in reply_exit_done(). Not strictly correct
4477 * but better than the other SMB1 async
4478 * code that double-charges at the moment.
4480 req = reply_exit_send(smb1req);
4482 /* Not going async, profile here. */
4483 START_PROFILE(SMBexit);
4484 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4485 END_PROFILE(SMBexit);
4489 /* We're async. This will complete later. */
4490 tevent_req_set_callback(req, reply_exit_done, smb1req);
4494 struct reply_exit_state {
4495 struct tevent_queue *wait_queue;
4498 static void reply_exit_wait_done(struct tevent_req *subreq);
4500 /****************************************************************************
4502 Note, on failure here we deallocate and return NULL to allow the caller to
4503 SMB1 return an error of ERRnomem immediately.
4504 ****************************************************************************/
4506 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4508 struct tevent_req *req;
4509 struct reply_exit_state *state;
4510 struct tevent_req *subreq;
4512 struct smbd_server_connection *sconn = smb1req->sconn;
4514 req = tevent_req_create(smb1req, &state,
4515 struct reply_exit_state);
4519 state->wait_queue = tevent_queue_create(state,
4520 "reply_exit_wait_queue");
4521 if (tevent_req_nomem(state->wait_queue, req)) {
4526 for (fsp = sconn->files; fsp; fsp = fsp->next) {
4527 if (fsp->file_pid != smb1req->smbpid) {
4530 if (fsp->vuid != smb1req->vuid) {
4534 * Flag the file as close in progress.
4535 * This will prevent any more IO being
4538 fsp->fsp_flags.closing = true;
4540 if (fsp->num_aio_requests > 0) {
4542 * Now wait until all aio requests on this fsp are
4545 * We don't set a callback, as we just want to block the
4546 * wait queue and the talloc_free() of fsp->aio_request
4547 * will remove the item from the wait queue.
4549 subreq = tevent_queue_wait_send(fsp->aio_requests,
4552 if (tevent_req_nomem(subreq, req)) {
4560 * Now we add our own waiter to the end of the queue,
4561 * this way we get notified when all pending requests are finished
4562 * and reply to the outstanding SMB1 request.
4564 subreq = tevent_queue_wait_send(state,
4567 if (tevent_req_nomem(subreq, req)) {
4573 * We're really going async - move the SMB1 request from
4574 * a talloc stackframe above us to the conn talloc-context.
4575 * We need this to stick around until the wait_done
4576 * callback is invoked.
4578 smb1req = talloc_move(sconn, &smb1req);
4580 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4585 static void reply_exit_wait_done(struct tevent_req *subreq)
4587 struct tevent_req *req = tevent_req_callback_data(
4588 subreq, struct tevent_req);
4590 tevent_queue_wait_recv(subreq);
4591 TALLOC_FREE(subreq);
4592 tevent_req_done(req);
4595 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4597 return tevent_req_simple_recv_ntstatus(req);
4600 static void reply_exit_done(struct tevent_req *req)
4602 struct smb_request *smb1req = tevent_req_callback_data(
4603 req, struct smb_request);
4604 struct smbd_server_connection *sconn = smb1req->sconn;
4605 struct smbXsrv_connection *xconn = smb1req->xconn;
4606 NTTIME now = timeval_to_nttime(&smb1req->request_time);
4607 struct smbXsrv_session *session = NULL;
4608 files_struct *fsp, *next;
4612 * Take the profile charge here. Not strictly
4613 * correct but better than the other SMB1 async
4614 * code that double-charges at the moment.
4616 START_PROFILE(SMBexit);
4618 status = reply_exit_recv(req);
4620 if (!NT_STATUS_IS_OK(status)) {
4621 TALLOC_FREE(smb1req);
4622 END_PROFILE(SMBexit);
4623 exit_server(__location__ ": reply_exit_recv failed");
4628 * Ensure the session is still valid.
4630 status = smb1srv_session_lookup(xconn,
4634 if (!NT_STATUS_IS_OK(status)) {
4635 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4636 smb_request_done(smb1req);
4637 END_PROFILE(SMBexit);
4641 * Ensure the vuid is still valid - no one
4642 * called reply_ulogoffX() in the meantime.
4643 * reply_exit() doesn't have AS_USER set, so
4644 * use set_current_user_info() directly.
4645 * This is the same logic as in switch_message().
4647 if (session->global->auth_session_info != NULL) {
4648 set_current_user_info(
4649 session->global->auth_session_info->unix_info->sanitized_username,
4650 session->global->auth_session_info->unix_info->unix_name,
4651 session->global->auth_session_info->info->domain_name);
4654 /* No more aio - do the actual closes. */
4655 for (fsp = sconn->files; fsp; fsp = next) {
4659 if (fsp->file_pid != smb1req->smbpid) {
4662 if (fsp->vuid != smb1req->vuid) {
4665 if (!fsp->fsp_flags.closing) {
4670 * reply_exit() has the DO_CHDIR flag set.
4672 ok = chdir_current_service(fsp->conn);
4674 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4675 smb_request_done(smb1req);
4676 END_PROFILE(SMBexit);
4678 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
4681 reply_smb1_outbuf(smb1req, 0, 0);
4683 * The following call is needed to push the
4684 * reply data back out the socket after async
4685 * return. Plus it frees smb1req.
4687 smb_request_done(smb1req);
4688 DBG_INFO("reply_exit complete\n");
4689 END_PROFILE(SMBexit);
4693 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
4695 static void reply_close_done(struct tevent_req *req);
4697 void reply_close(struct smb_request *smb1req)
4699 connection_struct *conn = smb1req->conn;
4700 NTSTATUS status = NT_STATUS_OK;
4701 files_struct *fsp = NULL;
4702 START_PROFILE(SMBclose);
4704 if (smb1req->wct < 3) {
4705 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
4706 END_PROFILE(SMBclose);
4710 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
4713 * We can only use check_fsp if we know it's not a directory.
4716 if (!check_fsp_open(conn, smb1req, fsp)) {
4717 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
4718 END_PROFILE(SMBclose);
4722 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
4723 fsp->fsp_flags.is_directory ?
4724 "directory" : "file",
4725 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
4726 conn->num_files_open);
4728 if (!fsp->fsp_flags.is_directory) {
4732 * Take care of any time sent in the close.
4735 t = srv_make_unix_date3(smb1req->vwv+1);
4736 set_close_write_time(fsp, time_t_to_full_timespec(t));
4739 if (fsp->num_aio_requests != 0) {
4740 struct tevent_req *req;
4742 req = reply_close_send(smb1req, fsp);
4744 status = NT_STATUS_NO_MEMORY;
4747 /* We're async. This will complete later. */
4748 tevent_req_set_callback(req, reply_close_done, smb1req);
4749 END_PROFILE(SMBclose);
4754 * close_file_free() returns the unix errno if an error was detected on
4755 * close - normally this is due to a disk full error. If not then it
4756 * was probably an I/O error.
4759 status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
4761 if (!NT_STATUS_IS_OK(status)) {
4762 reply_nterror(smb1req, status);
4763 END_PROFILE(SMBclose);
4767 reply_smb1_outbuf(smb1req, 0, 0);
4768 END_PROFILE(SMBclose);
4772 struct reply_close_state {
4774 struct tevent_queue *wait_queue;
4777 static void reply_close_wait_done(struct tevent_req *subreq);
4779 /****************************************************************************
4781 Note, on failure here we deallocate and return NULL to allow the caller to
4782 SMB1 return an error of ERRnomem immediately.
4783 ****************************************************************************/
4785 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
4788 struct tevent_req *req;
4789 struct reply_close_state *state;
4790 struct tevent_req *subreq;
4791 struct smbd_server_connection *sconn = smb1req->sconn;
4793 req = tevent_req_create(smb1req, &state,
4794 struct reply_close_state);
4798 state->wait_queue = tevent_queue_create(state,
4799 "reply_close_wait_queue");
4800 if (tevent_req_nomem(state->wait_queue, req)) {
4806 * Flag the file as close in progress.
4807 * This will prevent any more IO being
4810 fsp->fsp_flags.closing = true;
4813 * Now wait until all aio requests on this fsp are
4816 * We don't set a callback, as we just want to block the
4817 * wait queue and the talloc_free() of fsp->aio_request
4818 * will remove the item from the wait queue.
4820 subreq = tevent_queue_wait_send(fsp->aio_requests,
4823 if (tevent_req_nomem(subreq, req)) {
4829 * Now we add our own waiter to the end of the queue,
4830 * this way we get notified when all pending requests are finished
4831 * and reply to the outstanding SMB1 request.
4833 subreq = tevent_queue_wait_send(state,
4836 if (tevent_req_nomem(subreq, req)) {
4842 * We're really going async - move the SMB1 request from
4843 * a talloc stackframe above us to the conn talloc-context.
4844 * We need this to stick around until the wait_done
4845 * callback is invoked.
4847 smb1req = talloc_move(sconn, &smb1req);
4849 tevent_req_set_callback(subreq, reply_close_wait_done, req);
4854 static void reply_close_wait_done(struct tevent_req *subreq)
4856 struct tevent_req *req = tevent_req_callback_data(
4857 subreq, struct tevent_req);
4859 tevent_queue_wait_recv(subreq);
4860 TALLOC_FREE(subreq);
4861 tevent_req_done(req);
4864 static NTSTATUS reply_close_recv(struct tevent_req *req)
4866 return tevent_req_simple_recv_ntstatus(req);
4869 static void reply_close_done(struct tevent_req *req)
4871 struct smb_request *smb1req = tevent_req_callback_data(
4872 req, struct smb_request);
4873 struct reply_close_state *state = tevent_req_data(req,
4874 struct reply_close_state);
4877 status = reply_close_recv(req);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 TALLOC_FREE(smb1req);
4881 exit_server(__location__ ": reply_close_recv failed");
4885 status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
4886 if (NT_STATUS_IS_OK(status)) {
4887 reply_smb1_outbuf(smb1req, 0, 0);
4889 reply_nterror(smb1req, status);
4892 * The following call is needed to push the
4893 * reply data back out the socket after async
4894 * return. Plus it frees smb1req.
4896 smb_request_done(smb1req);
4899 /****************************************************************************
4900 Reply to a writeclose (Core+ protocol).
4901 ****************************************************************************/
4903 void reply_writeclose(struct smb_request *req)
4905 connection_struct *conn = req->conn;
4908 ssize_t nwritten = -1;
4909 NTSTATUS close_status = NT_STATUS_OK;
4912 struct timespec mtime;
4914 struct lock_struct lock;
4916 START_PROFILE(SMBwriteclose);
4919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4920 END_PROFILE(SMBwriteclose);
4924 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4926 if (!check_fsp(conn, req, fsp)) {
4927 END_PROFILE(SMBwriteclose);
4930 if (!CHECK_WRITE(fsp)) {
4931 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4932 END_PROFILE(SMBwriteclose);
4936 numtowrite = SVAL(req->vwv+1, 0);
4937 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4938 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
4939 data = (const char *)req->buf + 1;
4942 * Ensure client isn't asking us to write more than
4943 * they sent. CVE-2017-12163.
4945 remaining = smbreq_bufrem(req, data);
4946 if (numtowrite > remaining) {
4947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4948 END_PROFILE(SMBwriteclose);
4952 if (fsp->print_file == NULL) {
4953 init_strict_lock_struct(fsp,
4954 (uint64_t)req->smbpid,
4956 (uint64_t)numtowrite,
4958 lp_posix_cifsu_locktype(fsp),
4961 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4962 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4963 END_PROFILE(SMBwriteclose);
4968 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4970 set_close_write_time(fsp, mtime);
4973 * More insanity. W2K only closes the file if writelen > 0.
4977 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
4978 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
4979 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
4982 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4983 "file %s\n", fsp_str_dbg(fsp)));
4984 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
4987 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4988 reply_nterror(req, NT_STATUS_DISK_FULL);
4992 if(!NT_STATUS_IS_OK(close_status)) {
4993 reply_nterror(req, close_status);
4997 reply_smb1_outbuf(req, 1, 0);
4999 SSVAL(req->outbuf,smb_vwv0,nwritten);
5003 END_PROFILE(SMBwriteclose);
5008 #define DBGC_CLASS DBGC_LOCKING
5010 /****************************************************************************
5012 ****************************************************************************/
5014 static void reply_lock_done(struct tevent_req *subreq);
5016 void reply_lock(struct smb_request *req)
5018 struct tevent_req *subreq = NULL;
5019 connection_struct *conn = req->conn;
5021 struct smbd_lock_element *lck = NULL;
5023 START_PROFILE(SMBlock);
5026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5027 END_PROFILE(SMBlock);
5031 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5033 if (!check_fsp(conn, req, fsp)) {
5034 END_PROFILE(SMBlock);
5038 lck = talloc(req, struct smbd_lock_element);
5040 reply_nterror(req, NT_STATUS_NO_MEMORY);
5041 END_PROFILE(SMBlock);
5045 *lck = (struct smbd_lock_element) {
5046 .req_guid = smbd_request_guid(req, 0),
5047 .smblctx = req->smbpid,
5048 .brltype = WRITE_LOCK,
5049 .lock_flav = WINDOWS_LOCK,
5050 .count = IVAL(req->vwv+1, 0),
5051 .offset = IVAL(req->vwv+3, 0),
5054 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5060 subreq = smbd_smb1_do_locks_send(
5066 false, /* large_offset */
5069 if (subreq == NULL) {
5070 reply_nterror(req, NT_STATUS_NO_MEMORY);
5071 END_PROFILE(SMBlock);
5074 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5075 END_PROFILE(SMBlock);
5078 static void reply_lock_done(struct tevent_req *subreq)
5080 struct smb_request *req = NULL;
5084 START_PROFILE(SMBlock);
5086 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5089 status = smbd_smb1_do_locks_recv(subreq);
5090 TALLOC_FREE(subreq);
5092 if (NT_STATUS_IS_OK(status)) {
5093 reply_smb1_outbuf(req, 0, 0);
5095 reply_nterror(req, status);
5098 ok = smb1_srv_send(req->xconn,
5099 (char *)req->outbuf,
5102 IS_CONN_ENCRYPTED(req->conn),
5105 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5108 END_PROFILE(SMBlock);
5111 /****************************************************************************
5113 ****************************************************************************/
5115 void reply_unlock(struct smb_request *req)
5117 connection_struct *conn = req->conn;
5120 struct smbd_lock_element lck;
5122 START_PROFILE(SMBunlock);
5125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5126 END_PROFILE(SMBunlock);
5130 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5132 if (!check_fsp(conn, req, fsp)) {
5133 END_PROFILE(SMBunlock);
5137 lck = (struct smbd_lock_element) {
5138 .req_guid = smbd_request_guid(req, 0),
5139 .smblctx = req->smbpid,
5140 .brltype = UNLOCK_LOCK,
5141 .lock_flav = WINDOWS_LOCK,
5142 .offset = IVAL(req->vwv+3, 0),
5143 .count = IVAL(req->vwv+1, 0),
5146 status = smbd_do_unlocking(req, fsp, 1, &lck);
5148 if (!NT_STATUS_IS_OK(status)) {
5149 reply_nterror(req, status);
5150 END_PROFILE(SMBunlock);
5154 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5160 reply_smb1_outbuf(req, 0, 0);
5162 END_PROFILE(SMBunlock);
5167 #define DBGC_CLASS DBGC_ALL
5169 /****************************************************************************
5171 conn POINTER CAN BE NULL HERE !
5172 ****************************************************************************/
5174 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5175 static void reply_tdis_done(struct tevent_req *req);
5177 void reply_tdis(struct smb_request *smb1req)
5179 connection_struct *conn = smb1req->conn;
5180 struct tevent_req *req;
5183 * Don't setup the profile charge here, take
5184 * it in reply_tdis_done(). Not strictly correct
5185 * but better than the other SMB1 async
5186 * code that double-charges at the moment.
5190 /* Not going async, profile here. */
5191 START_PROFILE(SMBtdis);
5192 DBG_INFO("Invalid connection in tdis\n");
5193 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5194 END_PROFILE(SMBtdis);
5198 req = reply_tdis_send(smb1req);
5200 /* Not going async, profile here. */
5201 START_PROFILE(SMBtdis);
5202 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5203 END_PROFILE(SMBtdis);
5206 /* We're async. This will complete later. */
5207 tevent_req_set_callback(req, reply_tdis_done, smb1req);
5211 struct reply_tdis_state {
5212 struct tevent_queue *wait_queue;
5215 static void reply_tdis_wait_done(struct tevent_req *subreq);
5217 /****************************************************************************
5219 Note, on failure here we deallocate and return NULL to allow the caller to
5220 SMB1 return an error of ERRnomem immediately.
5221 ****************************************************************************/
5223 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5225 struct tevent_req *req;
5226 struct reply_tdis_state *state;
5227 struct tevent_req *subreq;
5228 connection_struct *conn = smb1req->conn;
5231 req = tevent_req_create(smb1req, &state,
5232 struct reply_tdis_state);
5236 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5237 if (tevent_req_nomem(state->wait_queue, req)) {
5243 * Make sure that no new request will be able to use this tcon.
5244 * This ensures that once all outstanding fsp->aio_requests
5245 * on this tcon are done, we are safe to close it.
5247 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5249 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5250 if (fsp->conn != conn) {
5254 * Flag the file as close in progress.
5255 * This will prevent any more IO being
5256 * done on it. Not strictly needed, but
5257 * doesn't hurt to flag it as closing.
5259 fsp->fsp_flags.closing = true;
5261 if (fsp->num_aio_requests > 0) {
5263 * Now wait until all aio requests on this fsp are
5266 * We don't set a callback, as we just want to block the
5267 * wait queue and the talloc_free() of fsp->aio_request
5268 * will remove the item from the wait queue.
5270 subreq = tevent_queue_wait_send(fsp->aio_requests,
5271 conn->sconn->ev_ctx,
5273 if (tevent_req_nomem(subreq, req)) {
5281 * Now we add our own waiter to the end of the queue,
5282 * this way we get notified when all pending requests are finished
5283 * and reply to the outstanding SMB1 request.
5285 subreq = tevent_queue_wait_send(state,
5286 conn->sconn->ev_ctx,
5288 if (tevent_req_nomem(subreq, req)) {
5294 * We're really going async - move the SMB1 request from
5295 * a talloc stackframe above us to the sconn talloc-context.
5296 * We need this to stick around until the wait_done
5297 * callback is invoked.
5299 smb1req = talloc_move(smb1req->sconn, &smb1req);
5301 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5306 static void reply_tdis_wait_done(struct tevent_req *subreq)
5308 struct tevent_req *req = tevent_req_callback_data(
5309 subreq, struct tevent_req);
5311 tevent_queue_wait_recv(subreq);
5312 TALLOC_FREE(subreq);
5313 tevent_req_done(req);
5316 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5318 return tevent_req_simple_recv_ntstatus(req);
5321 static void reply_tdis_done(struct tevent_req *req)
5323 struct smb_request *smb1req = tevent_req_callback_data(
5324 req, struct smb_request);
5326 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5330 * Take the profile charge here. Not strictly
5331 * correct but better than the other SMB1 async
5332 * code that double-charges at the moment.
5334 START_PROFILE(SMBtdis);
5336 status = reply_tdis_recv(req);
5338 if (!NT_STATUS_IS_OK(status)) {
5339 TALLOC_FREE(smb1req);
5340 END_PROFILE(SMBtdis);
5341 exit_server(__location__ ": reply_tdis_recv failed");
5346 * As we've been awoken, we may have changed
5347 * directory in the meantime.
5348 * reply_tdis() has the DO_CHDIR flag set.
5350 ok = chdir_current_service(smb1req->conn);
5352 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5353 smb_request_done(smb1req);
5354 END_PROFILE(SMBtdis);
5357 status = smbXsrv_tcon_disconnect(tcon,
5359 if (!NT_STATUS_IS_OK(status)) {
5360 TALLOC_FREE(smb1req);
5361 END_PROFILE(SMBtdis);
5362 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5366 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5367 smb1req->conn = NULL;
5371 reply_smb1_outbuf(smb1req, 0, 0);
5373 * The following call is needed to push the
5374 * reply data back out the socket after async
5375 * return. Plus it frees smb1req.
5377 smb_request_done(smb1req);
5378 END_PROFILE(SMBtdis);
5381 /****************************************************************************
5383 conn POINTER CAN BE NULL HERE !
5384 ****************************************************************************/
5386 void reply_echo(struct smb_request *req)
5388 connection_struct *conn = req->conn;
5389 struct smb_perfcount_data local_pcd;
5390 struct smb_perfcount_data *cur_pcd;
5394 START_PROFILE(SMBecho);
5396 smb_init_perfcount_data(&local_pcd);
5399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5400 END_PROFILE(SMBecho);
5404 smb_reverb = SVAL(req->vwv+0, 0);
5406 reply_smb1_outbuf(req, 1, req->buflen);
5408 /* copy any incoming data back out */
5409 if (req->buflen > 0) {
5410 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5413 if (smb_reverb > 100) {
5414 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5418 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5420 /* this makes sure we catch the request pcd */
5421 if (seq_num == smb_reverb) {
5422 cur_pcd = &req->pcd;
5424 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5425 cur_pcd = &local_pcd;
5428 SSVAL(req->outbuf,smb_vwv0,seq_num);
5430 show_msg((char *)req->outbuf);
5431 if (!smb1_srv_send(req->xconn,
5432 (char *)req->outbuf,
5433 true, req->seqnum+1,
5434 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5436 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5439 DEBUG(3,("echo %d times\n", smb_reverb));
5441 TALLOC_FREE(req->outbuf);
5443 END_PROFILE(SMBecho);
5447 /****************************************************************************
5448 Reply to a printopen.
5449 ****************************************************************************/
5451 void reply_printopen(struct smb_request *req)
5453 connection_struct *conn = req->conn;
5457 START_PROFILE(SMBsplopen);
5460 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5461 END_PROFILE(SMBsplopen);
5465 if (!CAN_PRINT(conn)) {
5466 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5467 END_PROFILE(SMBsplopen);
5471 status = file_new(req, conn, &fsp);
5472 if(!NT_STATUS_IS_OK(status)) {
5473 reply_nterror(req, status);
5474 END_PROFILE(SMBsplopen);
5478 /* Open for exclusive use, write only. */
5479 status = print_spool_open(fsp, NULL, req->vuid);
5481 if (!NT_STATUS_IS_OK(status)) {
5482 file_free(req, fsp);
5483 reply_nterror(req, status);
5484 END_PROFILE(SMBsplopen);
5488 reply_smb1_outbuf(req, 1, 0);
5489 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5491 DEBUG(3,("openprint fd=%d %s\n",
5492 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5494 END_PROFILE(SMBsplopen);
5498 /****************************************************************************
5499 Reply to a printclose.
5500 ****************************************************************************/
5502 void reply_printclose(struct smb_request *req)
5504 connection_struct *conn = req->conn;
5508 START_PROFILE(SMBsplclose);
5511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5512 END_PROFILE(SMBsplclose);
5516 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5518 if (!check_fsp(conn, req, fsp)) {
5519 END_PROFILE(SMBsplclose);
5523 if (!CAN_PRINT(conn)) {
5524 reply_force_doserror(req, ERRSRV, ERRerror);
5525 END_PROFILE(SMBsplclose);
5529 DEBUG(3,("printclose fd=%d %s\n",
5530 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5532 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5534 if(!NT_STATUS_IS_OK(status)) {
5535 reply_nterror(req, status);
5536 END_PROFILE(SMBsplclose);
5540 reply_smb1_outbuf(req, 0, 0);
5542 END_PROFILE(SMBsplclose);
5546 /****************************************************************************
5547 Reply to a printqueue.
5548 ****************************************************************************/
5550 void reply_printqueue(struct smb_request *req)
5552 const struct loadparm_substitution *lp_sub =
5553 loadparm_s3_global_substitution();
5554 connection_struct *conn = req->conn;
5558 START_PROFILE(SMBsplretq);
5561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5562 END_PROFILE(SMBsplretq);
5566 max_count = SVAL(req->vwv+0, 0);
5567 start_index = SVAL(req->vwv+1, 0);
5569 /* we used to allow the client to get the cnum wrong, but that
5570 is really quite gross and only worked when there was only
5571 one printer - I think we should now only accept it if they
5572 get it right (tridge) */
5573 if (!CAN_PRINT(conn)) {
5574 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5575 END_PROFILE(SMBsplretq);
5579 reply_smb1_outbuf(req, 2, 3);
5580 SSVAL(req->outbuf,smb_vwv0,0);
5581 SSVAL(req->outbuf,smb_vwv1,0);
5582 SCVAL(smb_buf(req->outbuf),0,1);
5583 SSVAL(smb_buf(req->outbuf),1,0);
5585 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5586 start_index, max_count));
5589 TALLOC_CTX *mem_ctx = talloc_tos();
5592 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5593 struct rpc_pipe_client *cli = NULL;
5594 struct dcerpc_binding_handle *b = NULL;
5595 struct policy_handle handle;
5596 struct spoolss_DevmodeContainer devmode_ctr;
5597 union spoolss_JobInfo *info;
5599 uint32_t num_to_get;
5603 ZERO_STRUCT(handle);
5605 status = rpc_pipe_open_interface(mem_ctx,
5608 conn->sconn->remote_address,
5609 conn->sconn->local_address,
5610 conn->sconn->msg_ctx,
5612 if (!NT_STATUS_IS_OK(status)) {
5613 DEBUG(0, ("reply_printqueue: "
5614 "could not connect to spoolss: %s\n",
5615 nt_errstr(status)));
5616 reply_nterror(req, status);
5619 b = cli->binding_handle;
5621 ZERO_STRUCT(devmode_ctr);
5623 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5626 SEC_FLAG_MAXIMUM_ALLOWED,
5629 if (!NT_STATUS_IS_OK(status)) {
5630 reply_nterror(req, status);
5633 if (!W_ERROR_IS_OK(werr)) {
5634 reply_nterror(req, werror_to_ntstatus(werr));
5638 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5646 if (!W_ERROR_IS_OK(werr)) {
5647 reply_nterror(req, werror_to_ntstatus(werr));
5651 if (max_count > 0) {
5652 first = start_index;
5654 first = start_index + max_count + 1;
5657 if (first >= count) {
5660 num_to_get = first + MIN(ABS(max_count), count - first);
5663 for (i = first; i < num_to_get; i++) {
5666 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5669 uint16_t qrapjobid = pjobid_to_rap(sharename,
5670 info[i].info2.job_id);
5672 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5678 srv_put_dos_date2(p, 0, qtime);
5679 SCVAL(p, 4, qstatus);
5680 SSVAL(p, 5, qrapjobid);
5681 SIVAL(p, 7, info[i].info2.size);
5683 status = srvstr_push(blob, req->flags2, p+12,
5684 info[i].info2.notify_name, 16, STR_ASCII, &len);
5685 if (!NT_STATUS_IS_OK(status)) {
5686 reply_nterror(req, status);
5689 if (message_push_blob(
5692 blob, sizeof(blob))) == -1) {
5693 reply_nterror(req, NT_STATUS_NO_MEMORY);
5699 SSVAL(req->outbuf,smb_vwv0,count);
5700 SSVAL(req->outbuf,smb_vwv1,
5701 (max_count>0?first+count:first-1));
5702 SCVAL(smb_buf(req->outbuf),0,1);
5703 SSVAL(smb_buf(req->outbuf),1,28*count);
5707 DEBUG(3, ("%u entries returned in queue\n",
5711 if (b && is_valid_policy_hnd(&handle)) {
5712 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5717 END_PROFILE(SMBsplretq);
5721 /****************************************************************************
5722 Reply to a printwrite.
5723 ****************************************************************************/
5725 void reply_printwrite(struct smb_request *req)
5727 connection_struct *conn = req->conn;
5732 START_PROFILE(SMBsplwr);
5735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5736 END_PROFILE(SMBsplwr);
5740 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5742 if (!check_fsp(conn, req, fsp)) {
5743 END_PROFILE(SMBsplwr);
5747 if (!fsp->print_file) {
5748 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5749 END_PROFILE(SMBsplwr);
5753 if (!CHECK_WRITE(fsp)) {
5754 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5755 END_PROFILE(SMBsplwr);
5759 numtowrite = SVAL(req->buf, 1);
5762 * This already protects us against CVE-2017-12163.
5764 if (req->buflen < numtowrite + 3) {
5765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5766 END_PROFILE(SMBsplwr);
5770 data = (const char *)req->buf + 3;
5772 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5773 reply_nterror(req, map_nt_error_from_unix(errno));
5774 END_PROFILE(SMBsplwr);
5778 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5780 reply_smb1_outbuf(req, 0, 0);
5782 END_PROFILE(SMBsplwr);
5786 /****************************************************************************
5788 ****************************************************************************/
5790 void reply_mkdir(struct smb_request *req)
5792 connection_struct *conn = req->conn;
5793 struct smb_filename *smb_dname = NULL;
5794 char *directory = NULL;
5797 TALLOC_CTX *ctx = talloc_tos();
5799 START_PROFILE(SMBmkdir);
5801 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5802 STR_TERMINATE, &status);
5803 if (!NT_STATUS_IS_OK(status)) {
5804 reply_nterror(req, status);
5808 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
5809 status = filename_convert(ctx, conn,
5814 if (!NT_STATUS_IS_OK(status)) {
5815 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5816 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5817 ERRSRV, ERRbadpath);
5820 reply_nterror(req, status);
5824 status = create_directory(conn, req, smb_dname);
5826 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5828 if (!NT_STATUS_IS_OK(status)) {
5830 if (!use_nt_status()
5831 && NT_STATUS_EQUAL(status,
5832 NT_STATUS_OBJECT_NAME_COLLISION)) {
5834 * Yes, in the DOS error code case we get a
5835 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5836 * samba4 torture test.
5838 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5841 reply_nterror(req, status);
5845 reply_smb1_outbuf(req, 0, 0);
5847 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5849 TALLOC_FREE(smb_dname);
5850 END_PROFILE(SMBmkdir);
5854 /****************************************************************************
5856 ****************************************************************************/
5858 void reply_rmdir(struct smb_request *req)
5860 connection_struct *conn = req->conn;
5861 struct smb_filename *smb_dname = NULL;
5862 char *directory = NULL;
5864 TALLOC_CTX *ctx = talloc_tos();
5865 struct files_struct *dirfsp = NULL;
5866 files_struct *fsp = NULL;
5869 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5871 START_PROFILE(SMBrmdir);
5873 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5874 STR_TERMINATE, &status);
5875 if (!NT_STATUS_IS_OK(status)) {
5876 reply_nterror(req, status);
5880 if (ucf_flags & UCF_GMT_PATHNAME) {
5881 extract_snapshot_token(directory, &twrp);
5883 status = filename_convert_dirfsp(ctx,
5890 if (!NT_STATUS_IS_OK(status)) {
5891 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5892 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5893 ERRSRV, ERRbadpath);
5896 reply_nterror(req, status);
5900 status = SMB_VFS_CREATE_FILE(
5903 dirfsp, /* dirfsp */
5904 smb_dname, /* fname */
5905 DELETE_ACCESS, /* access_mask */
5906 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5908 FILE_OPEN, /* create_disposition*/
5909 FILE_DIRECTORY_FILE, /* create_options */
5910 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5911 0, /* oplock_request */
5913 0, /* allocation_size */
5914 0, /* private_flags */
5919 NULL, NULL); /* create context */
5921 if (!NT_STATUS_IS_OK(status)) {
5922 if (open_was_deferred(req->xconn, req->mid)) {
5923 /* We have re-scheduled this call. */
5926 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5927 bool ok = defer_smb1_sharing_violation(req);
5932 reply_nterror(req, status);
5936 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5937 if (!NT_STATUS_IS_OK(status)) {
5938 close_file_free(req, &fsp, ERROR_CLOSE);
5939 reply_nterror(req, status);
5943 if (!set_delete_on_close(fsp, true,
5944 conn->session_info->security_token,
5945 conn->session_info->unix_token)) {
5946 close_file_free(req, &fsp, ERROR_CLOSE);
5947 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5951 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5952 if (!NT_STATUS_IS_OK(status)) {
5953 reply_nterror(req, status);
5955 reply_smb1_outbuf(req, 0, 0);
5958 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5960 TALLOC_FREE(smb_dname);
5961 END_PROFILE(SMBrmdir);
5965 /****************************************************************************
5967 ****************************************************************************/
5969 void reply_mv(struct smb_request *req)
5971 connection_struct *conn = req->conn;
5973 char *newname = NULL;
5977 TALLOC_CTX *ctx = talloc_tos();
5978 struct smb_filename *smb_fname_src = NULL;
5979 struct smb_filename *smb_fname_dst = NULL;
5980 const char *dst_original_lcomp = NULL;
5981 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
5982 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
5983 bool stream_rename = false;
5985 START_PROFILE(SMBmv);
5988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5992 attrs = SVAL(req->vwv+0, 0);
5994 p = (const char *)req->buf + 1;
5995 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
5997 if (!NT_STATUS_IS_OK(status)) {
5998 reply_nterror(req, status);
6002 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
6004 if (!NT_STATUS_IS_OK(status)) {
6005 reply_nterror(req, status);
6009 if (!req->posix_pathnames) {
6010 /* The newname must begin with a ':' if the
6011 name contains a ':'. */
6012 if (strchr_m(name, ':')) {
6013 if (newname[0] != ':') {
6014 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6017 stream_rename = true;
6021 status = filename_convert(ctx,
6028 if (!NT_STATUS_IS_OK(status)) {
6029 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6030 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6031 ERRSRV, ERRbadpath);
6034 reply_nterror(req, status);
6038 status = filename_convert(ctx,
6045 if (!NT_STATUS_IS_OK(status)) {
6046 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6047 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6048 ERRSRV, ERRbadpath);
6051 reply_nterror(req, status);
6055 /* Get the last component of the destination for rename_internals(). */
6056 dst_original_lcomp = get_original_lcomp(ctx,
6060 if (dst_original_lcomp == NULL) {
6061 reply_nterror(req, NT_STATUS_NO_MEMORY);
6065 if (stream_rename) {
6066 /* smb_fname_dst->base_name must be the same as
6067 smb_fname_src->base_name. */
6068 TALLOC_FREE(smb_fname_dst->base_name);
6069 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6070 smb_fname_src->base_name);
6071 if (!smb_fname_dst->base_name) {
6072 reply_nterror(req, NT_STATUS_NO_MEMORY);
6077 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6078 smb_fname_str_dbg(smb_fname_dst)));
6080 status = rename_internals(ctx,
6089 if (!NT_STATUS_IS_OK(status)) {
6090 if (open_was_deferred(req->xconn, req->mid)) {
6091 /* We have re-scheduled this call. */
6094 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6095 bool ok = defer_smb1_sharing_violation(req);
6100 reply_nterror(req, status);
6104 reply_smb1_outbuf(req, 0, 0);
6106 TALLOC_FREE(smb_fname_src);
6107 TALLOC_FREE(smb_fname_dst);
6112 /****************************************************************************
6113 Reply to a file copy.
6117 This command was introduced in the LAN Manager 1.0 dialect
6118 It was rendered obsolete in the NT LAN Manager dialect.
6119 This command was used to perform server-side file copies, but
6120 is no longer used. Clients SHOULD
6121 NOT send requests using this command code.
6122 Servers receiving requests with this command code
6123 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6124 ****************************************************************************/
6126 void reply_copy(struct smb_request *req)
6128 START_PROFILE(SMBcopy);
6129 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
6130 END_PROFILE(SMBcopy);
6135 #define DBGC_CLASS DBGC_LOCKING
6137 /****************************************************************************
6138 Get a lock pid, dealing with large count requests.
6139 ****************************************************************************/
6141 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6142 bool large_file_format)
6144 if(!large_file_format)
6145 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6147 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6150 /****************************************************************************
6151 Get a lock count, dealing with large count requests.
6152 ****************************************************************************/
6154 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6155 bool large_file_format)
6159 if(!large_file_format) {
6160 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6163 * No BVAL, this is reversed!
6165 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6166 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6172 /****************************************************************************
6173 Reply to a lockingX request.
6174 ****************************************************************************/
6176 static void reply_lockingx_done(struct tevent_req *subreq);
6178 void reply_lockingX(struct smb_request *req)
6180 connection_struct *conn = req->conn;
6182 unsigned char locktype;
6183 enum brl_type brltype;
6184 unsigned char oplocklevel;
6185 uint16_t num_ulocks;
6187 int32_t lock_timeout;
6189 const uint8_t *data;
6190 bool large_file_format;
6191 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6192 struct smbd_lock_element *locks = NULL;
6193 struct tevent_req *subreq = NULL;
6195 START_PROFILE(SMBlockingX);
6198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6199 END_PROFILE(SMBlockingX);
6203 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6204 locktype = CVAL(req->vwv+3, 0);
6205 oplocklevel = CVAL(req->vwv+3, 1);
6206 num_ulocks = SVAL(req->vwv+6, 0);
6207 num_locks = SVAL(req->vwv+7, 0);
6208 lock_timeout = IVAL(req->vwv+4, 0);
6209 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
6211 if (!check_fsp(conn, req, fsp)) {
6212 END_PROFILE(SMBlockingX);
6218 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6219 /* we don't support these - and CANCEL_LOCK makes w2k
6220 and XP reboot so I don't really want to be
6221 compatible! (tridge) */
6222 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
6223 END_PROFILE(SMBlockingX);
6227 /* Check if this is an oplock break on a file
6228 we have granted an oplock on.
6230 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
6231 /* Client can insist on breaking to none. */
6232 bool break_to_none = (oplocklevel == 0);
6235 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6236 "for %s\n", (unsigned int)oplocklevel,
6237 fsp_fnum_dbg(fsp)));
6240 * Make sure we have granted an exclusive or batch oplock on
6244 if (fsp->oplock_type == 0) {
6246 /* The Samba4 nbench simulator doesn't understand
6247 the difference between break to level2 and break
6248 to none from level2 - it sends oplock break
6249 replies in both cases. Don't keep logging an error
6250 message here - just ignore it. JRA. */
6252 DEBUG(5,("reply_lockingX: Error : oplock break from "
6253 "client for %s (oplock=%d) and no "
6254 "oplock granted on this file (%s).\n",
6255 fsp_fnum_dbg(fsp), fsp->oplock_type,
6258 /* if this is a pure oplock break request then don't
6260 if (num_locks == 0 && num_ulocks == 0) {
6261 END_PROFILE(SMBlockingX);
6265 END_PROFILE(SMBlockingX);
6266 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6270 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6272 result = remove_oplock(fsp);
6274 result = downgrade_oplock(fsp);
6278 DEBUG(0, ("reply_lockingX: error in removing "
6279 "oplock on file %s\n", fsp_str_dbg(fsp)));
6280 /* Hmmm. Is this panic justified? */
6281 smb_panic("internal tdb error");
6284 /* if this is a pure oplock break request then don't send a
6286 if (num_locks == 0 && num_ulocks == 0) {
6287 /* Sanity check - ensure a pure oplock break is not a
6289 if (CVAL(req->vwv+0, 0) != 0xff) {
6290 DEBUG(0,("reply_lockingX: Error : pure oplock "
6291 "break is a chained %d request !\n",
6292 (unsigned int)CVAL(req->vwv+0, 0)));
6294 END_PROFILE(SMBlockingX);
6300 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6302 END_PROFILE(SMBlockingX);
6306 if (num_ulocks != 0) {
6307 struct smbd_lock_element *ulocks = NULL;
6310 ulocks = talloc_array(
6311 req, struct smbd_lock_element, num_ulocks);
6312 if (ulocks == NULL) {
6313 reply_nterror(req, NT_STATUS_NO_MEMORY);
6314 END_PROFILE(SMBlockingX);
6319 * Data now points at the beginning of the list of
6320 * smb_unlkrng structs
6322 for (i = 0; i < num_ulocks; i++) {
6323 ulocks[i].req_guid = smbd_request_guid(req,
6325 ulocks[i].smblctx = get_lock_pid(
6326 data, i, large_file_format);
6327 ulocks[i].count = get_lock_count(
6328 data, i, large_file_format);
6329 ulocks[i].offset = get_lock_offset(
6330 data, i, large_file_format);
6331 ulocks[i].brltype = UNLOCK_LOCK;
6332 ulocks[i].lock_flav = WINDOWS_LOCK;
6336 * Unlock cancels pending locks
6339 ok = smbd_smb1_brl_finish_by_lock(
6345 reply_smb1_outbuf(req, 2, 0);
6346 SSVAL(req->outbuf, smb_vwv0, 0xff);
6347 SSVAL(req->outbuf, smb_vwv1, 0);
6348 END_PROFILE(SMBlockingX);
6352 status = smbd_do_unlocking(
6353 req, fsp, num_ulocks, ulocks);
6354 TALLOC_FREE(ulocks);
6355 if (!NT_STATUS_IS_OK(status)) {
6356 END_PROFILE(SMBlockingX);
6357 reply_nterror(req, status);
6362 /* Now do any requested locks */
6363 data += ((large_file_format ? 20 : 10)*num_ulocks);
6365 /* Data now points at the beginning of the list
6366 of smb_lkrng structs */
6368 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
6369 brltype = READ_LOCK;
6371 brltype = WRITE_LOCK;
6374 locks = talloc_array(req, struct smbd_lock_element, num_locks);
6375 if (locks == NULL) {
6376 reply_nterror(req, NT_STATUS_NO_MEMORY);
6377 END_PROFILE(SMBlockingX);
6381 for (i = 0; i < num_locks; i++) {
6382 locks[i].req_guid = smbd_request_guid(req, i),
6383 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
6384 locks[i].count = get_lock_count(data, i, large_file_format);
6385 locks[i].offset = get_lock_offset(data, i, large_file_format);
6386 locks[i].brltype = brltype;
6387 locks[i].lock_flav = WINDOWS_LOCK;
6390 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6394 if (num_locks == 0) {
6395 /* See smbtorture3 lock11 test */
6396 reply_smb1_outbuf(req, 2, 0);
6397 /* andx chain ends */
6398 SSVAL(req->outbuf, smb_vwv0, 0xff);
6399 SSVAL(req->outbuf, smb_vwv1, 0);
6400 END_PROFILE(SMBlockingX);
6404 ok = smbd_smb1_brl_finish_by_lock(
6407 locks[0], /* Windows only cancels the first lock */
6408 NT_STATUS_FILE_LOCK_CONFLICT);
6411 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
6412 END_PROFILE(SMBlockingX);
6416 reply_smb1_outbuf(req, 2, 0);
6417 SSVAL(req->outbuf, smb_vwv0, 0xff);
6418 SSVAL(req->outbuf, smb_vwv1, 0);
6419 END_PROFILE(SMBlockingX);
6423 subreq = smbd_smb1_do_locks_send(
6432 if (subreq == NULL) {
6433 reply_nterror(req, NT_STATUS_NO_MEMORY);
6434 END_PROFILE(SMBlockingX);
6437 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
6438 END_PROFILE(SMBlockingX);
6441 static void reply_lockingx_done(struct tevent_req *subreq)
6443 struct smb_request *req = NULL;
6447 START_PROFILE(SMBlockingX);
6449 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6452 status = smbd_smb1_do_locks_recv(subreq);
6453 TALLOC_FREE(subreq);
6455 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
6457 if (NT_STATUS_IS_OK(status)) {
6458 reply_smb1_outbuf(req, 2, 0);
6459 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
6460 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
6462 reply_nterror(req, status);
6465 ok = smb1_srv_send(req->xconn,
6466 (char *)req->outbuf,
6469 IS_CONN_ENCRYPTED(req->conn),
6472 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6475 END_PROFILE(SMBlockingX);
6479 #define DBGC_CLASS DBGC_ALL
6481 /****************************************************************************
6482 Reply to a SMBreadbmpx (read block multiplex) request.
6483 Always reply with an error, if someone has a platform really needs this,
6484 please contact vl@samba.org
6485 ****************************************************************************/
6487 void reply_readbmpx(struct smb_request *req)
6489 START_PROFILE(SMBreadBmpx);
6490 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6491 END_PROFILE(SMBreadBmpx);
6495 /****************************************************************************
6496 Reply to a SMBreadbs (read block multiplex secondary) request.
6497 Always reply with an error, if someone has a platform really needs this,
6498 please contact vl@samba.org
6499 ****************************************************************************/
6501 void reply_readbs(struct smb_request *req)
6503 START_PROFILE(SMBreadBs);
6504 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6505 END_PROFILE(SMBreadBs);
6509 /****************************************************************************
6510 Reply to a SMBsetattrE.
6511 ****************************************************************************/
6513 void reply_setattrE(struct smb_request *req)
6515 connection_struct *conn = req->conn;
6516 struct smb_file_time ft;
6520 START_PROFILE(SMBsetattrE);
6521 init_smb_file_time(&ft);
6524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6528 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6530 if(!fsp || (fsp->conn != conn)) {
6531 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6536 * Convert the DOS times into unix times.
6539 ft.atime = time_t_to_full_timespec(
6540 srv_make_unix_date2(req->vwv+3));
6541 ft.mtime = time_t_to_full_timespec(
6542 srv_make_unix_date2(req->vwv+5));
6543 ft.create_time = time_t_to_full_timespec(
6544 srv_make_unix_date2(req->vwv+1));
6546 reply_smb1_outbuf(req, 0, 0);
6549 * Patch from Ray Frush <frush@engr.colostate.edu>
6550 * Sometimes times are sent as zero - ignore them.
6553 /* Ensure we have a valid stat struct for the source. */
6554 status = vfs_stat_fsp(fsp);
6555 if (!NT_STATUS_IS_OK(status)) {
6556 reply_nterror(req, status);
6560 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6561 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6565 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
6566 if (!NT_STATUS_IS_OK(status)) {
6567 reply_nterror(req, status);
6571 if (fsp->fsp_flags.modified) {
6572 trigger_write_time_update_immediate(fsp);
6575 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6578 (unsigned int)ft.atime.tv_sec,
6579 (unsigned int)ft.mtime.tv_sec,
6580 (unsigned int)ft.create_time.tv_sec
6583 END_PROFILE(SMBsetattrE);
6588 /* Back from the dead for OS/2..... JRA. */
6590 /****************************************************************************
6591 Reply to a SMBwritebmpx (write block multiplex primary) request.
6592 Always reply with an error, if someone has a platform really needs this,
6593 please contact vl@samba.org
6594 ****************************************************************************/
6596 void reply_writebmpx(struct smb_request *req)
6598 START_PROFILE(SMBwriteBmpx);
6599 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6600 END_PROFILE(SMBwriteBmpx);
6604 /****************************************************************************
6605 Reply to a SMBwritebs (write block multiplex secondary) request.
6606 Always reply with an error, if someone has a platform really needs this,
6607 please contact vl@samba.org
6608 ****************************************************************************/
6610 void reply_writebs(struct smb_request *req)
6612 START_PROFILE(SMBwriteBs);
6613 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6614 END_PROFILE(SMBwriteBs);
6618 /****************************************************************************
6619 Reply to a SMBgetattrE.
6620 ****************************************************************************/
6622 void reply_getattrE(struct smb_request *req)
6624 connection_struct *conn = req->conn;
6627 struct timespec create_ts;
6630 START_PROFILE(SMBgetattrE);
6633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6634 END_PROFILE(SMBgetattrE);
6638 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6640 if(!fsp || (fsp->conn != conn)) {
6641 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6642 END_PROFILE(SMBgetattrE);
6646 /* Do an fstat on this file */
6647 status = vfs_stat_fsp(fsp);
6648 if (!NT_STATUS_IS_OK(status)) {
6649 reply_nterror(req, status);
6650 END_PROFILE(SMBgetattrE);
6654 mode = fdos_mode(fsp);
6657 * Convert the times into dos times. Set create
6658 * date to be last modify date as UNIX doesn't save
6662 reply_smb1_outbuf(req, 11, 0);
6664 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
6665 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
6666 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
6667 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
6668 /* Should we check pending modtime here ? JRA */
6669 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
6670 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
6672 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
6673 SIVAL(req->outbuf, smb_vwv6, 0);
6674 SIVAL(req->outbuf, smb_vwv8, 0);
6676 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
6677 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
6678 SIVAL(req->outbuf, smb_vwv8, allocation_size);
6680 SSVAL(req->outbuf,smb_vwv10, mode);
6682 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
6684 END_PROFILE(SMBgetattrE);
6688 /****************************************************************************
6689 Reply to a SMBfindclose (stop trans2 directory search).
6690 ****************************************************************************/
6692 void reply_findclose(struct smb_request *req)
6695 struct smbd_server_connection *sconn = req->sconn;
6696 files_struct *fsp = NULL;
6698 START_PROFILE(SMBfindclose);
6701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6702 END_PROFILE(SMBfindclose);
6706 dptr_num = SVALS(req->vwv+0, 0);
6708 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6711 * OS/2 seems to use -1 to indicate "close all directories"
6712 * This has to mean on this specific connection struct.
6714 if (dptr_num == -1) {
6715 dptr_closecnum(req->conn);
6717 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
6720 close_file_free(NULL, &fsp, NORMAL_CLOSE);
6724 reply_smb1_outbuf(req, 0, 0);
6726 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6728 END_PROFILE(SMBfindclose);
6732 /****************************************************************************
6733 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6734 ****************************************************************************/
6736 void reply_findnclose(struct smb_request *req)
6740 START_PROFILE(SMBfindnclose);
6743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6744 END_PROFILE(SMBfindnclose);
6748 dptr_num = SVAL(req->vwv+0, 0);
6750 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6752 /* We never give out valid handles for a
6753 findnotifyfirst - so any dptr_num is ok here.
6756 reply_smb1_outbuf(req, 0, 0);
6758 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6760 END_PROFILE(SMBfindnclose);