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 struct files_struct
*dirfsp
= NULL
;
565 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
567 TALLOC_CTX
*ctx
= talloc_tos();
569 START_PROFILE(SMBcheckpath
);
571 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
572 STR_TERMINATE
, &status
);
574 if (!NT_STATUS_IS_OK(status
)) {
575 status
= map_checkpath_error(req
->flags2
, status
);
576 reply_nterror(req
, status
);
577 END_PROFILE(SMBcheckpath
);
581 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
583 if (ucf_flags
& UCF_GMT_PATHNAME
) {
584 extract_snapshot_token(name
, &twrp
);
586 status
= filename_convert_dirfsp(ctx
,
593 if (!NT_STATUS_IS_OK(status
)) {
594 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
595 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
597 END_PROFILE(SMBcheckpath
);
603 if (!VALID_STAT(smb_fname
->st
) &&
604 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
605 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
606 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
607 status
= map_nt_error_from_unix(errno
);
611 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
612 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
617 reply_smb1_outbuf(req
, 0, 0);
620 /* We special case this - as when a Windows machine
621 is parsing a path is steps through the components
622 one at a time - if a component fails it expects
623 ERRbadpath, not ERRbadfile.
625 status
= map_checkpath_error(req
->flags2
, status
);
626 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
628 * Windows returns different error codes if
629 * the parent directory is valid but not the
630 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
631 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
632 * if the path is invalid.
634 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
639 reply_nterror(req
, status
);
642 TALLOC_FREE(smb_fname
);
643 END_PROFILE(SMBcheckpath
);
647 /****************************************************************************
649 ****************************************************************************/
651 void reply_getatr(struct smb_request
*req
)
653 connection_struct
*conn
= req
->conn
;
654 struct smb_filename
*smb_fname
= NULL
;
661 TALLOC_CTX
*ctx
= talloc_tos();
662 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
664 START_PROFILE(SMBgetatr
);
666 p
= (const char *)req
->buf
+ 1;
667 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
668 if (!NT_STATUS_IS_OK(status
)) {
669 reply_nterror(req
, status
);
674 * dos sometimes asks for a stat of "" - it returns a "hidden
675 * directory" under WfWg - weird!
677 if (*fname
== '\0') {
678 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
679 if (!CAN_WRITE(conn
)) {
680 mode
|= FILE_ATTRIBUTE_READONLY
;
685 struct files_struct
*dirfsp
= NULL
;
686 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
688 if (ucf_flags
& UCF_GMT_PATHNAME
) {
689 extract_snapshot_token(fname
, &twrp
);
691 status
= filename_convert_dirfsp(ctx
,
698 if (!NT_STATUS_IS_OK(status
)) {
699 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
700 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
704 reply_nterror(req
, status
);
707 if (!VALID_STAT(smb_fname
->st
) &&
708 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
709 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
710 smb_fname_str_dbg(smb_fname
),
712 reply_nterror(req
, map_nt_error_from_unix(errno
));
716 mode
= fdos_mode(smb_fname
->fsp
);
717 size
= smb_fname
->st
.st_ex_size
;
720 struct timespec write_time_ts
;
721 struct file_id fileid
;
723 ZERO_STRUCT(write_time_ts
);
724 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
725 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
726 if (!is_omit_timespec(&write_time_ts
)) {
727 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
731 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
732 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
737 reply_smb1_outbuf(req
, 10, 0);
739 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
740 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
741 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
743 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
745 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
747 if (get_Protocol() >= PROTOCOL_NT1
) {
748 SSVAL(req
->outbuf
, smb_flg2
,
749 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
752 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
753 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
756 TALLOC_FREE(smb_fname
);
758 END_PROFILE(SMBgetatr
);
762 /****************************************************************************
764 ****************************************************************************/
766 void reply_setatr(struct smb_request
*req
)
768 struct smb_file_time ft
;
769 connection_struct
*conn
= req
->conn
;
770 struct smb_filename
*smb_fname
= NULL
;
771 struct files_struct
*dirfsp
= NULL
;
777 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
779 TALLOC_CTX
*ctx
= talloc_tos();
781 START_PROFILE(SMBsetatr
);
782 init_smb_file_time(&ft
);
785 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
789 p
= (const char *)req
->buf
+ 1;
790 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
791 if (!NT_STATUS_IS_OK(status
)) {
792 reply_nterror(req
, status
);
796 if (ucf_flags
& UCF_GMT_PATHNAME
) {
797 extract_snapshot_token(fname
, &twrp
);
799 status
= filename_convert_dirfsp(ctx
,
806 if (!NT_STATUS_IS_OK(status
)) {
807 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
808 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
812 reply_nterror(req
, status
);
816 if (ISDOT(smb_fname
->base_name
)) {
818 * Not sure here is the right place to catch this
819 * condition. Might be moved to somewhere else later -- vl
821 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
825 if (smb_fname
->fsp
== NULL
) {
826 /* Can't set access rights on a symlink. */
827 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
831 mode
= SVAL(req
->vwv
+0, 0);
832 mtime
= srv_make_unix_date3(req
->vwv
+1);
834 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
835 if (VALID_STAT_OF_DIR(smb_fname
->st
))
836 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
838 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
840 status
= smbd_check_access_rights_fsp(conn
->cwd_fsp
,
843 FILE_WRITE_ATTRIBUTES
);
844 if (!NT_STATUS_IS_OK(status
)) {
845 reply_nterror(req
, status
);
849 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
851 reply_nterror(req
, map_nt_error_from_unix(errno
));
856 ft
.mtime
= time_t_to_full_timespec(mtime
);
858 status
= smb_set_file_time(conn
, smb_fname
->fsp
, smb_fname
, &ft
, true);
859 if (!NT_STATUS_IS_OK(status
)) {
860 reply_nterror(req
, status
);
864 reply_smb1_outbuf(req
, 0, 0);
866 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
869 TALLOC_FREE(smb_fname
);
870 END_PROFILE(SMBsetatr
);
874 /****************************************************************************
876 ****************************************************************************/
878 void reply_dskattr(struct smb_request
*req
)
880 connection_struct
*conn
= req
->conn
;
882 uint64_t dfree
,dsize
,bsize
;
883 struct smb_filename smb_fname
;
884 START_PROFILE(SMBdskattr
);
886 ZERO_STRUCT(smb_fname
);
887 smb_fname
.base_name
= discard_const_p(char, ".");
889 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
890 reply_nterror(req
, map_nt_error_from_unix(errno
));
891 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
892 END_PROFILE(SMBdskattr
);
896 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
897 if (ret
== (uint64_t)-1) {
898 reply_nterror(req
, map_nt_error_from_unix(errno
));
899 END_PROFILE(SMBdskattr
);
904 * Force max to fit in 16 bit fields.
906 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
910 if (bsize
> (WORDMAX
*512)) {
911 bsize
= (WORDMAX
*512);
920 reply_smb1_outbuf(req
, 5, 0);
922 if (get_Protocol() <= PROTOCOL_LANMAN2
) {
923 double total_space
, free_space
;
924 /* we need to scale this to a number that DOS6 can handle. We
925 use floating point so we can handle large drives on systems
926 that don't have 64 bit integers
928 we end up displaying a maximum of 2G to DOS systems
930 total_space
= dsize
* (double)bsize
;
931 free_space
= dfree
* (double)bsize
;
933 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
934 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
936 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
937 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
939 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
940 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
941 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
942 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
944 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
945 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
946 SSVAL(req
->outbuf
,smb_vwv2
,512);
947 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
950 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
952 END_PROFILE(SMBdskattr
);
956 /****************************************************************************
958 ****************************************************************************/
960 static bool make_dir_struct(TALLOC_CTX
*ctx
,
970 char *mask2
= talloc_strdup(ctx
, mask
);
976 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
980 memset(buf
+1,' ',11);
981 if ((p
= strchr_m(mask2
,'.')) != NULL
) {
983 push_ascii(buf
+1,mask2
,8, 0);
984 push_ascii(buf
+9,p
+1,3, 0);
987 push_ascii(buf
+1,mask2
,11, 0);
990 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
992 srv_put_dos_date(buf
,22,date
);
993 SSVAL(buf
,26,size
& 0xFFFF);
994 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
995 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
996 Strange, but verified on W2K3. Needed for OS/2. JRA. */
997 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
998 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1002 /****************************************************************************
1004 Can be called from SMBsearch, SMBffirst or SMBfunique.
1005 ****************************************************************************/
1007 void reply_search(struct smb_request
*req
)
1009 connection_struct
*conn
= req
->conn
;
1012 char *directory
= NULL
;
1013 struct smb_filename
*smb_fname
= NULL
;
1017 struct timespec date
;
1019 unsigned int numentries
= 0;
1020 unsigned int maxentries
= 0;
1021 bool finished
= False
;
1026 bool check_descend
= False
;
1027 bool expect_close
= False
;
1029 bool mask_contains_wcard
= False
;
1030 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1031 TALLOC_CTX
*ctx
= talloc_tos();
1032 bool ask_sharemode
= lp_smbd_search_ask_sharemode(SNUM(conn
));
1033 struct smbXsrv_connection
*xconn
= req
->xconn
;
1034 struct smbd_server_connection
*sconn
= req
->sconn
;
1035 files_struct
*fsp
= NULL
;
1036 const struct loadparm_substitution
*lp_sub
=
1037 loadparm_s3_global_substitution();
1039 START_PROFILE(SMBsearch
);
1042 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1046 if (req
->posix_pathnames
) {
1047 reply_unknown_new(req
, req
->cmd
);
1051 /* If we were called as SMBffirst then we must expect close. */
1052 if(req
->cmd
== SMBffirst
) {
1053 expect_close
= True
;
1056 reply_smb1_outbuf(req
, 1, 3);
1057 maxentries
= SVAL(req
->vwv
+0, 0);
1058 dirtype
= SVAL(req
->vwv
+1, 0);
1059 p
= (const char *)req
->buf
+ 1;
1060 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1062 if (!NT_STATUS_IS_OK(nt_status
)) {
1063 reply_nterror(req
, nt_status
);
1067 if (smbreq_bufrem(req
, p
) < 3) {
1068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1073 status_len
= SVAL(p
, 0);
1076 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1078 if (status_len
== 0) {
1079 const char *dirpath
;
1080 struct files_struct
*dirfsp
= NULL
;
1081 struct smb_filename
*smb_dname
= NULL
;
1082 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1084 nt_status
= filename_convert_smb1_search_path(ctx
,
1092 if (!NT_STATUS_IS_OK(nt_status
)) {
1093 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1094 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1095 ERRSRV
, ERRbadpath
);
1098 reply_nterror(req
, nt_status
);
1102 memset((char *)status
,'\0',21);
1103 SCVAL(status
,0,(dirtype
& 0x1F));
1106 * Open an fsp on this directory for the dptr.
1108 nt_status
= SMB_VFS_CREATE_FILE(
1111 dirfsp
, /* dirfsp */
1112 smb_dname
, /* dname */
1113 FILE_LIST_DIRECTORY
, /* access_mask */
1115 FILE_SHARE_WRITE
, /* share_access */
1116 FILE_OPEN
, /* create_disposition*/
1117 FILE_DIRECTORY_FILE
, /* create_options */
1118 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1119 NO_OPLOCK
, /* oplock_request */
1121 0, /* allocation_size */
1122 0, /* private_flags */
1127 NULL
, /* in_context */
1128 NULL
);/* out_context */
1130 if (!NT_STATUS_IS_OK(nt_status
)) {
1131 DBG_ERR("failed to open directory %s\n",
1132 smb_fname_str_dbg(smb_dname
));
1133 reply_nterror(req
, nt_status
);
1137 nt_status
= dptr_create(conn
,
1147 TALLOC_FREE(smb_dname
);
1149 if (!NT_STATUS_IS_OK(nt_status
)) {
1151 * Use NULL here for the first parameter (req)
1152 * as this is not a client visible handle so
1153 * can'tbe part of an SMB1 chain.
1155 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1156 reply_nterror(req
, nt_status
);
1160 dptr_num
= dptr_dnum(fsp
->dptr
);
1161 dirpath
= dptr_path(sconn
, dptr_num
);
1162 directory
= talloc_strdup(ctx
, dirpath
);
1164 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1170 const char *dirpath
;
1172 if (smbreq_bufrem(req
, p
) < 21) {
1173 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1177 memcpy(status
,p
,21);
1178 status_dirtype
= CVAL(status
,0) & 0x1F;
1179 if (status_dirtype
!= (dirtype
& 0x1F)) {
1180 dirtype
= status_dirtype
;
1183 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
1187 dirpath
= dptr_path(sconn
, dptr_num
);
1188 directory
= talloc_strdup(ctx
, dirpath
);
1190 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1194 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1198 dirtype
= dptr_attr(sconn
, dptr_num
);
1201 mask_contains_wcard
= dptr_has_wild(fsp
->dptr
);
1203 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1205 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1206 char buf
[DIR_STRUCT_SIZE
];
1207 memcpy(buf
,status
,21);
1208 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(ctx
, SNUM(conn
)),
1209 0,FILE_ATTRIBUTE_VOLUME
,0,!allow_long_path_components
)) {
1210 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1213 dptr_fill(sconn
, buf
+12,dptr_num
);
1214 if (dptr_zero(buf
+12) && (status_len
==0)) {
1219 if (message_push_blob(&req
->outbuf
,
1220 data_blob_const(buf
, sizeof(buf
)))
1222 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1227 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1228 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1230 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1232 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1233 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1234 if (in_list(directory
, lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),True
)) {
1235 check_descend
= True
;
1238 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1239 finished
= !get_dir_entry(ctx
,
1250 char buf
[DIR_STRUCT_SIZE
];
1251 memcpy(buf
,status
,21);
1252 if (!make_dir_struct(ctx
,
1258 convert_timespec_to_time_t(date
),
1259 !allow_long_path_components
)) {
1260 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1263 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1266 if (message_push_blob(&req
->outbuf
,
1267 data_blob_const(buf
, sizeof(buf
)))
1269 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1279 /* If we were called as SMBffirst with smb_search_id == NULL
1280 and no entries were found then return error and close fsp->dptr
1283 if (numentries
== 0) {
1286 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1288 } else if(expect_close
&& status_len
== 0) {
1289 /* Close the dptr - we know it's gone */
1292 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1296 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1297 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1299 /* fsp may have been closed above. */
1301 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1305 if ((numentries
== 0) && !mask_contains_wcard
) {
1306 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1310 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1311 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1312 SCVAL(smb_buf(req
->outbuf
),0,5);
1313 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1315 /* The replies here are never long name. */
1316 SSVAL(req
->outbuf
, smb_flg2
,
1317 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1318 if (!allow_long_path_components
) {
1319 SSVAL(req
->outbuf
, smb_flg2
,
1320 SVAL(req
->outbuf
, smb_flg2
)
1321 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1324 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1325 SSVAL(req
->outbuf
, smb_flg2
,
1326 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1328 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1329 smb_fn_name(req
->cmd
),
1336 TALLOC_FREE(directory
);
1338 TALLOC_FREE(smb_fname
);
1339 END_PROFILE(SMBsearch
);
1343 /****************************************************************************
1344 Reply to a fclose (stop directory search).
1345 ****************************************************************************/
1347 void reply_fclose(struct smb_request
*req
)
1355 TALLOC_CTX
*ctx
= talloc_tos();
1356 struct smbd_server_connection
*sconn
= req
->sconn
;
1357 files_struct
*fsp
= NULL
;
1359 START_PROFILE(SMBfclose
);
1361 if (req
->posix_pathnames
) {
1362 reply_unknown_new(req
, req
->cmd
);
1363 END_PROFILE(SMBfclose
);
1367 p
= (const char *)req
->buf
+ 1;
1368 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1370 if (!NT_STATUS_IS_OK(err
)) {
1371 reply_nterror(req
, err
);
1372 END_PROFILE(SMBfclose
);
1376 if (smbreq_bufrem(req
, p
) < 3) {
1377 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1378 END_PROFILE(SMBfclose
);
1383 status_len
= SVAL(p
,0);
1386 if (status_len
== 0) {
1387 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1388 END_PROFILE(SMBfclose
);
1392 if (smbreq_bufrem(req
, p
) < 21) {
1393 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1394 END_PROFILE(SMBfclose
);
1398 memcpy(status
,p
,21);
1400 fsp
= dptr_fetch_fsp(sconn
, status
+12,&dptr_num
);
1402 /* Close the file - we know it's gone */
1403 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1407 reply_smb1_outbuf(req
, 1, 0);
1408 SSVAL(req
->outbuf
,smb_vwv0
,0);
1410 DEBUG(3,("search close\n"));
1412 END_PROFILE(SMBfclose
);
1416 /****************************************************************************
1418 ****************************************************************************/
1420 void reply_open(struct smb_request
*req
)
1422 connection_struct
*conn
= req
->conn
;
1423 struct smb_filename
*smb_fname
= NULL
;
1429 struct files_struct
*dirfsp
= NULL
;
1434 uint32_t access_mask
;
1435 uint32_t share_mode
;
1436 uint32_t create_disposition
;
1437 uint32_t create_options
= 0;
1438 uint32_t private_flags
= 0;
1442 TALLOC_CTX
*ctx
= talloc_tos();
1444 START_PROFILE(SMBopen
);
1447 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1451 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1452 deny_mode
= SVAL(req
->vwv
+0, 0);
1453 dos_attr
= SVAL(req
->vwv
+1, 0);
1455 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1456 STR_TERMINATE
, &status
);
1457 if (!NT_STATUS_IS_OK(status
)) {
1458 reply_nterror(req
, status
);
1462 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1463 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1464 &share_mode
, &create_disposition
,
1465 &create_options
, &private_flags
)) {
1466 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1470 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
1472 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1473 extract_snapshot_token(fname
, &twrp
);
1475 status
= filename_convert_dirfsp(ctx
,
1482 if (!NT_STATUS_IS_OK(status
)) {
1483 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1484 reply_botherror(req
,
1485 NT_STATUS_PATH_NOT_COVERED
,
1486 ERRSRV
, ERRbadpath
);
1489 reply_nterror(req
, status
);
1493 status
= SMB_VFS_CREATE_FILE(
1496 dirfsp
, /* dirfsp */
1497 smb_fname
, /* fname */
1498 access_mask
, /* access_mask */
1499 share_mode
, /* share_access */
1500 create_disposition
, /* create_disposition*/
1501 create_options
, /* create_options */
1502 dos_attr
, /* file_attributes */
1503 oplock_request
, /* oplock_request */
1505 0, /* allocation_size */
1511 NULL
, NULL
); /* create context */
1513 if (!NT_STATUS_IS_OK(status
)) {
1514 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1515 /* We have re-scheduled this call. */
1519 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1520 reply_openerror(req
, status
);
1524 fsp
= fcb_or_dos_open(
1531 bool ok
= defer_smb1_sharing_violation(req
);
1535 reply_openerror(req
, status
);
1540 /* Ensure we're pointing at the correct stat struct. */
1541 TALLOC_FREE(smb_fname
);
1542 smb_fname
= fsp
->fsp_name
;
1544 size
= smb_fname
->st
.st_ex_size
;
1545 fattr
= fdos_mode(fsp
);
1547 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1549 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1550 DEBUG(3,("attempt to open a directory %s\n",
1552 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1553 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1554 ERRDOS
, ERRnoaccess
);
1558 reply_smb1_outbuf(req
, 7, 0);
1559 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1560 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1561 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1562 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1564 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1566 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
1567 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1569 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1570 SCVAL(req
->outbuf
,smb_flg
,
1571 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1574 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1575 SCVAL(req
->outbuf
,smb_flg
,
1576 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1579 END_PROFILE(SMBopen
);
1583 /****************************************************************************
1584 Reply to an open and X.
1585 ****************************************************************************/
1587 void reply_open_and_X(struct smb_request
*req
)
1589 connection_struct
*conn
= req
->conn
;
1590 struct smb_filename
*smb_fname
= NULL
;
1592 uint16_t open_flags
;
1595 /* Breakout the oplock request bits so we can set the
1596 reply bits separately. */
1597 int ex_oplock_request
;
1598 int core_oplock_request
;
1601 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1602 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
1608 struct files_struct
*dirfsp
= NULL
;
1611 uint64_t allocation_size
;
1612 ssize_t retval
= -1;
1613 uint32_t access_mask
;
1614 uint32_t share_mode
;
1615 uint32_t create_disposition
;
1616 uint32_t create_options
= 0;
1617 uint32_t private_flags
= 0;
1620 TALLOC_CTX
*ctx
= talloc_tos();
1622 START_PROFILE(SMBopenX
);
1624 if (req
->wct
< 15) {
1625 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1629 open_flags
= SVAL(req
->vwv
+2, 0);
1630 deny_mode
= SVAL(req
->vwv
+3, 0);
1631 smb_attr
= SVAL(req
->vwv
+5, 0);
1632 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1633 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1634 oplock_request
= ex_oplock_request
| core_oplock_request
;
1635 smb_ofun
= SVAL(req
->vwv
+8, 0);
1636 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1638 /* If it's an IPC, pass off the pipe handler. */
1640 if (lp_nt_pipe_support()) {
1641 reply_open_pipe_and_X(conn
, req
);
1643 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1648 /* XXXX we need to handle passed times, sattr and flags */
1649 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1650 STR_TERMINATE
, &status
);
1651 if (!NT_STATUS_IS_OK(status
)) {
1652 reply_nterror(req
, status
);
1656 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1658 &access_mask
, &share_mode
,
1659 &create_disposition
,
1662 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1666 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
1668 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1669 extract_snapshot_token(fname
, &twrp
);
1672 status
= filename_convert_dirfsp(ctx
,
1679 if (!NT_STATUS_IS_OK(status
)) {
1680 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1681 reply_botherror(req
,
1682 NT_STATUS_PATH_NOT_COVERED
,
1683 ERRSRV
, ERRbadpath
);
1686 reply_nterror(req
, status
);
1690 status
= SMB_VFS_CREATE_FILE(
1693 dirfsp
, /* dirfsp */
1694 smb_fname
, /* fname */
1695 access_mask
, /* access_mask */
1696 share_mode
, /* share_access */
1697 create_disposition
, /* create_disposition*/
1698 create_options
, /* create_options */
1699 smb_attr
, /* file_attributes */
1700 oplock_request
, /* oplock_request */
1702 0, /* allocation_size */
1707 &smb_action
, /* pinfo */
1708 NULL
, NULL
); /* create context */
1710 if (!NT_STATUS_IS_OK(status
)) {
1711 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1712 /* We have re-scheduled this call. */
1716 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1717 reply_openerror(req
, status
);
1721 fsp
= fcb_or_dos_open(
1728 bool ok
= defer_smb1_sharing_violation(req
);
1732 reply_openerror(req
, status
);
1737 smb_action
= FILE_WAS_OPENED
;
1740 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1741 if the file is truncated or created. */
1742 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1743 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1744 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1745 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1746 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1749 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
1751 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1752 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1755 status
= vfs_stat_fsp(fsp
);
1756 if (!NT_STATUS_IS_OK(status
)) {
1757 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1758 reply_nterror(req
, status
);
1763 fattr
= fdos_mode(fsp
);
1764 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1765 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1766 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1769 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
1771 /* If the caller set the extended oplock request bit
1772 and we granted one (by whatever means) - set the
1773 correct bit for extended oplock reply.
1776 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1777 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1780 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1781 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1784 /* If the caller set the core oplock request bit
1785 and we granted one (by whatever means) - set the
1786 correct bit for core oplock reply.
1789 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1790 reply_smb1_outbuf(req
, 19, 0);
1792 reply_smb1_outbuf(req
, 15, 0);
1795 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
1796 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
1798 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1799 SCVAL(req
->outbuf
, smb_flg
,
1800 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1803 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1804 SCVAL(req
->outbuf
, smb_flg
,
1805 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1808 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
1809 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
1810 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1811 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
1813 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
1815 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
1816 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
1817 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
1819 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1820 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
1824 TALLOC_FREE(smb_fname
);
1825 END_PROFILE(SMBopenX
);
1829 /****************************************************************************
1830 Reply to a SMBulogoffX.
1831 ****************************************************************************/
1833 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
1834 struct smbXsrv_session
*session
);
1835 static void reply_ulogoffX_done(struct tevent_req
*req
);
1837 void reply_ulogoffX(struct smb_request
*smb1req
)
1839 struct timeval now
= timeval_current();
1840 struct smbXsrv_session
*session
= NULL
;
1841 struct tevent_req
*req
;
1845 * Don't setup the profile charge here, take
1846 * it in reply_ulogoffX_done(). Not strictly correct
1847 * but better than the other SMB1 async
1848 * code that double-charges at the moment.
1851 status
= smb1srv_session_lookup(smb1req
->xconn
,
1853 timeval_to_nttime(&now
),
1855 if (!NT_STATUS_IS_OK(status
)) {
1856 /* Not going async, profile here. */
1857 START_PROFILE(SMBulogoffX
);
1858 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
1859 (unsigned long long)smb1req
->vuid
);
1861 smb1req
->vuid
= UID_FIELD_INVALID
;
1862 reply_force_doserror(smb1req
, ERRSRV
, ERRbaduid
);
1863 END_PROFILE(SMBulogoffX
);
1867 req
= reply_ulogoffX_send(smb1req
, session
);
1869 /* Not going async, profile here. */
1870 START_PROFILE(SMBulogoffX
);
1871 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
1872 END_PROFILE(SMBulogoffX
);
1876 /* We're async. This will complete later. */
1877 tevent_req_set_callback(req
, reply_ulogoffX_done
, smb1req
);
1881 struct reply_ulogoffX_state
{
1882 struct tevent_queue
*wait_queue
;
1883 struct smbXsrv_session
*session
;
1886 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
);
1888 /****************************************************************************
1889 Async SMB1 ulogoffX.
1890 Note, on failure here we deallocate and return NULL to allow the caller to
1891 SMB1 return an error of ERRnomem immediately.
1892 ****************************************************************************/
1894 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
1895 struct smbXsrv_session
*session
)
1897 struct tevent_req
*req
;
1898 struct reply_ulogoffX_state
*state
;
1899 struct tevent_req
*subreq
;
1901 struct smbd_server_connection
*sconn
= session
->client
->sconn
;
1902 uint64_t vuid
= session
->global
->session_wire_id
;
1904 req
= tevent_req_create(smb1req
, &state
,
1905 struct reply_ulogoffX_state
);
1909 state
->wait_queue
= tevent_queue_create(state
,
1910 "reply_ulogoffX_wait_queue");
1911 if (tevent_req_nomem(state
->wait_queue
, req
)) {
1915 state
->session
= session
;
1918 * Make sure that no new request will be able to use this session.
1919 * This ensures that once all outstanding fsp->aio_requests
1920 * on this session are done, we are safe to close it.
1922 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
1924 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
1925 if (fsp
->vuid
!= vuid
) {
1929 * Flag the file as close in progress.
1930 * This will prevent any more IO being
1933 fsp
->fsp_flags
.closing
= true;
1935 if (fsp
->num_aio_requests
> 0) {
1937 * Now wait until all aio requests on this fsp are
1940 * We don't set a callback, as we just want to block the
1941 * wait queue and the talloc_free() of fsp->aio_request
1942 * will remove the item from the wait queue.
1944 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
1947 if (tevent_req_nomem(subreq
, req
)) {
1955 * Now we add our own waiter to the end of the queue,
1956 * this way we get notified when all pending requests are finished
1957 * and reply to the outstanding SMB1 request.
1959 subreq
= tevent_queue_wait_send(state
,
1962 if (tevent_req_nomem(subreq
, req
)) {
1968 * We're really going async - move the SMB1 request from
1969 * a talloc stackframe above us to the sconn talloc-context.
1970 * We need this to stick around until the wait_done
1971 * callback is invoked.
1973 smb1req
= talloc_move(sconn
, &smb1req
);
1975 tevent_req_set_callback(subreq
, reply_ulogoffX_wait_done
, req
);
1980 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
)
1982 struct tevent_req
*req
= tevent_req_callback_data(
1983 subreq
, struct tevent_req
);
1985 tevent_queue_wait_recv(subreq
);
1986 TALLOC_FREE(subreq
);
1987 tevent_req_done(req
);
1990 static NTSTATUS
reply_ulogoffX_recv(struct tevent_req
*req
)
1992 return tevent_req_simple_recv_ntstatus(req
);
1995 static void reply_ulogoffX_done(struct tevent_req
*req
)
1997 struct smb_request
*smb1req
= tevent_req_callback_data(
1998 req
, struct smb_request
);
1999 struct reply_ulogoffX_state
*state
= tevent_req_data(req
,
2000 struct reply_ulogoffX_state
);
2001 struct smbXsrv_session
*session
= state
->session
;
2005 * Take the profile charge here. Not strictly
2006 * correct but better than the other SMB1 async
2007 * code that double-charges at the moment.
2009 START_PROFILE(SMBulogoffX
);
2011 status
= reply_ulogoffX_recv(req
);
2013 if (!NT_STATUS_IS_OK(status
)) {
2014 TALLOC_FREE(smb1req
);
2015 END_PROFILE(SMBulogoffX
);
2016 exit_server(__location__
": reply_ulogoffX_recv failed");
2020 status
= smbXsrv_session_logoff(session
);
2021 if (!NT_STATUS_IS_OK(status
)) {
2022 TALLOC_FREE(smb1req
);
2023 END_PROFILE(SMBulogoffX
);
2024 exit_server(__location__
": smbXsrv_session_logoff failed");
2028 TALLOC_FREE(session
);
2030 reply_smb1_outbuf(smb1req
, 2, 0);
2031 SSVAL(smb1req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2032 SSVAL(smb1req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2034 DBG_NOTICE("ulogoffX vuid=%llu\n",
2035 (unsigned long long)smb1req
->vuid
);
2037 smb1req
->vuid
= UID_FIELD_INVALID
;
2039 * The following call is needed to push the
2040 * reply data back out the socket after async
2041 * return. Plus it frees smb1req.
2043 smb_request_done(smb1req
);
2044 END_PROFILE(SMBulogoffX
);
2047 /****************************************************************************
2048 Reply to a mknew or a create.
2049 ****************************************************************************/
2051 void reply_mknew(struct smb_request
*req
)
2053 connection_struct
*conn
= req
->conn
;
2054 struct smb_filename
*smb_fname
= NULL
;
2057 struct smb_file_time ft
;
2058 struct files_struct
*dirfsp
= NULL
;
2060 int oplock_request
= 0;
2062 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2063 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2064 uint32_t create_disposition
;
2065 uint32_t create_options
= 0;
2068 TALLOC_CTX
*ctx
= talloc_tos();
2070 START_PROFILE(SMBcreate
);
2071 init_smb_file_time(&ft
);
2074 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2078 fattr
= SVAL(req
->vwv
+0, 0);
2079 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2081 if (req
->cmd
== SMBmknew
) {
2082 /* We should fail if file exists. */
2083 create_disposition
= FILE_CREATE
;
2085 /* Create if file doesn't exist, truncate if it does. */
2086 create_disposition
= FILE_OVERWRITE_IF
;
2090 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+1));
2092 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2093 STR_TERMINATE
, &status
);
2094 if (!NT_STATUS_IS_OK(status
)) {
2095 reply_nterror(req
, status
);
2099 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2100 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2101 extract_snapshot_token(fname
, &twrp
);
2104 status
= filename_convert_dirfsp(ctx
,
2111 if (!NT_STATUS_IS_OK(status
)) {
2112 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2113 reply_botherror(req
,
2114 NT_STATUS_PATH_NOT_COVERED
,
2115 ERRSRV
, ERRbadpath
);
2118 reply_nterror(req
, status
);
2122 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2123 DEBUG(0,("Attempt to create file (%s) with volid set - "
2124 "please report this\n",
2125 smb_fname_str_dbg(smb_fname
)));
2128 status
= SMB_VFS_CREATE_FILE(
2131 dirfsp
, /* dirfsp */
2132 smb_fname
, /* fname */
2133 access_mask
, /* access_mask */
2134 share_mode
, /* share_access */
2135 create_disposition
, /* create_disposition*/
2136 create_options
, /* create_options */
2137 fattr
, /* file_attributes */
2138 oplock_request
, /* oplock_request */
2140 0, /* allocation_size */
2141 0, /* private_flags */
2146 NULL
, NULL
); /* create context */
2148 if (!NT_STATUS_IS_OK(status
)) {
2149 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2150 /* We have re-scheduled this call. */
2153 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2154 bool ok
= defer_smb1_sharing_violation(req
);
2159 reply_openerror(req
, status
);
2163 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2164 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2165 if (!NT_STATUS_IS_OK(status
)) {
2166 END_PROFILE(SMBcreate
);
2170 reply_smb1_outbuf(req
, 1, 0);
2171 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2173 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2174 SCVAL(req
->outbuf
,smb_flg
,
2175 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2178 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2179 SCVAL(req
->outbuf
,smb_flg
,
2180 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2183 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2184 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2185 smb_fname_str_dbg(smb_fname
), fsp_get_io_fd(fsp
),
2186 (unsigned int)fattr
));
2189 TALLOC_FREE(smb_fname
);
2190 END_PROFILE(SMBcreate
);
2194 /****************************************************************************
2195 Reply to a create temporary file.
2196 ****************************************************************************/
2198 void reply_ctemp(struct smb_request
*req
)
2200 connection_struct
*conn
= req
->conn
;
2201 struct smb_filename
*smb_fname
= NULL
;
2202 char *wire_name
= NULL
;
2205 struct files_struct
*dirfsp
= NULL
;
2213 TALLOC_CTX
*ctx
= talloc_tos();
2215 START_PROFILE(SMBctemp
);
2218 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2222 fattr
= SVAL(req
->vwv
+0, 0);
2223 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2225 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2226 STR_TERMINATE
, &status
);
2227 if (!NT_STATUS_IS_OK(status
)) {
2228 reply_nterror(req
, status
);
2232 for (i
= 0; i
< 10; i
++) {
2234 fname
= talloc_asprintf(ctx
,
2237 generate_random_str_list(ctx
, 5, "0123456789"));
2239 fname
= talloc_asprintf(ctx
,
2241 generate_random_str_list(ctx
, 5, "0123456789"));
2245 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2249 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2250 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2251 extract_snapshot_token(fname
, &twrp
);
2253 status
= filename_convert_dirfsp(ctx
,
2260 if (!NT_STATUS_IS_OK(status
)) {
2261 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2262 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2263 ERRSRV
, ERRbadpath
);
2266 reply_nterror(req
, status
);
2270 /* Create the file. */
2271 status
= SMB_VFS_CREATE_FILE(
2274 dirfsp
, /* dirfsp */
2275 smb_fname
, /* fname */
2276 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2277 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2278 FILE_CREATE
, /* create_disposition*/
2279 0, /* create_options */
2280 fattr
, /* file_attributes */
2281 oplock_request
, /* oplock_request */
2283 0, /* allocation_size */
2284 0, /* private_flags */
2289 NULL
, NULL
); /* create context */
2291 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2293 TALLOC_FREE(dirfsp
);
2294 TALLOC_FREE(smb_fname
);
2298 if (!NT_STATUS_IS_OK(status
)) {
2299 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2300 /* We have re-scheduled this call. */
2303 if (NT_STATUS_EQUAL(
2304 status
, NT_STATUS_SHARING_VIOLATION
)) {
2305 bool ok
= defer_smb1_sharing_violation(req
);
2310 reply_openerror(req
, status
);
2318 /* Collision after 10 times... */
2319 reply_nterror(req
, status
);
2323 reply_smb1_outbuf(req
, 1, 0);
2324 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2326 /* the returned filename is relative to the directory */
2327 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2329 s
= fsp
->fsp_name
->base_name
;
2335 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2336 thing in the byte section. JRA */
2337 SSVALS(p
, 0, -1); /* what is this? not in spec */
2339 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2341 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2345 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2346 SCVAL(req
->outbuf
, smb_flg
,
2347 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2350 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2351 SCVAL(req
->outbuf
, smb_flg
,
2352 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2355 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2356 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2357 fsp_get_io_fd(fsp
), (unsigned int)smb_fname
->st
.st_ex_mode
));
2359 TALLOC_FREE(smb_fname
);
2360 TALLOC_FREE(wire_name
);
2361 END_PROFILE(SMBctemp
);
2365 /****************************************************************************
2367 ****************************************************************************/
2369 void reply_unlink(struct smb_request
*req
)
2371 connection_struct
*conn
= req
->conn
;
2373 struct files_struct
*dirfsp
= NULL
;
2374 struct smb_filename
*smb_fname
= NULL
;
2377 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
2379 TALLOC_CTX
*ctx
= talloc_tos();
2381 START_PROFILE(SMBunlink
);
2384 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2388 dirtype
= SVAL(req
->vwv
+0, 0);
2390 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2391 STR_TERMINATE
, &status
);
2392 if (!NT_STATUS_IS_OK(status
)) {
2393 reply_nterror(req
, status
);
2397 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2398 extract_snapshot_token(name
, &twrp
);
2400 status
= filename_convert_dirfsp(ctx
,
2407 if (!NT_STATUS_IS_OK(status
)) {
2408 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2409 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2410 ERRSRV
, ERRbadpath
);
2413 reply_nterror(req
, status
);
2417 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2419 status
= unlink_internals(conn
, req
, dirtype
, dirfsp
, smb_fname
);
2420 if (!NT_STATUS_IS_OK(status
)) {
2421 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2422 /* We have re-scheduled this call. */
2425 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2426 bool ok
= defer_smb1_sharing_violation(req
);
2431 reply_nterror(req
, status
);
2435 reply_smb1_outbuf(req
, 0, 0);
2437 TALLOC_FREE(smb_fname
);
2438 END_PROFILE(SMBunlink
);
2442 /****************************************************************************
2444 ****************************************************************************/
2446 static void fail_readraw(void)
2448 const char *errstr
= talloc_asprintf(talloc_tos(),
2449 "FAIL ! reply_readbraw: socket write fail (%s)",
2454 exit_server_cleanly(errstr
);
2457 /****************************************************************************
2458 Return a readbraw error (4 bytes of zero).
2459 ****************************************************************************/
2461 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
2467 smbd_lock_socket(xconn
);
2468 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
2469 int saved_errno
= errno
;
2471 * Try and give an error message saying what
2474 DEBUG(0, ("write_data failed for client %s. "
2476 smbXsrv_connection_dbg(xconn
),
2477 strerror(saved_errno
)));
2478 errno
= saved_errno
;
2482 smbd_unlock_socket(xconn
);
2485 /*******************************************************************
2486 Ensure we don't use sendfile if server smb signing is active.
2487 ********************************************************************/
2489 static bool lp_use_sendfile(int snum
, struct smb1_signing_state
*signing_state
)
2491 bool sign_active
= false;
2493 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2494 if (get_Protocol() < PROTOCOL_NT1
) {
2497 if (signing_state
) {
2498 sign_active
= smb1_signing_is_active(signing_state
);
2500 return (lp__use_sendfile(snum
) &&
2501 (get_remote_arch() != RA_WIN95
) &&
2504 /****************************************************************************
2505 Use sendfile in readbraw.
2506 ****************************************************************************/
2508 static void send_file_readbraw(connection_struct
*conn
,
2509 struct smb_request
*req
,
2515 struct smbXsrv_connection
*xconn
= req
->xconn
;
2516 char *outbuf
= NULL
;
2520 * We can only use sendfile on a non-chained packet
2521 * but we can use on a non-oplocked file. tridge proved this
2522 * on a train in Germany :-). JRA.
2523 * reply_readbraw has already checked the length.
2526 if ( !req_is_in_chain(req
) &&
2528 !fsp_is_alternate_stream(fsp
) &&
2529 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
2530 ssize_t sendfile_read
= -1;
2532 DATA_BLOB header_blob
;
2534 _smb_setlen(header
,nread
);
2535 header_blob
= data_blob_const(header
, 4);
2537 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
2538 &header_blob
, startpos
,
2540 if (sendfile_read
== -1) {
2541 /* Returning ENOSYS means no data at all was sent.
2542 * Do this as a normal read. */
2543 if (errno
== ENOSYS
) {
2544 goto normal_readbraw
;
2548 * Special hack for broken Linux with no working sendfile. If we
2549 * return EINTR we sent the header but not the rest of the data.
2550 * Fake this up by doing read/write calls.
2552 if (errno
== EINTR
) {
2553 /* Ensure we don't do this again. */
2554 set_use_sendfile(SNUM(conn
), False
);
2555 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2557 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
2558 DEBUG(0,("send_file_readbraw: "
2559 "fake_sendfile failed for "
2563 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2568 DEBUG(0,("send_file_readbraw: sendfile failed for "
2569 "file %s (%s). Terminating\n",
2570 fsp_str_dbg(fsp
), strerror(errno
)));
2571 exit_server_cleanly("send_file_readbraw sendfile failed");
2572 } else if (sendfile_read
== 0) {
2574 * Some sendfile implementations return 0 to indicate
2575 * that there was a short read, but nothing was
2576 * actually written to the socket. In this case,
2577 * fallback to the normal read path so the header gets
2578 * the correct byte count.
2580 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2581 "bytes falling back to the normal read: "
2582 "%s\n", fsp_str_dbg(fsp
)));
2583 goto normal_readbraw
;
2586 /* Deal with possible short send. */
2587 if (sendfile_read
!= 4+nread
) {
2588 ret
= sendfile_short_send(xconn
, fsp
,
2589 sendfile_read
, 4, nread
);
2599 outbuf
= talloc_array(NULL
, char, nread
+4);
2601 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2602 (unsigned)(nread
+4)));
2603 reply_readbraw_error(xconn
);
2608 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2609 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2618 _smb_setlen(outbuf
,ret
);
2619 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
2620 int saved_errno
= errno
;
2622 * Try and give an error message saying what
2625 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2626 smbXsrv_connection_dbg(xconn
),
2627 strerror(saved_errno
)));
2628 errno
= saved_errno
;
2633 TALLOC_FREE(outbuf
);
2636 /****************************************************************************
2637 Reply to a readbraw (core+ protocol).
2638 ****************************************************************************/
2640 void reply_readbraw(struct smb_request
*req
)
2642 connection_struct
*conn
= req
->conn
;
2643 struct smbXsrv_connection
*xconn
= req
->xconn
;
2644 ssize_t maxcount
,mincount
;
2648 struct lock_struct lock
;
2652 START_PROFILE(SMBreadbraw
);
2654 if (smb1_srv_is_signing_active(xconn
) || req
->encrypted
) {
2655 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2656 "raw reads/writes are disallowed.");
2660 reply_readbraw_error(xconn
);
2661 END_PROFILE(SMBreadbraw
);
2665 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
2666 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
2667 "'async smb echo handler = yes'\n"));
2668 reply_readbraw_error(xconn
);
2669 END_PROFILE(SMBreadbraw
);
2674 * Special check if an oplock break has been issued
2675 * and the readraw request croses on the wire, we must
2676 * return a zero length response here.
2679 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
2682 * We have to do a check_fsp by hand here, as
2683 * we must always return 4 zero bytes on error,
2689 conn
!= fsp
->conn
||
2690 req
->vuid
!= fsp
->vuid
||
2691 fsp
->fsp_flags
.is_directory
||
2692 fsp_get_io_fd(fsp
) == -1)
2695 * fsp could be NULL here so use the value from the packet. JRA.
2697 DEBUG(3,("reply_readbraw: fnum %d not valid "
2699 (int)SVAL(req
->vwv
+0, 0)));
2700 reply_readbraw_error(xconn
);
2701 END_PROFILE(SMBreadbraw
);
2705 /* Do a "by hand" version of CHECK_READ. */
2706 if (!(fsp
->fsp_flags
.can_read
||
2707 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
2708 (fsp
->access_mask
& FILE_EXECUTE
)))) {
2709 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2710 (int)SVAL(req
->vwv
+0, 0)));
2711 reply_readbraw_error(xconn
);
2712 END_PROFILE(SMBreadbraw
);
2716 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
2717 if(req
->wct
== 10) {
2719 * This is a large offset (64 bit) read.
2722 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
2725 DEBUG(0,("reply_readbraw: negative 64 bit "
2726 "readraw offset (%.0f) !\n",
2727 (double)startpos
));
2728 reply_readbraw_error(xconn
);
2729 END_PROFILE(SMBreadbraw
);
2734 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
2735 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
2737 /* ensure we don't overrun the packet size */
2738 maxcount
= MIN(65535,maxcount
);
2740 init_strict_lock_struct(fsp
,
2741 (uint64_t)req
->smbpid
,
2745 lp_posix_cifsu_locktype(fsp
),
2748 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
2749 reply_readbraw_error(xconn
);
2750 END_PROFILE(SMBreadbraw
);
2754 status
= vfs_stat_fsp(fsp
);
2755 if (NT_STATUS_IS_OK(status
)) {
2756 size
= fsp
->fsp_name
->st
.st_ex_size
;
2759 if (startpos
>= size
) {
2762 nread
= MIN(maxcount
,(size
- startpos
));
2765 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2766 if (nread
< mincount
)
2770 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
2771 "min=%lu nread=%lu\n",
2772 fsp_fnum_dbg(fsp
), (double)startpos
,
2773 (unsigned long)maxcount
,
2774 (unsigned long)mincount
,
2775 (unsigned long)nread
) );
2777 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
2779 DEBUG(5,("reply_readbraw finished\n"));
2781 END_PROFILE(SMBreadbraw
);
2786 #define DBGC_CLASS DBGC_LOCKING
2788 /****************************************************************************
2789 Reply to a lockread (core+ protocol).
2790 ****************************************************************************/
2792 static void reply_lockread_locked(struct tevent_req
*subreq
);
2794 void reply_lockread(struct smb_request
*req
)
2796 struct tevent_req
*subreq
= NULL
;
2797 connection_struct
*conn
= req
->conn
;
2799 struct smbd_lock_element
*lck
= NULL
;
2801 START_PROFILE(SMBlockread
);
2804 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2805 END_PROFILE(SMBlockread
);
2809 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
2811 if (!check_fsp(conn
, req
, fsp
)) {
2812 END_PROFILE(SMBlockread
);
2816 if (!CHECK_READ(fsp
,req
)) {
2817 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2818 END_PROFILE(SMBlockread
);
2822 lck
= talloc(req
, struct smbd_lock_element
);
2824 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2825 END_PROFILE(SMBlockread
);
2830 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2831 * protocol request that predates the read/write lock concept.
2832 * Thus instead of asking for a read lock here we need to ask
2833 * for a write lock. JRA.
2834 * Note that the requested lock size is unaffected by max_send.
2837 *lck
= (struct smbd_lock_element
) {
2838 .req_guid
= smbd_request_guid(req
, 0),
2839 .smblctx
= req
->smbpid
,
2840 .brltype
= WRITE_LOCK
,
2841 .lock_flav
= WINDOWS_LOCK
,
2842 .count
= SVAL(req
->vwv
+1, 0),
2843 .offset
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0),
2846 subreq
= smbd_smb1_do_locks_send(
2852 false, /* large_offset */
2855 if (subreq
== NULL
) {
2856 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2857 END_PROFILE(SMBlockread
);
2860 tevent_req_set_callback(subreq
, reply_lockread_locked
, NULL
);
2861 END_PROFILE(SMBlockread
);
2864 static void reply_lockread_locked(struct tevent_req
*subreq
)
2866 struct smb_request
*req
= NULL
;
2872 size_t numtoread
, maxtoread
;
2873 struct files_struct
*fsp
= NULL
;
2876 START_PROFILE(SMBlockread
);
2878 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
2881 status
= smbd_smb1_do_locks_recv(subreq
);
2882 TALLOC_FREE(subreq
);
2884 if (!NT_STATUS_IS_OK(status
)) {
2885 reply_nterror(req
, status
);
2889 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
2891 reply_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
2895 numtoread
= SVAL(req
->vwv
+1, 0);
2896 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
2899 * However the requested READ size IS affected by max_send. Insanity.... JRA.
2901 maxtoread
= req
->xconn
->smb1
.sessions
.max_send
- (MIN_SMB_SIZE
+ 5*2 + 3);
2903 if (numtoread
> maxtoread
) {
2904 DBG_WARNING("requested read size (%zu) is greater than "
2905 "maximum allowed (%zu/%d). "
2906 "Returning short read of maximum allowed for "
2907 "compatibility with Windows 2000.\n",
2910 req
->xconn
->smb1
.sessions
.max_send
);
2911 numtoread
= maxtoread
;
2914 reply_smb1_outbuf(req
, 5, numtoread
+ 3);
2916 data
= smb_buf(req
->outbuf
) + 3;
2918 nread
= read_file(fsp
,data
,startpos
,numtoread
);
2921 reply_nterror(req
, map_nt_error_from_unix(errno
));
2925 srv_smb1_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
2927 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
2928 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
2929 p
= smb_buf(req
->outbuf
);
2930 SCVAL(p
,0,0); /* pad byte. */
2933 DEBUG(3,("lockread %s num=%d nread=%d\n",
2934 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
2937 ok
= smb1_srv_send(req
->xconn
,
2938 (char *)req
->outbuf
,
2941 IS_CONN_ENCRYPTED(req
->conn
),
2944 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
2947 END_PROFILE(SMBlockread
);
2952 #define DBGC_CLASS DBGC_ALL
2954 /****************************************************************************
2956 ****************************************************************************/
2958 void reply_read(struct smb_request
*req
)
2960 connection_struct
*conn
= req
->conn
;
2967 struct lock_struct lock
;
2968 struct smbXsrv_connection
*xconn
= req
->xconn
;
2970 START_PROFILE(SMBread
);
2973 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2974 END_PROFILE(SMBread
);
2978 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
2980 if (!check_fsp(conn
, req
, fsp
)) {
2981 END_PROFILE(SMBread
);
2985 if (!CHECK_READ(fsp
,req
)) {
2986 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2987 END_PROFILE(SMBread
);
2991 numtoread
= SVAL(req
->vwv
+1, 0);
2992 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
2995 * The requested read size cannot be greater than max_send. JRA.
2997 maxtoread
= xconn
->smb1
.sessions
.max_send
- (MIN_SMB_SIZE
+ 5*2 + 3);
2999 if (numtoread
> maxtoread
) {
3000 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3001 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3002 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3003 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3004 numtoread
= maxtoread
;
3007 reply_smb1_outbuf(req
, 5, numtoread
+3);
3009 data
= smb_buf(req
->outbuf
) + 3;
3011 init_strict_lock_struct(fsp
,
3012 (uint64_t)req
->smbpid
,
3014 (uint64_t)numtoread
,
3016 lp_posix_cifsu_locktype(fsp
),
3019 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3020 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3021 END_PROFILE(SMBread
);
3026 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3029 reply_nterror(req
, map_nt_error_from_unix(errno
));
3033 srv_smb1_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3035 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3036 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3037 SCVAL(smb_buf(req
->outbuf
),0,1);
3038 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3040 DEBUG(3, ("read %s num=%d nread=%d\n",
3041 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3044 END_PROFILE(SMBread
);
3048 /****************************************************************************
3050 ****************************************************************************/
3052 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3056 outsize
= srv_smb1_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3059 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3061 SCVAL(outbuf
,smb_vwv0
,0xFF);
3062 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3063 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3064 SSVAL(outbuf
,smb_vwv6
,
3065 (smb_wct
- 4) /* offset from smb header to wct */
3066 + 1 /* the wct field */
3067 + 12 * sizeof(uint16_t) /* vwv */
3068 + 2 /* the buflen field */
3069 + 1); /* padding byte */
3070 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3071 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3072 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3073 _smb_setlen_large(outbuf
,
3074 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3078 /****************************************************************************
3079 Reply to a read and X - possibly using sendfile.
3080 ****************************************************************************/
3082 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3083 files_struct
*fsp
, off_t startpos
,
3086 struct smbXsrv_connection
*xconn
= req
->xconn
;
3088 struct lock_struct lock
;
3089 int saved_errno
= 0;
3092 init_strict_lock_struct(fsp
,
3093 (uint64_t)req
->smbpid
,
3095 (uint64_t)smb_maxcnt
,
3097 lp_posix_cifsu_locktype(fsp
),
3100 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3101 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3106 * We can only use sendfile on a non-chained packet
3107 * but we can use on a non-oplocked file. tridge proved this
3108 * on a train in Germany :-). JRA.
3111 if (!req_is_in_chain(req
) &&
3113 !fsp_is_alternate_stream(fsp
) &&
3114 lp_use_sendfile(SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3115 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3118 status
= vfs_stat_fsp(fsp
);
3119 if (!NT_STATUS_IS_OK(status
)) {
3120 reply_nterror(req
, status
);
3124 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3125 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3126 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3128 * We already know that we would do a short read, so don't
3129 * try the sendfile() path.
3131 goto nosendfile_read
;
3135 * Set up the packet header before send. We
3136 * assume here the sendfile will work (get the
3137 * correct amount of data).
3140 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3142 construct_smb1_reply_common_req(req
, (char *)headerbuf
);
3143 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3145 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
3146 startpos
, smb_maxcnt
);
3148 saved_errno
= errno
;
3150 /* Returning ENOSYS means no data at all was sent.
3151 Do this as a normal read. */
3152 if (errno
== ENOSYS
) {
3157 * Special hack for broken Linux with no working sendfile. If we
3158 * return EINTR we sent the header but not the rest of the data.
3159 * Fake this up by doing read/write calls.
3162 if (errno
== EINTR
) {
3163 /* Ensure we don't do this again. */
3164 set_use_sendfile(SNUM(conn
), False
);
3165 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3166 nread
= fake_sendfile(xconn
, fsp
, startpos
,
3169 saved_errno
= errno
;
3170 DEBUG(0,("send_file_readX: "
3171 "fake_sendfile failed for "
3172 "file %s (%s) for client %s. "
3175 smbXsrv_connection_dbg(xconn
),
3176 strerror(saved_errno
)));
3177 errno
= saved_errno
;
3178 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3180 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3181 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3182 /* No outbuf here means successful sendfile. */
3186 DEBUG(0,("send_file_readX: sendfile failed for file "
3187 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3189 exit_server_cleanly("send_file_readX sendfile failed");
3190 } else if (nread
== 0) {
3192 * Some sendfile implementations return 0 to indicate
3193 * that there was a short read, but nothing was
3194 * actually written to the socket. In this case,
3195 * fallback to the normal read path so the header gets
3196 * the correct byte count.
3198 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3199 "falling back to the normal read: %s\n",
3204 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3205 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3207 /* Deal with possible short send. */
3208 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3211 ret
= sendfile_short_send(xconn
, fsp
, nread
,
3212 sizeof(headerbuf
), smb_maxcnt
);
3215 r
= "send_file_readX: sendfile_short_send failed";
3216 DEBUG(0,("%s for file %s (%s).\n",
3217 r
, fsp_str_dbg(fsp
), strerror(errno
)));
3218 exit_server_cleanly(r
);
3221 /* No outbuf here means successful sendfile. */
3222 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3223 SMB_PERFCOUNT_END(&req
->pcd
);
3229 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3230 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
3233 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3234 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3235 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3237 * We already know that we would do a short
3238 * read, so don't try the sendfile() path.
3240 goto nosendfile_read
;
3243 construct_smb1_reply_common_req(req
, (char *)headerbuf
);
3244 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3246 /* Send out the header. */
3247 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
3249 if (ret
!= sizeof(headerbuf
)) {
3250 saved_errno
= errno
;
3252 * Try and give an error message saying what
3255 DEBUG(0,("send_file_readX: write_data failed for file "
3256 "%s (%s) for client %s. Terminating\n",
3258 smbXsrv_connection_dbg(xconn
),
3259 strerror(saved_errno
)));
3260 errno
= saved_errno
;
3261 exit_server_cleanly("send_file_readX sendfile failed");
3263 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
3265 saved_errno
= errno
;
3266 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3267 "%s (%s) for client %s. Terminating\n",
3269 smbXsrv_connection_dbg(xconn
),
3270 strerror(saved_errno
)));
3271 errno
= saved_errno
;
3272 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3279 reply_smb1_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
3280 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3281 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3283 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
3284 startpos
, smb_maxcnt
);
3285 saved_errno
= errno
;
3288 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3292 setup_readX_header((char *)req
->outbuf
, nread
);
3294 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3295 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3299 TALLOC_FREE(req
->outbuf
);
3303 /****************************************************************************
3304 Work out how much space we have for a read return.
3305 ****************************************************************************/
3307 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3309 struct smbXsrv_connection
*xconn
= req
->xconn
;
3311 if (xconn
->protocol
< PROTOCOL_NT1
) {
3312 return xconn
->smb1
.sessions
.max_send
;
3315 if (!lp_large_readwrite()) {
3316 return xconn
->smb1
.sessions
.max_send
;
3319 if (req_is_in_chain(req
)) {
3320 return xconn
->smb1
.sessions
.max_send
;
3323 if (req
->encrypted
) {
3325 * Don't take encrypted traffic up to the
3326 * limit. There are padding considerations
3327 * that make that tricky.
3329 return xconn
->smb1
.sessions
.max_send
;
3332 if (smb1_srv_is_signing_active(xconn
)) {
3336 if (!lp_smb1_unix_extensions()) {
3341 * We can do ultra-large POSIX reads.
3346 /****************************************************************************
3347 Calculate how big a read can be. Copes with all clients. It's always
3348 safe to return a short read - Windows does this.
3349 ****************************************************************************/
3351 static size_t calc_read_size(const struct smb_request
*req
,
3355 struct smbXsrv_connection
*xconn
= req
->xconn
;
3356 size_t max_pdu
= calc_max_read_pdu(req
);
3357 size_t total_size
= 0;
3358 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
3359 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
3362 * Windows explicitly ignores upper size of 0xFFFF.
3363 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3364 * We must do the same as these will never fit even in
3365 * an extended size NetBIOS packet.
3367 if (upper_size
== 0xFFFF) {
3371 if (xconn
->protocol
< PROTOCOL_NT1
) {
3375 total_size
= ((upper_size
<<16) | lower_size
);
3378 * LARGE_READX test shows it's always safe to return
3379 * a short read. Windows does so.
3381 return MIN(total_size
, max_len
);
3384 /****************************************************************************
3385 Reply to a read and X.
3386 ****************************************************************************/
3388 void reply_read_and_X(struct smb_request
*req
)
3390 connection_struct
*conn
= req
->conn
;
3395 bool big_readX
= False
;
3397 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3400 START_PROFILE(SMBreadX
);
3402 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3407 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3408 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3409 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3411 /* If it's an IPC, pass off the pipe handler. */
3413 reply_pipe_read_and_X(req
);
3414 END_PROFILE(SMBreadX
);
3418 if (!check_fsp(conn
, req
, fsp
)) {
3419 END_PROFILE(SMBreadX
);
3423 if (!CHECK_READ(fsp
,req
)) {
3424 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3425 END_PROFILE(SMBreadX
);
3429 upper_size
= SVAL(req
->vwv
+7, 0);
3430 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
3431 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
3433 * This is a heuristic to avoid keeping large
3434 * outgoing buffers around over long-lived aio
3440 if (req
->wct
== 12) {
3442 * This is a large offset (64 bit) read.
3444 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
3449 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3454 if (NT_STATUS_IS_OK(status
)) {
3455 /* Read scheduled - we're done. */
3458 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3459 /* Real error - report to client. */
3460 END_PROFILE(SMBreadX
);
3461 reply_nterror(req
, status
);
3464 /* NT_STATUS_RETRY - fall back to sync read. */
3467 smbd_lock_socket(req
->xconn
);
3468 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3469 smbd_unlock_socket(req
->xconn
);
3472 END_PROFILE(SMBreadX
);
3476 /****************************************************************************
3477 Error replies to writebraw must have smb_wct == 1. Fix this up.
3478 ****************************************************************************/
3480 void error_to_writebrawerr(struct smb_request
*req
)
3482 uint8_t *old_outbuf
= req
->outbuf
;
3484 reply_smb1_outbuf(req
, 1, 0);
3486 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3487 TALLOC_FREE(old_outbuf
);
3490 /****************************************************************************
3491 Read 4 bytes of a smb packet and return the smb length of the packet.
3492 Store the result in the buffer. This version of the function will
3493 never return a session keepalive (length of zero).
3494 Timeout is in milliseconds.
3495 ****************************************************************************/
3497 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3500 uint8_t msgtype
= NBSSkeepalive
;
3502 while (msgtype
== NBSSkeepalive
) {
3505 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3507 if (!NT_STATUS_IS_OK(status
)) {
3508 char addr
[INET6_ADDRSTRLEN
];
3509 /* Try and give an error message
3510 * saying what client failed. */
3511 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3512 "client %s read error = %s.\n",
3513 get_peer_addr(fd
,addr
,sizeof(addr
)),
3514 nt_errstr(status
)));
3518 msgtype
= CVAL(inbuf
, 0);
3521 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3522 (unsigned long)len
));
3524 return NT_STATUS_OK
;
3527 /****************************************************************************
3528 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3529 ****************************************************************************/
3531 void reply_writebraw(struct smb_request
*req
)
3533 connection_struct
*conn
= req
->conn
;
3534 struct smbXsrv_connection
*xconn
= req
->xconn
;
3537 ssize_t total_written
=0;
3538 size_t numtowrite
=0;
3541 const char *data
=NULL
;
3544 struct lock_struct lock
;
3547 START_PROFILE(SMBwritebraw
);
3550 * If we ever reply with an error, it must have the SMB command
3551 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3554 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3556 if (smb1_srv_is_signing_active(xconn
)) {
3557 END_PROFILE(SMBwritebraw
);
3558 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3559 "raw reads/writes are disallowed.");
3562 if (req
->wct
< 12) {
3563 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3564 error_to_writebrawerr(req
);
3565 END_PROFILE(SMBwritebraw
);
3569 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3570 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3571 "'async smb echo handler = yes'\n"));
3572 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3573 error_to_writebrawerr(req
);
3574 END_PROFILE(SMBwritebraw
);
3578 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3579 if (!check_fsp(conn
, req
, fsp
)) {
3580 error_to_writebrawerr(req
);
3581 END_PROFILE(SMBwritebraw
);
3585 if (!CHECK_WRITE(fsp
)) {
3586 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3587 error_to_writebrawerr(req
);
3588 END_PROFILE(SMBwritebraw
);
3592 tcount
= IVAL(req
->vwv
+1, 0);
3593 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3594 write_through
= BITSETW(req
->vwv
+7,0);
3596 /* We have to deal with slightly different formats depending
3597 on whether we are using the core+ or lanman1.0 protocol */
3599 if(get_Protocol() <= PROTOCOL_COREPLUS
) {
3600 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
3601 data
= smb_buf_const(req
->inbuf
);
3603 numtowrite
= SVAL(req
->vwv
+10, 0);
3604 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3607 /* Ensure we don't write bytes past the end of this packet. */
3609 * This already protects us against CVE-2017-12163.
3611 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3612 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3613 error_to_writebrawerr(req
);
3614 END_PROFILE(SMBwritebraw
);
3618 if (!fsp
->print_file
) {
3619 init_strict_lock_struct(fsp
,
3620 (uint64_t)req
->smbpid
,
3624 lp_posix_cifsu_locktype(fsp
),
3627 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3628 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3629 error_to_writebrawerr(req
);
3630 END_PROFILE(SMBwritebraw
);
3636 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3639 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3640 "wrote=%d sync=%d\n",
3641 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
3642 (int)nwritten
, (int)write_through
));
3644 if (nwritten
< (ssize_t
)numtowrite
) {
3645 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3646 error_to_writebrawerr(req
);
3650 total_written
= nwritten
;
3652 /* Allocate a buffer of 64k + length. */
3653 buf
= talloc_array(NULL
, char, 65540);
3655 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3656 error_to_writebrawerr(req
);
3660 /* Return a SMBwritebraw message to the redirector to tell
3661 * it to send more bytes */
3663 memcpy(buf
, req
->inbuf
, smb_size
);
3664 srv_smb1_set_message(buf
,get_Protocol()>PROTOCOL_COREPLUS
?1:0,0,True
);
3665 SCVAL(buf
,smb_com
,SMBwritebraw
);
3666 SSVALS(buf
,smb_vwv0
,0xFFFF);
3668 if (!smb1_srv_send(req
->xconn
,
3670 false, 0, /* no signing */
3671 IS_CONN_ENCRYPTED(conn
),
3673 exit_server_cleanly("reply_writebraw: smb1_srv_send "
3677 /* Now read the raw data into the buffer and write it */
3678 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
3680 if (!NT_STATUS_IS_OK(status
)) {
3681 exit_server_cleanly("secondary writebraw failed");
3684 /* Set up outbuf to return the correct size */
3685 reply_smb1_outbuf(req
, 1, 0);
3687 if (numtowrite
!= 0) {
3689 if (numtowrite
> 0xFFFF) {
3690 DEBUG(0,("reply_writebraw: Oversize secondary write "
3691 "raw requested (%u). Terminating\n",
3692 (unsigned int)numtowrite
));
3693 exit_server_cleanly("secondary writebraw failed");
3696 if (tcount
> nwritten
+numtowrite
) {
3697 DEBUG(3,("reply_writebraw: Client overestimated the "
3699 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3702 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
3705 if (!NT_STATUS_IS_OK(status
)) {
3706 /* Try and give an error message
3707 * saying what client failed. */
3708 DEBUG(0, ("reply_writebraw: Oversize secondary write "
3709 "raw read failed (%s) for client %s. "
3710 "Terminating\n", nt_errstr(status
),
3711 smbXsrv_connection_dbg(xconn
)));
3712 exit_server_cleanly("secondary writebraw failed");
3716 * We are not vulnerable to CVE-2017-12163
3717 * here as we are guaranteed to have numtowrite
3718 * bytes available - we just read from the client.
3720 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3721 if (nwritten
== -1) {
3723 reply_nterror(req
, map_nt_error_from_unix(errno
));
3724 error_to_writebrawerr(req
);
3728 if (nwritten
< (ssize_t
)numtowrite
) {
3729 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3730 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3734 total_written
+= nwritten
;
3739 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3741 status
= sync_file(conn
, fsp
, write_through
);
3742 if (!NT_STATUS_IS_OK(status
)) {
3743 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3744 fsp_str_dbg(fsp
), nt_errstr(status
)));
3745 reply_nterror(req
, status
);
3746 error_to_writebrawerr(req
);
3750 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
3752 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
3753 (int)total_written
));
3755 /* We won't return a status if write through is not selected - this
3756 * follows what WfWg does */
3757 END_PROFILE(SMBwritebraw
);
3759 if (!write_through
&& total_written
==tcount
) {
3761 #if RABBIT_PELLET_FIX
3763 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3764 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
3767 if (!send_keepalive(xconn
->transport
.sock
)) {
3768 exit_server_cleanly("reply_writebraw: send of "
3769 "keepalive failed");
3772 TALLOC_FREE(req
->outbuf
);
3777 END_PROFILE(SMBwritebraw
);
3782 #define DBGC_CLASS DBGC_LOCKING
3784 /****************************************************************************
3785 Reply to a writeunlock (core+).
3786 ****************************************************************************/
3788 void reply_writeunlock(struct smb_request
*req
)
3790 connection_struct
*conn
= req
->conn
;
3791 ssize_t nwritten
= -1;
3796 NTSTATUS status
= NT_STATUS_OK
;
3798 struct lock_struct lock
;
3799 int saved_errno
= 0;
3801 START_PROFILE(SMBwriteunlock
);
3804 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3805 END_PROFILE(SMBwriteunlock
);
3809 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3811 if (!check_fsp(conn
, req
, fsp
)) {
3812 END_PROFILE(SMBwriteunlock
);
3816 if (!CHECK_WRITE(fsp
)) {
3817 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3818 END_PROFILE(SMBwriteunlock
);
3822 numtowrite
= SVAL(req
->vwv
+1, 0);
3823 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3824 data
= (const char *)req
->buf
+ 3;
3827 * Ensure client isn't asking us to write more than
3828 * they sent. CVE-2017-12163.
3830 remaining
= smbreq_bufrem(req
, data
);
3831 if (numtowrite
> remaining
) {
3832 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3833 END_PROFILE(SMBwriteunlock
);
3837 if (!fsp
->print_file
&& numtowrite
> 0) {
3838 init_strict_lock_struct(fsp
,
3839 (uint64_t)req
->smbpid
,
3841 (uint64_t)numtowrite
,
3843 lp_posix_cifsu_locktype(fsp
),
3846 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3847 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3848 END_PROFILE(SMBwriteunlock
);
3853 /* The special X/Open SMB protocol handling of
3854 zero length writes is *NOT* done for
3856 if(numtowrite
== 0) {
3859 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3860 saved_errno
= errno
;
3863 status
= sync_file(conn
, fsp
, False
/* write through */);
3864 if (!NT_STATUS_IS_OK(status
)) {
3865 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3866 fsp_str_dbg(fsp
), nt_errstr(status
)));
3867 reply_nterror(req
, status
);
3872 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3876 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
3877 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3881 if (numtowrite
&& !fsp
->print_file
) {
3882 struct smbd_lock_element l
= {
3883 .req_guid
= smbd_request_guid(req
, 0),
3884 .smblctx
= req
->smbpid
,
3885 .brltype
= UNLOCK_LOCK
,
3886 .lock_flav
= WINDOWS_LOCK
,
3888 .count
= numtowrite
,
3890 status
= smbd_do_unlocking(req
, fsp
, 1, &l
);
3891 if (NT_STATUS_V(status
)) {
3892 reply_nterror(req
, status
);
3897 reply_smb1_outbuf(req
, 1, 0);
3899 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
3901 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
3902 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
3905 END_PROFILE(SMBwriteunlock
);
3910 #define DBGC_CLASS DBGC_ALL
3912 /****************************************************************************
3914 ****************************************************************************/
3916 void reply_write(struct smb_request
*req
)
3918 connection_struct
*conn
= req
->conn
;
3921 ssize_t nwritten
= -1;
3925 struct lock_struct lock
;
3927 int saved_errno
= 0;
3929 START_PROFILE(SMBwrite
);
3932 END_PROFILE(SMBwrite
);
3933 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3937 /* If it's an IPC, pass off the pipe handler. */
3939 reply_pipe_write(req
);
3940 END_PROFILE(SMBwrite
);
3944 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3946 if (!check_fsp(conn
, req
, fsp
)) {
3947 END_PROFILE(SMBwrite
);
3951 if (!CHECK_WRITE(fsp
)) {
3952 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3953 END_PROFILE(SMBwrite
);
3957 numtowrite
= SVAL(req
->vwv
+1, 0);
3958 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3959 data
= (const char *)req
->buf
+ 3;
3962 * Ensure client isn't asking us to write more than
3963 * they sent. CVE-2017-12163.
3965 remaining
= smbreq_bufrem(req
, data
);
3966 if (numtowrite
> remaining
) {
3967 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3968 END_PROFILE(SMBwrite
);
3972 if (!fsp
->print_file
) {
3973 init_strict_lock_struct(fsp
,
3974 (uint64_t)req
->smbpid
,
3976 (uint64_t)numtowrite
,
3978 lp_posix_cifsu_locktype(fsp
),
3981 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3982 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3983 END_PROFILE(SMBwrite
);
3989 * X/Open SMB protocol says that if smb_vwv1 is
3990 * zero then the file size should be extended or
3991 * truncated to the size given in smb_vwv[2-3].
3994 if(numtowrite
== 0) {
3996 * This is actually an allocate call, and set EOF. JRA.
3998 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4000 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4003 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4005 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4008 trigger_write_time_update_immediate(fsp
);
4010 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4013 status
= sync_file(conn
, fsp
, False
);
4014 if (!NT_STATUS_IS_OK(status
)) {
4015 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4016 fsp_str_dbg(fsp
), nt_errstr(status
)));
4017 reply_nterror(req
, status
);
4022 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4026 if((nwritten
== 0) && (numtowrite
!= 0)) {
4027 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4031 reply_smb1_outbuf(req
, 1, 0);
4033 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4035 if (nwritten
< (ssize_t
)numtowrite
) {
4036 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4037 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4040 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4043 END_PROFILE(SMBwrite
);
4047 /****************************************************************************
4048 Ensure a buffer is a valid writeX for recvfile purposes.
4049 ****************************************************************************/
4051 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4052 (2*14) + /* word count (including bcc) */ \
4055 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4056 const uint8_t *inbuf
)
4059 unsigned int doff
= 0;
4060 size_t len
= smb_len_large(inbuf
);
4062 struct smbXsrv_open
*op
= NULL
;
4063 struct files_struct
*fsp
= NULL
;
4066 if (is_encrypted_packet(inbuf
)) {
4067 /* Can't do this on encrypted
4072 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4076 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4077 CVAL(inbuf
,smb_wct
) != 14) {
4078 DEBUG(10,("is_valid_writeX_buffer: chained or "
4079 "invalid word length.\n"));
4083 fnum
= SVAL(inbuf
, smb_vwv2
);
4084 status
= smb1srv_open_lookup(xconn
,
4088 if (!NT_STATUS_IS_OK(status
)) {
4089 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4094 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4097 if (fsp
->conn
== NULL
) {
4098 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4102 if (IS_IPC(fsp
->conn
)) {
4103 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4106 if (IS_PRINT(fsp
->conn
)) {
4107 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4110 if (fsp_is_alternate_stream(fsp
)) {
4111 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4114 doff
= SVAL(inbuf
,smb_vwv11
);
4116 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4118 if (len
> doff
&& len
- doff
> 0xFFFF) {
4119 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4122 if (numtowrite
== 0) {
4123 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4127 /* Ensure the sizes match up. */
4128 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4129 /* no pad byte...old smbclient :-( */
4130 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4132 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4136 if (len
- doff
!= numtowrite
) {
4137 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4138 "len = %u, doff = %u, numtowrite = %u\n",
4141 (unsigned int)numtowrite
));
4145 DEBUG(10,("is_valid_writeX_buffer: true "
4146 "len = %u, doff = %u, numtowrite = %u\n",
4149 (unsigned int)numtowrite
));
4154 /****************************************************************************
4155 Reply to a write and X.
4156 ****************************************************************************/
4158 void reply_write_and_X(struct smb_request
*req
)
4160 connection_struct
*conn
= req
->conn
;
4161 struct smbXsrv_connection
*xconn
= req
->xconn
;
4163 struct lock_struct lock
;
4168 unsigned int smb_doff
;
4169 unsigned int smblen
;
4172 int saved_errno
= 0;
4174 START_PROFILE(SMBwriteX
);
4176 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4177 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4181 numtowrite
= SVAL(req
->vwv
+10, 0);
4182 smb_doff
= SVAL(req
->vwv
+11, 0);
4183 smblen
= smb_len(req
->inbuf
);
4185 if (req
->unread_bytes
> 0xFFFF ||
4186 (smblen
> smb_doff
&&
4187 smblen
- smb_doff
> 0xFFFF)) {
4188 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4191 if (req
->unread_bytes
) {
4192 /* Can't do a recvfile write on IPC$ */
4194 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4197 if (numtowrite
!= req
->unread_bytes
) {
4198 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4203 * This already protects us against CVE-2017-12163.
4205 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4206 smb_doff
+ numtowrite
> smblen
) {
4207 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4212 /* If it's an IPC, pass off the pipe handler. */
4214 if (req
->unread_bytes
) {
4215 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4218 reply_pipe_write_and_X(req
);
4222 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4223 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4224 write_through
= BITSETW(req
->vwv
+7,0);
4226 if (!check_fsp(conn
, req
, fsp
)) {
4230 if (!CHECK_WRITE(fsp
)) {
4231 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4235 data
= smb_base(req
->inbuf
) + smb_doff
;
4237 if(req
->wct
== 14) {
4239 * This is a large offset (64 bit) write.
4241 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4245 /* X/Open SMB protocol says that, unlike SMBwrite
4246 if the length is zero then NO truncation is
4247 done, just a write of zero. To truncate a file,
4250 if(numtowrite
== 0) {
4253 if (req
->unread_bytes
== 0) {
4254 status
= schedule_aio_write_and_X(conn
,
4261 if (NT_STATUS_IS_OK(status
)) {
4262 /* write scheduled - we're done. */
4265 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4266 /* Real error - report to client. */
4267 reply_nterror(req
, status
);
4270 /* NT_STATUS_RETRY - fall through to sync write. */
4273 init_strict_lock_struct(fsp
,
4274 (uint64_t)req
->smbpid
,
4276 (uint64_t)numtowrite
,
4278 lp_posix_cifsu_locktype(fsp
),
4281 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4282 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4286 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4287 saved_errno
= errno
;
4291 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4295 if((nwritten
== 0) && (numtowrite
!= 0)) {
4296 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4300 reply_smb1_outbuf(req
, 6, 0);
4301 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4302 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4303 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4304 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4306 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4307 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4309 status
= sync_file(conn
, fsp
, write_through
);
4310 if (!NT_STATUS_IS_OK(status
)) {
4311 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4312 fsp_str_dbg(fsp
), nt_errstr(status
)));
4313 reply_nterror(req
, status
);
4317 END_PROFILE(SMBwriteX
);
4321 if (req
->unread_bytes
) {
4322 /* writeX failed. drain socket. */
4323 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
4324 req
->unread_bytes
) {
4325 smb_panic("failed to drain pending bytes");
4327 req
->unread_bytes
= 0;
4330 END_PROFILE(SMBwriteX
);
4334 /****************************************************************************
4336 ****************************************************************************/
4338 void reply_lseek(struct smb_request
*req
)
4340 connection_struct
*conn
= req
->conn
;
4347 START_PROFILE(SMBlseek
);
4350 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4351 END_PROFILE(SMBlseek
);
4355 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4357 if (!check_fsp(conn
, req
, fsp
)) {
4361 mode
= SVAL(req
->vwv
+1, 0) & 3;
4362 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4363 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4372 res
= fh_get_pos(fsp
->fh
) + startpos
;
4383 if (umode
== SEEK_END
) {
4384 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4385 if(errno
== EINVAL
) {
4386 off_t current_pos
= startpos
;
4388 status
= vfs_stat_fsp(fsp
);
4389 if (!NT_STATUS_IS_OK(status
)) {
4390 reply_nterror(req
, status
);
4391 END_PROFILE(SMBlseek
);
4395 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4397 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4402 reply_nterror(req
, map_nt_error_from_unix(errno
));
4403 END_PROFILE(SMBlseek
);
4408 fh_set_pos(fsp
->fh
, res
);
4410 reply_smb1_outbuf(req
, 2, 0);
4411 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4413 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4414 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4416 END_PROFILE(SMBlseek
);
4420 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
4423 connection_struct
*conn
= talloc_get_type_abort(
4424 private_data
, connection_struct
);
4426 if (conn
!= fsp
->conn
) {
4429 if (fsp_get_io_fd(fsp
) == -1) {
4432 sync_file(conn
, fsp
, True
/* write through */);
4434 if (fsp
->fsp_flags
.modified
) {
4435 trigger_write_time_update_immediate(fsp
);
4441 /****************************************************************************
4443 ****************************************************************************/
4445 void reply_flush(struct smb_request
*req
)
4447 connection_struct
*conn
= req
->conn
;
4451 START_PROFILE(SMBflush
);
4454 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4458 fnum
= SVAL(req
->vwv
+0, 0);
4459 fsp
= file_fsp(req
, fnum
);
4461 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4466 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
4468 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4469 if (!NT_STATUS_IS_OK(status
)) {
4470 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4471 fsp_str_dbg(fsp
), nt_errstr(status
)));
4472 reply_nterror(req
, status
);
4473 END_PROFILE(SMBflush
);
4476 if (fsp
->fsp_flags
.modified
) {
4477 trigger_write_time_update_immediate(fsp
);
4481 reply_smb1_outbuf(req
, 0, 0);
4483 DEBUG(3,("flush\n"));
4484 END_PROFILE(SMBflush
);
4488 /****************************************************************************
4490 conn POINTER CAN BE NULL HERE !
4491 ****************************************************************************/
4493 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
);
4494 static void reply_exit_done(struct tevent_req
*req
);
4496 void reply_exit(struct smb_request
*smb1req
)
4498 struct tevent_req
*req
;
4501 * Don't setup the profile charge here, take
4502 * it in reply_exit_done(). Not strictly correct
4503 * but better than the other SMB1 async
4504 * code that double-charges at the moment.
4506 req
= reply_exit_send(smb1req
);
4508 /* Not going async, profile here. */
4509 START_PROFILE(SMBexit
);
4510 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
4511 END_PROFILE(SMBexit
);
4515 /* We're async. This will complete later. */
4516 tevent_req_set_callback(req
, reply_exit_done
, smb1req
);
4520 struct reply_exit_state
{
4521 struct tevent_queue
*wait_queue
;
4524 static void reply_exit_wait_done(struct tevent_req
*subreq
);
4526 /****************************************************************************
4528 Note, on failure here we deallocate and return NULL to allow the caller to
4529 SMB1 return an error of ERRnomem immediately.
4530 ****************************************************************************/
4532 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
)
4534 struct tevent_req
*req
;
4535 struct reply_exit_state
*state
;
4536 struct tevent_req
*subreq
;
4538 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4540 req
= tevent_req_create(smb1req
, &state
,
4541 struct reply_exit_state
);
4545 state
->wait_queue
= tevent_queue_create(state
,
4546 "reply_exit_wait_queue");
4547 if (tevent_req_nomem(state
->wait_queue
, req
)) {
4552 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
4553 if (fsp
->file_pid
!= smb1req
->smbpid
) {
4556 if (fsp
->vuid
!= smb1req
->vuid
) {
4560 * Flag the file as close in progress.
4561 * This will prevent any more IO being
4564 fsp
->fsp_flags
.closing
= true;
4566 if (fsp
->num_aio_requests
> 0) {
4568 * Now wait until all aio requests on this fsp are
4571 * We don't set a callback, as we just want to block the
4572 * wait queue and the talloc_free() of fsp->aio_request
4573 * will remove the item from the wait queue.
4575 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
4578 if (tevent_req_nomem(subreq
, req
)) {
4586 * Now we add our own waiter to the end of the queue,
4587 * this way we get notified when all pending requests are finished
4588 * and reply to the outstanding SMB1 request.
4590 subreq
= tevent_queue_wait_send(state
,
4593 if (tevent_req_nomem(subreq
, req
)) {
4599 * We're really going async - move the SMB1 request from
4600 * a talloc stackframe above us to the conn talloc-context.
4601 * We need this to stick around until the wait_done
4602 * callback is invoked.
4604 smb1req
= talloc_move(sconn
, &smb1req
);
4606 tevent_req_set_callback(subreq
, reply_exit_wait_done
, req
);
4611 static void reply_exit_wait_done(struct tevent_req
*subreq
)
4613 struct tevent_req
*req
= tevent_req_callback_data(
4614 subreq
, struct tevent_req
);
4616 tevent_queue_wait_recv(subreq
);
4617 TALLOC_FREE(subreq
);
4618 tevent_req_done(req
);
4621 static NTSTATUS
reply_exit_recv(struct tevent_req
*req
)
4623 return tevent_req_simple_recv_ntstatus(req
);
4626 static void reply_exit_done(struct tevent_req
*req
)
4628 struct smb_request
*smb1req
= tevent_req_callback_data(
4629 req
, struct smb_request
);
4630 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4631 struct smbXsrv_connection
*xconn
= smb1req
->xconn
;
4632 NTTIME now
= timeval_to_nttime(&smb1req
->request_time
);
4633 struct smbXsrv_session
*session
= NULL
;
4634 files_struct
*fsp
, *next
;
4638 * Take the profile charge here. Not strictly
4639 * correct but better than the other SMB1 async
4640 * code that double-charges at the moment.
4642 START_PROFILE(SMBexit
);
4644 status
= reply_exit_recv(req
);
4646 if (!NT_STATUS_IS_OK(status
)) {
4647 TALLOC_FREE(smb1req
);
4648 END_PROFILE(SMBexit
);
4649 exit_server(__location__
": reply_exit_recv failed");
4654 * Ensure the session is still valid.
4656 status
= smb1srv_session_lookup(xconn
,
4660 if (!NT_STATUS_IS_OK(status
)) {
4661 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
4662 smb_request_done(smb1req
);
4663 END_PROFILE(SMBexit
);
4667 * Ensure the vuid is still valid - no one
4668 * called reply_ulogoffX() in the meantime.
4669 * reply_exit() doesn't have AS_USER set, so
4670 * use set_current_user_info() directly.
4671 * This is the same logic as in switch_message().
4673 if (session
->global
->auth_session_info
!= NULL
) {
4674 set_current_user_info(
4675 session
->global
->auth_session_info
->unix_info
->sanitized_username
,
4676 session
->global
->auth_session_info
->unix_info
->unix_name
,
4677 session
->global
->auth_session_info
->info
->domain_name
);
4680 /* No more aio - do the actual closes. */
4681 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
4685 if (fsp
->file_pid
!= smb1req
->smbpid
) {
4688 if (fsp
->vuid
!= smb1req
->vuid
) {
4691 if (!fsp
->fsp_flags
.closing
) {
4696 * reply_exit() has the DO_CHDIR flag set.
4698 ok
= chdir_current_service(fsp
->conn
);
4700 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
4701 smb_request_done(smb1req
);
4702 END_PROFILE(SMBexit
);
4704 close_file_free(NULL
, &fsp
, SHUTDOWN_CLOSE
);
4707 reply_smb1_outbuf(smb1req
, 0, 0);
4709 * The following call is needed to push the
4710 * reply data back out the socket after async
4711 * return. Plus it frees smb1req.
4713 smb_request_done(smb1req
);
4714 DBG_INFO("reply_exit complete\n");
4715 END_PROFILE(SMBexit
);
4719 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
4721 static void reply_close_done(struct tevent_req
*req
);
4723 void reply_close(struct smb_request
*smb1req
)
4725 connection_struct
*conn
= smb1req
->conn
;
4726 NTSTATUS status
= NT_STATUS_OK
;
4727 files_struct
*fsp
= NULL
;
4728 START_PROFILE(SMBclose
);
4730 if (smb1req
->wct
< 3) {
4731 reply_nterror(smb1req
, NT_STATUS_INVALID_PARAMETER
);
4732 END_PROFILE(SMBclose
);
4736 fsp
= file_fsp(smb1req
, SVAL(smb1req
->vwv
+0, 0));
4739 * We can only use check_fsp if we know it's not a directory.
4742 if (!check_fsp_open(conn
, smb1req
, fsp
)) {
4743 reply_nterror(smb1req
, NT_STATUS_INVALID_HANDLE
);
4744 END_PROFILE(SMBclose
);
4748 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
4749 fsp
->fsp_flags
.is_directory
?
4750 "directory" : "file",
4751 fsp_get_pathref_fd(fsp
), fsp_fnum_dbg(fsp
),
4752 conn
->num_files_open
);
4754 if (!fsp
->fsp_flags
.is_directory
) {
4758 * Take care of any time sent in the close.
4761 t
= srv_make_unix_date3(smb1req
->vwv
+1);
4762 set_close_write_time(fsp
, time_t_to_full_timespec(t
));
4765 if (fsp
->num_aio_requests
!= 0) {
4766 struct tevent_req
*req
;
4768 req
= reply_close_send(smb1req
, fsp
);
4770 status
= NT_STATUS_NO_MEMORY
;
4773 /* We're async. This will complete later. */
4774 tevent_req_set_callback(req
, reply_close_done
, smb1req
);
4775 END_PROFILE(SMBclose
);
4780 * close_file_free() returns the unix errno if an error was detected on
4781 * close - normally this is due to a disk full error. If not then it
4782 * was probably an I/O error.
4785 status
= close_file_free(smb1req
, &fsp
, NORMAL_CLOSE
);
4787 if (!NT_STATUS_IS_OK(status
)) {
4788 reply_nterror(smb1req
, status
);
4789 END_PROFILE(SMBclose
);
4793 reply_smb1_outbuf(smb1req
, 0, 0);
4794 END_PROFILE(SMBclose
);
4798 struct reply_close_state
{
4800 struct tevent_queue
*wait_queue
;
4803 static void reply_close_wait_done(struct tevent_req
*subreq
);
4805 /****************************************************************************
4807 Note, on failure here we deallocate and return NULL to allow the caller to
4808 SMB1 return an error of ERRnomem immediately.
4809 ****************************************************************************/
4811 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
4814 struct tevent_req
*req
;
4815 struct reply_close_state
*state
;
4816 struct tevent_req
*subreq
;
4817 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4819 req
= tevent_req_create(smb1req
, &state
,
4820 struct reply_close_state
);
4824 state
->wait_queue
= tevent_queue_create(state
,
4825 "reply_close_wait_queue");
4826 if (tevent_req_nomem(state
->wait_queue
, req
)) {
4832 * Flag the file as close in progress.
4833 * This will prevent any more IO being
4836 fsp
->fsp_flags
.closing
= true;
4839 * Now wait until all aio requests on this fsp are
4842 * We don't set a callback, as we just want to block the
4843 * wait queue and the talloc_free() of fsp->aio_request
4844 * will remove the item from the wait queue.
4846 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
4849 if (tevent_req_nomem(subreq
, req
)) {
4855 * Now we add our own waiter to the end of the queue,
4856 * this way we get notified when all pending requests are finished
4857 * and reply to the outstanding SMB1 request.
4859 subreq
= tevent_queue_wait_send(state
,
4862 if (tevent_req_nomem(subreq
, req
)) {
4868 * We're really going async - move the SMB1 request from
4869 * a talloc stackframe above us to the conn talloc-context.
4870 * We need this to stick around until the wait_done
4871 * callback is invoked.
4873 smb1req
= talloc_move(sconn
, &smb1req
);
4875 tevent_req_set_callback(subreq
, reply_close_wait_done
, req
);
4880 static void reply_close_wait_done(struct tevent_req
*subreq
)
4882 struct tevent_req
*req
= tevent_req_callback_data(
4883 subreq
, struct tevent_req
);
4885 tevent_queue_wait_recv(subreq
);
4886 TALLOC_FREE(subreq
);
4887 tevent_req_done(req
);
4890 static NTSTATUS
reply_close_recv(struct tevent_req
*req
)
4892 return tevent_req_simple_recv_ntstatus(req
);
4895 static void reply_close_done(struct tevent_req
*req
)
4897 struct smb_request
*smb1req
= tevent_req_callback_data(
4898 req
, struct smb_request
);
4899 struct reply_close_state
*state
= tevent_req_data(req
,
4900 struct reply_close_state
);
4903 status
= reply_close_recv(req
);
4905 if (!NT_STATUS_IS_OK(status
)) {
4906 TALLOC_FREE(smb1req
);
4907 exit_server(__location__
": reply_close_recv failed");
4911 status
= close_file_free(smb1req
, &state
->fsp
, NORMAL_CLOSE
);
4912 if (NT_STATUS_IS_OK(status
)) {
4913 reply_smb1_outbuf(smb1req
, 0, 0);
4915 reply_nterror(smb1req
, status
);
4918 * The following call is needed to push the
4919 * reply data back out the socket after async
4920 * return. Plus it frees smb1req.
4922 smb_request_done(smb1req
);
4925 /****************************************************************************
4926 Reply to a writeclose (Core+ protocol).
4927 ****************************************************************************/
4929 void reply_writeclose(struct smb_request
*req
)
4931 connection_struct
*conn
= req
->conn
;
4934 ssize_t nwritten
= -1;
4935 NTSTATUS close_status
= NT_STATUS_OK
;
4938 struct timespec mtime
;
4940 struct lock_struct lock
;
4942 START_PROFILE(SMBwriteclose
);
4945 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4946 END_PROFILE(SMBwriteclose
);
4950 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4952 if (!check_fsp(conn
, req
, fsp
)) {
4953 END_PROFILE(SMBwriteclose
);
4956 if (!CHECK_WRITE(fsp
)) {
4957 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4958 END_PROFILE(SMBwriteclose
);
4962 numtowrite
= SVAL(req
->vwv
+1, 0);
4963 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4964 mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+4));
4965 data
= (const char *)req
->buf
+ 1;
4968 * Ensure client isn't asking us to write more than
4969 * they sent. CVE-2017-12163.
4971 remaining
= smbreq_bufrem(req
, data
);
4972 if (numtowrite
> remaining
) {
4973 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4974 END_PROFILE(SMBwriteclose
);
4978 if (fsp
->print_file
== NULL
) {
4979 init_strict_lock_struct(fsp
,
4980 (uint64_t)req
->smbpid
,
4982 (uint64_t)numtowrite
,
4984 lp_posix_cifsu_locktype(fsp
),
4987 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4988 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4989 END_PROFILE(SMBwriteclose
);
4994 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4996 set_close_write_time(fsp
, mtime
);
4999 * More insanity. W2K only closes the file if writelen > 0.
5003 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5004 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5005 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5008 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5009 "file %s\n", fsp_str_dbg(fsp
)));
5010 close_status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5013 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5014 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5018 if(!NT_STATUS_IS_OK(close_status
)) {
5019 reply_nterror(req
, close_status
);
5023 reply_smb1_outbuf(req
, 1, 0);
5025 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5029 END_PROFILE(SMBwriteclose
);
5034 #define DBGC_CLASS DBGC_LOCKING
5036 /****************************************************************************
5038 ****************************************************************************/
5040 static void reply_lock_done(struct tevent_req
*subreq
);
5042 void reply_lock(struct smb_request
*req
)
5044 struct tevent_req
*subreq
= NULL
;
5045 connection_struct
*conn
= req
->conn
;
5047 struct smbd_lock_element
*lck
= NULL
;
5049 START_PROFILE(SMBlock
);
5052 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5053 END_PROFILE(SMBlock
);
5057 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5059 if (!check_fsp(conn
, req
, fsp
)) {
5060 END_PROFILE(SMBlock
);
5064 lck
= talloc(req
, struct smbd_lock_element
);
5066 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5067 END_PROFILE(SMBlock
);
5071 *lck
= (struct smbd_lock_element
) {
5072 .req_guid
= smbd_request_guid(req
, 0),
5073 .smblctx
= req
->smbpid
,
5074 .brltype
= WRITE_LOCK
,
5075 .lock_flav
= WINDOWS_LOCK
,
5076 .count
= IVAL(req
->vwv
+1, 0),
5077 .offset
= IVAL(req
->vwv
+3, 0),
5080 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5086 subreq
= smbd_smb1_do_locks_send(
5092 false, /* large_offset */
5095 if (subreq
== NULL
) {
5096 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5097 END_PROFILE(SMBlock
);
5100 tevent_req_set_callback(subreq
, reply_lock_done
, NULL
);
5101 END_PROFILE(SMBlock
);
5104 static void reply_lock_done(struct tevent_req
*subreq
)
5106 struct smb_request
*req
= NULL
;
5110 START_PROFILE(SMBlock
);
5112 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
5115 status
= smbd_smb1_do_locks_recv(subreq
);
5116 TALLOC_FREE(subreq
);
5118 if (NT_STATUS_IS_OK(status
)) {
5119 reply_smb1_outbuf(req
, 0, 0);
5121 reply_nterror(req
, status
);
5124 ok
= smb1_srv_send(req
->xconn
,
5125 (char *)req
->outbuf
,
5128 IS_CONN_ENCRYPTED(req
->conn
),
5131 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5134 END_PROFILE(SMBlock
);
5137 /****************************************************************************
5139 ****************************************************************************/
5141 void reply_unlock(struct smb_request
*req
)
5143 connection_struct
*conn
= req
->conn
;
5146 struct smbd_lock_element lck
;
5148 START_PROFILE(SMBunlock
);
5151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5152 END_PROFILE(SMBunlock
);
5156 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5158 if (!check_fsp(conn
, req
, fsp
)) {
5159 END_PROFILE(SMBunlock
);
5163 lck
= (struct smbd_lock_element
) {
5164 .req_guid
= smbd_request_guid(req
, 0),
5165 .smblctx
= req
->smbpid
,
5166 .brltype
= UNLOCK_LOCK
,
5167 .lock_flav
= WINDOWS_LOCK
,
5168 .offset
= IVAL(req
->vwv
+3, 0),
5169 .count
= IVAL(req
->vwv
+1, 0),
5172 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
);
5174 if (!NT_STATUS_IS_OK(status
)) {
5175 reply_nterror(req
, status
);
5176 END_PROFILE(SMBunlock
);
5180 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5186 reply_smb1_outbuf(req
, 0, 0);
5188 END_PROFILE(SMBunlock
);
5193 #define DBGC_CLASS DBGC_ALL
5195 /****************************************************************************
5197 conn POINTER CAN BE NULL HERE !
5198 ****************************************************************************/
5200 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
);
5201 static void reply_tdis_done(struct tevent_req
*req
);
5203 void reply_tdis(struct smb_request
*smb1req
)
5205 connection_struct
*conn
= smb1req
->conn
;
5206 struct tevent_req
*req
;
5209 * Don't setup the profile charge here, take
5210 * it in reply_tdis_done(). Not strictly correct
5211 * but better than the other SMB1 async
5212 * code that double-charges at the moment.
5216 /* Not going async, profile here. */
5217 START_PROFILE(SMBtdis
);
5218 DBG_INFO("Invalid connection in tdis\n");
5219 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5220 END_PROFILE(SMBtdis
);
5224 req
= reply_tdis_send(smb1req
);
5226 /* Not going async, profile here. */
5227 START_PROFILE(SMBtdis
);
5228 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
5229 END_PROFILE(SMBtdis
);
5232 /* We're async. This will complete later. */
5233 tevent_req_set_callback(req
, reply_tdis_done
, smb1req
);
5237 struct reply_tdis_state
{
5238 struct tevent_queue
*wait_queue
;
5241 static void reply_tdis_wait_done(struct tevent_req
*subreq
);
5243 /****************************************************************************
5245 Note, on failure here we deallocate and return NULL to allow the caller to
5246 SMB1 return an error of ERRnomem immediately.
5247 ****************************************************************************/
5249 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
)
5251 struct tevent_req
*req
;
5252 struct reply_tdis_state
*state
;
5253 struct tevent_req
*subreq
;
5254 connection_struct
*conn
= smb1req
->conn
;
5257 req
= tevent_req_create(smb1req
, &state
,
5258 struct reply_tdis_state
);
5262 state
->wait_queue
= tevent_queue_create(state
, "reply_tdis_wait_queue");
5263 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5269 * Make sure that no new request will be able to use this tcon.
5270 * This ensures that once all outstanding fsp->aio_requests
5271 * on this tcon are done, we are safe to close it.
5273 conn
->tcon
->status
= NT_STATUS_NETWORK_NAME_DELETED
;
5275 for (fsp
= conn
->sconn
->files
; fsp
; fsp
= fsp
->next
) {
5276 if (fsp
->conn
!= conn
) {
5280 * Flag the file as close in progress.
5281 * This will prevent any more IO being
5282 * done on it. Not strictly needed, but
5283 * doesn't hurt to flag it as closing.
5285 fsp
->fsp_flags
.closing
= true;
5287 if (fsp
->num_aio_requests
> 0) {
5289 * Now wait until all aio requests on this fsp are
5292 * We don't set a callback, as we just want to block the
5293 * wait queue and the talloc_free() of fsp->aio_request
5294 * will remove the item from the wait queue.
5296 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5297 conn
->sconn
->ev_ctx
,
5299 if (tevent_req_nomem(subreq
, req
)) {
5307 * Now we add our own waiter to the end of the queue,
5308 * this way we get notified when all pending requests are finished
5309 * and reply to the outstanding SMB1 request.
5311 subreq
= tevent_queue_wait_send(state
,
5312 conn
->sconn
->ev_ctx
,
5314 if (tevent_req_nomem(subreq
, req
)) {
5320 * We're really going async - move the SMB1 request from
5321 * a talloc stackframe above us to the sconn talloc-context.
5322 * We need this to stick around until the wait_done
5323 * callback is invoked.
5325 smb1req
= talloc_move(smb1req
->sconn
, &smb1req
);
5327 tevent_req_set_callback(subreq
, reply_tdis_wait_done
, req
);
5332 static void reply_tdis_wait_done(struct tevent_req
*subreq
)
5334 struct tevent_req
*req
= tevent_req_callback_data(
5335 subreq
, struct tevent_req
);
5337 tevent_queue_wait_recv(subreq
);
5338 TALLOC_FREE(subreq
);
5339 tevent_req_done(req
);
5342 static NTSTATUS
reply_tdis_recv(struct tevent_req
*req
)
5344 return tevent_req_simple_recv_ntstatus(req
);
5347 static void reply_tdis_done(struct tevent_req
*req
)
5349 struct smb_request
*smb1req
= tevent_req_callback_data(
5350 req
, struct smb_request
);
5352 struct smbXsrv_tcon
*tcon
= smb1req
->conn
->tcon
;
5356 * Take the profile charge here. Not strictly
5357 * correct but better than the other SMB1 async
5358 * code that double-charges at the moment.
5360 START_PROFILE(SMBtdis
);
5362 status
= reply_tdis_recv(req
);
5364 if (!NT_STATUS_IS_OK(status
)) {
5365 TALLOC_FREE(smb1req
);
5366 END_PROFILE(SMBtdis
);
5367 exit_server(__location__
": reply_tdis_recv failed");
5372 * As we've been awoken, we may have changed
5373 * directory in the meantime.
5374 * reply_tdis() has the DO_CHDIR flag set.
5376 ok
= chdir_current_service(smb1req
->conn
);
5378 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5379 smb_request_done(smb1req
);
5380 END_PROFILE(SMBtdis
);
5383 status
= smbXsrv_tcon_disconnect(tcon
,
5385 if (!NT_STATUS_IS_OK(status
)) {
5386 TALLOC_FREE(smb1req
);
5387 END_PROFILE(SMBtdis
);
5388 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5392 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5393 smb1req
->conn
= NULL
;
5397 reply_smb1_outbuf(smb1req
, 0, 0);
5399 * The following call is needed to push the
5400 * reply data back out the socket after async
5401 * return. Plus it frees smb1req.
5403 smb_request_done(smb1req
);
5404 END_PROFILE(SMBtdis
);
5407 /****************************************************************************
5409 conn POINTER CAN BE NULL HERE !
5410 ****************************************************************************/
5412 void reply_echo(struct smb_request
*req
)
5414 connection_struct
*conn
= req
->conn
;
5415 struct smb_perfcount_data local_pcd
;
5416 struct smb_perfcount_data
*cur_pcd
;
5420 START_PROFILE(SMBecho
);
5422 smb_init_perfcount_data(&local_pcd
);
5425 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5426 END_PROFILE(SMBecho
);
5430 smb_reverb
= SVAL(req
->vwv
+0, 0);
5432 reply_smb1_outbuf(req
, 1, req
->buflen
);
5434 /* copy any incoming data back out */
5435 if (req
->buflen
> 0) {
5436 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5439 if (smb_reverb
> 100) {
5440 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5444 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5446 /* this makes sure we catch the request pcd */
5447 if (seq_num
== smb_reverb
) {
5448 cur_pcd
= &req
->pcd
;
5450 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
5451 cur_pcd
= &local_pcd
;
5454 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5456 show_msg((char *)req
->outbuf
);
5457 if (!smb1_srv_send(req
->xconn
,
5458 (char *)req
->outbuf
,
5459 true, req
->seqnum
+1,
5460 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
5462 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5465 DEBUG(3,("echo %d times\n", smb_reverb
));
5467 TALLOC_FREE(req
->outbuf
);
5469 END_PROFILE(SMBecho
);
5473 /****************************************************************************
5474 Reply to a printopen.
5475 ****************************************************************************/
5477 void reply_printopen(struct smb_request
*req
)
5479 connection_struct
*conn
= req
->conn
;
5483 START_PROFILE(SMBsplopen
);
5486 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5487 END_PROFILE(SMBsplopen
);
5491 if (!CAN_PRINT(conn
)) {
5492 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5493 END_PROFILE(SMBsplopen
);
5497 status
= file_new(req
, conn
, &fsp
);
5498 if(!NT_STATUS_IS_OK(status
)) {
5499 reply_nterror(req
, status
);
5500 END_PROFILE(SMBsplopen
);
5504 /* Open for exclusive use, write only. */
5505 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5507 if (!NT_STATUS_IS_OK(status
)) {
5508 file_free(req
, fsp
);
5509 reply_nterror(req
, status
);
5510 END_PROFILE(SMBsplopen
);
5514 reply_smb1_outbuf(req
, 1, 0);
5515 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5517 DEBUG(3,("openprint fd=%d %s\n",
5518 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
5520 END_PROFILE(SMBsplopen
);
5524 /****************************************************************************
5525 Reply to a printclose.
5526 ****************************************************************************/
5528 void reply_printclose(struct smb_request
*req
)
5530 connection_struct
*conn
= req
->conn
;
5534 START_PROFILE(SMBsplclose
);
5537 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5538 END_PROFILE(SMBsplclose
);
5542 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5544 if (!check_fsp(conn
, req
, fsp
)) {
5545 END_PROFILE(SMBsplclose
);
5549 if (!CAN_PRINT(conn
)) {
5550 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5551 END_PROFILE(SMBsplclose
);
5555 DEBUG(3,("printclose fd=%d %s\n",
5556 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
5558 status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5560 if(!NT_STATUS_IS_OK(status
)) {
5561 reply_nterror(req
, status
);
5562 END_PROFILE(SMBsplclose
);
5566 reply_smb1_outbuf(req
, 0, 0);
5568 END_PROFILE(SMBsplclose
);
5572 /****************************************************************************
5573 Reply to a printqueue.
5574 ****************************************************************************/
5576 void reply_printqueue(struct smb_request
*req
)
5578 const struct loadparm_substitution
*lp_sub
=
5579 loadparm_s3_global_substitution();
5580 connection_struct
*conn
= req
->conn
;
5584 START_PROFILE(SMBsplretq
);
5587 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5588 END_PROFILE(SMBsplretq
);
5592 max_count
= SVAL(req
->vwv
+0, 0);
5593 start_index
= SVAL(req
->vwv
+1, 0);
5595 /* we used to allow the client to get the cnum wrong, but that
5596 is really quite gross and only worked when there was only
5597 one printer - I think we should now only accept it if they
5598 get it right (tridge) */
5599 if (!CAN_PRINT(conn
)) {
5600 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5601 END_PROFILE(SMBsplretq
);
5605 reply_smb1_outbuf(req
, 2, 3);
5606 SSVAL(req
->outbuf
,smb_vwv0
,0);
5607 SSVAL(req
->outbuf
,smb_vwv1
,0);
5608 SCVAL(smb_buf(req
->outbuf
),0,1);
5609 SSVAL(smb_buf(req
->outbuf
),1,0);
5611 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5612 start_index
, max_count
));
5615 TALLOC_CTX
*mem_ctx
= talloc_tos();
5618 const char *sharename
= lp_servicename(mem_ctx
, lp_sub
, SNUM(conn
));
5619 struct rpc_pipe_client
*cli
= NULL
;
5620 struct dcerpc_binding_handle
*b
= NULL
;
5621 struct policy_handle handle
;
5622 struct spoolss_DevmodeContainer devmode_ctr
;
5623 union spoolss_JobInfo
*info
;
5625 uint32_t num_to_get
;
5629 ZERO_STRUCT(handle
);
5631 status
= rpc_pipe_open_interface(mem_ctx
,
5634 conn
->sconn
->remote_address
,
5635 conn
->sconn
->local_address
,
5636 conn
->sconn
->msg_ctx
,
5638 if (!NT_STATUS_IS_OK(status
)) {
5639 DEBUG(0, ("reply_printqueue: "
5640 "could not connect to spoolss: %s\n",
5641 nt_errstr(status
)));
5642 reply_nterror(req
, status
);
5645 b
= cli
->binding_handle
;
5647 ZERO_STRUCT(devmode_ctr
);
5649 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5652 SEC_FLAG_MAXIMUM_ALLOWED
,
5655 if (!NT_STATUS_IS_OK(status
)) {
5656 reply_nterror(req
, status
);
5659 if (!W_ERROR_IS_OK(werr
)) {
5660 reply_nterror(req
, werror_to_ntstatus(werr
));
5664 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
5672 if (!W_ERROR_IS_OK(werr
)) {
5673 reply_nterror(req
, werror_to_ntstatus(werr
));
5677 if (max_count
> 0) {
5678 first
= start_index
;
5680 first
= start_index
+ max_count
+ 1;
5683 if (first
>= count
) {
5686 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
5689 for (i
= first
; i
< num_to_get
; i
++) {
5692 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
5695 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
5696 info
[i
].info2
.job_id
);
5698 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
5704 srv_put_dos_date2(p
, 0, qtime
);
5705 SCVAL(p
, 4, qstatus
);
5706 SSVAL(p
, 5, qrapjobid
);
5707 SIVAL(p
, 7, info
[i
].info2
.size
);
5709 status
= srvstr_push(blob
, req
->flags2
, p
+12,
5710 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
5711 if (!NT_STATUS_IS_OK(status
)) {
5712 reply_nterror(req
, status
);
5715 if (message_push_blob(
5718 blob
, sizeof(blob
))) == -1) {
5719 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5725 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5726 SSVAL(req
->outbuf
,smb_vwv1
,
5727 (max_count
>0?first
+count
:first
-1));
5728 SCVAL(smb_buf(req
->outbuf
),0,1);
5729 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5733 DEBUG(3, ("%u entries returned in queue\n",
5737 if (b
&& is_valid_policy_hnd(&handle
)) {
5738 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
5743 END_PROFILE(SMBsplretq
);
5747 /****************************************************************************
5748 Reply to a printwrite.
5749 ****************************************************************************/
5751 void reply_printwrite(struct smb_request
*req
)
5753 connection_struct
*conn
= req
->conn
;
5758 START_PROFILE(SMBsplwr
);
5761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5762 END_PROFILE(SMBsplwr
);
5766 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5768 if (!check_fsp(conn
, req
, fsp
)) {
5769 END_PROFILE(SMBsplwr
);
5773 if (!fsp
->print_file
) {
5774 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5775 END_PROFILE(SMBsplwr
);
5779 if (!CHECK_WRITE(fsp
)) {
5780 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5781 END_PROFILE(SMBsplwr
);
5785 numtowrite
= SVAL(req
->buf
, 1);
5788 * This already protects us against CVE-2017-12163.
5790 if (req
->buflen
< numtowrite
+ 3) {
5791 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5792 END_PROFILE(SMBsplwr
);
5796 data
= (const char *)req
->buf
+ 3;
5798 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
5799 reply_nterror(req
, map_nt_error_from_unix(errno
));
5800 END_PROFILE(SMBsplwr
);
5804 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
5806 reply_smb1_outbuf(req
, 0, 0);
5808 END_PROFILE(SMBsplwr
);
5812 /****************************************************************************
5814 ****************************************************************************/
5816 void reply_mkdir(struct smb_request
*req
)
5818 connection_struct
*conn
= req
->conn
;
5819 struct files_struct
*dirfsp
= NULL
;
5820 struct smb_filename
*smb_dname
= NULL
;
5821 char *directory
= NULL
;
5825 TALLOC_CTX
*ctx
= talloc_tos();
5827 START_PROFILE(SMBmkdir
);
5829 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5830 STR_TERMINATE
, &status
);
5831 if (!NT_STATUS_IS_OK(status
)) {
5832 reply_nterror(req
, status
);
5836 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
5837 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5838 extract_snapshot_token(directory
, &twrp
);
5840 status
= filename_convert_dirfsp(ctx
,
5847 if (!NT_STATUS_IS_OK(status
)) {
5848 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5849 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5850 ERRSRV
, ERRbadpath
);
5853 reply_nterror(req
, status
);
5857 status
= create_directory(conn
, req
, dirfsp
, smb_dname
);
5859 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5861 if (!NT_STATUS_IS_OK(status
)) {
5863 if (!use_nt_status()
5864 && NT_STATUS_EQUAL(status
,
5865 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5867 * Yes, in the DOS error code case we get a
5868 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5869 * samba4 torture test.
5871 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5874 reply_nterror(req
, status
);
5878 reply_smb1_outbuf(req
, 0, 0);
5880 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5882 TALLOC_FREE(smb_dname
);
5883 END_PROFILE(SMBmkdir
);
5887 /****************************************************************************
5889 ****************************************************************************/
5891 void reply_rmdir(struct smb_request
*req
)
5893 connection_struct
*conn
= req
->conn
;
5894 struct smb_filename
*smb_dname
= NULL
;
5895 char *directory
= NULL
;
5897 TALLOC_CTX
*ctx
= talloc_tos();
5898 struct files_struct
*dirfsp
= NULL
;
5899 files_struct
*fsp
= NULL
;
5902 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
5904 START_PROFILE(SMBrmdir
);
5906 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5907 STR_TERMINATE
, &status
);
5908 if (!NT_STATUS_IS_OK(status
)) {
5909 reply_nterror(req
, status
);
5913 if (ucf_flags
& UCF_GMT_PATHNAME
) {
5914 extract_snapshot_token(directory
, &twrp
);
5916 status
= filename_convert_dirfsp(ctx
,
5923 if (!NT_STATUS_IS_OK(status
)) {
5924 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5925 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5926 ERRSRV
, ERRbadpath
);
5929 reply_nterror(req
, status
);
5933 status
= SMB_VFS_CREATE_FILE(
5936 dirfsp
, /* dirfsp */
5937 smb_dname
, /* fname */
5938 DELETE_ACCESS
, /* access_mask */
5939 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
5941 FILE_OPEN
, /* create_disposition*/
5942 FILE_DIRECTORY_FILE
, /* create_options */
5943 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
5944 0, /* oplock_request */
5946 0, /* allocation_size */
5947 0, /* private_flags */
5952 NULL
, NULL
); /* create context */
5954 if (!NT_STATUS_IS_OK(status
)) {
5955 if (open_was_deferred(req
->xconn
, req
->mid
)) {
5956 /* We have re-scheduled this call. */
5959 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
5960 bool ok
= defer_smb1_sharing_violation(req
);
5965 reply_nterror(req
, status
);
5969 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
5970 if (!NT_STATUS_IS_OK(status
)) {
5971 close_file_free(req
, &fsp
, ERROR_CLOSE
);
5972 reply_nterror(req
, status
);
5976 if (!set_delete_on_close(fsp
, true,
5977 conn
->session_info
->security_token
,
5978 conn
->session_info
->unix_token
)) {
5979 close_file_free(req
, &fsp
, ERROR_CLOSE
);
5980 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5984 status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5985 if (!NT_STATUS_IS_OK(status
)) {
5986 reply_nterror(req
, status
);
5988 reply_smb1_outbuf(req
, 0, 0);
5991 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5993 TALLOC_FREE(smb_dname
);
5994 END_PROFILE(SMBrmdir
);
5998 /****************************************************************************
6000 ****************************************************************************/
6002 void reply_mv(struct smb_request
*req
)
6004 connection_struct
*conn
= req
->conn
;
6006 char *newname
= NULL
;
6010 TALLOC_CTX
*ctx
= talloc_tos();
6011 struct files_struct
*src_dirfsp
= NULL
;
6012 struct smb_filename
*smb_fname_src
= NULL
;
6013 struct files_struct
*dst_dirfsp
= NULL
;
6014 struct smb_filename
*smb_fname_dst
= NULL
;
6015 const char *dst_original_lcomp
= NULL
;
6016 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
);
6017 NTTIME src_twrp
= 0;
6018 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
);
6019 NTTIME dst_twrp
= 0;
6020 bool stream_rename
= false;
6022 START_PROFILE(SMBmv
);
6025 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6029 attrs
= SVAL(req
->vwv
+0, 0);
6031 p
= (const char *)req
->buf
+ 1;
6032 p
+= srvstr_get_path_req(ctx
, req
, &name
, p
, STR_TERMINATE
,
6034 if (!NT_STATUS_IS_OK(status
)) {
6035 reply_nterror(req
, status
);
6039 p
+= srvstr_get_path_req(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6041 if (!NT_STATUS_IS_OK(status
)) {
6042 reply_nterror(req
, status
);
6046 if (!req
->posix_pathnames
) {
6047 /* The newname must begin with a ':' if the
6048 name contains a ':'. */
6049 if (strchr_m(name
, ':')) {
6050 if (newname
[0] != ':') {
6051 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6054 stream_rename
= true;
6058 if (src_ucf_flags
& UCF_GMT_PATHNAME
) {
6059 extract_snapshot_token(name
, &src_twrp
);
6061 status
= filename_convert_dirfsp(ctx
,
6069 if (!NT_STATUS_IS_OK(status
)) {
6070 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6071 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6072 ERRSRV
, ERRbadpath
);
6075 reply_nterror(req
, status
);
6079 if (dst_ucf_flags
& UCF_GMT_PATHNAME
) {
6080 extract_snapshot_token(newname
, &dst_twrp
);
6082 status
= filename_convert_dirfsp(ctx
,
6090 if (!NT_STATUS_IS_OK(status
)) {
6091 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6092 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6093 ERRSRV
, ERRbadpath
);
6096 reply_nterror(req
, status
);
6100 /* Get the last component of the destination for rename_internals(). */
6101 dst_original_lcomp
= get_original_lcomp(ctx
,
6105 if (dst_original_lcomp
== NULL
) {
6106 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6110 if (stream_rename
) {
6111 /* smb_fname_dst->base_name must be the same as
6112 smb_fname_src->base_name. */
6113 TALLOC_FREE(smb_fname_dst
->base_name
);
6114 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6115 smb_fname_src
->base_name
);
6116 if (!smb_fname_dst
->base_name
) {
6117 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6122 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6123 smb_fname_str_dbg(smb_fname_dst
)));
6125 status
= rename_internals(ctx
,
6128 src_dirfsp
, /* src_dirfsp */
6130 dst_dirfsp
, /* dst_dirfsp */
6136 if (!NT_STATUS_IS_OK(status
)) {
6137 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6138 /* We have re-scheduled this call. */
6141 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6142 bool ok
= defer_smb1_sharing_violation(req
);
6147 reply_nterror(req
, status
);
6151 reply_smb1_outbuf(req
, 0, 0);
6153 TALLOC_FREE(smb_fname_src
);
6154 TALLOC_FREE(smb_fname_dst
);
6159 /****************************************************************************
6160 Reply to a file copy.
6164 This command was introduced in the LAN Manager 1.0 dialect
6165 It was rendered obsolete in the NT LAN Manager dialect.
6166 This command was used to perform server-side file copies, but
6167 is no longer used. Clients SHOULD
6168 NOT send requests using this command code.
6169 Servers receiving requests with this command code
6170 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6171 ****************************************************************************/
6173 void reply_copy(struct smb_request
*req
)
6175 START_PROFILE(SMBcopy
);
6176 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
6177 END_PROFILE(SMBcopy
);
6182 #define DBGC_CLASS DBGC_LOCKING
6184 /****************************************************************************
6185 Get a lock pid, dealing with large count requests.
6186 ****************************************************************************/
6188 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
6189 bool large_file_format
)
6191 if(!large_file_format
)
6192 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6194 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6197 /****************************************************************************
6198 Get a lock count, dealing with large count requests.
6199 ****************************************************************************/
6201 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
6202 bool large_file_format
)
6206 if(!large_file_format
) {
6207 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6210 * No BVAL, this is reversed!
6212 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6213 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6219 /****************************************************************************
6220 Reply to a lockingX request.
6221 ****************************************************************************/
6223 static void reply_lockingx_done(struct tevent_req
*subreq
);
6225 void reply_lockingX(struct smb_request
*req
)
6227 connection_struct
*conn
= req
->conn
;
6229 unsigned char locktype
;
6230 enum brl_type brltype
;
6231 unsigned char oplocklevel
;
6232 uint16_t num_ulocks
;
6234 int32_t lock_timeout
;
6236 const uint8_t *data
;
6237 bool large_file_format
;
6238 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6239 struct smbd_lock_element
*locks
= NULL
;
6240 struct tevent_req
*subreq
= NULL
;
6242 START_PROFILE(SMBlockingX
);
6245 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6246 END_PROFILE(SMBlockingX
);
6250 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
6251 locktype
= CVAL(req
->vwv
+3, 0);
6252 oplocklevel
= CVAL(req
->vwv
+3, 1);
6253 num_ulocks
= SVAL(req
->vwv
+6, 0);
6254 num_locks
= SVAL(req
->vwv
+7, 0);
6255 lock_timeout
= IVAL(req
->vwv
+4, 0);
6256 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
6258 if (!check_fsp(conn
, req
, fsp
)) {
6259 END_PROFILE(SMBlockingX
);
6265 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6266 /* we don't support these - and CANCEL_LOCK makes w2k
6267 and XP reboot so I don't really want to be
6268 compatible! (tridge) */
6269 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
6270 END_PROFILE(SMBlockingX
);
6274 /* Check if this is an oplock break on a file
6275 we have granted an oplock on.
6277 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
6278 /* Client can insist on breaking to none. */
6279 bool break_to_none
= (oplocklevel
== 0);
6282 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6283 "for %s\n", (unsigned int)oplocklevel
,
6284 fsp_fnum_dbg(fsp
)));
6287 * Make sure we have granted an exclusive or batch oplock on
6291 if (fsp
->oplock_type
== 0) {
6293 /* The Samba4 nbench simulator doesn't understand
6294 the difference between break to level2 and break
6295 to none from level2 - it sends oplock break
6296 replies in both cases. Don't keep logging an error
6297 message here - just ignore it. JRA. */
6299 DEBUG(5,("reply_lockingX: Error : oplock break from "
6300 "client for %s (oplock=%d) and no "
6301 "oplock granted on this file (%s).\n",
6302 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
6305 /* if this is a pure oplock break request then don't
6307 if (num_locks
== 0 && num_ulocks
== 0) {
6308 END_PROFILE(SMBlockingX
);
6312 END_PROFILE(SMBlockingX
);
6313 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
6317 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6319 result
= remove_oplock(fsp
);
6321 result
= downgrade_oplock(fsp
);
6325 DEBUG(0, ("reply_lockingX: error in removing "
6326 "oplock on file %s\n", fsp_str_dbg(fsp
)));
6327 /* Hmmm. Is this panic justified? */
6328 smb_panic("internal tdb error");
6331 /* if this is a pure oplock break request then don't send a
6333 if (num_locks
== 0 && num_ulocks
== 0) {
6334 /* Sanity check - ensure a pure oplock break is not a
6336 if (CVAL(req
->vwv
+0, 0) != 0xff) {
6337 DEBUG(0,("reply_lockingX: Error : pure oplock "
6338 "break is a chained %d request !\n",
6339 (unsigned int)CVAL(req
->vwv
+0, 0)));
6341 END_PROFILE(SMBlockingX
);
6347 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6348 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6349 END_PROFILE(SMBlockingX
);
6353 if (num_ulocks
!= 0) {
6354 struct smbd_lock_element
*ulocks
= NULL
;
6357 ulocks
= talloc_array(
6358 req
, struct smbd_lock_element
, num_ulocks
);
6359 if (ulocks
== NULL
) {
6360 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6361 END_PROFILE(SMBlockingX
);
6366 * Data now points at the beginning of the list of
6367 * smb_unlkrng structs
6369 for (i
= 0; i
< num_ulocks
; i
++) {
6370 ulocks
[i
].req_guid
= smbd_request_guid(req
,
6372 ulocks
[i
].smblctx
= get_lock_pid(
6373 data
, i
, large_file_format
);
6374 ulocks
[i
].count
= get_lock_count(
6375 data
, i
, large_file_format
);
6376 ulocks
[i
].offset
= get_lock_offset(
6377 data
, i
, large_file_format
);
6378 ulocks
[i
].brltype
= UNLOCK_LOCK
;
6379 ulocks
[i
].lock_flav
= WINDOWS_LOCK
;
6383 * Unlock cancels pending locks
6386 ok
= smbd_smb1_brl_finish_by_lock(
6392 reply_smb1_outbuf(req
, 2, 0);
6393 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6394 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6395 END_PROFILE(SMBlockingX
);
6399 status
= smbd_do_unlocking(
6400 req
, fsp
, num_ulocks
, ulocks
);
6401 TALLOC_FREE(ulocks
);
6402 if (!NT_STATUS_IS_OK(status
)) {
6403 END_PROFILE(SMBlockingX
);
6404 reply_nterror(req
, status
);
6409 /* Now do any requested locks */
6410 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6412 /* Data now points at the beginning of the list
6413 of smb_lkrng structs */
6415 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
6416 brltype
= READ_LOCK
;
6418 brltype
= WRITE_LOCK
;
6421 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
6422 if (locks
== NULL
) {
6423 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6424 END_PROFILE(SMBlockingX
);
6428 for (i
= 0; i
< num_locks
; i
++) {
6429 locks
[i
].req_guid
= smbd_request_guid(req
, i
),
6430 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
6431 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
6432 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
6433 locks
[i
].brltype
= brltype
;
6434 locks
[i
].lock_flav
= WINDOWS_LOCK
;
6437 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6441 if (num_locks
== 0) {
6442 /* See smbtorture3 lock11 test */
6443 reply_smb1_outbuf(req
, 2, 0);
6444 /* andx chain ends */
6445 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6446 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6447 END_PROFILE(SMBlockingX
);
6451 ok
= smbd_smb1_brl_finish_by_lock(
6454 locks
[0], /* Windows only cancels the first lock */
6455 NT_STATUS_FILE_LOCK_CONFLICT
);
6458 reply_force_doserror(req
, ERRDOS
, ERRcancelviolation
);
6459 END_PROFILE(SMBlockingX
);
6463 reply_smb1_outbuf(req
, 2, 0);
6464 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6465 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6466 END_PROFILE(SMBlockingX
);
6470 subreq
= smbd_smb1_do_locks_send(
6479 if (subreq
== NULL
) {
6480 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6481 END_PROFILE(SMBlockingX
);
6484 tevent_req_set_callback(subreq
, reply_lockingx_done
, NULL
);
6485 END_PROFILE(SMBlockingX
);
6488 static void reply_lockingx_done(struct tevent_req
*subreq
)
6490 struct smb_request
*req
= NULL
;
6494 START_PROFILE(SMBlockingX
);
6496 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
6499 status
= smbd_smb1_do_locks_recv(subreq
);
6500 TALLOC_FREE(subreq
);
6502 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status
));
6504 if (NT_STATUS_IS_OK(status
)) {
6505 reply_smb1_outbuf(req
, 2, 0);
6506 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
6507 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
6509 reply_nterror(req
, status
);
6512 ok
= smb1_srv_send(req
->xconn
,
6513 (char *)req
->outbuf
,
6516 IS_CONN_ENCRYPTED(req
->conn
),
6519 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6522 END_PROFILE(SMBlockingX
);
6526 #define DBGC_CLASS DBGC_ALL
6528 /****************************************************************************
6529 Reply to a SMBreadbmpx (read block multiplex) request.
6530 Always reply with an error, if someone has a platform really needs this,
6531 please contact vl@samba.org
6532 ****************************************************************************/
6534 void reply_readbmpx(struct smb_request
*req
)
6536 START_PROFILE(SMBreadBmpx
);
6537 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6538 END_PROFILE(SMBreadBmpx
);
6542 /****************************************************************************
6543 Reply to a SMBreadbs (read block multiplex secondary) request.
6544 Always reply with an error, if someone has a platform really needs this,
6545 please contact vl@samba.org
6546 ****************************************************************************/
6548 void reply_readbs(struct smb_request
*req
)
6550 START_PROFILE(SMBreadBs
);
6551 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6552 END_PROFILE(SMBreadBs
);
6556 /****************************************************************************
6557 Reply to a SMBsetattrE.
6558 ****************************************************************************/
6560 void reply_setattrE(struct smb_request
*req
)
6562 connection_struct
*conn
= req
->conn
;
6563 struct smb_file_time ft
;
6567 START_PROFILE(SMBsetattrE
);
6568 init_smb_file_time(&ft
);
6571 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6575 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6577 if(!fsp
|| (fsp
->conn
!= conn
)) {
6578 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6583 * Convert the DOS times into unix times.
6586 ft
.atime
= time_t_to_full_timespec(
6587 srv_make_unix_date2(req
->vwv
+3));
6588 ft
.mtime
= time_t_to_full_timespec(
6589 srv_make_unix_date2(req
->vwv
+5));
6590 ft
.create_time
= time_t_to_full_timespec(
6591 srv_make_unix_date2(req
->vwv
+1));
6593 reply_smb1_outbuf(req
, 0, 0);
6596 * Patch from Ray Frush <frush@engr.colostate.edu>
6597 * Sometimes times are sent as zero - ignore them.
6600 /* Ensure we have a valid stat struct for the source. */
6601 status
= vfs_stat_fsp(fsp
);
6602 if (!NT_STATUS_IS_OK(status
)) {
6603 reply_nterror(req
, status
);
6607 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6608 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6612 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
6613 if (!NT_STATUS_IS_OK(status
)) {
6614 reply_nterror(req
, status
);
6618 if (fsp
->fsp_flags
.modified
) {
6619 trigger_write_time_update_immediate(fsp
);
6622 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6625 (unsigned int)ft
.atime
.tv_sec
,
6626 (unsigned int)ft
.mtime
.tv_sec
,
6627 (unsigned int)ft
.create_time
.tv_sec
6630 END_PROFILE(SMBsetattrE
);
6635 /* Back from the dead for OS/2..... JRA. */
6637 /****************************************************************************
6638 Reply to a SMBwritebmpx (write block multiplex primary) request.
6639 Always reply with an error, if someone has a platform really needs this,
6640 please contact vl@samba.org
6641 ****************************************************************************/
6643 void reply_writebmpx(struct smb_request
*req
)
6645 START_PROFILE(SMBwriteBmpx
);
6646 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6647 END_PROFILE(SMBwriteBmpx
);
6651 /****************************************************************************
6652 Reply to a SMBwritebs (write block multiplex secondary) request.
6653 Always reply with an error, if someone has a platform really needs this,
6654 please contact vl@samba.org
6655 ****************************************************************************/
6657 void reply_writebs(struct smb_request
*req
)
6659 START_PROFILE(SMBwriteBs
);
6660 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6661 END_PROFILE(SMBwriteBs
);
6665 /****************************************************************************
6666 Reply to a SMBgetattrE.
6667 ****************************************************************************/
6669 void reply_getattrE(struct smb_request
*req
)
6671 connection_struct
*conn
= req
->conn
;
6674 struct timespec create_ts
;
6677 START_PROFILE(SMBgetattrE
);
6680 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6681 END_PROFILE(SMBgetattrE
);
6685 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6687 if(!fsp
|| (fsp
->conn
!= conn
)) {
6688 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6689 END_PROFILE(SMBgetattrE
);
6693 /* Do an fstat on this file */
6694 status
= vfs_stat_fsp(fsp
);
6695 if (!NT_STATUS_IS_OK(status
)) {
6696 reply_nterror(req
, status
);
6697 END_PROFILE(SMBgetattrE
);
6701 mode
= fdos_mode(fsp
);
6704 * Convert the times into dos times. Set create
6705 * date to be last modify date as UNIX doesn't save
6709 reply_smb1_outbuf(req
, 11, 0);
6711 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
6712 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
6713 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
6714 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
6715 /* Should we check pending modtime here ? JRA */
6716 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
6717 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
6719 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
6720 SIVAL(req
->outbuf
, smb_vwv6
, 0);
6721 SIVAL(req
->outbuf
, smb_vwv8
, 0);
6723 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
6724 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
6725 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
6727 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
6729 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
6731 END_PROFILE(SMBgetattrE
);
6735 /****************************************************************************
6736 Reply to a SMBfindclose (stop trans2 directory search).
6737 ****************************************************************************/
6739 void reply_findclose(struct smb_request
*req
)
6742 struct smbd_server_connection
*sconn
= req
->sconn
;
6743 files_struct
*fsp
= NULL
;
6745 START_PROFILE(SMBfindclose
);
6748 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6749 END_PROFILE(SMBfindclose
);
6753 dptr_num
= SVALS(req
->vwv
+0, 0);
6755 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
6758 * OS/2 seems to use -1 to indicate "close all directories"
6759 * This has to mean on this specific connection struct.
6761 if (dptr_num
== -1) {
6762 dptr_closecnum(req
->conn
);
6764 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
6767 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
6771 reply_smb1_outbuf(req
, 0, 0);
6773 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
6775 END_PROFILE(SMBfindclose
);
6779 /****************************************************************************
6780 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6781 ****************************************************************************/
6783 void reply_findnclose(struct smb_request
*req
)
6787 START_PROFILE(SMBfindnclose
);
6790 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6791 END_PROFILE(SMBfindnclose
);
6795 dptr_num
= SVAL(req
->vwv
+0, 0);
6797 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
6799 /* We never give out valid handles for a
6800 findnotifyfirst - so any dptr_num is ok here.
6803 reply_smb1_outbuf(req
, 0, 0);
6805 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
6807 END_PROFILE(SMBfindnclose
);