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 /****************************************************************************
56 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
57 ****************************************************************************/
59 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
62 if ((fsp
== NULL
) || (conn
== NULL
)) {
63 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
66 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
67 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
73 /****************************************************************************
74 SMB1 version of smb2_strip_dfs_path()
75 Differs from SMB2 in that all Windows path separator '\' characters
76 have already been converted to '/' by check_path_syntax().
77 ****************************************************************************/
79 NTSTATUS
smb1_strip_dfs_path(TALLOC_CTX
*mem_ctx
,
83 uint32_t ucf_flags
= *_ucf_flags
;
84 char *path
= *in_path
;
85 char *return_path
= NULL
;
87 if (!(ucf_flags
& UCF_DFS_PATHNAME
)) {
91 /* Strip any leading '/' characters - MacOSX client behavior. */
92 while (*path
== '/') {
96 /* We should now be pointing at the server name. Go past it. */
99 /* End of complete path. Exit OK. */
103 /* End of server name. Go past and break. */
107 path
++; /* Continue looking for end of server name or string. */
110 /* We should now be pointing at the share name. Go past it. */
113 /* End of complete path. Exit OK. */
117 /* End of share name. Go past and break. */
122 /* Only invalid character in sharename. */
123 return NT_STATUS_OBJECT_NAME_INVALID
;
125 path
++; /* Continue looking for end of share name or string. */
129 /* path now points at the start of the real filename (if any). */
130 /* Duplicate it first. */
131 return_path
= talloc_strdup(mem_ctx
, path
);
132 if (return_path
== NULL
) {
133 return NT_STATUS_NO_MEMORY
;
136 /* Now we can free the original (path points to part of this). */
137 TALLOC_FREE(*in_path
);
139 *in_path
= return_path
;
140 ucf_flags
&= ~UCF_DFS_PATHNAME
;
141 *_ucf_flags
= ucf_flags
;
145 /****************************************************************************
146 Check if we have a correct fsp pointing to a file.
147 ****************************************************************************/
149 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
152 if (!check_fsp_open(conn
, req
, fsp
)) {
155 if (fsp
->fsp_flags
.is_directory
) {
156 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
159 if (fsp_get_pathref_fd(fsp
) == -1) {
160 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
163 fsp
->num_smb_operations
++;
167 /****************************************************************************
169 conn POINTER CAN BE NULL HERE !
170 ****************************************************************************/
172 void reply_tcon(struct smb_request
*req
)
174 connection_struct
*conn
= req
->conn
;
176 char *service_buf
= NULL
;
177 char *password
= NULL
;
183 TALLOC_CTX
*ctx
= talloc_tos();
184 struct smbXsrv_connection
*xconn
= req
->xconn
;
185 NTTIME now
= timeval_to_nttime(&req
->request_time
);
187 START_PROFILE(SMBtcon
);
189 if (req
->buflen
< 4) {
190 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
191 END_PROFILE(SMBtcon
);
196 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
198 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
200 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
203 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
204 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
205 END_PROFILE(SMBtcon
);
208 p2
= strrchr_m(service_buf
,'\\');
212 service
= service_buf
;
215 conn
= make_connection(req
, now
, service
, dev
,
216 req
->vuid
,&nt_status
);
220 reply_nterror(req
, nt_status
);
221 END_PROFILE(SMBtcon
);
225 reply_smb1_outbuf(req
, 2, 0);
226 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
227 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
228 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
230 DEBUG(3,("tcon service=%s cnum=%d\n",
231 service
, conn
->cnum
));
233 END_PROFILE(SMBtcon
);
237 /****************************************************************************
238 Reply to a tcon and X.
239 conn POINTER CAN BE NULL HERE !
240 ****************************************************************************/
242 void reply_tcon_and_X(struct smb_request
*req
)
244 const struct loadparm_substitution
*lp_sub
=
245 loadparm_s3_global_substitution();
246 connection_struct
*conn
= req
->conn
;
247 const char *service
= NULL
;
248 TALLOC_CTX
*ctx
= talloc_tos();
249 /* what the client thinks the device is */
250 char *client_devicetype
= NULL
;
251 /* what the server tells the client the share represents */
252 const char *server_devicetype
;
259 struct smbXsrv_session
*session
= NULL
;
260 NTTIME now
= timeval_to_nttime(&req
->request_time
);
261 bool session_key_updated
= false;
262 uint16_t optional_support
= 0;
263 struct smbXsrv_connection
*xconn
= req
->xconn
;
265 START_PROFILE(SMBtconX
);
268 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
269 END_PROFILE(SMBtconX
);
273 passlen
= SVAL(req
->vwv
+3, 0);
274 tcon_flags
= SVAL(req
->vwv
+2, 0);
276 /* we might have to close an old one */
277 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
278 struct smbXsrv_tcon
*tcon
;
286 * TODO: cancel all outstanding requests on the tcon
288 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
289 if (!NT_STATUS_IS_OK(status
)) {
290 DEBUG(0, ("reply_tcon_and_X: "
291 "smbXsrv_tcon_disconnect() failed: %s\n",
294 * If we hit this case, there is something completely
295 * wrong, so we better disconnect the transport connection.
297 END_PROFILE(SMBtconX
);
298 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
304 * This tree id is gone. Make sure we can't re-use it
310 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
311 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
312 END_PROFILE(SMBtconX
);
316 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
317 p
= req
->buf
+ passlen
;
319 p
= req
->buf
+ passlen
+ 1;
322 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
325 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
326 END_PROFILE(SMBtconX
);
331 * the service name can be either: \\server\share
332 * or share directly like on the DELL PowerVault 705
335 q
= strchr_m(path
+2,'\\');
337 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
338 END_PROFILE(SMBtconX
);
346 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
347 &client_devicetype
, p
,
348 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
350 if (client_devicetype
== NULL
) {
351 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
352 END_PROFILE(SMBtconX
);
356 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
358 nt_status
= smb1srv_session_lookup(xconn
,
359 req
->vuid
, now
, &session
);
360 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
361 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
362 END_PROFILE(SMBtconX
);
365 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
366 reply_nterror(req
, nt_status
);
367 END_PROFILE(SMBtconX
);
370 if (!NT_STATUS_IS_OK(nt_status
)) {
371 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
372 END_PROFILE(SMBtconX
);
376 if (session
->global
->auth_session_info
== NULL
) {
377 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
378 END_PROFILE(SMBtconX
);
383 * If there is no application key defined yet
386 * This means we setup the application key on the
387 * first tcon that happens via the given session.
389 * Once the application key is defined, it does not
392 if (session
->global
->application_key_blob
.length
== 0 &&
393 smb2_signing_key_valid(session
->global
->signing_key
))
395 struct smbXsrv_session
*x
= session
;
396 struct auth_session_info
*session_info
=
397 session
->global
->auth_session_info
;
398 uint8_t session_key
[16];
400 ZERO_STRUCT(session_key
);
401 memcpy(session_key
, x
->global
->signing_key
->blob
.data
,
402 MIN(x
->global
->signing_key
->blob
.length
, sizeof(session_key
)));
405 * The application key is truncated/padded to 16 bytes
407 x
->global
->application_key_blob
= data_blob_talloc(x
->global
,
409 sizeof(session_key
));
410 ZERO_STRUCT(session_key
);
411 if (x
->global
->application_key_blob
.data
== NULL
) {
412 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
413 END_PROFILE(SMBtconX
);
416 talloc_keep_secret(x
->global
->application_key_blob
.data
);
418 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
421 status
= smb1_key_derivation(x
->global
->application_key_blob
.data
,
422 x
->global
->application_key_blob
.length
,
423 x
->global
->application_key_blob
.data
);
424 if (!NT_STATUS_IS_OK(status
)) {
425 DBG_ERR("smb1_key_derivation failed: %s\n",
427 END_PROFILE(SMBtconX
);
430 optional_support
|= SMB_EXTENDED_SIGNATURES
;
434 * Place the application key into the session_info
436 data_blob_clear_free(&session_info
->session_key
);
437 session_info
->session_key
= data_blob_dup_talloc(session_info
,
438 x
->global
->application_key_blob
);
439 if (session_info
->session_key
.data
== NULL
) {
440 data_blob_clear_free(&x
->global
->application_key_blob
);
441 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
442 END_PROFILE(SMBtconX
);
445 talloc_keep_secret(session_info
->session_key
.data
);
446 session_key_updated
= true;
449 conn
= make_connection(req
, now
, service
, client_devicetype
,
450 req
->vuid
, &nt_status
);
454 if (session_key_updated
) {
455 struct smbXsrv_session
*x
= session
;
456 struct auth_session_info
*session_info
=
457 session
->global
->auth_session_info
;
458 data_blob_clear_free(&x
->global
->application_key_blob
);
459 data_blob_clear_free(&session_info
->session_key
);
461 reply_nterror(req
, nt_status
);
462 END_PROFILE(SMBtconX
);
467 server_devicetype
= "IPC";
468 else if ( IS_PRINT(conn
) )
469 server_devicetype
= "LPT1:";
471 server_devicetype
= "A:";
473 if (xconn
->protocol
< PROTOCOL_NT1
) {
474 reply_smb1_outbuf(req
, 2, 0);
475 if (message_push_string(&req
->outbuf
, server_devicetype
,
476 STR_TERMINATE
|STR_ASCII
) == -1) {
477 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
478 END_PROFILE(SMBtconX
);
482 /* NT sets the fstype of IPC$ to the null string */
483 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
485 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
486 /* Return permissions. */
490 reply_smb1_outbuf(req
, 7, 0);
493 perm1
= FILE_ALL_ACCESS
;
494 perm2
= FILE_ALL_ACCESS
;
496 perm1
= conn
->share_access
;
499 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
500 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
502 reply_smb1_outbuf(req
, 3, 0);
505 if ((message_push_string(&req
->outbuf
, server_devicetype
,
506 STR_TERMINATE
|STR_ASCII
) == -1)
507 || (message_push_string(&req
->outbuf
, fstype
,
508 STR_TERMINATE
) == -1)) {
509 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
510 END_PROFILE(SMBtconX
);
514 /* what does setting this bit do? It is set by NT4 and
515 may affect the ability to autorun mounted cdroms */
516 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
518 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
520 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
521 DEBUG(2,("Serving %s as a Dfs root\n",
522 lp_servicename(ctx
, lp_sub
, SNUM(conn
)) ));
523 optional_support
|= SMB_SHARE_IN_DFS
;
526 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
529 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
530 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
532 DEBUG(3,("tconX service=%s \n",
535 /* set the incoming and outgoing tid to the just created one */
536 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
537 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
539 END_PROFILE(SMBtconX
);
541 req
->tid
= conn
->cnum
;
544 /****************************************************************************
545 Reply to an unknown type.
546 ****************************************************************************/
548 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
550 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
551 smb_fn_name(type
), type
, type
));
552 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
556 /****************************************************************************
558 conn POINTER CAN BE NULL HERE !
559 ****************************************************************************/
561 void reply_ioctl(struct smb_request
*req
)
563 const struct loadparm_substitution
*lp_sub
=
564 loadparm_s3_global_substitution();
565 connection_struct
*conn
= req
->conn
;
572 START_PROFILE(SMBioctl
);
575 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
576 END_PROFILE(SMBioctl
);
580 device
= SVAL(req
->vwv
+1, 0);
581 function
= SVAL(req
->vwv
+2, 0);
582 ioctl_code
= (device
<< 16) + function
;
584 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
586 switch (ioctl_code
) {
587 case IOCTL_QUERY_JOB_INFO
:
591 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
592 END_PROFILE(SMBioctl
);
596 reply_smb1_outbuf(req
, 8, replysize
+1);
597 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
598 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
599 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
600 p
= smb_buf(req
->outbuf
);
601 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
602 p
+= 1; /* Allow for alignment */
604 switch (ioctl_code
) {
605 case IOCTL_QUERY_JOB_INFO
:
609 files_struct
*fsp
= file_fsp(
610 req
, SVAL(req
->vwv
+0, 0));
612 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
613 END_PROFILE(SMBioctl
);
617 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
619 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
620 lp_netbios_name(), 15,
621 STR_TERMINATE
|STR_ASCII
, &len
);
622 if (!NT_STATUS_IS_OK(status
)) {
623 reply_nterror(req
, status
);
624 END_PROFILE(SMBioctl
);
628 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
630 lp_servicename(talloc_tos(),
633 13, STR_TERMINATE
|STR_ASCII
, &len
);
634 if (!NT_STATUS_IS_OK(status
)) {
635 reply_nterror(req
, status
);
636 END_PROFILE(SMBioctl
);
646 END_PROFILE(SMBioctl
);
650 /****************************************************************************
651 Strange checkpath NTSTATUS mapping.
652 ****************************************************************************/
654 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
656 /* Strange DOS error code semantics only for checkpath... */
657 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
658 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
659 /* We need to map to ERRbadpath */
660 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
666 /****************************************************************************
667 Reply to a checkpath.
668 ****************************************************************************/
670 void reply_checkpath(struct smb_request
*req
)
672 connection_struct
*conn
= req
->conn
;
673 struct smb_filename
*smb_fname
= NULL
;
676 struct files_struct
*dirfsp
= NULL
;
677 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
679 TALLOC_CTX
*ctx
= talloc_tos();
681 START_PROFILE(SMBcheckpath
);
683 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
684 STR_TERMINATE
, &status
);
686 if (!NT_STATUS_IS_OK(status
)) {
687 status
= map_checkpath_error(req
->flags2
, status
);
688 reply_nterror(req
, status
);
689 END_PROFILE(SMBcheckpath
);
693 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
695 if (ucf_flags
& UCF_GMT_PATHNAME
) {
696 extract_snapshot_token(name
, &twrp
);
698 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &name
);
699 if (!NT_STATUS_IS_OK(status
)) {
700 reply_nterror(req
, status
);
704 status
= filename_convert_dirfsp(ctx
,
711 if (!NT_STATUS_IS_OK(status
)) {
712 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
713 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
715 END_PROFILE(SMBcheckpath
);
721 if (!VALID_STAT(smb_fname
->st
) &&
722 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
723 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
724 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
725 status
= map_nt_error_from_unix(errno
);
729 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
730 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
735 reply_smb1_outbuf(req
, 0, 0);
738 /* We special case this - as when a Windows machine
739 is parsing a path is steps through the components
740 one at a time - if a component fails it expects
741 ERRbadpath, not ERRbadfile.
743 status
= map_checkpath_error(req
->flags2
, status
);
744 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
746 * Windows returns different error codes if
747 * the parent directory is valid but not the
748 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
749 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
750 * if the path is invalid.
752 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
757 reply_nterror(req
, status
);
760 TALLOC_FREE(smb_fname
);
761 END_PROFILE(SMBcheckpath
);
765 /****************************************************************************
767 ****************************************************************************/
769 void reply_getatr(struct smb_request
*req
)
771 struct smbXsrv_connection
*xconn
= req
->xconn
;
772 connection_struct
*conn
= req
->conn
;
773 struct smb_filename
*smb_fname
= NULL
;
780 TALLOC_CTX
*ctx
= talloc_tos();
782 START_PROFILE(SMBgetatr
);
784 p
= (const char *)req
->buf
+ 1;
785 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
786 if (!NT_STATUS_IS_OK(status
)) {
787 reply_nterror(req
, status
);
792 * dos sometimes asks for a stat of "" - it returns a "hidden
793 * directory" under WfWg - weird!
795 if (*fname
== '\0') {
796 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
797 if (!CAN_WRITE(conn
)) {
798 mode
|= FILE_ATTRIBUTE_READONLY
;
803 struct files_struct
*dirfsp
= NULL
;
804 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
808 if (ucf_flags
& UCF_GMT_PATHNAME
) {
809 extract_snapshot_token(fname
, &twrp
);
811 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
812 if (!NT_STATUS_IS_OK(status
)) {
813 reply_nterror(req
, status
);
816 status
= filename_convert_dirfsp(ctx
,
823 if (!NT_STATUS_IS_OK(status
)) {
824 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
825 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
829 reply_nterror(req
, status
);
832 if (!VALID_STAT(smb_fname
->st
) &&
833 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
834 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
835 smb_fname_str_dbg(smb_fname
),
837 reply_nterror(req
, map_nt_error_from_unix(errno
));
841 mode
= fdos_mode(smb_fname
->fsp
);
842 size
= smb_fname
->st
.st_ex_size
;
844 ask_sharemode
= fsp_search_ask_sharemode(smb_fname
->fsp
);
846 struct timespec write_time_ts
;
847 struct file_id fileid
;
849 ZERO_STRUCT(write_time_ts
);
850 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
851 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
852 if (!is_omit_timespec(&write_time_ts
)) {
853 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
857 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
858 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
863 reply_smb1_outbuf(req
, 10, 0);
865 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
866 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
867 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
869 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
871 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
873 if (xconn
->protocol
>= PROTOCOL_NT1
) {
874 SSVAL(req
->outbuf
, smb_flg2
,
875 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
878 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
879 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
882 TALLOC_FREE(smb_fname
);
884 END_PROFILE(SMBgetatr
);
888 /****************************************************************************
890 ****************************************************************************/
892 void reply_setatr(struct smb_request
*req
)
894 struct smb_file_time ft
;
895 connection_struct
*conn
= req
->conn
;
896 struct smb_filename
*smb_fname
= NULL
;
897 struct files_struct
*dirfsp
= NULL
;
903 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
905 TALLOC_CTX
*ctx
= talloc_tos();
907 START_PROFILE(SMBsetatr
);
908 init_smb_file_time(&ft
);
911 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
915 p
= (const char *)req
->buf
+ 1;
916 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
917 if (!NT_STATUS_IS_OK(status
)) {
918 reply_nterror(req
, status
);
922 if (ucf_flags
& UCF_GMT_PATHNAME
) {
923 extract_snapshot_token(fname
, &twrp
);
925 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
926 if (!NT_STATUS_IS_OK(status
)) {
927 reply_nterror(req
, status
);
930 status
= filename_convert_dirfsp(ctx
,
937 if (!NT_STATUS_IS_OK(status
)) {
938 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
939 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
943 reply_nterror(req
, status
);
947 if (ISDOT(smb_fname
->base_name
)) {
949 * Not sure here is the right place to catch this
950 * condition. Might be moved to somewhere else later -- vl
952 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
956 if (smb_fname
->fsp
== NULL
) {
957 /* Can't set access rights on a symlink. */
958 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
962 mode
= SVAL(req
->vwv
+0, 0);
963 mtime
= srv_make_unix_date3(req
->vwv
+1);
965 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
966 if (VALID_STAT_OF_DIR(smb_fname
->st
))
967 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
969 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
971 status
= smbd_check_access_rights_fsp(conn
->cwd_fsp
,
974 FILE_WRITE_ATTRIBUTES
);
975 if (!NT_STATUS_IS_OK(status
)) {
976 reply_nterror(req
, status
);
980 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
982 reply_nterror(req
, map_nt_error_from_unix(errno
));
987 ft
.mtime
= time_t_to_full_timespec(mtime
);
989 status
= smb_set_file_time(conn
, smb_fname
->fsp
, smb_fname
, &ft
, true);
990 if (!NT_STATUS_IS_OK(status
)) {
991 reply_nterror(req
, status
);
995 reply_smb1_outbuf(req
, 0, 0);
997 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1000 TALLOC_FREE(smb_fname
);
1001 END_PROFILE(SMBsetatr
);
1005 /****************************************************************************
1007 ****************************************************************************/
1009 void reply_dskattr(struct smb_request
*req
)
1011 struct smbXsrv_connection
*xconn
= req
->xconn
;
1012 connection_struct
*conn
= req
->conn
;
1014 uint64_t dfree
,dsize
,bsize
;
1015 struct smb_filename smb_fname
;
1016 START_PROFILE(SMBdskattr
);
1018 ZERO_STRUCT(smb_fname
);
1019 smb_fname
.base_name
= discard_const_p(char, ".");
1021 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1022 reply_nterror(req
, map_nt_error_from_unix(errno
));
1023 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1024 END_PROFILE(SMBdskattr
);
1028 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1029 if (ret
== (uint64_t)-1) {
1030 reply_nterror(req
, map_nt_error_from_unix(errno
));
1031 END_PROFILE(SMBdskattr
);
1036 * Force max to fit in 16 bit fields.
1038 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1042 if (bsize
> (WORDMAX
*512)) {
1043 bsize
= (WORDMAX
*512);
1044 if (dsize
> WORDMAX
)
1046 if (dfree
> WORDMAX
)
1052 reply_smb1_outbuf(req
, 5, 0);
1054 if (xconn
->protocol
<= PROTOCOL_LANMAN2
) {
1055 double total_space
, free_space
;
1056 /* we need to scale this to a number that DOS6 can handle. We
1057 use floating point so we can handle large drives on systems
1058 that don't have 64 bit integers
1060 we end up displaying a maximum of 2G to DOS systems
1062 total_space
= dsize
* (double)bsize
;
1063 free_space
= dfree
* (double)bsize
;
1065 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1066 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1068 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1069 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1071 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1072 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1073 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1074 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1076 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1077 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1078 SSVAL(req
->outbuf
,smb_vwv2
,512);
1079 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1082 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1084 END_PROFILE(SMBdskattr
);
1088 /****************************************************************************
1090 ****************************************************************************/
1092 static void make_dir_struct(TALLOC_CTX
*ctx
,
1103 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1107 memset(buf
+1,' ',11);
1108 if ((p
= strchr_m(mask
, '.')) != NULL
) {
1109 char name
[p
- mask
+ 1];
1110 strlcpy(name
, mask
, sizeof(name
));
1111 push_ascii(buf
+ 1, name
, 8, 0);
1112 push_ascii(buf
+9,p
+1,3, 0);
1114 push_ascii(buf
+ 1, mask
, 11, 0);
1117 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1119 srv_put_dos_date(buf
,22,date
);
1120 SSVAL(buf
,26,size
& 0xFFFF);
1121 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1122 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1123 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1124 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1125 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1128 static bool mangle_mask_match(connection_struct
*conn
,
1129 const char *filename
,
1134 if (!name_to_8_3(filename
, mname
, False
, conn
->params
)) {
1137 return mask_match_search(mname
, mask
, False
);
1140 /****************************************************************************
1141 Get an 8.3 directory entry.
1142 ****************************************************************************/
1144 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1150 connection_struct
*conn
= (connection_struct
*)private_data
;
1152 if ((strcmp(mask
, "*.*") == 0) ||
1153 mask_match_search(dname
, mask
, false) ||
1154 mangle_mask_match(conn
, dname
, mask
)) {
1158 * Ensure we can push the original name as UCS2. If
1159 * not, then just don't return this name.
1163 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1164 uint8_t *tmp
= talloc_array(talloc_tos(), uint8_t, len
);
1166 status
= srvstr_push(NULL
,
1167 FLAGS2_UNICODE_STRINGS
,
1176 if (!NT_STATUS_IS_OK(status
)) {
1180 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1182 name_to_8_3(dname
, mname
, false, conn
->params
);
1191 *_fname
= talloc_strdup(ctx
, fname
);
1192 if (*_fname
== NULL
) {
1202 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX
*ctx
,
1204 struct files_struct
*dirfsp
,
1205 struct smb_filename
*smb_fname
,
1209 if (*_mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1211 * Don't show symlinks/special files to old clients
1217 SMB_ASSERT(smb_fname
!= NULL
);
1218 *_mode
= fdos_mode(smb_fname
->fsp
);
1219 if (smb_fname
->fsp
!= NULL
) {
1220 smb_fname
->st
= smb_fname
->fsp
->fsp_name
->st
;
1226 static bool get_dir_entry(TALLOC_CTX
*ctx
,
1227 connection_struct
*conn
,
1228 struct dptr_struct
*dirptr
,
1234 struct timespec
*_date
,
1239 struct smb_filename
*smb_fname
= NULL
;
1243 ok
= smbd_dirptr_get_entry(ctx
,
1250 smbd_dirptr_8_3_match_fn
,
1251 smbd_dirptr_8_3_mode_fn
,
1260 *_fname
= talloc_move(ctx
, &fname
);
1261 *_size
= smb_fname
->st
.st_ex_size
;
1263 *_date
= smb_fname
->st
.st_ex_mtime
;
1264 TALLOC_FREE(smb_fname
);
1268 /****************************************************************************
1270 Can be called from SMBsearch, SMBffirst or SMBfunique.
1271 ****************************************************************************/
1273 void reply_search(struct smb_request
*req
)
1275 connection_struct
*conn
= req
->conn
;
1278 char *directory
= NULL
;
1279 struct smb_filename
*smb_fname
= NULL
;
1283 struct timespec date
;
1285 unsigned int numentries
= 0;
1286 unsigned int maxentries
= 0;
1287 bool finished
= False
;
1292 bool check_descend
= False
;
1293 bool expect_close
= False
;
1295 bool mask_contains_wcard
= False
;
1296 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1297 TALLOC_CTX
*ctx
= talloc_tos();
1298 struct smbXsrv_connection
*xconn
= req
->xconn
;
1299 struct smbd_server_connection
*sconn
= req
->sconn
;
1300 files_struct
*fsp
= NULL
;
1301 const struct loadparm_substitution
*lp_sub
=
1302 loadparm_s3_global_substitution();
1304 START_PROFILE(SMBsearch
);
1307 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1311 if (req
->posix_pathnames
) {
1312 reply_unknown_new(req
, req
->cmd
);
1316 /* If we were called as SMBffirst then we must expect close. */
1317 if(req
->cmd
== SMBffirst
) {
1318 expect_close
= True
;
1321 reply_smb1_outbuf(req
, 1, 3);
1322 maxentries
= SVAL(req
->vwv
+0, 0);
1323 dirtype
= SVAL(req
->vwv
+1, 0);
1324 p
= (const char *)req
->buf
+ 1;
1325 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1327 if (!NT_STATUS_IS_OK(nt_status
)) {
1328 reply_nterror(req
, nt_status
);
1332 if (smbreq_bufrem(req
, p
) < 3) {
1333 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1338 status_len
= SVAL(p
, 0);
1341 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1343 if (status_len
== 0) {
1344 const char *dirpath
;
1345 struct files_struct
*dirfsp
= NULL
;
1346 struct smb_filename
*smb_dname
= NULL
;
1347 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1349 nt_status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &path
);
1350 if (!NT_STATUS_IS_OK(nt_status
)) {
1351 reply_nterror(req
, nt_status
);
1355 nt_status
= filename_convert_smb1_search_path(ctx
,
1363 if (!NT_STATUS_IS_OK(nt_status
)) {
1364 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1365 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1366 ERRSRV
, ERRbadpath
);
1369 reply_nterror(req
, nt_status
);
1373 memset((char *)status
,'\0',21);
1374 SCVAL(status
,0,(dirtype
& 0x1F));
1377 * Open an fsp on this directory for the dptr.
1379 nt_status
= SMB_VFS_CREATE_FILE(
1382 dirfsp
, /* dirfsp */
1383 smb_dname
, /* dname */
1384 FILE_LIST_DIRECTORY
, /* access_mask */
1386 FILE_SHARE_WRITE
, /* share_access */
1387 FILE_OPEN
, /* create_disposition*/
1388 FILE_DIRECTORY_FILE
, /* create_options */
1389 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1390 NO_OPLOCK
, /* oplock_request */
1392 0, /* allocation_size */
1393 0, /* private_flags */
1398 NULL
, /* in_context */
1399 NULL
);/* out_context */
1401 if (!NT_STATUS_IS_OK(nt_status
)) {
1402 DBG_ERR("failed to open directory %s\n",
1403 smb_fname_str_dbg(smb_dname
));
1404 reply_nterror(req
, nt_status
);
1408 nt_status
= dptr_create(conn
,
1416 TALLOC_FREE(smb_dname
);
1418 if (!NT_STATUS_IS_OK(nt_status
)) {
1420 * Use NULL here for the first parameter (req)
1421 * as this is not a client visible handle so
1422 * can't be part of an SMB1 chain.
1424 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1425 reply_nterror(req
, nt_status
);
1429 dptr_num
= dptr_dnum(fsp
->dptr
);
1430 dirpath
= dptr_path(sconn
, dptr_num
);
1431 directory
= talloc_strdup(ctx
, dirpath
);
1433 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1439 const char *dirpath
;
1440 unsigned int dptr_filenum
;
1441 uint32_t resume_key_index
;
1443 if (smbreq_bufrem(req
, p
) < 21) {
1444 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1448 memcpy(status
,p
,21);
1449 status_dirtype
= CVAL(status
,0) & 0x1F;
1450 if (status_dirtype
!= (dirtype
& 0x1F)) {
1451 dirtype
= status_dirtype
;
1454 dptr_num
= CVAL(status
, 12);
1455 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
1460 resume_key_index
= PULL_LE_U32(status
, 13);
1461 dptr_filenum
= dptr_FileNumber(fsp
->dptr
);
1463 if (resume_key_index
> dptr_filenum
) {
1465 * Haven't seen this resume key yet. Just stop
1471 if (resume_key_index
< dptr_filenum
) {
1473 * The resume key was not the last one we
1474 * sent, rewind and skip to what the client
1477 dptr_RewindDir(fsp
->dptr
);
1479 dptr_filenum
= dptr_FileNumber(fsp
->dptr
);
1480 SMB_ASSERT(dptr_filenum
== 0);
1482 while (dptr_filenum
< resume_key_index
) {
1483 bool ok
= get_dir_entry(
1487 dptr_wcard(sconn
, dptr_num
),
1500 dptr_filenum
= dptr_FileNumber(fsp
->dptr
);
1504 dirpath
= dptr_path(sconn
, dptr_num
);
1505 directory
= talloc_strdup(ctx
, dirpath
);
1507 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1511 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1515 dirtype
= dptr_attr(sconn
, dptr_num
);
1518 mask_contains_wcard
= dptr_has_wild(fsp
->dptr
);
1520 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1522 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1523 char buf
[DIR_STRUCT_SIZE
];
1524 memcpy(buf
,status
,21);
1525 make_dir_struct(ctx
,
1528 volume_label(ctx
, SNUM(conn
)),
1530 FILE_ATTRIBUTE_VOLUME
,
1532 !allow_long_path_components
);
1533 SCVAL(buf
, 12, dptr_num
);
1535 if (message_push_blob(&req
->outbuf
,
1536 data_blob_const(buf
, sizeof(buf
)))
1538 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1543 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1544 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1547 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1549 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1550 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1551 if (in_list(directory
, lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),True
)) {
1552 check_descend
= True
;
1555 ask_sharemode
= fsp_search_ask_sharemode(fsp
);
1557 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1558 finished
= !get_dir_entry(ctx
,
1570 char buf
[DIR_STRUCT_SIZE
];
1571 memcpy(buf
,status
,21);
1579 convert_timespec_to_time_t(date
),
1580 !allow_long_path_components
);
1581 SCVAL(buf
, 12, dptr_num
);
1584 dptr_FileNumber(fsp
->dptr
));
1585 if (message_push_blob(&req
->outbuf
,
1586 data_blob_const(buf
, sizeof(buf
)))
1588 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1599 /* If we were called as SMBffirst with smb_search_id == NULL
1600 and no entries were found then return error and close fsp->dptr
1603 if (numentries
== 0) {
1606 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1608 } else if(expect_close
&& status_len
== 0) {
1609 /* Close the dptr - we know it's gone */
1612 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1616 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1617 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1619 /* fsp may have been closed above. */
1621 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1625 if ((numentries
== 0) && !mask_contains_wcard
) {
1626 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1630 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1631 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1632 SCVAL(smb_buf(req
->outbuf
),0,5);
1633 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1635 /* The replies here are never long name. */
1636 SSVAL(req
->outbuf
, smb_flg2
,
1637 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1638 if (!allow_long_path_components
) {
1639 SSVAL(req
->outbuf
, smb_flg2
,
1640 SVAL(req
->outbuf
, smb_flg2
)
1641 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1644 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1645 SSVAL(req
->outbuf
, smb_flg2
,
1646 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1648 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1649 smb_fn_name(req
->cmd
),
1656 TALLOC_FREE(directory
);
1658 TALLOC_FREE(smb_fname
);
1659 END_PROFILE(SMBsearch
);
1663 /****************************************************************************
1664 Reply to a fclose (stop directory search).
1665 ****************************************************************************/
1667 void reply_fclose(struct smb_request
*req
)
1674 TALLOC_CTX
*ctx
= talloc_tos();
1675 struct smbd_server_connection
*sconn
= req
->sconn
;
1676 files_struct
*fsp
= NULL
;
1678 START_PROFILE(SMBfclose
);
1680 if (req
->posix_pathnames
) {
1681 reply_unknown_new(req
, req
->cmd
);
1682 END_PROFILE(SMBfclose
);
1686 p
= (const char *)req
->buf
+ 1;
1687 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1689 if (!NT_STATUS_IS_OK(err
)) {
1690 reply_nterror(req
, err
);
1691 END_PROFILE(SMBfclose
);
1695 if (smbreq_bufrem(req
, p
) < 3) {
1696 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1697 END_PROFILE(SMBfclose
);
1702 status_len
= SVAL(p
,0);
1705 if (status_len
== 0) {
1706 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1707 END_PROFILE(SMBfclose
);
1711 if (smbreq_bufrem(req
, p
) < 21) {
1712 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1713 END_PROFILE(SMBfclose
);
1717 dptr_num
= CVAL(p
, 12);
1719 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
1721 /* Close the file - we know it's gone */
1722 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1726 reply_smb1_outbuf(req
, 1, 0);
1727 SSVAL(req
->outbuf
,smb_vwv0
,0);
1729 DEBUG(3,("search close\n"));
1731 END_PROFILE(SMBfclose
);
1735 /****************************************************************************
1737 ****************************************************************************/
1739 void reply_open(struct smb_request
*req
)
1741 connection_struct
*conn
= req
->conn
;
1742 struct smb_filename
*smb_fname
= NULL
;
1748 struct files_struct
*dirfsp
= NULL
;
1753 uint32_t access_mask
;
1754 uint32_t share_mode
;
1755 uint32_t create_disposition
;
1756 uint32_t create_options
= 0;
1757 uint32_t private_flags
= 0;
1761 TALLOC_CTX
*ctx
= talloc_tos();
1763 START_PROFILE(SMBopen
);
1766 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1770 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1771 deny_mode
= SVAL(req
->vwv
+0, 0);
1772 dos_attr
= SVAL(req
->vwv
+1, 0);
1774 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1775 STR_TERMINATE
, &status
);
1776 if (!NT_STATUS_IS_OK(status
)) {
1777 reply_nterror(req
, status
);
1781 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1782 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1783 &share_mode
, &create_disposition
,
1784 &create_options
, &private_flags
)) {
1785 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1789 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
1791 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1792 extract_snapshot_token(fname
, &twrp
);
1794 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
1795 if (!NT_STATUS_IS_OK(status
)) {
1796 reply_nterror(req
, status
);
1799 status
= filename_convert_dirfsp(ctx
,
1806 if (!NT_STATUS_IS_OK(status
)) {
1807 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1808 reply_botherror(req
,
1809 NT_STATUS_PATH_NOT_COVERED
,
1810 ERRSRV
, ERRbadpath
);
1813 reply_nterror(req
, status
);
1817 status
= SMB_VFS_CREATE_FILE(
1820 dirfsp
, /* dirfsp */
1821 smb_fname
, /* fname */
1822 access_mask
, /* access_mask */
1823 share_mode
, /* share_access */
1824 create_disposition
, /* create_disposition*/
1825 create_options
, /* create_options */
1826 dos_attr
, /* file_attributes */
1827 oplock_request
, /* oplock_request */
1829 0, /* allocation_size */
1835 NULL
, NULL
); /* create context */
1837 if (!NT_STATUS_IS_OK(status
)) {
1838 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1839 /* We have re-scheduled this call. */
1843 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1844 reply_openerror(req
, status
);
1848 fsp
= fcb_or_dos_open(
1855 bool ok
= defer_smb1_sharing_violation(req
);
1859 reply_openerror(req
, status
);
1864 /* Ensure we're pointing at the correct stat struct. */
1865 TALLOC_FREE(smb_fname
);
1866 smb_fname
= fsp
->fsp_name
;
1868 size
= smb_fname
->st
.st_ex_size
;
1869 fattr
= fdos_mode(fsp
);
1871 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1873 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1874 DEBUG(3,("attempt to open a directory %s\n",
1876 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1877 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1878 ERRDOS
, ERRnoaccess
);
1882 reply_smb1_outbuf(req
, 7, 0);
1883 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1884 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1885 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1886 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1888 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1890 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
1891 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1893 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1894 SCVAL(req
->outbuf
,smb_flg
,
1895 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1898 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1899 SCVAL(req
->outbuf
,smb_flg
,
1900 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1903 END_PROFILE(SMBopen
);
1907 /****************************************************************************
1908 Reply to an open and X.
1909 ****************************************************************************/
1911 void reply_open_and_X(struct smb_request
*req
)
1913 connection_struct
*conn
= req
->conn
;
1914 struct smb_filename
*smb_fname
= NULL
;
1916 uint16_t open_flags
;
1919 /* Breakout the oplock request bits so we can set the
1920 reply bits separately. */
1921 int ex_oplock_request
;
1922 int core_oplock_request
;
1925 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1926 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
1932 struct files_struct
*dirfsp
= NULL
;
1935 uint64_t allocation_size
;
1936 ssize_t retval
= -1;
1937 uint32_t access_mask
;
1938 uint32_t share_mode
;
1939 uint32_t create_disposition
;
1940 uint32_t create_options
= 0;
1941 uint32_t private_flags
= 0;
1944 TALLOC_CTX
*ctx
= talloc_tos();
1946 START_PROFILE(SMBopenX
);
1948 if (req
->wct
< 15) {
1949 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1953 open_flags
= SVAL(req
->vwv
+2, 0);
1954 deny_mode
= SVAL(req
->vwv
+3, 0);
1955 smb_attr
= SVAL(req
->vwv
+5, 0);
1956 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1957 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1958 oplock_request
= ex_oplock_request
| core_oplock_request
;
1959 smb_ofun
= SVAL(req
->vwv
+8, 0);
1960 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1962 /* If it's an IPC, pass off the pipe handler. */
1964 if (lp_nt_pipe_support()) {
1965 reply_open_pipe_and_X(conn
, req
);
1967 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1972 /* XXXX we need to handle passed times, sattr and flags */
1973 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1974 STR_TERMINATE
, &status
);
1975 if (!NT_STATUS_IS_OK(status
)) {
1976 reply_nterror(req
, status
);
1980 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1982 &access_mask
, &share_mode
,
1983 &create_disposition
,
1986 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1990 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
1992 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1993 extract_snapshot_token(fname
, &twrp
);
1995 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
1996 if (!NT_STATUS_IS_OK(status
)) {
1997 reply_nterror(req
, status
);
2001 status
= filename_convert_dirfsp(ctx
,
2008 if (!NT_STATUS_IS_OK(status
)) {
2009 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2010 reply_botherror(req
,
2011 NT_STATUS_PATH_NOT_COVERED
,
2012 ERRSRV
, ERRbadpath
);
2015 reply_nterror(req
, status
);
2019 status
= SMB_VFS_CREATE_FILE(
2022 dirfsp
, /* dirfsp */
2023 smb_fname
, /* fname */
2024 access_mask
, /* access_mask */
2025 share_mode
, /* share_access */
2026 create_disposition
, /* create_disposition*/
2027 create_options
, /* create_options */
2028 smb_attr
, /* file_attributes */
2029 oplock_request
, /* oplock_request */
2031 0, /* allocation_size */
2036 &smb_action
, /* pinfo */
2037 NULL
, NULL
); /* create context */
2039 if (!NT_STATUS_IS_OK(status
)) {
2040 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2041 /* We have re-scheduled this call. */
2045 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2046 reply_openerror(req
, status
);
2050 fsp
= fcb_or_dos_open(
2057 bool ok
= defer_smb1_sharing_violation(req
);
2061 reply_openerror(req
, status
);
2066 smb_action
= FILE_WAS_OPENED
;
2069 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2070 if the file is truncated or created. */
2071 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2072 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2073 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2074 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2075 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2078 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2080 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2081 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2084 status
= vfs_stat_fsp(fsp
);
2085 if (!NT_STATUS_IS_OK(status
)) {
2086 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2087 reply_nterror(req
, status
);
2092 fattr
= fdos_mode(fsp
);
2093 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2094 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2095 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2098 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2100 /* If the caller set the extended oplock request bit
2101 and we granted one (by whatever means) - set the
2102 correct bit for extended oplock reply.
2105 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2106 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2109 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2110 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2113 /* If the caller set the core oplock request bit
2114 and we granted one (by whatever means) - set the
2115 correct bit for core oplock reply.
2118 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2119 reply_smb1_outbuf(req
, 19, 0);
2121 reply_smb1_outbuf(req
, 15, 0);
2124 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2125 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2127 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2128 SCVAL(req
->outbuf
, smb_flg
,
2129 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2132 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2133 SCVAL(req
->outbuf
, smb_flg
,
2134 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2137 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2138 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2139 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2140 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2142 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2144 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2145 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2146 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2148 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2149 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2153 TALLOC_FREE(smb_fname
);
2154 END_PROFILE(SMBopenX
);
2158 /****************************************************************************
2159 Reply to a SMBulogoffX.
2160 ****************************************************************************/
2162 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2163 struct smbXsrv_session
*session
);
2164 static void reply_ulogoffX_done(struct tevent_req
*req
);
2166 void reply_ulogoffX(struct smb_request
*smb1req
)
2168 struct timeval now
= timeval_current();
2169 struct smbXsrv_session
*session
= NULL
;
2170 struct tevent_req
*req
;
2174 * Don't setup the profile charge here, take
2175 * it in reply_ulogoffX_done(). Not strictly correct
2176 * but better than the other SMB1 async
2177 * code that double-charges at the moment.
2180 status
= smb1srv_session_lookup(smb1req
->xconn
,
2182 timeval_to_nttime(&now
),
2184 if (!NT_STATUS_IS_OK(status
)) {
2185 /* Not going async, profile here. */
2186 START_PROFILE(SMBulogoffX
);
2187 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2188 (unsigned long long)smb1req
->vuid
);
2190 smb1req
->vuid
= UID_FIELD_INVALID
;
2191 reply_force_doserror(smb1req
, ERRSRV
, ERRbaduid
);
2192 END_PROFILE(SMBulogoffX
);
2196 req
= reply_ulogoffX_send(smb1req
, session
);
2198 /* Not going async, profile here. */
2199 START_PROFILE(SMBulogoffX
);
2200 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
2201 END_PROFILE(SMBulogoffX
);
2205 /* We're async. This will complete later. */
2206 tevent_req_set_callback(req
, reply_ulogoffX_done
, smb1req
);
2210 struct reply_ulogoffX_state
{
2211 struct tevent_queue
*wait_queue
;
2212 struct smbXsrv_session
*session
;
2215 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
);
2217 /****************************************************************************
2218 Async SMB1 ulogoffX.
2219 Note, on failure here we deallocate and return NULL to allow the caller to
2220 SMB1 return an error of ERRnomem immediately.
2221 ****************************************************************************/
2223 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2224 struct smbXsrv_session
*session
)
2226 struct tevent_req
*req
;
2227 struct reply_ulogoffX_state
*state
;
2228 struct tevent_req
*subreq
;
2230 struct smbd_server_connection
*sconn
= session
->client
->sconn
;
2231 uint64_t vuid
= session
->global
->session_wire_id
;
2233 req
= tevent_req_create(smb1req
, &state
,
2234 struct reply_ulogoffX_state
);
2238 state
->wait_queue
= tevent_queue_create(state
,
2239 "reply_ulogoffX_wait_queue");
2240 if (tevent_req_nomem(state
->wait_queue
, req
)) {
2244 state
->session
= session
;
2247 * Make sure that no new request will be able to use this session.
2248 * This ensures that once all outstanding fsp->aio_requests
2249 * on this session are done, we are safe to close it.
2251 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
2253 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
2254 if (fsp
->vuid
!= vuid
) {
2258 * Flag the file as close in progress.
2259 * This will prevent any more IO being
2262 fsp
->fsp_flags
.closing
= true;
2264 if (fsp
->num_aio_requests
> 0) {
2266 * Now wait until all aio requests on this fsp are
2269 * We don't set a callback, as we just want to block the
2270 * wait queue and the talloc_free() of fsp->aio_request
2271 * will remove the item from the wait queue.
2273 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
2276 if (tevent_req_nomem(subreq
, req
)) {
2284 * Now we add our own waiter to the end of the queue,
2285 * this way we get notified when all pending requests are finished
2286 * and reply to the outstanding SMB1 request.
2288 subreq
= tevent_queue_wait_send(state
,
2291 if (tevent_req_nomem(subreq
, req
)) {
2297 * We're really going async - move the SMB1 request from
2298 * a talloc stackframe above us to the sconn talloc-context.
2299 * We need this to stick around until the wait_done
2300 * callback is invoked.
2302 smb1req
= talloc_move(sconn
, &smb1req
);
2304 tevent_req_set_callback(subreq
, reply_ulogoffX_wait_done
, req
);
2309 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
)
2311 struct tevent_req
*req
= tevent_req_callback_data(
2312 subreq
, struct tevent_req
);
2314 tevent_queue_wait_recv(subreq
);
2315 TALLOC_FREE(subreq
);
2316 tevent_req_done(req
);
2319 static NTSTATUS
reply_ulogoffX_recv(struct tevent_req
*req
)
2321 return tevent_req_simple_recv_ntstatus(req
);
2324 static void reply_ulogoffX_done(struct tevent_req
*req
)
2326 struct smb_request
*smb1req
= tevent_req_callback_data(
2327 req
, struct smb_request
);
2328 struct reply_ulogoffX_state
*state
= tevent_req_data(req
,
2329 struct reply_ulogoffX_state
);
2330 struct smbXsrv_session
*session
= state
->session
;
2334 * Take the profile charge here. Not strictly
2335 * correct but better than the other SMB1 async
2336 * code that double-charges at the moment.
2338 START_PROFILE(SMBulogoffX
);
2340 status
= reply_ulogoffX_recv(req
);
2342 if (!NT_STATUS_IS_OK(status
)) {
2343 TALLOC_FREE(smb1req
);
2344 END_PROFILE(SMBulogoffX
);
2345 exit_server(__location__
": reply_ulogoffX_recv failed");
2349 status
= smbXsrv_session_logoff(session
);
2350 if (!NT_STATUS_IS_OK(status
)) {
2351 TALLOC_FREE(smb1req
);
2352 END_PROFILE(SMBulogoffX
);
2353 exit_server(__location__
": smbXsrv_session_logoff failed");
2357 TALLOC_FREE(session
);
2359 reply_smb1_outbuf(smb1req
, 2, 0);
2360 SSVAL(smb1req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2361 SSVAL(smb1req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2363 DBG_NOTICE("ulogoffX vuid=%llu\n",
2364 (unsigned long long)smb1req
->vuid
);
2366 smb1req
->vuid
= UID_FIELD_INVALID
;
2368 * The following call is needed to push the
2369 * reply data back out the socket after async
2370 * return. Plus it frees smb1req.
2372 smb_request_done(smb1req
);
2373 END_PROFILE(SMBulogoffX
);
2376 /****************************************************************************
2377 Reply to a mknew or a create.
2378 ****************************************************************************/
2380 void reply_mknew(struct smb_request
*req
)
2382 connection_struct
*conn
= req
->conn
;
2383 struct smb_filename
*smb_fname
= NULL
;
2386 struct smb_file_time ft
;
2387 struct files_struct
*dirfsp
= NULL
;
2389 int oplock_request
= 0;
2391 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2392 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2393 uint32_t create_disposition
;
2394 uint32_t create_options
= 0;
2397 TALLOC_CTX
*ctx
= talloc_tos();
2399 START_PROFILE(SMBcreate
);
2400 init_smb_file_time(&ft
);
2403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2407 fattr
= SVAL(req
->vwv
+0, 0);
2408 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2410 if (req
->cmd
== SMBmknew
) {
2411 /* We should fail if file exists. */
2412 create_disposition
= FILE_CREATE
;
2414 /* Create if file doesn't exist, truncate if it does. */
2415 create_disposition
= FILE_OVERWRITE_IF
;
2419 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+1));
2421 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2422 STR_TERMINATE
, &status
);
2423 if (!NT_STATUS_IS_OK(status
)) {
2424 reply_nterror(req
, status
);
2428 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2429 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2430 extract_snapshot_token(fname
, &twrp
);
2432 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
2433 if (!NT_STATUS_IS_OK(status
)) {
2434 reply_nterror(req
, status
);
2438 status
= filename_convert_dirfsp(ctx
,
2445 if (!NT_STATUS_IS_OK(status
)) {
2446 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2447 reply_botherror(req
,
2448 NT_STATUS_PATH_NOT_COVERED
,
2449 ERRSRV
, ERRbadpath
);
2452 reply_nterror(req
, status
);
2456 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2457 DEBUG(0,("Attempt to create file (%s) with volid set - "
2458 "please report this\n",
2459 smb_fname_str_dbg(smb_fname
)));
2462 status
= SMB_VFS_CREATE_FILE(
2465 dirfsp
, /* dirfsp */
2466 smb_fname
, /* fname */
2467 access_mask
, /* access_mask */
2468 share_mode
, /* share_access */
2469 create_disposition
, /* create_disposition*/
2470 create_options
, /* create_options */
2471 fattr
, /* file_attributes */
2472 oplock_request
, /* oplock_request */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2480 NULL
, NULL
); /* create context */
2482 if (!NT_STATUS_IS_OK(status
)) {
2483 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2484 /* We have re-scheduled this call. */
2487 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2488 bool ok
= defer_smb1_sharing_violation(req
);
2493 reply_openerror(req
, status
);
2497 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2498 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2499 if (!NT_STATUS_IS_OK(status
)) {
2500 END_PROFILE(SMBcreate
);
2504 reply_smb1_outbuf(req
, 1, 0);
2505 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2507 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2508 SCVAL(req
->outbuf
,smb_flg
,
2509 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2512 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2513 SCVAL(req
->outbuf
,smb_flg
,
2514 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2517 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2518 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2519 smb_fname_str_dbg(smb_fname
), fsp_get_io_fd(fsp
),
2520 (unsigned int)fattr
));
2523 TALLOC_FREE(smb_fname
);
2524 END_PROFILE(SMBcreate
);
2528 /****************************************************************************
2529 Reply to a create temporary file.
2530 ****************************************************************************/
2532 void reply_ctemp(struct smb_request
*req
)
2534 connection_struct
*conn
= req
->conn
;
2535 struct smb_filename
*smb_fname
= NULL
;
2536 char *wire_name
= NULL
;
2539 struct files_struct
*dirfsp
= NULL
;
2547 TALLOC_CTX
*ctx
= talloc_tos();
2549 START_PROFILE(SMBctemp
);
2552 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2556 fattr
= SVAL(req
->vwv
+0, 0);
2557 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2559 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2560 STR_TERMINATE
, &status
);
2561 if (!NT_STATUS_IS_OK(status
)) {
2562 reply_nterror(req
, status
);
2566 for (i
= 0; i
< 10; i
++) {
2568 fname
= talloc_asprintf(ctx
,
2571 generate_random_str_list(ctx
, 5, "0123456789"));
2573 fname
= talloc_asprintf(ctx
,
2575 generate_random_str_list(ctx
, 5, "0123456789"));
2579 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2583 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2584 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2585 extract_snapshot_token(fname
, &twrp
);
2587 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
2588 if (!NT_STATUS_IS_OK(status
)) {
2589 reply_nterror(req
, status
);
2593 status
= filename_convert_dirfsp(ctx
,
2600 if (!NT_STATUS_IS_OK(status
)) {
2601 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2602 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2603 ERRSRV
, ERRbadpath
);
2606 reply_nterror(req
, status
);
2610 /* Create the file. */
2611 status
= SMB_VFS_CREATE_FILE(
2614 dirfsp
, /* dirfsp */
2615 smb_fname
, /* fname */
2616 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2617 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2618 FILE_CREATE
, /* create_disposition*/
2619 0, /* create_options */
2620 fattr
, /* file_attributes */
2621 oplock_request
, /* oplock_request */
2623 0, /* allocation_size */
2624 0, /* private_flags */
2629 NULL
, NULL
); /* create context */
2631 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2633 TALLOC_FREE(dirfsp
);
2634 TALLOC_FREE(smb_fname
);
2638 if (!NT_STATUS_IS_OK(status
)) {
2639 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2640 /* We have re-scheduled this call. */
2643 if (NT_STATUS_EQUAL(
2644 status
, NT_STATUS_SHARING_VIOLATION
)) {
2645 bool ok
= defer_smb1_sharing_violation(req
);
2650 reply_openerror(req
, status
);
2658 /* Collision after 10 times... */
2659 reply_nterror(req
, status
);
2663 reply_smb1_outbuf(req
, 1, 0);
2664 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2666 /* the returned filename is relative to the directory */
2667 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2669 s
= fsp
->fsp_name
->base_name
;
2675 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2676 thing in the byte section. JRA */
2677 SSVALS(p
, 0, -1); /* what is this? not in spec */
2679 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2681 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2685 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2686 SCVAL(req
->outbuf
, smb_flg
,
2687 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2690 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2691 SCVAL(req
->outbuf
, smb_flg
,
2692 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2695 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2696 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2697 fsp_get_io_fd(fsp
), (unsigned int)smb_fname
->st
.st_ex_mode
));
2699 TALLOC_FREE(smb_fname
);
2700 TALLOC_FREE(wire_name
);
2701 END_PROFILE(SMBctemp
);
2705 /****************************************************************************
2707 ****************************************************************************/
2709 void reply_unlink(struct smb_request
*req
)
2711 connection_struct
*conn
= req
->conn
;
2713 struct files_struct
*dirfsp
= NULL
;
2714 struct smb_filename
*smb_fname
= NULL
;
2717 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
2719 TALLOC_CTX
*ctx
= talloc_tos();
2721 START_PROFILE(SMBunlink
);
2724 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2728 dirtype
= SVAL(req
->vwv
+0, 0);
2730 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2731 STR_TERMINATE
, &status
);
2732 if (!NT_STATUS_IS_OK(status
)) {
2733 reply_nterror(req
, status
);
2737 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2738 extract_snapshot_token(name
, &twrp
);
2740 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &name
);
2741 if (!NT_STATUS_IS_OK(status
)) {
2742 reply_nterror(req
, status
);
2745 status
= filename_convert_dirfsp(ctx
,
2752 if (!NT_STATUS_IS_OK(status
)) {
2753 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2754 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2755 ERRSRV
, ERRbadpath
);
2758 reply_nterror(req
, status
);
2762 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2764 status
= unlink_internals(conn
, req
, dirtype
, dirfsp
, smb_fname
);
2765 if (!NT_STATUS_IS_OK(status
)) {
2766 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2767 /* We have re-scheduled this call. */
2770 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2771 bool ok
= defer_smb1_sharing_violation(req
);
2776 reply_nterror(req
, status
);
2780 reply_smb1_outbuf(req
, 0, 0);
2782 TALLOC_FREE(smb_fname
);
2783 END_PROFILE(SMBunlink
);
2787 /****************************************************************************
2789 ****************************************************************************/
2791 static void fail_readraw(void)
2793 const char *errstr
= talloc_asprintf(talloc_tos(),
2794 "FAIL ! reply_readbraw: socket write fail (%s)",
2799 exit_server_cleanly(errstr
);
2802 /****************************************************************************
2803 Return a readbraw error (4 bytes of zero).
2804 ****************************************************************************/
2806 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
2812 smbd_lock_socket(xconn
);
2813 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
2814 int saved_errno
= errno
;
2816 * Try and give an error message saying what
2819 DEBUG(0, ("write_data failed for client %s. "
2821 smbXsrv_connection_dbg(xconn
),
2822 strerror(saved_errno
)));
2823 errno
= saved_errno
;
2827 smbd_unlock_socket(xconn
);
2830 /*******************************************************************
2831 Ensure we don't use sendfile if server smb signing is active.
2832 ********************************************************************/
2834 static bool lp_use_sendfile(struct smbXsrv_connection
*xconn
,
2836 struct smb1_signing_state
*signing_state
)
2838 bool sign_active
= false;
2840 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2841 if (xconn
->protocol
< PROTOCOL_NT1
) {
2844 if (signing_state
) {
2845 sign_active
= smb1_signing_is_active(signing_state
);
2847 return (lp__use_sendfile(snum
) &&
2848 (get_remote_arch() != RA_WIN95
) &&
2851 /****************************************************************************
2852 Use sendfile in readbraw.
2853 ****************************************************************************/
2855 static void send_file_readbraw(connection_struct
*conn
,
2856 struct smb_request
*req
,
2862 struct smbXsrv_connection
*xconn
= req
->xconn
;
2863 char *outbuf
= NULL
;
2867 * We can only use sendfile on a non-chained packet
2868 * but we can use on a non-oplocked file. tridge proved this
2869 * on a train in Germany :-). JRA.
2870 * reply_readbraw has already checked the length.
2873 if ( !req_is_in_chain(req
) &&
2875 !fsp_is_alternate_stream(fsp
) &&
2876 lp_use_sendfile(xconn
, SNUM(conn
), xconn
->smb1
.signing_state
) ) {
2877 ssize_t sendfile_read
= -1;
2879 DATA_BLOB header_blob
;
2881 _smb_setlen(header
,nread
);
2882 header_blob
= data_blob_const(header
, 4);
2884 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
2885 &header_blob
, startpos
,
2887 if (sendfile_read
== -1) {
2888 /* Returning ENOSYS means no data at all was sent.
2889 * Do this as a normal read. */
2890 if (errno
== ENOSYS
) {
2891 goto normal_readbraw
;
2895 * Special hack for broken Linux with no working sendfile. If we
2896 * return EINTR we sent the header but not the rest of the data.
2897 * Fake this up by doing read/write calls.
2899 if (errno
== EINTR
) {
2900 /* Ensure we don't do this again. */
2901 set_use_sendfile(SNUM(conn
), False
);
2902 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2904 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
2905 DEBUG(0,("send_file_readbraw: "
2906 "fake_sendfile failed for "
2910 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2915 DEBUG(0,("send_file_readbraw: sendfile failed for "
2916 "file %s (%s). Terminating\n",
2917 fsp_str_dbg(fsp
), strerror(errno
)));
2918 exit_server_cleanly("send_file_readbraw sendfile failed");
2919 } else if (sendfile_read
== 0) {
2921 * Some sendfile implementations return 0 to indicate
2922 * that there was a short read, but nothing was
2923 * actually written to the socket. In this case,
2924 * fallback to the normal read path so the header gets
2925 * the correct byte count.
2927 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2928 "bytes falling back to the normal read: "
2929 "%s\n", fsp_str_dbg(fsp
)));
2930 goto normal_readbraw
;
2933 /* Deal with possible short send. */
2934 if (sendfile_read
!= 4+nread
) {
2935 ret
= sendfile_short_send(xconn
, fsp
,
2936 sendfile_read
, 4, nread
);
2946 outbuf
= talloc_array(NULL
, char, nread
+4);
2948 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2949 (unsigned)(nread
+4)));
2950 reply_readbraw_error(xconn
);
2955 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2956 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2965 _smb_setlen(outbuf
,ret
);
2966 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
2967 int saved_errno
= errno
;
2969 * Try and give an error message saying what
2972 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2973 smbXsrv_connection_dbg(xconn
),
2974 strerror(saved_errno
)));
2975 errno
= saved_errno
;
2980 TALLOC_FREE(outbuf
);
2983 /****************************************************************************
2984 Reply to a readbraw (core+ protocol).
2985 ****************************************************************************/
2987 void reply_readbraw(struct smb_request
*req
)
2989 connection_struct
*conn
= req
->conn
;
2990 struct smbXsrv_connection
*xconn
= req
->xconn
;
2991 ssize_t maxcount
,mincount
;
2995 struct lock_struct lock
;
2999 START_PROFILE(SMBreadbraw
);
3001 if (smb1_srv_is_signing_active(xconn
) || req
->encrypted
) {
3002 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3003 "raw reads/writes are disallowed.");
3007 reply_readbraw_error(xconn
);
3008 END_PROFILE(SMBreadbraw
);
3012 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3013 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3014 "'async smb echo handler = yes'\n"));
3015 reply_readbraw_error(xconn
);
3016 END_PROFILE(SMBreadbraw
);
3021 * Special check if an oplock break has been issued
3022 * and the readraw request croses on the wire, we must
3023 * return a zero length response here.
3026 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3029 * We have to do a check_fsp by hand here, as
3030 * we must always return 4 zero bytes on error,
3036 conn
!= fsp
->conn
||
3037 req
->vuid
!= fsp
->vuid
||
3038 fsp
->fsp_flags
.is_directory
||
3039 fsp_get_io_fd(fsp
) == -1)
3042 * fsp could be NULL here so use the value from the packet. JRA.
3044 DEBUG(3,("reply_readbraw: fnum %d not valid "
3046 (int)SVAL(req
->vwv
+0, 0)));
3047 reply_readbraw_error(xconn
);
3048 END_PROFILE(SMBreadbraw
);
3052 /* Do a "by hand" version of CHECK_READ. */
3053 if (!(fsp
->fsp_flags
.can_read
||
3054 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3055 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3056 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3057 (int)SVAL(req
->vwv
+0, 0)));
3058 reply_readbraw_error(xconn
);
3059 END_PROFILE(SMBreadbraw
);
3063 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3064 if(req
->wct
== 10) {
3066 * This is a large offset (64 bit) read.
3069 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3072 DEBUG(0,("reply_readbraw: negative 64 bit "
3073 "readraw offset (%.0f) !\n",
3074 (double)startpos
));
3075 reply_readbraw_error(xconn
);
3076 END_PROFILE(SMBreadbraw
);
3081 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3082 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3084 /* ensure we don't overrun the packet size */
3085 maxcount
= MIN(65535,maxcount
);
3087 init_strict_lock_struct(fsp
,
3088 (uint64_t)req
->smbpid
,
3092 lp_posix_cifsu_locktype(fsp
),
3095 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3096 reply_readbraw_error(xconn
);
3097 END_PROFILE(SMBreadbraw
);
3101 status
= vfs_stat_fsp(fsp
);
3102 if (NT_STATUS_IS_OK(status
)) {
3103 size
= fsp
->fsp_name
->st
.st_ex_size
;
3106 if (startpos
>= size
) {
3109 nread
= MIN(maxcount
,(size
- startpos
));
3112 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3113 if (nread
< mincount
)
3117 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3118 "min=%lu nread=%lu\n",
3119 fsp_fnum_dbg(fsp
), (double)startpos
,
3120 (unsigned long)maxcount
,
3121 (unsigned long)mincount
,
3122 (unsigned long)nread
) );
3124 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3126 DEBUG(5,("reply_readbraw finished\n"));
3128 END_PROFILE(SMBreadbraw
);
3133 #define DBGC_CLASS DBGC_LOCKING
3135 /****************************************************************************
3136 Reply to a lockread (core+ protocol).
3137 ****************************************************************************/
3139 static void reply_lockread_locked(struct tevent_req
*subreq
);
3141 void reply_lockread(struct smb_request
*req
)
3143 struct tevent_req
*subreq
= NULL
;
3144 connection_struct
*conn
= req
->conn
;
3146 struct smbd_lock_element
*lck
= NULL
;
3148 START_PROFILE(SMBlockread
);
3151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3152 END_PROFILE(SMBlockread
);
3156 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3158 if (!check_fsp(conn
, req
, fsp
)) {
3159 END_PROFILE(SMBlockread
);
3163 if (!CHECK_READ(fsp
,req
)) {
3164 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3165 END_PROFILE(SMBlockread
);
3169 lck
= talloc(req
, struct smbd_lock_element
);
3171 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3172 END_PROFILE(SMBlockread
);
3177 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3178 * protocol request that predates the read/write lock concept.
3179 * Thus instead of asking for a read lock here we need to ask
3180 * for a write lock. JRA.
3181 * Note that the requested lock size is unaffected by max_send.
3184 *lck
= (struct smbd_lock_element
) {
3185 .req_guid
= smbd_request_guid(req
, 0),
3186 .smblctx
= req
->smbpid
,
3187 .brltype
= WRITE_LOCK
,
3188 .lock_flav
= WINDOWS_LOCK
,
3189 .count
= SVAL(req
->vwv
+1, 0),
3190 .offset
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0),
3193 subreq
= smbd_smb1_do_locks_send(
3199 false, /* large_offset */
3202 if (subreq
== NULL
) {
3203 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3204 END_PROFILE(SMBlockread
);
3207 tevent_req_set_callback(subreq
, reply_lockread_locked
, NULL
);
3208 END_PROFILE(SMBlockread
);
3211 static void reply_lockread_locked(struct tevent_req
*subreq
)
3213 struct smb_request
*req
= NULL
;
3219 size_t numtoread
, maxtoread
;
3220 struct files_struct
*fsp
= NULL
;
3223 START_PROFILE(SMBlockread
);
3225 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
3228 status
= smbd_smb1_do_locks_recv(subreq
);
3229 TALLOC_FREE(subreq
);
3231 if (!NT_STATUS_IS_OK(status
)) {
3232 reply_nterror(req
, status
);
3236 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3238 reply_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
3242 numtoread
= SVAL(req
->vwv
+1, 0);
3243 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3246 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3248 maxtoread
= req
->xconn
->smb1
.sessions
.max_send
- (MIN_SMB_SIZE
+ 5*2 + 3);
3250 if (numtoread
> maxtoread
) {
3251 DBG_WARNING("requested read size (%zu) is greater than "
3252 "maximum allowed (%zu/%d). "
3253 "Returning short read of maximum allowed for "
3254 "compatibility with Windows 2000.\n",
3257 req
->xconn
->smb1
.sessions
.max_send
);
3258 numtoread
= maxtoread
;
3261 reply_smb1_outbuf(req
, 5, numtoread
+ 3);
3263 data
= smb_buf(req
->outbuf
) + 3;
3265 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3268 reply_nterror(req
, map_nt_error_from_unix(errno
));
3272 srv_smb1_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3274 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3275 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3276 p
= smb_buf(req
->outbuf
);
3277 SCVAL(p
,0,0); /* pad byte. */
3280 DEBUG(3,("lockread %s num=%d nread=%d\n",
3281 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3284 ok
= smb1_srv_send(req
->xconn
,
3285 (char *)req
->outbuf
,
3288 IS_CONN_ENCRYPTED(req
->conn
));
3290 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
3293 END_PROFILE(SMBlockread
);
3298 #define DBGC_CLASS DBGC_ALL
3300 /****************************************************************************
3302 ****************************************************************************/
3304 void reply_read(struct smb_request
*req
)
3306 connection_struct
*conn
= req
->conn
;
3313 struct lock_struct lock
;
3314 struct smbXsrv_connection
*xconn
= req
->xconn
;
3316 START_PROFILE(SMBread
);
3319 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3320 END_PROFILE(SMBread
);
3324 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3326 if (!check_fsp(conn
, req
, fsp
)) {
3327 END_PROFILE(SMBread
);
3331 if (!CHECK_READ(fsp
,req
)) {
3332 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3333 END_PROFILE(SMBread
);
3337 numtoread
= SVAL(req
->vwv
+1, 0);
3338 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3341 * The requested read size cannot be greater than max_send. JRA.
3343 maxtoread
= xconn
->smb1
.sessions
.max_send
- (MIN_SMB_SIZE
+ 5*2 + 3);
3345 if (numtoread
> maxtoread
) {
3346 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3347 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3348 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3349 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3350 numtoread
= maxtoread
;
3353 reply_smb1_outbuf(req
, 5, numtoread
+3);
3355 data
= smb_buf(req
->outbuf
) + 3;
3357 init_strict_lock_struct(fsp
,
3358 (uint64_t)req
->smbpid
,
3360 (uint64_t)numtoread
,
3362 lp_posix_cifsu_locktype(fsp
),
3365 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3366 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3367 END_PROFILE(SMBread
);
3372 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3375 reply_nterror(req
, map_nt_error_from_unix(errno
));
3379 srv_smb1_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3381 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3382 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3383 SCVAL(smb_buf(req
->outbuf
),0,1);
3384 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3386 DEBUG(3, ("read %s num=%d nread=%d\n",
3387 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3390 END_PROFILE(SMBread
);
3394 /****************************************************************************
3396 ****************************************************************************/
3398 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3402 outsize
= srv_smb1_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3405 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3407 SCVAL(outbuf
,smb_vwv0
,0xFF);
3408 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3409 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3410 SSVAL(outbuf
,smb_vwv6
,
3411 (smb_wct
- 4) /* offset from smb header to wct */
3412 + 1 /* the wct field */
3413 + 12 * sizeof(uint16_t) /* vwv */
3414 + 2 /* the buflen field */
3415 + 1); /* padding byte */
3416 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3417 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3418 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3419 _smb_setlen_large(outbuf
,
3420 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3424 /****************************************************************************
3425 Reply to a read and X - possibly using sendfile.
3426 ****************************************************************************/
3428 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3429 files_struct
*fsp
, off_t startpos
,
3432 struct smbXsrv_connection
*xconn
= req
->xconn
;
3434 struct lock_struct lock
;
3435 int saved_errno
= 0;
3438 init_strict_lock_struct(fsp
,
3439 (uint64_t)req
->smbpid
,
3441 (uint64_t)smb_maxcnt
,
3443 lp_posix_cifsu_locktype(fsp
),
3446 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3447 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3452 * We can only use sendfile on a non-chained packet
3453 * but we can use on a non-oplocked file. tridge proved this
3454 * on a train in Germany :-). JRA.
3457 if (!req_is_in_chain(req
) &&
3459 !fsp_is_alternate_stream(fsp
) &&
3460 lp_use_sendfile(xconn
, SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3461 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3464 status
= vfs_stat_fsp(fsp
);
3465 if (!NT_STATUS_IS_OK(status
)) {
3466 reply_nterror(req
, status
);
3470 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3471 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3472 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3474 * We already know that we would do a short read, so don't
3475 * try the sendfile() path.
3477 goto nosendfile_read
;
3481 * Set up the packet header before send. We
3482 * assume here the sendfile will work (get the
3483 * correct amount of data).
3486 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3488 construct_smb1_reply_common_req(req
, (char *)headerbuf
);
3489 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3491 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
3492 startpos
, smb_maxcnt
);
3494 saved_errno
= errno
;
3496 /* Returning ENOSYS means no data at all was sent.
3497 Do this as a normal read. */
3498 if (errno
== ENOSYS
) {
3503 * Special hack for broken Linux with no working sendfile. If we
3504 * return EINTR we sent the header but not the rest of the data.
3505 * Fake this up by doing read/write calls.
3508 if (errno
== EINTR
) {
3509 /* Ensure we don't do this again. */
3510 set_use_sendfile(SNUM(conn
), False
);
3511 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3512 nread
= fake_sendfile(xconn
, fsp
, startpos
,
3515 saved_errno
= errno
;
3516 DEBUG(0,("send_file_readX: "
3517 "fake_sendfile failed for "
3518 "file %s (%s) for client %s. "
3521 smbXsrv_connection_dbg(xconn
),
3522 strerror(saved_errno
)));
3523 errno
= saved_errno
;
3524 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3526 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3527 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3528 /* No outbuf here means successful sendfile. */
3532 DEBUG(0,("send_file_readX: sendfile failed for file "
3533 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3535 exit_server_cleanly("send_file_readX sendfile failed");
3536 } else if (nread
== 0) {
3538 * Some sendfile implementations return 0 to indicate
3539 * that there was a short read, but nothing was
3540 * actually written to the socket. In this case,
3541 * fallback to the normal read path so the header gets
3542 * the correct byte count.
3544 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3545 "falling back to the normal read: %s\n",
3550 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3551 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3553 /* Deal with possible short send. */
3554 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3557 ret
= sendfile_short_send(xconn
, fsp
, nread
,
3558 sizeof(headerbuf
), smb_maxcnt
);
3561 r
= "send_file_readX: sendfile_short_send failed";
3562 DEBUG(0,("%s for file %s (%s).\n",
3563 r
, fsp_str_dbg(fsp
), strerror(errno
)));
3564 exit_server_cleanly(r
);
3567 /* No outbuf here means successful sendfile. */
3573 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3574 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
3577 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3578 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3579 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3581 * We already know that we would do a short
3582 * read, so don't try the sendfile() path.
3584 goto nosendfile_read
;
3587 construct_smb1_reply_common_req(req
, (char *)headerbuf
);
3588 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3590 /* Send out the header. */
3591 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
3593 if (ret
!= sizeof(headerbuf
)) {
3594 saved_errno
= errno
;
3596 * Try and give an error message saying what
3599 DEBUG(0,("send_file_readX: write_data failed for file "
3600 "%s (%s) for client %s. Terminating\n",
3602 smbXsrv_connection_dbg(xconn
),
3603 strerror(saved_errno
)));
3604 errno
= saved_errno
;
3605 exit_server_cleanly("send_file_readX sendfile failed");
3607 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
3609 saved_errno
= errno
;
3610 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3611 "%s (%s) for client %s. Terminating\n",
3613 smbXsrv_connection_dbg(xconn
),
3614 strerror(saved_errno
)));
3615 errno
= saved_errno
;
3616 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3623 reply_smb1_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
3624 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3625 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3627 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
3628 startpos
, smb_maxcnt
);
3629 saved_errno
= errno
;
3632 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3636 setup_readX_header((char *)req
->outbuf
, nread
);
3638 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3639 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3643 TALLOC_FREE(req
->outbuf
);
3647 /****************************************************************************
3648 Work out how much space we have for a read return.
3649 ****************************************************************************/
3651 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3653 struct smbXsrv_connection
*xconn
= req
->xconn
;
3655 if (xconn
->protocol
< PROTOCOL_NT1
) {
3656 return xconn
->smb1
.sessions
.max_send
;
3659 if (!lp_large_readwrite()) {
3660 return xconn
->smb1
.sessions
.max_send
;
3663 if (req_is_in_chain(req
)) {
3664 return xconn
->smb1
.sessions
.max_send
;
3667 if (req
->encrypted
) {
3669 * Don't take encrypted traffic up to the
3670 * limit. There are padding considerations
3671 * that make that tricky.
3673 return xconn
->smb1
.sessions
.max_send
;
3676 if (smb1_srv_is_signing_active(xconn
)) {
3680 if (!lp_smb1_unix_extensions()) {
3685 * We can do ultra-large POSIX reads.
3690 /****************************************************************************
3691 Calculate how big a read can be. Copes with all clients. It's always
3692 safe to return a short read - Windows does this.
3693 ****************************************************************************/
3695 static size_t calc_read_size(const struct smb_request
*req
,
3699 struct smbXsrv_connection
*xconn
= req
->xconn
;
3700 size_t max_pdu
= calc_max_read_pdu(req
);
3701 size_t total_size
= 0;
3702 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
3703 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
3706 * Windows explicitly ignores upper size of 0xFFFF.
3707 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3708 * We must do the same as these will never fit even in
3709 * an extended size NetBIOS packet.
3711 if (upper_size
== 0xFFFF) {
3715 if (xconn
->protocol
< PROTOCOL_NT1
) {
3719 total_size
= ((upper_size
<<16) | lower_size
);
3722 * LARGE_READX test shows it's always safe to return
3723 * a short read. Windows does so.
3725 return MIN(total_size
, max_len
);
3728 /****************************************************************************
3729 Reply to a read and X.
3730 ****************************************************************************/
3732 void reply_read_and_X(struct smb_request
*req
)
3734 connection_struct
*conn
= req
->conn
;
3739 bool big_readX
= False
;
3741 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3744 START_PROFILE(SMBreadX
);
3746 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3747 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3751 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3752 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3753 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3755 /* If it's an IPC, pass off the pipe handler. */
3757 reply_pipe_read_and_X(req
);
3758 END_PROFILE(SMBreadX
);
3762 if (!check_fsp(conn
, req
, fsp
)) {
3763 END_PROFILE(SMBreadX
);
3767 if (!CHECK_READ(fsp
,req
)) {
3768 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3769 END_PROFILE(SMBreadX
);
3773 upper_size
= SVAL(req
->vwv
+7, 0);
3774 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
3775 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
3777 * This is a heuristic to avoid keeping large
3778 * outgoing buffers around over long-lived aio
3784 if (req
->wct
== 12) {
3786 * This is a large offset (64 bit) read.
3788 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
3793 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3798 if (NT_STATUS_IS_OK(status
)) {
3799 /* Read scheduled - we're done. */
3802 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3803 /* Real error - report to client. */
3804 END_PROFILE(SMBreadX
);
3805 reply_nterror(req
, status
);
3808 /* NT_STATUS_RETRY - fall back to sync read. */
3811 smbd_lock_socket(req
->xconn
);
3812 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3813 smbd_unlock_socket(req
->xconn
);
3816 END_PROFILE(SMBreadX
);
3820 /****************************************************************************
3821 Error replies to writebraw must have smb_wct == 1. Fix this up.
3822 ****************************************************************************/
3824 void error_to_writebrawerr(struct smb_request
*req
)
3826 uint8_t *old_outbuf
= req
->outbuf
;
3828 reply_smb1_outbuf(req
, 1, 0);
3830 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3831 TALLOC_FREE(old_outbuf
);
3834 /****************************************************************************
3835 Read 4 bytes of a smb packet and return the smb length of the packet.
3836 Store the result in the buffer. This version of the function will
3837 never return a session keepalive (length of zero).
3838 Timeout is in milliseconds.
3839 ****************************************************************************/
3841 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3844 uint8_t msgtype
= NBSSkeepalive
;
3846 while (msgtype
== NBSSkeepalive
) {
3849 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3851 if (!NT_STATUS_IS_OK(status
)) {
3852 char addr
[INET6_ADDRSTRLEN
];
3853 /* Try and give an error message
3854 * saying what client failed. */
3855 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3856 "client %s read error = %s.\n",
3857 get_peer_addr(fd
,addr
,sizeof(addr
)),
3858 nt_errstr(status
)));
3862 msgtype
= CVAL(inbuf
, 0);
3865 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3866 (unsigned long)len
));
3868 return NT_STATUS_OK
;
3871 /****************************************************************************
3872 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3873 ****************************************************************************/
3875 void reply_writebraw(struct smb_request
*req
)
3877 connection_struct
*conn
= req
->conn
;
3878 struct smbXsrv_connection
*xconn
= req
->xconn
;
3881 ssize_t total_written
=0;
3882 size_t numtowrite
=0;
3885 const char *data
=NULL
;
3888 struct lock_struct lock
;
3891 START_PROFILE(SMBwritebraw
);
3894 * If we ever reply with an error, it must have the SMB command
3895 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3898 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3900 if (smb1_srv_is_signing_active(xconn
)) {
3901 END_PROFILE(SMBwritebraw
);
3902 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3903 "raw reads/writes are disallowed.");
3906 if (req
->wct
< 12) {
3907 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3908 error_to_writebrawerr(req
);
3909 END_PROFILE(SMBwritebraw
);
3913 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3914 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3915 "'async smb echo handler = yes'\n"));
3916 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3917 error_to_writebrawerr(req
);
3918 END_PROFILE(SMBwritebraw
);
3922 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3923 if (!check_fsp(conn
, req
, fsp
)) {
3924 error_to_writebrawerr(req
);
3925 END_PROFILE(SMBwritebraw
);
3929 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
3930 if (!NT_STATUS_IS_OK(status
)) {
3931 reply_nterror(req
, status
);
3932 error_to_writebrawerr(req
);
3933 END_PROFILE(SMBwritebraw
);
3937 tcount
= IVAL(req
->vwv
+1, 0);
3938 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3939 write_through
= BITSETW(req
->vwv
+7,0);
3941 /* We have to deal with slightly different formats depending
3942 on whether we are using the core+ or lanman1.0 protocol */
3944 if(xconn
->protocol
<= PROTOCOL_COREPLUS
) {
3945 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
3946 data
= smb_buf_const(req
->inbuf
);
3948 numtowrite
= SVAL(req
->vwv
+10, 0);
3949 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3952 /* Ensure we don't write bytes past the end of this packet. */
3954 * This already protects us against CVE-2017-12163.
3956 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3957 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3958 error_to_writebrawerr(req
);
3959 END_PROFILE(SMBwritebraw
);
3963 if (!fsp
->print_file
) {
3964 init_strict_lock_struct(fsp
,
3965 (uint64_t)req
->smbpid
,
3969 lp_posix_cifsu_locktype(fsp
),
3972 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3973 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3974 error_to_writebrawerr(req
);
3975 END_PROFILE(SMBwritebraw
);
3981 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3984 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3985 "wrote=%d sync=%d\n",
3986 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
3987 (int)nwritten
, (int)write_through
));
3989 if (nwritten
< (ssize_t
)numtowrite
) {
3990 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3991 error_to_writebrawerr(req
);
3995 total_written
= nwritten
;
3997 /* Allocate a buffer of 64k + length. */
3998 buf
= talloc_array(NULL
, char, 65540);
4000 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4001 error_to_writebrawerr(req
);
4005 /* Return a SMBwritebraw message to the redirector to tell
4006 * it to send more bytes */
4008 memcpy(buf
, req
->inbuf
, smb_size
);
4009 srv_smb1_set_message(buf
,xconn
->protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
4010 SCVAL(buf
,smb_com
,SMBwritebraw
);
4011 SSVALS(buf
,smb_vwv0
,0xFFFF);
4013 if (!smb1_srv_send(req
->xconn
,
4017 IS_CONN_ENCRYPTED(conn
))) {
4018 exit_server_cleanly("reply_writebraw: smb1_srv_send "
4022 /* Now read the raw data into the buffer and write it */
4023 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4025 if (!NT_STATUS_IS_OK(status
)) {
4026 exit_server_cleanly("secondary writebraw failed");
4029 /* Set up outbuf to return the correct size */
4030 reply_smb1_outbuf(req
, 1, 0);
4032 if (numtowrite
!= 0) {
4034 if (numtowrite
> 0xFFFF) {
4035 DEBUG(0,("reply_writebraw: Oversize secondary write "
4036 "raw requested (%u). Terminating\n",
4037 (unsigned int)numtowrite
));
4038 exit_server_cleanly("secondary writebraw failed");
4041 if (tcount
> nwritten
+numtowrite
) {
4042 DEBUG(3,("reply_writebraw: Client overestimated the "
4044 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4047 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4050 if (!NT_STATUS_IS_OK(status
)) {
4051 /* Try and give an error message
4052 * saying what client failed. */
4053 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4054 "raw read failed (%s) for client %s. "
4055 "Terminating\n", nt_errstr(status
),
4056 smbXsrv_connection_dbg(xconn
)));
4057 exit_server_cleanly("secondary writebraw failed");
4061 * We are not vulnerable to CVE-2017-12163
4062 * here as we are guaranteed to have numtowrite
4063 * bytes available - we just read from the client.
4065 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4066 if (nwritten
== -1) {
4068 reply_nterror(req
, map_nt_error_from_unix(errno
));
4069 error_to_writebrawerr(req
);
4073 if (nwritten
< (ssize_t
)numtowrite
) {
4074 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4075 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4079 total_written
+= nwritten
;
4084 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4086 status
= sync_file(conn
, fsp
, write_through
);
4087 if (!NT_STATUS_IS_OK(status
)) {
4088 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4089 fsp_str_dbg(fsp
), nt_errstr(status
)));
4090 reply_nterror(req
, status
);
4091 error_to_writebrawerr(req
);
4095 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4097 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4098 (int)total_written
));
4100 /* We won't return a status if write through is not selected - this
4101 * follows what WfWg does */
4102 END_PROFILE(SMBwritebraw
);
4104 if (!write_through
&& total_written
==tcount
) {
4106 #if RABBIT_PELLET_FIX
4108 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4109 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4112 if (!send_keepalive(xconn
->transport
.sock
)) {
4113 exit_server_cleanly("reply_writebraw: send of "
4114 "keepalive failed");
4117 TALLOC_FREE(req
->outbuf
);
4122 END_PROFILE(SMBwritebraw
);
4127 #define DBGC_CLASS DBGC_LOCKING
4129 /****************************************************************************
4130 Reply to a writeunlock (core+).
4131 ****************************************************************************/
4133 void reply_writeunlock(struct smb_request
*req
)
4135 connection_struct
*conn
= req
->conn
;
4136 ssize_t nwritten
= -1;
4141 NTSTATUS status
= NT_STATUS_OK
;
4143 struct lock_struct lock
;
4144 int saved_errno
= 0;
4146 START_PROFILE(SMBwriteunlock
);
4149 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4150 END_PROFILE(SMBwriteunlock
);
4154 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4156 if (!check_fsp(conn
, req
, fsp
)) {
4157 END_PROFILE(SMBwriteunlock
);
4161 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
4162 if (!NT_STATUS_IS_OK(status
)) {
4163 reply_nterror(req
, status
);
4164 END_PROFILE(SMBwriteunlock
);
4168 numtowrite
= SVAL(req
->vwv
+1, 0);
4169 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4170 data
= (const char *)req
->buf
+ 3;
4173 * Ensure client isn't asking us to write more than
4174 * they sent. CVE-2017-12163.
4176 remaining
= smbreq_bufrem(req
, data
);
4177 if (numtowrite
> remaining
) {
4178 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4179 END_PROFILE(SMBwriteunlock
);
4183 if (!fsp
->print_file
&& numtowrite
> 0) {
4184 init_strict_lock_struct(fsp
,
4185 (uint64_t)req
->smbpid
,
4187 (uint64_t)numtowrite
,
4189 lp_posix_cifsu_locktype(fsp
),
4192 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4193 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4194 END_PROFILE(SMBwriteunlock
);
4199 /* The special X/Open SMB protocol handling of
4200 zero length writes is *NOT* done for
4202 if(numtowrite
== 0) {
4205 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4206 saved_errno
= errno
;
4209 status
= sync_file(conn
, fsp
, False
/* write through */);
4210 if (!NT_STATUS_IS_OK(status
)) {
4211 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4212 fsp_str_dbg(fsp
), nt_errstr(status
)));
4213 reply_nterror(req
, status
);
4218 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4222 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4223 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4227 if (numtowrite
&& !fsp
->print_file
) {
4228 struct smbd_lock_element l
= {
4229 .req_guid
= smbd_request_guid(req
, 0),
4230 .smblctx
= req
->smbpid
,
4231 .brltype
= UNLOCK_LOCK
,
4232 .lock_flav
= WINDOWS_LOCK
,
4234 .count
= numtowrite
,
4236 status
= smbd_do_unlocking(req
, fsp
, 1, &l
);
4237 if (NT_STATUS_V(status
)) {
4238 reply_nterror(req
, status
);
4243 reply_smb1_outbuf(req
, 1, 0);
4245 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4247 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4248 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4251 END_PROFILE(SMBwriteunlock
);
4256 #define DBGC_CLASS DBGC_ALL
4258 /****************************************************************************
4260 ****************************************************************************/
4262 void reply_write(struct smb_request
*req
)
4264 connection_struct
*conn
= req
->conn
;
4267 ssize_t nwritten
= -1;
4271 struct lock_struct lock
;
4273 int saved_errno
= 0;
4275 START_PROFILE(SMBwrite
);
4278 END_PROFILE(SMBwrite
);
4279 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4283 /* If it's an IPC, pass off the pipe handler. */
4285 reply_pipe_write(req
);
4286 END_PROFILE(SMBwrite
);
4290 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4292 if (!check_fsp(conn
, req
, fsp
)) {
4293 END_PROFILE(SMBwrite
);
4297 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
4298 if (!NT_STATUS_IS_OK(status
)) {
4299 reply_nterror(req
, status
);
4300 END_PROFILE(SMBwrite
);
4304 numtowrite
= SVAL(req
->vwv
+1, 0);
4305 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4306 data
= (const char *)req
->buf
+ 3;
4309 * Ensure client isn't asking us to write more than
4310 * they sent. CVE-2017-12163.
4312 remaining
= smbreq_bufrem(req
, data
);
4313 if (numtowrite
> remaining
) {
4314 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4315 END_PROFILE(SMBwrite
);
4319 if (!fsp
->print_file
) {
4320 init_strict_lock_struct(fsp
,
4321 (uint64_t)req
->smbpid
,
4323 (uint64_t)numtowrite
,
4325 lp_posix_cifsu_locktype(fsp
),
4328 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4329 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4330 END_PROFILE(SMBwrite
);
4336 * X/Open SMB protocol says that if smb_vwv1 is
4337 * zero then the file size should be extended or
4338 * truncated to the size given in smb_vwv[2-3].
4341 if(numtowrite
== 0) {
4343 * This is actually an allocate call, and set EOF. JRA.
4345 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4347 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4350 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4352 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4355 trigger_write_time_update_immediate(fsp
);
4357 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4360 status
= sync_file(conn
, fsp
, False
);
4361 if (!NT_STATUS_IS_OK(status
)) {
4362 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4363 fsp_str_dbg(fsp
), nt_errstr(status
)));
4364 reply_nterror(req
, status
);
4369 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4373 if((nwritten
== 0) && (numtowrite
!= 0)) {
4374 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4378 reply_smb1_outbuf(req
, 1, 0);
4380 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4382 if (nwritten
< (ssize_t
)numtowrite
) {
4383 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4384 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4387 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4390 END_PROFILE(SMBwrite
);
4394 /****************************************************************************
4395 Ensure a buffer is a valid writeX for recvfile purposes.
4396 ****************************************************************************/
4398 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4399 (2*14) + /* word count (including bcc) */ \
4402 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4403 const uint8_t *inbuf
)
4406 unsigned int doff
= 0;
4407 size_t len
= smb_len_large(inbuf
);
4409 struct smbXsrv_open
*op
= NULL
;
4410 struct files_struct
*fsp
= NULL
;
4413 if (is_encrypted_packet(inbuf
)) {
4414 /* Can't do this on encrypted
4419 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4423 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4424 CVAL(inbuf
,smb_wct
) != 14) {
4425 DEBUG(10,("is_valid_writeX_buffer: chained or "
4426 "invalid word length.\n"));
4430 fnum
= SVAL(inbuf
, smb_vwv2
);
4431 status
= smb1srv_open_lookup(xconn
,
4435 if (!NT_STATUS_IS_OK(status
)) {
4436 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4441 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4444 if (fsp
->conn
== NULL
) {
4445 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4449 if (IS_IPC(fsp
->conn
)) {
4450 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4453 if (IS_PRINT(fsp
->conn
)) {
4454 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4457 if (fsp_is_alternate_stream(fsp
)) {
4458 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4461 doff
= SVAL(inbuf
,smb_vwv11
);
4463 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4465 if (len
> doff
&& len
- doff
> 0xFFFF) {
4466 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4469 if (numtowrite
== 0) {
4470 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4474 /* Ensure the sizes match up. */
4475 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4476 /* no pad byte...old smbclient :-( */
4477 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4479 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4483 if (len
- doff
!= numtowrite
) {
4484 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4485 "len = %u, doff = %u, numtowrite = %u\n",
4488 (unsigned int)numtowrite
));
4492 DEBUG(10,("is_valid_writeX_buffer: true "
4493 "len = %u, doff = %u, numtowrite = %u\n",
4496 (unsigned int)numtowrite
));
4501 /****************************************************************************
4502 Reply to a write and X.
4503 ****************************************************************************/
4505 void reply_write_and_X(struct smb_request
*req
)
4507 connection_struct
*conn
= req
->conn
;
4508 struct smbXsrv_connection
*xconn
= req
->xconn
;
4510 struct lock_struct lock
;
4515 unsigned int smb_doff
;
4516 unsigned int smblen
;
4519 int saved_errno
= 0;
4521 START_PROFILE(SMBwriteX
);
4523 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4524 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4528 numtowrite
= SVAL(req
->vwv
+10, 0);
4529 smb_doff
= SVAL(req
->vwv
+11, 0);
4530 smblen
= smb_len(req
->inbuf
);
4532 if (req
->unread_bytes
> 0xFFFF ||
4533 (smblen
> smb_doff
&&
4534 smblen
- smb_doff
> 0xFFFF)) {
4535 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4538 if (req
->unread_bytes
) {
4539 /* Can't do a recvfile write on IPC$ */
4541 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4544 if (numtowrite
!= req
->unread_bytes
) {
4545 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4550 * This already protects us against CVE-2017-12163.
4552 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4553 smb_doff
+ numtowrite
> smblen
) {
4554 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4559 /* If it's an IPC, pass off the pipe handler. */
4561 if (req
->unread_bytes
) {
4562 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4565 reply_pipe_write_and_X(req
);
4569 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4570 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4571 write_through
= BITSETW(req
->vwv
+7,0);
4573 if (!check_fsp(conn
, req
, fsp
)) {
4577 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
4578 if (!NT_STATUS_IS_OK(status
)) {
4579 reply_nterror(req
, status
);
4583 data
= smb_base(req
->inbuf
) + smb_doff
;
4585 if(req
->wct
== 14) {
4587 * This is a large offset (64 bit) write.
4589 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4593 /* X/Open SMB protocol says that, unlike SMBwrite
4594 if the length is zero then NO truncation is
4595 done, just a write of zero. To truncate a file,
4598 if(numtowrite
== 0) {
4601 if (req
->unread_bytes
== 0) {
4602 status
= schedule_aio_write_and_X(conn
,
4609 if (NT_STATUS_IS_OK(status
)) {
4610 /* write scheduled - we're done. */
4613 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4614 /* Real error - report to client. */
4615 reply_nterror(req
, status
);
4618 /* NT_STATUS_RETRY - fall through to sync write. */
4621 init_strict_lock_struct(fsp
,
4622 (uint64_t)req
->smbpid
,
4624 (uint64_t)numtowrite
,
4626 lp_posix_cifsu_locktype(fsp
),
4629 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4630 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4634 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4635 saved_errno
= errno
;
4639 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4643 if((nwritten
== 0) && (numtowrite
!= 0)) {
4644 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4648 reply_smb1_outbuf(req
, 6, 0);
4649 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4650 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4651 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4652 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4654 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4655 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4657 status
= sync_file(conn
, fsp
, write_through
);
4658 if (!NT_STATUS_IS_OK(status
)) {
4659 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4660 fsp_str_dbg(fsp
), nt_errstr(status
)));
4661 reply_nterror(req
, status
);
4665 END_PROFILE(SMBwriteX
);
4669 if (req
->unread_bytes
) {
4670 /* writeX failed. drain socket. */
4671 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
4672 req
->unread_bytes
) {
4673 smb_panic("failed to drain pending bytes");
4675 req
->unread_bytes
= 0;
4678 END_PROFILE(SMBwriteX
);
4682 /****************************************************************************
4684 ****************************************************************************/
4686 void reply_lseek(struct smb_request
*req
)
4688 connection_struct
*conn
= req
->conn
;
4695 START_PROFILE(SMBlseek
);
4698 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4699 END_PROFILE(SMBlseek
);
4703 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4705 if (!check_fsp(conn
, req
, fsp
)) {
4709 mode
= SVAL(req
->vwv
+1, 0) & 3;
4710 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4711 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4720 res
= fh_get_pos(fsp
->fh
) + startpos
;
4731 if (umode
== SEEK_END
) {
4732 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4733 if(errno
== EINVAL
) {
4734 off_t current_pos
= startpos
;
4736 status
= vfs_stat_fsp(fsp
);
4737 if (!NT_STATUS_IS_OK(status
)) {
4738 reply_nterror(req
, status
);
4739 END_PROFILE(SMBlseek
);
4743 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4745 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4750 reply_nterror(req
, map_nt_error_from_unix(errno
));
4751 END_PROFILE(SMBlseek
);
4756 fh_set_pos(fsp
->fh
, res
);
4758 reply_smb1_outbuf(req
, 2, 0);
4759 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4761 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4762 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4764 END_PROFILE(SMBlseek
);
4768 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
4771 connection_struct
*conn
= talloc_get_type_abort(
4772 private_data
, connection_struct
);
4774 if (conn
!= fsp
->conn
) {
4777 if (fsp_get_io_fd(fsp
) == -1) {
4780 sync_file(conn
, fsp
, True
/* write through */);
4782 if (fsp
->fsp_flags
.modified
) {
4783 trigger_write_time_update_immediate(fsp
);
4789 /****************************************************************************
4791 ****************************************************************************/
4793 void reply_flush(struct smb_request
*req
)
4795 connection_struct
*conn
= req
->conn
;
4799 START_PROFILE(SMBflush
);
4802 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4806 fnum
= SVAL(req
->vwv
+0, 0);
4807 fsp
= file_fsp(req
, fnum
);
4809 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4814 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
4816 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4817 if (!NT_STATUS_IS_OK(status
)) {
4818 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4819 fsp_str_dbg(fsp
), nt_errstr(status
)));
4820 reply_nterror(req
, status
);
4821 END_PROFILE(SMBflush
);
4824 if (fsp
->fsp_flags
.modified
) {
4825 trigger_write_time_update_immediate(fsp
);
4829 reply_smb1_outbuf(req
, 0, 0);
4831 DEBUG(3,("flush\n"));
4832 END_PROFILE(SMBflush
);
4836 /****************************************************************************
4838 conn POINTER CAN BE NULL HERE !
4839 ****************************************************************************/
4841 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
);
4842 static void reply_exit_done(struct tevent_req
*req
);
4844 void reply_exit(struct smb_request
*smb1req
)
4846 struct tevent_req
*req
;
4849 * Don't setup the profile charge here, take
4850 * it in reply_exit_done(). Not strictly correct
4851 * but better than the other SMB1 async
4852 * code that double-charges at the moment.
4854 req
= reply_exit_send(smb1req
);
4856 /* Not going async, profile here. */
4857 START_PROFILE(SMBexit
);
4858 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
4859 END_PROFILE(SMBexit
);
4863 /* We're async. This will complete later. */
4864 tevent_req_set_callback(req
, reply_exit_done
, smb1req
);
4868 struct reply_exit_state
{
4869 struct tevent_queue
*wait_queue
;
4872 static void reply_exit_wait_done(struct tevent_req
*subreq
);
4874 /****************************************************************************
4876 Note, on failure here we deallocate and return NULL to allow the caller to
4877 SMB1 return an error of ERRnomem immediately.
4878 ****************************************************************************/
4880 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
)
4882 struct tevent_req
*req
;
4883 struct reply_exit_state
*state
;
4884 struct tevent_req
*subreq
;
4886 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4888 req
= tevent_req_create(smb1req
, &state
,
4889 struct reply_exit_state
);
4893 state
->wait_queue
= tevent_queue_create(state
,
4894 "reply_exit_wait_queue");
4895 if (tevent_req_nomem(state
->wait_queue
, req
)) {
4900 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
4901 if (fsp
->file_pid
!= smb1req
->smbpid
) {
4904 if (fsp
->vuid
!= smb1req
->vuid
) {
4908 * Flag the file as close in progress.
4909 * This will prevent any more IO being
4912 fsp
->fsp_flags
.closing
= true;
4914 if (fsp
->num_aio_requests
> 0) {
4916 * Now wait until all aio requests on this fsp are
4919 * We don't set a callback, as we just want to block the
4920 * wait queue and the talloc_free() of fsp->aio_request
4921 * will remove the item from the wait queue.
4923 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
4926 if (tevent_req_nomem(subreq
, req
)) {
4934 * Now we add our own waiter to the end of the queue,
4935 * this way we get notified when all pending requests are finished
4936 * and reply to the outstanding SMB1 request.
4938 subreq
= tevent_queue_wait_send(state
,
4941 if (tevent_req_nomem(subreq
, req
)) {
4947 * We're really going async - move the SMB1 request from
4948 * a talloc stackframe above us to the conn talloc-context.
4949 * We need this to stick around until the wait_done
4950 * callback is invoked.
4952 smb1req
= talloc_move(sconn
, &smb1req
);
4954 tevent_req_set_callback(subreq
, reply_exit_wait_done
, req
);
4959 static void reply_exit_wait_done(struct tevent_req
*subreq
)
4961 struct tevent_req
*req
= tevent_req_callback_data(
4962 subreq
, struct tevent_req
);
4964 tevent_queue_wait_recv(subreq
);
4965 TALLOC_FREE(subreq
);
4966 tevent_req_done(req
);
4969 static NTSTATUS
reply_exit_recv(struct tevent_req
*req
)
4971 return tevent_req_simple_recv_ntstatus(req
);
4974 static void reply_exit_done(struct tevent_req
*req
)
4976 struct smb_request
*smb1req
= tevent_req_callback_data(
4977 req
, struct smb_request
);
4978 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4979 struct smbXsrv_connection
*xconn
= smb1req
->xconn
;
4980 NTTIME now
= timeval_to_nttime(&smb1req
->request_time
);
4981 struct smbXsrv_session
*session
= NULL
;
4982 files_struct
*fsp
, *next
;
4986 * Take the profile charge here. Not strictly
4987 * correct but better than the other SMB1 async
4988 * code that double-charges at the moment.
4990 START_PROFILE(SMBexit
);
4992 status
= reply_exit_recv(req
);
4994 if (!NT_STATUS_IS_OK(status
)) {
4995 TALLOC_FREE(smb1req
);
4996 END_PROFILE(SMBexit
);
4997 exit_server(__location__
": reply_exit_recv failed");
5002 * Ensure the session is still valid.
5004 status
= smb1srv_session_lookup(xconn
,
5008 if (!NT_STATUS_IS_OK(status
)) {
5009 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5010 smb_request_done(smb1req
);
5011 END_PROFILE(SMBexit
);
5016 * Ensure the vuid is still valid - no one
5017 * called reply_ulogoffX() in the meantime.
5018 * reply_exit() doesn't have AS_USER set, so
5019 * use set_current_user_info() directly.
5020 * This is the same logic as in switch_message().
5022 if (session
->global
->auth_session_info
!= NULL
) {
5023 set_current_user_info(
5024 session
->global
->auth_session_info
->unix_info
->sanitized_username
,
5025 session
->global
->auth_session_info
->unix_info
->unix_name
,
5026 session
->global
->auth_session_info
->info
->domain_name
);
5029 /* No more aio - do the actual closes. */
5030 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
5034 if (fsp
->file_pid
!= smb1req
->smbpid
) {
5037 if (fsp
->vuid
!= smb1req
->vuid
) {
5040 if (!fsp
->fsp_flags
.closing
) {
5045 * reply_exit() has the DO_CHDIR flag set.
5047 ok
= chdir_current_service(fsp
->conn
);
5049 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5050 smb_request_done(smb1req
);
5051 END_PROFILE(SMBexit
);
5054 close_file_free(NULL
, &fsp
, SHUTDOWN_CLOSE
);
5057 reply_smb1_outbuf(smb1req
, 0, 0);
5059 * The following call is needed to push the
5060 * reply data back out the socket after async
5061 * return. Plus it frees smb1req.
5063 smb_request_done(smb1req
);
5064 DBG_INFO("reply_exit complete\n");
5065 END_PROFILE(SMBexit
);
5069 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
5071 static void reply_close_done(struct tevent_req
*req
);
5073 void reply_close(struct smb_request
*smb1req
)
5075 connection_struct
*conn
= smb1req
->conn
;
5076 NTSTATUS status
= NT_STATUS_OK
;
5077 files_struct
*fsp
= NULL
;
5078 START_PROFILE(SMBclose
);
5080 if (smb1req
->wct
< 3) {
5081 reply_nterror(smb1req
, NT_STATUS_INVALID_PARAMETER
);
5082 END_PROFILE(SMBclose
);
5086 fsp
= file_fsp(smb1req
, SVAL(smb1req
->vwv
+0, 0));
5089 * We can only use check_fsp if we know it's not a directory.
5092 if (!check_fsp_open(conn
, smb1req
, fsp
)) {
5093 END_PROFILE(SMBclose
);
5097 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5098 fsp
->fsp_flags
.is_directory
?
5099 "directory" : "file",
5100 fsp_get_pathref_fd(fsp
), fsp_fnum_dbg(fsp
),
5101 conn
->num_files_open
);
5103 if (!fsp
->fsp_flags
.is_directory
) {
5107 * Take care of any time sent in the close.
5110 t
= srv_make_unix_date3(smb1req
->vwv
+1);
5111 set_close_write_time(fsp
, time_t_to_full_timespec(t
));
5114 if (fsp
->num_aio_requests
!= 0) {
5115 struct tevent_req
*req
;
5117 req
= reply_close_send(smb1req
, fsp
);
5119 status
= NT_STATUS_NO_MEMORY
;
5122 /* We're async. This will complete later. */
5123 tevent_req_set_callback(req
, reply_close_done
, smb1req
);
5124 END_PROFILE(SMBclose
);
5129 * close_file_free() returns the unix errno if an error was detected on
5130 * close - normally this is due to a disk full error. If not then it
5131 * was probably an I/O error.
5134 status
= close_file_free(smb1req
, &fsp
, NORMAL_CLOSE
);
5136 if (!NT_STATUS_IS_OK(status
)) {
5137 reply_nterror(smb1req
, status
);
5138 END_PROFILE(SMBclose
);
5142 reply_smb1_outbuf(smb1req
, 0, 0);
5143 END_PROFILE(SMBclose
);
5147 struct reply_close_state
{
5149 struct tevent_queue
*wait_queue
;
5152 static void reply_close_wait_done(struct tevent_req
*subreq
);
5154 /****************************************************************************
5156 Note, on failure here we deallocate and return NULL to allow the caller to
5157 SMB1 return an error of ERRnomem immediately.
5158 ****************************************************************************/
5160 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
5163 struct tevent_req
*req
;
5164 struct reply_close_state
*state
;
5165 struct tevent_req
*subreq
;
5166 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
5168 req
= tevent_req_create(smb1req
, &state
,
5169 struct reply_close_state
);
5173 state
->wait_queue
= tevent_queue_create(state
,
5174 "reply_close_wait_queue");
5175 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5181 * Flag the file as close in progress.
5182 * This will prevent any more IO being
5185 fsp
->fsp_flags
.closing
= true;
5188 * Now wait until all aio requests on this fsp are
5191 * We don't set a callback, as we just want to block the
5192 * wait queue and the talloc_free() of fsp->aio_request
5193 * will remove the item from the wait queue.
5195 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5198 if (tevent_req_nomem(subreq
, req
)) {
5204 * Now we add our own waiter to the end of the queue,
5205 * this way we get notified when all pending requests are finished
5206 * and reply to the outstanding SMB1 request.
5208 subreq
= tevent_queue_wait_send(state
,
5211 if (tevent_req_nomem(subreq
, req
)) {
5217 * We're really going async - move the SMB1 request from
5218 * a talloc stackframe above us to the conn talloc-context.
5219 * We need this to stick around until the wait_done
5220 * callback is invoked.
5222 smb1req
= talloc_move(sconn
, &smb1req
);
5224 tevent_req_set_callback(subreq
, reply_close_wait_done
, req
);
5229 static void reply_close_wait_done(struct tevent_req
*subreq
)
5231 struct tevent_req
*req
= tevent_req_callback_data(
5232 subreq
, struct tevent_req
);
5234 tevent_queue_wait_recv(subreq
);
5235 TALLOC_FREE(subreq
);
5236 tevent_req_done(req
);
5239 static NTSTATUS
reply_close_recv(struct tevent_req
*req
)
5241 return tevent_req_simple_recv_ntstatus(req
);
5244 static void reply_close_done(struct tevent_req
*req
)
5246 struct smb_request
*smb1req
= tevent_req_callback_data(
5247 req
, struct smb_request
);
5248 struct reply_close_state
*state
= tevent_req_data(req
,
5249 struct reply_close_state
);
5252 status
= reply_close_recv(req
);
5254 if (!NT_STATUS_IS_OK(status
)) {
5255 TALLOC_FREE(smb1req
);
5256 exit_server(__location__
": reply_close_recv failed");
5260 status
= close_file_free(smb1req
, &state
->fsp
, NORMAL_CLOSE
);
5261 if (NT_STATUS_IS_OK(status
)) {
5262 reply_smb1_outbuf(smb1req
, 0, 0);
5264 reply_nterror(smb1req
, status
);
5267 * The following call is needed to push the
5268 * reply data back out the socket after async
5269 * return. Plus it frees smb1req.
5271 smb_request_done(smb1req
);
5274 /****************************************************************************
5275 Reply to a writeclose (Core+ protocol).
5276 ****************************************************************************/
5278 void reply_writeclose(struct smb_request
*req
)
5280 connection_struct
*conn
= req
->conn
;
5283 ssize_t nwritten
= -1;
5284 NTSTATUS close_status
= NT_STATUS_OK
;
5287 struct timespec mtime
;
5289 struct lock_struct lock
;
5292 START_PROFILE(SMBwriteclose
);
5295 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5296 END_PROFILE(SMBwriteclose
);
5300 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5302 if (!check_fsp(conn
, req
, fsp
)) {
5303 END_PROFILE(SMBwriteclose
);
5306 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
5307 if (!NT_STATUS_IS_OK(status
)) {
5308 reply_nterror(req
, status
);
5309 END_PROFILE(SMBwriteclose
);
5313 numtowrite
= SVAL(req
->vwv
+1, 0);
5314 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5315 mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+4));
5316 data
= (const char *)req
->buf
+ 1;
5319 * Ensure client isn't asking us to write more than
5320 * they sent. CVE-2017-12163.
5322 remaining
= smbreq_bufrem(req
, data
);
5323 if (numtowrite
> remaining
) {
5324 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5325 END_PROFILE(SMBwriteclose
);
5329 if (fsp
->print_file
== NULL
) {
5330 init_strict_lock_struct(fsp
,
5331 (uint64_t)req
->smbpid
,
5333 (uint64_t)numtowrite
,
5335 lp_posix_cifsu_locktype(fsp
),
5338 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5339 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5340 END_PROFILE(SMBwriteclose
);
5345 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5347 set_close_write_time(fsp
, mtime
);
5350 * More insanity. W2K only closes the file if writelen > 0.
5354 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5355 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5356 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5359 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5360 "file %s\n", fsp_str_dbg(fsp
)));
5361 close_status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5364 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5365 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5369 if(!NT_STATUS_IS_OK(close_status
)) {
5370 reply_nterror(req
, close_status
);
5374 reply_smb1_outbuf(req
, 1, 0);
5376 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5380 END_PROFILE(SMBwriteclose
);
5385 #define DBGC_CLASS DBGC_LOCKING
5387 /****************************************************************************
5389 ****************************************************************************/
5391 static void reply_lock_done(struct tevent_req
*subreq
);
5393 void reply_lock(struct smb_request
*req
)
5395 struct tevent_req
*subreq
= NULL
;
5396 connection_struct
*conn
= req
->conn
;
5398 struct smbd_lock_element
*lck
= NULL
;
5400 START_PROFILE(SMBlock
);
5403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5404 END_PROFILE(SMBlock
);
5408 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5410 if (!check_fsp(conn
, req
, fsp
)) {
5411 END_PROFILE(SMBlock
);
5415 lck
= talloc(req
, struct smbd_lock_element
);
5417 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5418 END_PROFILE(SMBlock
);
5422 *lck
= (struct smbd_lock_element
) {
5423 .req_guid
= smbd_request_guid(req
, 0),
5424 .smblctx
= req
->smbpid
,
5425 .brltype
= WRITE_LOCK
,
5426 .lock_flav
= WINDOWS_LOCK
,
5427 .count
= IVAL(req
->vwv
+1, 0),
5428 .offset
= IVAL(req
->vwv
+3, 0),
5431 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5437 subreq
= smbd_smb1_do_locks_send(
5443 false, /* large_offset */
5446 if (subreq
== NULL
) {
5447 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5448 END_PROFILE(SMBlock
);
5451 tevent_req_set_callback(subreq
, reply_lock_done
, NULL
);
5452 END_PROFILE(SMBlock
);
5455 static void reply_lock_done(struct tevent_req
*subreq
)
5457 struct smb_request
*req
= NULL
;
5461 START_PROFILE(SMBlock
);
5463 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
5466 status
= smbd_smb1_do_locks_recv(subreq
);
5467 TALLOC_FREE(subreq
);
5469 if (NT_STATUS_IS_OK(status
)) {
5470 reply_smb1_outbuf(req
, 0, 0);
5472 reply_nterror(req
, status
);
5475 ok
= smb1_srv_send(req
->xconn
,
5476 (char *)req
->outbuf
,
5479 IS_CONN_ENCRYPTED(req
->conn
));
5481 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5484 END_PROFILE(SMBlock
);
5487 /****************************************************************************
5489 ****************************************************************************/
5491 void reply_unlock(struct smb_request
*req
)
5493 connection_struct
*conn
= req
->conn
;
5496 struct smbd_lock_element lck
;
5498 START_PROFILE(SMBunlock
);
5501 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5502 END_PROFILE(SMBunlock
);
5506 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5508 if (!check_fsp(conn
, req
, fsp
)) {
5509 END_PROFILE(SMBunlock
);
5513 lck
= (struct smbd_lock_element
) {
5514 .req_guid
= smbd_request_guid(req
, 0),
5515 .smblctx
= req
->smbpid
,
5516 .brltype
= UNLOCK_LOCK
,
5517 .lock_flav
= WINDOWS_LOCK
,
5518 .offset
= IVAL(req
->vwv
+3, 0),
5519 .count
= IVAL(req
->vwv
+1, 0),
5522 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
);
5524 if (!NT_STATUS_IS_OK(status
)) {
5525 reply_nterror(req
, status
);
5526 END_PROFILE(SMBunlock
);
5530 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5536 reply_smb1_outbuf(req
, 0, 0);
5538 END_PROFILE(SMBunlock
);
5543 #define DBGC_CLASS DBGC_ALL
5545 /****************************************************************************
5547 conn POINTER CAN BE NULL HERE !
5548 ****************************************************************************/
5550 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
);
5551 static void reply_tdis_done(struct tevent_req
*req
);
5553 void reply_tdis(struct smb_request
*smb1req
)
5555 connection_struct
*conn
= smb1req
->conn
;
5556 struct tevent_req
*req
;
5559 * Don't setup the profile charge here, take
5560 * it in reply_tdis_done(). Not strictly correct
5561 * but better than the other SMB1 async
5562 * code that double-charges at the moment.
5566 /* Not going async, profile here. */
5567 START_PROFILE(SMBtdis
);
5568 DBG_INFO("Invalid connection in tdis\n");
5569 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5570 END_PROFILE(SMBtdis
);
5574 req
= reply_tdis_send(smb1req
);
5576 /* Not going async, profile here. */
5577 START_PROFILE(SMBtdis
);
5578 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
5579 END_PROFILE(SMBtdis
);
5582 /* We're async. This will complete later. */
5583 tevent_req_set_callback(req
, reply_tdis_done
, smb1req
);
5587 struct reply_tdis_state
{
5588 struct tevent_queue
*wait_queue
;
5591 static void reply_tdis_wait_done(struct tevent_req
*subreq
);
5593 /****************************************************************************
5595 Note, on failure here we deallocate and return NULL to allow the caller to
5596 SMB1 return an error of ERRnomem immediately.
5597 ****************************************************************************/
5599 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
)
5601 struct tevent_req
*req
;
5602 struct reply_tdis_state
*state
;
5603 struct tevent_req
*subreq
;
5604 connection_struct
*conn
= smb1req
->conn
;
5607 req
= tevent_req_create(smb1req
, &state
,
5608 struct reply_tdis_state
);
5612 state
->wait_queue
= tevent_queue_create(state
, "reply_tdis_wait_queue");
5613 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5619 * Make sure that no new request will be able to use this tcon.
5620 * This ensures that once all outstanding fsp->aio_requests
5621 * on this tcon are done, we are safe to close it.
5623 conn
->tcon
->status
= NT_STATUS_NETWORK_NAME_DELETED
;
5625 for (fsp
= conn
->sconn
->files
; fsp
; fsp
= fsp
->next
) {
5626 if (fsp
->conn
!= conn
) {
5630 * Flag the file as close in progress.
5631 * This will prevent any more IO being
5632 * done on it. Not strictly needed, but
5633 * doesn't hurt to flag it as closing.
5635 fsp
->fsp_flags
.closing
= true;
5637 if (fsp
->num_aio_requests
> 0) {
5639 * Now wait until all aio requests on this fsp are
5642 * We don't set a callback, as we just want to block the
5643 * wait queue and the talloc_free() of fsp->aio_request
5644 * will remove the item from the wait queue.
5646 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5647 conn
->sconn
->ev_ctx
,
5649 if (tevent_req_nomem(subreq
, req
)) {
5657 * Now we add our own waiter to the end of the queue,
5658 * this way we get notified when all pending requests are finished
5659 * and reply to the outstanding SMB1 request.
5661 subreq
= tevent_queue_wait_send(state
,
5662 conn
->sconn
->ev_ctx
,
5664 if (tevent_req_nomem(subreq
, req
)) {
5670 * We're really going async - move the SMB1 request from
5671 * a talloc stackframe above us to the sconn talloc-context.
5672 * We need this to stick around until the wait_done
5673 * callback is invoked.
5675 smb1req
= talloc_move(smb1req
->sconn
, &smb1req
);
5677 tevent_req_set_callback(subreq
, reply_tdis_wait_done
, req
);
5682 static void reply_tdis_wait_done(struct tevent_req
*subreq
)
5684 struct tevent_req
*req
= tevent_req_callback_data(
5685 subreq
, struct tevent_req
);
5687 tevent_queue_wait_recv(subreq
);
5688 TALLOC_FREE(subreq
);
5689 tevent_req_done(req
);
5692 static NTSTATUS
reply_tdis_recv(struct tevent_req
*req
)
5694 return tevent_req_simple_recv_ntstatus(req
);
5697 static void reply_tdis_done(struct tevent_req
*req
)
5699 struct smb_request
*smb1req
= tevent_req_callback_data(
5700 req
, struct smb_request
);
5702 struct smbXsrv_tcon
*tcon
= smb1req
->conn
->tcon
;
5706 * Take the profile charge here. Not strictly
5707 * correct but better than the other SMB1 async
5708 * code that double-charges at the moment.
5710 START_PROFILE(SMBtdis
);
5712 status
= reply_tdis_recv(req
);
5714 if (!NT_STATUS_IS_OK(status
)) {
5715 TALLOC_FREE(smb1req
);
5716 END_PROFILE(SMBtdis
);
5717 exit_server(__location__
": reply_tdis_recv failed");
5722 * As we've been awoken, we may have changed
5723 * directory in the meantime.
5724 * reply_tdis() has the DO_CHDIR flag set.
5726 ok
= chdir_current_service(smb1req
->conn
);
5728 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5729 smb_request_done(smb1req
);
5730 END_PROFILE(SMBtdis
);
5733 status
= smbXsrv_tcon_disconnect(tcon
,
5735 if (!NT_STATUS_IS_OK(status
)) {
5736 TALLOC_FREE(smb1req
);
5737 END_PROFILE(SMBtdis
);
5738 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5742 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5743 smb1req
->conn
= NULL
;
5747 reply_smb1_outbuf(smb1req
, 0, 0);
5749 * The following call is needed to push the
5750 * reply data back out the socket after async
5751 * return. Plus it frees smb1req.
5753 smb_request_done(smb1req
);
5754 END_PROFILE(SMBtdis
);
5757 /****************************************************************************
5759 conn POINTER CAN BE NULL HERE !
5760 ****************************************************************************/
5762 void reply_echo(struct smb_request
*req
)
5764 connection_struct
*conn
= req
->conn
;
5768 START_PROFILE(SMBecho
);
5771 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5772 END_PROFILE(SMBecho
);
5776 smb_reverb
= SVAL(req
->vwv
+0, 0);
5778 reply_smb1_outbuf(req
, 1, req
->buflen
);
5780 /* copy any incoming data back out */
5781 if (req
->buflen
> 0) {
5782 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5785 if (smb_reverb
> 100) {
5786 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5790 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5792 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5794 show_msg((char *)req
->outbuf
);
5795 if (!smb1_srv_send(req
->xconn
,
5796 (char *)req
->outbuf
,
5799 IS_CONN_ENCRYPTED(conn
) || req
->encrypted
))
5800 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5803 DEBUG(3,("echo %d times\n", smb_reverb
));
5805 TALLOC_FREE(req
->outbuf
);
5807 END_PROFILE(SMBecho
);
5811 /****************************************************************************
5812 Reply to a printopen.
5813 ****************************************************************************/
5815 void reply_printopen(struct smb_request
*req
)
5817 connection_struct
*conn
= req
->conn
;
5821 START_PROFILE(SMBsplopen
);
5824 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5825 END_PROFILE(SMBsplopen
);
5829 if (!CAN_PRINT(conn
)) {
5830 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5831 END_PROFILE(SMBsplopen
);
5835 status
= file_new(req
, conn
, &fsp
);
5836 if(!NT_STATUS_IS_OK(status
)) {
5837 reply_nterror(req
, status
);
5838 END_PROFILE(SMBsplopen
);
5842 /* Open for exclusive use, write only. */
5843 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5845 if (!NT_STATUS_IS_OK(status
)) {
5846 file_free(req
, fsp
);
5847 reply_nterror(req
, status
);
5848 END_PROFILE(SMBsplopen
);
5852 reply_smb1_outbuf(req
, 1, 0);
5853 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5855 DEBUG(3,("openprint fd=%d %s\n",
5856 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
5858 END_PROFILE(SMBsplopen
);
5862 /****************************************************************************
5863 Reply to a printclose.
5864 ****************************************************************************/
5866 void reply_printclose(struct smb_request
*req
)
5868 connection_struct
*conn
= req
->conn
;
5872 START_PROFILE(SMBsplclose
);
5875 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5876 END_PROFILE(SMBsplclose
);
5880 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5882 if (!check_fsp(conn
, req
, fsp
)) {
5883 END_PROFILE(SMBsplclose
);
5887 if (!CAN_PRINT(conn
)) {
5888 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5889 END_PROFILE(SMBsplclose
);
5893 DEBUG(3,("printclose fd=%d %s\n",
5894 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
5896 status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5898 if(!NT_STATUS_IS_OK(status
)) {
5899 reply_nterror(req
, status
);
5900 END_PROFILE(SMBsplclose
);
5904 reply_smb1_outbuf(req
, 0, 0);
5906 END_PROFILE(SMBsplclose
);
5910 /****************************************************************************
5911 Reply to a printqueue.
5912 ****************************************************************************/
5914 void reply_printqueue(struct smb_request
*req
)
5916 const struct loadparm_substitution
*lp_sub
=
5917 loadparm_s3_global_substitution();
5918 connection_struct
*conn
= req
->conn
;
5922 START_PROFILE(SMBsplretq
);
5925 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5926 END_PROFILE(SMBsplretq
);
5930 max_count
= SVAL(req
->vwv
+0, 0);
5931 start_index
= SVAL(req
->vwv
+1, 0);
5933 /* we used to allow the client to get the cnum wrong, but that
5934 is really quite gross and only worked when there was only
5935 one printer - I think we should now only accept it if they
5936 get it right (tridge) */
5937 if (!CAN_PRINT(conn
)) {
5938 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5939 END_PROFILE(SMBsplretq
);
5943 reply_smb1_outbuf(req
, 2, 3);
5944 SSVAL(req
->outbuf
,smb_vwv0
,0);
5945 SSVAL(req
->outbuf
,smb_vwv1
,0);
5946 SCVAL(smb_buf(req
->outbuf
),0,1);
5947 SSVAL(smb_buf(req
->outbuf
),1,0);
5949 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5950 start_index
, max_count
));
5953 TALLOC_CTX
*mem_ctx
= talloc_tos();
5956 const char *sharename
= lp_servicename(mem_ctx
, lp_sub
, SNUM(conn
));
5957 struct rpc_pipe_client
*cli
= NULL
;
5958 struct dcerpc_binding_handle
*b
= NULL
;
5959 struct policy_handle handle
;
5960 struct spoolss_DevmodeContainer devmode_ctr
;
5961 union spoolss_JobInfo
*info
;
5963 uint32_t num_to_get
;
5967 ZERO_STRUCT(handle
);
5969 status
= rpc_pipe_open_interface(mem_ctx
,
5972 conn
->sconn
->remote_address
,
5973 conn
->sconn
->local_address
,
5974 conn
->sconn
->msg_ctx
,
5976 if (!NT_STATUS_IS_OK(status
)) {
5977 DEBUG(0, ("reply_printqueue: "
5978 "could not connect to spoolss: %s\n",
5979 nt_errstr(status
)));
5980 reply_nterror(req
, status
);
5983 b
= cli
->binding_handle
;
5985 ZERO_STRUCT(devmode_ctr
);
5987 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5990 SEC_FLAG_MAXIMUM_ALLOWED
,
5993 if (!NT_STATUS_IS_OK(status
)) {
5994 reply_nterror(req
, status
);
5997 if (!W_ERROR_IS_OK(werr
)) {
5998 reply_nterror(req
, werror_to_ntstatus(werr
));
6002 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6010 if (!W_ERROR_IS_OK(werr
)) {
6011 reply_nterror(req
, werror_to_ntstatus(werr
));
6015 if (max_count
> 0) {
6016 first
= start_index
;
6018 first
= start_index
+ max_count
+ 1;
6021 if (first
>= count
) {
6024 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6027 for (i
= first
; i
< num_to_get
; i
++) {
6030 time_t qtime
= spoolss_Time_to_time_t(&info
[i
].info2
.submitted
);
6033 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6034 info
[i
].info2
.job_id
);
6036 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6042 srv_put_dos_date2(p
, 0, qtime
);
6043 SCVAL(p
, 4, qstatus
);
6044 SSVAL(p
, 5, qrapjobid
);
6045 SIVAL(p
, 7, info
[i
].info2
.size
);
6047 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6048 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6049 if (!NT_STATUS_IS_OK(status
)) {
6050 reply_nterror(req
, status
);
6053 if (message_push_blob(
6056 blob
, sizeof(blob
))) == -1) {
6057 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6063 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6064 SSVAL(req
->outbuf
,smb_vwv1
,
6065 (max_count
>0?first
+count
:first
-1));
6066 SCVAL(smb_buf(req
->outbuf
),0,1);
6067 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6071 DEBUG(3, ("%u entries returned in queue\n",
6075 if (b
&& is_valid_policy_hnd(&handle
)) {
6076 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6081 END_PROFILE(SMBsplretq
);
6085 /****************************************************************************
6086 Reply to a printwrite.
6087 ****************************************************************************/
6089 void reply_printwrite(struct smb_request
*req
)
6091 connection_struct
*conn
= req
->conn
;
6097 START_PROFILE(SMBsplwr
);
6100 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6101 END_PROFILE(SMBsplwr
);
6105 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6107 if (!check_fsp(conn
, req
, fsp
)) {
6108 END_PROFILE(SMBsplwr
);
6112 if (!fsp
->print_file
) {
6113 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6114 END_PROFILE(SMBsplwr
);
6118 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
6119 if (!NT_STATUS_IS_OK(status
)) {
6120 reply_nterror(req
, status
);
6121 END_PROFILE(SMBsplwr
);
6125 numtowrite
= SVAL(req
->buf
, 1);
6128 * This already protects us against CVE-2017-12163.
6130 if (req
->buflen
< numtowrite
+ 3) {
6131 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6132 END_PROFILE(SMBsplwr
);
6136 data
= (const char *)req
->buf
+ 3;
6138 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6139 reply_nterror(req
, map_nt_error_from_unix(errno
));
6140 END_PROFILE(SMBsplwr
);
6144 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6146 reply_smb1_outbuf(req
, 0, 0);
6148 END_PROFILE(SMBsplwr
);
6152 /****************************************************************************
6154 ****************************************************************************/
6156 void reply_mkdir(struct smb_request
*req
)
6158 connection_struct
*conn
= req
->conn
;
6159 struct files_struct
*dirfsp
= NULL
;
6160 struct smb_filename
*smb_dname
= NULL
;
6161 char *directory
= NULL
;
6165 TALLOC_CTX
*ctx
= talloc_tos();
6167 START_PROFILE(SMBmkdir
);
6169 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6170 STR_TERMINATE
, &status
);
6171 if (!NT_STATUS_IS_OK(status
)) {
6172 reply_nterror(req
, status
);
6176 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6177 if (ucf_flags
& UCF_GMT_PATHNAME
) {
6178 extract_snapshot_token(directory
, &twrp
);
6180 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
6181 if (!NT_STATUS_IS_OK(status
)) {
6182 reply_nterror(req
, status
);
6186 status
= filename_convert_dirfsp(ctx
,
6193 if (!NT_STATUS_IS_OK(status
)) {
6194 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6195 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6196 ERRSRV
, ERRbadpath
);
6199 reply_nterror(req
, status
);
6203 status
= create_directory(conn
, req
, dirfsp
, smb_dname
);
6205 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6207 if (!NT_STATUS_IS_OK(status
)) {
6209 if (!use_nt_status()
6210 && NT_STATUS_EQUAL(status
,
6211 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6213 * Yes, in the DOS error code case we get a
6214 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6215 * samba4 torture test.
6217 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6220 reply_nterror(req
, status
);
6224 reply_smb1_outbuf(req
, 0, 0);
6226 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6228 TALLOC_FREE(smb_dname
);
6229 END_PROFILE(SMBmkdir
);
6233 /****************************************************************************
6235 ****************************************************************************/
6237 void reply_rmdir(struct smb_request
*req
)
6239 connection_struct
*conn
= req
->conn
;
6240 struct smb_filename
*smb_dname
= NULL
;
6241 char *directory
= NULL
;
6243 TALLOC_CTX
*ctx
= talloc_tos();
6244 struct files_struct
*dirfsp
= NULL
;
6245 files_struct
*fsp
= NULL
;
6248 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6250 START_PROFILE(SMBrmdir
);
6252 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6253 STR_TERMINATE
, &status
);
6254 if (!NT_STATUS_IS_OK(status
)) {
6255 reply_nterror(req
, status
);
6259 if (ucf_flags
& UCF_GMT_PATHNAME
) {
6260 extract_snapshot_token(directory
, &twrp
);
6262 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
6263 if (!NT_STATUS_IS_OK(status
)) {
6264 reply_nterror(req
, status
);
6268 status
= filename_convert_dirfsp(ctx
,
6275 if (!NT_STATUS_IS_OK(status
)) {
6276 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6277 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6278 ERRSRV
, ERRbadpath
);
6281 reply_nterror(req
, status
);
6285 status
= SMB_VFS_CREATE_FILE(
6288 dirfsp
, /* dirfsp */
6289 smb_dname
, /* fname */
6290 DELETE_ACCESS
, /* access_mask */
6291 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6293 FILE_OPEN
, /* create_disposition*/
6294 FILE_DIRECTORY_FILE
, /* create_options */
6295 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6296 0, /* oplock_request */
6298 0, /* allocation_size */
6299 0, /* private_flags */
6304 NULL
, NULL
); /* create context */
6306 if (!NT_STATUS_IS_OK(status
)) {
6307 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6308 /* We have re-scheduled this call. */
6311 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6312 bool ok
= defer_smb1_sharing_violation(req
);
6317 reply_nterror(req
, status
);
6321 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6322 if (!NT_STATUS_IS_OK(status
)) {
6323 close_file_free(req
, &fsp
, ERROR_CLOSE
);
6324 reply_nterror(req
, status
);
6328 if (!set_delete_on_close(fsp
, true,
6329 conn
->session_info
->security_token
,
6330 conn
->session_info
->unix_token
)) {
6331 close_file_free(req
, &fsp
, ERROR_CLOSE
);
6332 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6336 status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6337 if (!NT_STATUS_IS_OK(status
)) {
6338 reply_nterror(req
, status
);
6340 reply_smb1_outbuf(req
, 0, 0);
6343 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6345 TALLOC_FREE(smb_dname
);
6346 END_PROFILE(SMBrmdir
);
6350 /****************************************************************************
6352 ****************************************************************************/
6354 void reply_mv(struct smb_request
*req
)
6356 connection_struct
*conn
= req
->conn
;
6358 char *newname
= NULL
;
6362 TALLOC_CTX
*ctx
= talloc_tos();
6363 struct files_struct
*src_dirfsp
= NULL
;
6364 struct smb_filename
*smb_fname_src
= NULL
;
6365 struct files_struct
*dst_dirfsp
= NULL
;
6366 struct smb_filename
*smb_fname_dst
= NULL
;
6367 const char *dst_original_lcomp
= NULL
;
6368 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
);
6369 NTTIME src_twrp
= 0;
6370 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
);
6371 NTTIME dst_twrp
= 0;
6372 bool stream_rename
= false;
6374 START_PROFILE(SMBmv
);
6377 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6381 attrs
= SVAL(req
->vwv
+0, 0);
6383 p
= (const char *)req
->buf
+ 1;
6384 p
+= srvstr_get_path_req(ctx
, req
, &name
, p
, STR_TERMINATE
,
6386 if (!NT_STATUS_IS_OK(status
)) {
6387 reply_nterror(req
, status
);
6391 p
+= srvstr_get_path_req(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6393 if (!NT_STATUS_IS_OK(status
)) {
6394 reply_nterror(req
, status
);
6398 if (!req
->posix_pathnames
) {
6399 /* The newname must begin with a ':' if the
6400 name contains a ':'. */
6401 if (strchr_m(name
, ':')) {
6402 if (newname
[0] != ':') {
6403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6406 stream_rename
= true;
6410 if (src_ucf_flags
& UCF_GMT_PATHNAME
) {
6411 extract_snapshot_token(name
, &src_twrp
);
6413 status
= smb1_strip_dfs_path(ctx
, &src_ucf_flags
, &name
);
6414 if (!NT_STATUS_IS_OK(status
)) {
6415 reply_nterror(req
, status
);
6418 status
= filename_convert_dirfsp(ctx
,
6426 if (!NT_STATUS_IS_OK(status
)) {
6427 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6428 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6429 ERRSRV
, ERRbadpath
);
6432 reply_nterror(req
, status
);
6436 if (dst_ucf_flags
& UCF_GMT_PATHNAME
) {
6437 extract_snapshot_token(newname
, &dst_twrp
);
6439 status
= smb1_strip_dfs_path(ctx
, &dst_ucf_flags
, &newname
);
6440 if (!NT_STATUS_IS_OK(status
)) {
6441 reply_nterror(req
, status
);
6444 status
= filename_convert_dirfsp(ctx
,
6452 if (!NT_STATUS_IS_OK(status
)) {
6453 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6454 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6455 ERRSRV
, ERRbadpath
);
6458 reply_nterror(req
, status
);
6462 /* Get the last component of the destination for rename_internals(). */
6463 dst_original_lcomp
= get_original_lcomp(ctx
,
6467 if (dst_original_lcomp
== NULL
) {
6468 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6472 if (stream_rename
) {
6473 /* smb_fname_dst->base_name must be the same as
6474 smb_fname_src->base_name. */
6475 TALLOC_FREE(smb_fname_dst
->base_name
);
6476 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6477 smb_fname_src
->base_name
);
6478 if (!smb_fname_dst
->base_name
) {
6479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6484 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6485 smb_fname_str_dbg(smb_fname_dst
)));
6487 status
= rename_internals(ctx
,
6490 src_dirfsp
, /* src_dirfsp */
6492 dst_dirfsp
, /* dst_dirfsp */
6498 if (!NT_STATUS_IS_OK(status
)) {
6499 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6500 /* We have re-scheduled this call. */
6503 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6504 bool ok
= defer_smb1_sharing_violation(req
);
6509 reply_nterror(req
, status
);
6513 reply_smb1_outbuf(req
, 0, 0);
6515 TALLOC_FREE(smb_fname_src
);
6516 TALLOC_FREE(smb_fname_dst
);
6521 /****************************************************************************
6522 Reply to a file copy.
6526 This command was introduced in the LAN Manager 1.0 dialect
6527 It was rendered obsolete in the NT LAN Manager dialect.
6528 This command was used to perform server-side file copies, but
6529 is no longer used. Clients SHOULD
6530 NOT send requests using this command code.
6531 Servers receiving requests with this command code
6532 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6533 ****************************************************************************/
6535 void reply_copy(struct smb_request
*req
)
6537 START_PROFILE(SMBcopy
);
6538 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
6539 END_PROFILE(SMBcopy
);
6544 #define DBGC_CLASS DBGC_LOCKING
6546 /****************************************************************************
6547 Get a lock pid, dealing with large count requests.
6548 ****************************************************************************/
6550 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
6551 bool large_file_format
)
6553 if(!large_file_format
)
6554 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6556 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6559 /****************************************************************************
6560 Get a lock count, dealing with large count requests.
6561 ****************************************************************************/
6563 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
6564 bool large_file_format
)
6568 if(!large_file_format
) {
6569 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6572 * No BVAL, this is reversed!
6574 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6575 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6581 /****************************************************************************
6582 Reply to a lockingX request.
6583 ****************************************************************************/
6585 static void reply_lockingx_done(struct tevent_req
*subreq
);
6587 void reply_lockingX(struct smb_request
*req
)
6589 connection_struct
*conn
= req
->conn
;
6591 unsigned char locktype
;
6592 enum brl_type brltype
;
6593 unsigned char oplocklevel
;
6594 uint16_t num_ulocks
;
6596 int32_t lock_timeout
;
6598 const uint8_t *data
;
6599 bool large_file_format
;
6600 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6601 struct smbd_lock_element
*locks
= NULL
;
6602 struct tevent_req
*subreq
= NULL
;
6604 START_PROFILE(SMBlockingX
);
6607 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6608 END_PROFILE(SMBlockingX
);
6612 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
6613 locktype
= CVAL(req
->vwv
+3, 0);
6614 oplocklevel
= CVAL(req
->vwv
+3, 1);
6615 num_ulocks
= SVAL(req
->vwv
+6, 0);
6616 num_locks
= SVAL(req
->vwv
+7, 0);
6617 lock_timeout
= IVAL(req
->vwv
+4, 0);
6618 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
6620 if (!check_fsp(conn
, req
, fsp
)) {
6621 END_PROFILE(SMBlockingX
);
6627 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6628 /* we don't support these - and CANCEL_LOCK makes w2k
6629 and XP reboot so I don't really want to be
6630 compatible! (tridge) */
6631 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
6632 END_PROFILE(SMBlockingX
);
6636 /* Check if this is an oplock break on a file
6637 we have granted an oplock on.
6639 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
6640 /* Client can insist on breaking to none. */
6641 bool break_to_none
= (oplocklevel
== 0);
6644 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6645 "for %s\n", (unsigned int)oplocklevel
,
6646 fsp_fnum_dbg(fsp
)));
6649 * Make sure we have granted an exclusive or batch oplock on
6653 if (fsp
->oplock_type
== 0) {
6655 /* The Samba4 nbench simulator doesn't understand
6656 the difference between break to level2 and break
6657 to none from level2 - it sends oplock break
6658 replies in both cases. Don't keep logging an error
6659 message here - just ignore it. JRA. */
6661 DEBUG(5,("reply_lockingX: Error : oplock break from "
6662 "client for %s (oplock=%d) and no "
6663 "oplock granted on this file (%s).\n",
6664 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
6667 /* if this is a pure oplock break request then don't
6669 if (num_locks
== 0 && num_ulocks
== 0) {
6670 END_PROFILE(SMBlockingX
);
6674 END_PROFILE(SMBlockingX
);
6675 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
6679 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6681 result
= remove_oplock(fsp
);
6683 result
= downgrade_oplock(fsp
);
6687 DEBUG(0, ("reply_lockingX: error in removing "
6688 "oplock on file %s\n", fsp_str_dbg(fsp
)));
6689 /* Hmmm. Is this panic justified? */
6690 smb_panic("internal tdb error");
6693 /* if this is a pure oplock break request then don't send a
6695 if (num_locks
== 0 && num_ulocks
== 0) {
6696 /* Sanity check - ensure a pure oplock break is not a
6698 if (CVAL(req
->vwv
+0, 0) != 0xff) {
6699 DEBUG(0,("reply_lockingX: Error : pure oplock "
6700 "break is a chained %d request !\n",
6701 (unsigned int)CVAL(req
->vwv
+0, 0)));
6703 END_PROFILE(SMBlockingX
);
6709 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6710 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6711 END_PROFILE(SMBlockingX
);
6715 if (num_ulocks
!= 0) {
6716 struct smbd_lock_element
*ulocks
= NULL
;
6719 ulocks
= talloc_array(
6720 req
, struct smbd_lock_element
, num_ulocks
);
6721 if (ulocks
== NULL
) {
6722 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6723 END_PROFILE(SMBlockingX
);
6728 * Data now points at the beginning of the list of
6729 * smb_unlkrng structs
6731 for (i
= 0; i
< num_ulocks
; i
++) {
6732 ulocks
[i
].req_guid
= smbd_request_guid(req
,
6734 ulocks
[i
].smblctx
= get_lock_pid(
6735 data
, i
, large_file_format
);
6736 ulocks
[i
].count
= get_lock_count(
6737 data
, i
, large_file_format
);
6738 ulocks
[i
].offset
= get_lock_offset(
6739 data
, i
, large_file_format
);
6740 ulocks
[i
].brltype
= UNLOCK_LOCK
;
6741 ulocks
[i
].lock_flav
= WINDOWS_LOCK
;
6745 * Unlock cancels pending locks
6748 ok
= smbd_smb1_brl_finish_by_lock(
6754 reply_smb1_outbuf(req
, 2, 0);
6755 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6756 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6757 END_PROFILE(SMBlockingX
);
6761 status
= smbd_do_unlocking(
6762 req
, fsp
, num_ulocks
, ulocks
);
6763 TALLOC_FREE(ulocks
);
6764 if (!NT_STATUS_IS_OK(status
)) {
6765 END_PROFILE(SMBlockingX
);
6766 reply_nterror(req
, status
);
6771 /* Now do any requested locks */
6772 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6774 /* Data now points at the beginning of the list
6775 of smb_lkrng structs */
6777 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
6778 brltype
= READ_LOCK
;
6780 brltype
= WRITE_LOCK
;
6783 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
6784 if (locks
== NULL
) {
6785 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6786 END_PROFILE(SMBlockingX
);
6790 for (i
= 0; i
< num_locks
; i
++) {
6791 locks
[i
].req_guid
= smbd_request_guid(req
, i
),
6792 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
6793 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
6794 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
6795 locks
[i
].brltype
= brltype
;
6796 locks
[i
].lock_flav
= WINDOWS_LOCK
;
6799 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6803 if (num_locks
== 0) {
6804 /* See smbtorture3 lock11 test */
6805 reply_smb1_outbuf(req
, 2, 0);
6806 /* andx chain ends */
6807 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6808 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6809 END_PROFILE(SMBlockingX
);
6813 ok
= smbd_smb1_brl_finish_by_lock(
6816 locks
[0], /* Windows only cancels the first lock */
6817 NT_STATUS_FILE_LOCK_CONFLICT
);
6820 reply_force_doserror(req
, ERRDOS
, ERRcancelviolation
);
6821 END_PROFILE(SMBlockingX
);
6825 reply_smb1_outbuf(req
, 2, 0);
6826 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6827 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6828 END_PROFILE(SMBlockingX
);
6832 subreq
= smbd_smb1_do_locks_send(
6841 if (subreq
== NULL
) {
6842 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6843 END_PROFILE(SMBlockingX
);
6846 tevent_req_set_callback(subreq
, reply_lockingx_done
, NULL
);
6847 END_PROFILE(SMBlockingX
);
6850 static void reply_lockingx_done(struct tevent_req
*subreq
)
6852 struct smb_request
*req
= NULL
;
6856 START_PROFILE(SMBlockingX
);
6858 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
6861 status
= smbd_smb1_do_locks_recv(subreq
);
6862 TALLOC_FREE(subreq
);
6864 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status
));
6866 if (NT_STATUS_IS_OK(status
)) {
6867 reply_smb1_outbuf(req
, 2, 0);
6868 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
6869 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
6871 reply_nterror(req
, status
);
6874 ok
= smb1_srv_send(req
->xconn
,
6875 (char *)req
->outbuf
,
6878 IS_CONN_ENCRYPTED(req
->conn
));
6880 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6883 END_PROFILE(SMBlockingX
);
6887 #define DBGC_CLASS DBGC_ALL
6889 /****************************************************************************
6890 Reply to a SMBreadbmpx (read block multiplex) request.
6891 Always reply with an error, if someone has a platform really needs this,
6892 please contact vl@samba.org
6893 ****************************************************************************/
6895 void reply_readbmpx(struct smb_request
*req
)
6897 START_PROFILE(SMBreadBmpx
);
6898 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6899 END_PROFILE(SMBreadBmpx
);
6903 /****************************************************************************
6904 Reply to a SMBreadbs (read block multiplex secondary) request.
6905 Always reply with an error, if someone has a platform really needs this,
6906 please contact vl@samba.org
6907 ****************************************************************************/
6909 void reply_readbs(struct smb_request
*req
)
6911 START_PROFILE(SMBreadBs
);
6912 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6913 END_PROFILE(SMBreadBs
);
6917 /****************************************************************************
6918 Reply to a SMBsetattrE.
6919 ****************************************************************************/
6921 void reply_setattrE(struct smb_request
*req
)
6923 connection_struct
*conn
= req
->conn
;
6924 struct smb_file_time ft
;
6928 START_PROFILE(SMBsetattrE
);
6929 init_smb_file_time(&ft
);
6932 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6936 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6938 if(!fsp
|| (fsp
->conn
!= conn
)) {
6939 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6944 * Convert the DOS times into unix times.
6947 ft
.atime
= time_t_to_full_timespec(
6948 srv_make_unix_date2(req
->vwv
+3));
6949 ft
.mtime
= time_t_to_full_timespec(
6950 srv_make_unix_date2(req
->vwv
+5));
6951 ft
.create_time
= time_t_to_full_timespec(
6952 srv_make_unix_date2(req
->vwv
+1));
6954 reply_smb1_outbuf(req
, 0, 0);
6957 * Patch from Ray Frush <frush@engr.colostate.edu>
6958 * Sometimes times are sent as zero - ignore them.
6961 /* Ensure we have a valid stat struct for the source. */
6962 status
= vfs_stat_fsp(fsp
);
6963 if (!NT_STATUS_IS_OK(status
)) {
6964 reply_nterror(req
, status
);
6968 if (!(fsp
->access_mask
& FILE_WRITE_ATTRIBUTES
)) {
6969 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6973 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
6974 if (!NT_STATUS_IS_OK(status
)) {
6975 reply_nterror(req
, status
);
6979 if (fsp
->fsp_flags
.modified
) {
6980 trigger_write_time_update_immediate(fsp
);
6983 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6986 (unsigned int)ft
.atime
.tv_sec
,
6987 (unsigned int)ft
.mtime
.tv_sec
,
6988 (unsigned int)ft
.create_time
.tv_sec
6991 END_PROFILE(SMBsetattrE
);
6996 /* Back from the dead for OS/2..... JRA. */
6998 /****************************************************************************
6999 Reply to a SMBwritebmpx (write block multiplex primary) request.
7000 Always reply with an error, if someone has a platform really needs this,
7001 please contact vl@samba.org
7002 ****************************************************************************/
7004 void reply_writebmpx(struct smb_request
*req
)
7006 START_PROFILE(SMBwriteBmpx
);
7007 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7008 END_PROFILE(SMBwriteBmpx
);
7012 /****************************************************************************
7013 Reply to a SMBwritebs (write block multiplex secondary) request.
7014 Always reply with an error, if someone has a platform really needs this,
7015 please contact vl@samba.org
7016 ****************************************************************************/
7018 void reply_writebs(struct smb_request
*req
)
7020 START_PROFILE(SMBwriteBs
);
7021 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7022 END_PROFILE(SMBwriteBs
);
7026 /****************************************************************************
7027 Reply to a SMBgetattrE.
7028 ****************************************************************************/
7030 void reply_getattrE(struct smb_request
*req
)
7032 connection_struct
*conn
= req
->conn
;
7035 struct timespec create_ts
;
7038 START_PROFILE(SMBgetattrE
);
7041 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7042 END_PROFILE(SMBgetattrE
);
7046 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7048 if(!fsp
|| (fsp
->conn
!= conn
)) {
7049 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7050 END_PROFILE(SMBgetattrE
);
7054 /* Do an fstat on this file */
7055 status
= vfs_stat_fsp(fsp
);
7056 if (!NT_STATUS_IS_OK(status
)) {
7057 reply_nterror(req
, status
);
7058 END_PROFILE(SMBgetattrE
);
7062 mode
= fdos_mode(fsp
);
7065 * Convert the times into dos times. Set create
7066 * date to be last modify date as UNIX doesn't save
7070 reply_smb1_outbuf(req
, 11, 0);
7072 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
7073 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7074 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
7075 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_atime
));
7076 /* Should we check pending modtime here ? JRA */
7077 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
7078 convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
));
7080 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
7081 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7082 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7084 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
7085 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
7086 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7088 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7090 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
7092 END_PROFILE(SMBgetattrE
);
7096 /****************************************************************************
7097 Reply to a SMBfindclose (stop trans2 directory search).
7098 ****************************************************************************/
7100 void reply_findclose(struct smb_request
*req
)
7103 struct smbd_server_connection
*sconn
= req
->sconn
;
7104 files_struct
*fsp
= NULL
;
7106 START_PROFILE(SMBfindclose
);
7109 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7110 END_PROFILE(SMBfindclose
);
7114 dptr_num
= SVALS(req
->vwv
+0, 0);
7116 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7119 * OS/2 seems to use -1 to indicate "close all directories"
7120 * This has to mean on this specific connection struct.
7122 if (dptr_num
== -1) {
7123 dptr_closecnum(req
->conn
);
7125 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
7128 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
7132 reply_smb1_outbuf(req
, 0, 0);
7134 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7136 END_PROFILE(SMBfindclose
);
7140 /****************************************************************************
7141 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7142 ****************************************************************************/
7144 void reply_findnclose(struct smb_request
*req
)
7148 START_PROFILE(SMBfindnclose
);
7151 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7152 END_PROFILE(SMBfindnclose
);
7156 dptr_num
= SVAL(req
->vwv
+0, 0);
7158 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7160 /* We never give out valid handles for a
7161 findnotifyfirst - so any dptr_num is ok here.
7164 reply_smb1_outbuf(req
, 0, 0);
7166 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7168 END_PROFILE(SMBfindnclose
);