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 "source3/smbd/smbXsrv_session.h"
35 #include "smbd/smbXsrv_open.h"
36 #include "fake_file.h"
37 #include "rpc_client/rpc_client.h"
38 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
39 #include "rpc_client/cli_spoolss.h"
40 #include "rpc_client/init_spoolss.h"
41 #include "rpc_server/rpc_ncacn_np.h"
42 #include "libcli/security/security.h"
43 #include "libsmb/nmblib.h"
45 #include "smbprofile.h"
46 #include "../lib/tsocket/tsocket.h"
47 #include "lib/util/tevent_ntstatus.h"
48 #include "libcli/smb/smb_signing.h"
49 #include "lib/util/sys_rw_data.h"
50 #include "librpc/gen_ndr/open_files.h"
51 #include "libcli/smb/smb2_posix.h"
52 #include "lib/util/string_wrappers.h"
53 #include "source3/printing/rap_jobid.h"
54 #include "source3/lib/substitute.h"
55 #include "source3/smbd/dir.h"
57 /****************************************************************************
58 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
59 ****************************************************************************/
61 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
64 if ((fsp
== NULL
) || (conn
== NULL
)) {
65 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
68 if ((conn
!= fsp
->conn
) || (req
->vuid
!= fsp
->vuid
)) {
69 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
75 /****************************************************************************
76 SMB1 version of smb2_strip_dfs_path()
77 Differs from SMB2 in that all Windows path separator '\' characters
78 have already been converted to '/' by check_path_syntax().
79 ****************************************************************************/
81 NTSTATUS
smb1_strip_dfs_path(TALLOC_CTX
*mem_ctx
,
85 uint32_t ucf_flags
= *_ucf_flags
;
86 char *path
= *in_path
;
87 char *return_path
= NULL
;
89 if (!(ucf_flags
& UCF_DFS_PATHNAME
)) {
93 /* Strip any leading '/' characters - MacOSX client behavior. */
94 while (*path
== '/') {
98 /* We should now be pointing at the server name. Go past it. */
101 /* End of complete path. Exit OK. */
105 /* End of server name. Go past and break. */
109 path
++; /* Continue looking for end of server name or string. */
112 /* We should now be pointing at the share name. Go past it. */
115 /* End of complete path. Exit OK. */
119 /* End of share name. Go past and break. */
124 /* Only invalid character in sharename. */
125 return NT_STATUS_OBJECT_NAME_INVALID
;
127 path
++; /* Continue looking for end of share name or string. */
131 /* path now points at the start of the real filename (if any). */
132 /* Duplicate it first. */
133 return_path
= talloc_strdup(mem_ctx
, path
);
134 if (return_path
== NULL
) {
135 return NT_STATUS_NO_MEMORY
;
138 /* Now we can free the original (path points to part of this). */
139 TALLOC_FREE(*in_path
);
141 *in_path
= return_path
;
142 ucf_flags
&= ~UCF_DFS_PATHNAME
;
143 *_ucf_flags
= ucf_flags
;
147 /****************************************************************************
148 Check if we have a correct fsp pointing to a file.
149 ****************************************************************************/
151 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
154 if (!check_fsp_open(conn
, req
, fsp
)) {
157 if (fsp
->fsp_flags
.is_directory
) {
158 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
161 if (fsp_get_pathref_fd(fsp
) == -1) {
162 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
165 fsp
->num_smb_operations
++;
169 /****************************************************************************
171 conn POINTER CAN BE NULL HERE !
172 ****************************************************************************/
174 void reply_tcon(struct smb_request
*req
)
176 connection_struct
*conn
= req
->conn
;
178 char *service_buf
= NULL
;
179 char *password
= NULL
;
185 TALLOC_CTX
*ctx
= talloc_tos();
186 struct smbXsrv_connection
*xconn
= req
->xconn
;
187 NTTIME now
= timeval_to_nttime(&req
->request_time
);
189 START_PROFILE(SMBtcon
);
191 if (req
->buflen
< 4) {
192 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
193 END_PROFILE(SMBtcon
);
198 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
200 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
202 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
205 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
206 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
207 END_PROFILE(SMBtcon
);
210 p2
= strrchr_m(service_buf
,'\\');
214 service
= service_buf
;
217 conn
= make_connection(req
, now
, service
, dev
,
218 req
->vuid
,&nt_status
);
222 reply_nterror(req
, nt_status
);
223 END_PROFILE(SMBtcon
);
227 reply_smb1_outbuf(req
, 2, 0);
228 SSVAL(req
->outbuf
,smb_vwv0
,xconn
->smb1
.negprot
.max_recv
);
229 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
230 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
232 DEBUG(3,("tcon service=%s cnum=%d\n",
233 service
, conn
->cnum
));
235 END_PROFILE(SMBtcon
);
239 /****************************************************************************
240 Reply to a tcon and X.
241 conn POINTER CAN BE NULL HERE !
242 ****************************************************************************/
244 void reply_tcon_and_X(struct smb_request
*req
)
246 const struct loadparm_substitution
*lp_sub
=
247 loadparm_s3_global_substitution();
248 connection_struct
*conn
= req
->conn
;
249 const char *service
= NULL
;
250 TALLOC_CTX
*ctx
= talloc_tos();
251 /* what the client thinks the device is */
252 char *client_devicetype
= NULL
;
253 /* what the server tells the client the share represents */
254 const char *server_devicetype
;
261 struct smbXsrv_session
*session
= NULL
;
262 NTTIME now
= timeval_to_nttime(&req
->request_time
);
263 bool session_key_updated
= false;
264 uint16_t optional_support
= 0;
265 struct smbXsrv_connection
*xconn
= req
->xconn
;
267 START_PROFILE(SMBtconX
);
270 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
271 END_PROFILE(SMBtconX
);
275 passlen
= SVAL(req
->vwv
+3, 0);
276 tcon_flags
= SVAL(req
->vwv
+2, 0);
278 /* we might have to close an old one */
279 if ((tcon_flags
& TCONX_FLAG_DISCONNECT_TID
) && conn
) {
280 struct smbXsrv_tcon
*tcon
;
288 * TODO: cancel all outstanding requests on the tcon
290 status
= smbXsrv_tcon_disconnect(tcon
, req
->vuid
);
291 if (!NT_STATUS_IS_OK(status
)) {
292 DEBUG(0, ("reply_tcon_and_X: "
293 "smbXsrv_tcon_disconnect() failed: %s\n",
296 * If we hit this case, there is something completely
297 * wrong, so we better disconnect the transport connection.
299 END_PROFILE(SMBtconX
);
300 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
306 * This tree id is gone. Make sure we can't re-use it
312 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
313 reply_force_doserror(req
, ERRDOS
, ERRbuftoosmall
);
314 END_PROFILE(SMBtconX
);
318 if (xconn
->smb1
.negprot
.encrypted_passwords
) {
319 p
= req
->buf
+ passlen
;
321 p
= req
->buf
+ passlen
+ 1;
324 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
327 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
328 END_PROFILE(SMBtconX
);
333 * the service name can be either: \\server\share
334 * or share directly like on the DELL PowerVault 705
337 q
= strchr_m(path
+2,'\\');
339 reply_nterror(req
, NT_STATUS_BAD_NETWORK_NAME
);
340 END_PROFILE(SMBtconX
);
348 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
349 &client_devicetype
, p
,
350 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
352 if (client_devicetype
== NULL
) {
353 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
354 END_PROFILE(SMBtconX
);
358 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
360 nt_status
= smb1srv_session_lookup(xconn
,
361 req
->vuid
, now
, &session
);
362 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_USER_SESSION_DELETED
)) {
363 reply_force_doserror(req
, ERRSRV
, ERRbaduid
);
364 END_PROFILE(SMBtconX
);
367 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NETWORK_SESSION_EXPIRED
)) {
368 reply_nterror(req
, nt_status
);
369 END_PROFILE(SMBtconX
);
372 if (!NT_STATUS_IS_OK(nt_status
)) {
373 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
374 END_PROFILE(SMBtconX
);
378 if (session
->global
->auth_session_info
== NULL
) {
379 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
380 END_PROFILE(SMBtconX
);
385 * If there is no application key defined yet
388 * This means we setup the application key on the
389 * first tcon that happens via the given session.
391 * Once the application key is defined, it does not
394 if (session
->global
->application_key_blob
.length
== 0 &&
395 smb2_signing_key_valid(session
->global
->signing_key
))
397 struct smbXsrv_session
*x
= session
;
398 struct auth_session_info
*session_info
=
399 session
->global
->auth_session_info
;
400 uint8_t session_key
[16];
402 ZERO_STRUCT(session_key
);
403 memcpy(session_key
, x
->global
->signing_key
->blob
.data
,
404 MIN(x
->global
->signing_key
->blob
.length
, sizeof(session_key
)));
407 * The application key is truncated/padded to 16 bytes
409 x
->global
->application_key_blob
= data_blob_talloc(x
->global
,
411 sizeof(session_key
));
412 ZERO_STRUCT(session_key
);
413 if (x
->global
->application_key_blob
.data
== NULL
) {
414 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
415 END_PROFILE(SMBtconX
);
418 talloc_keep_secret(x
->global
->application_key_blob
.data
);
420 if (tcon_flags
& TCONX_FLAG_EXTENDED_SIGNATURES
) {
423 status
= smb1_key_derivation(x
->global
->application_key_blob
.data
,
424 x
->global
->application_key_blob
.length
,
425 x
->global
->application_key_blob
.data
);
426 if (!NT_STATUS_IS_OK(status
)) {
427 DBG_ERR("smb1_key_derivation failed: %s\n",
429 END_PROFILE(SMBtconX
);
432 optional_support
|= SMB_EXTENDED_SIGNATURES
;
436 * Place the application key into the session_info
438 data_blob_clear_free(&session_info
->session_key
);
439 session_info
->session_key
= data_blob_dup_talloc(session_info
,
440 x
->global
->application_key_blob
);
441 if (session_info
->session_key
.data
== NULL
) {
442 data_blob_clear_free(&x
->global
->application_key_blob
);
443 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
444 END_PROFILE(SMBtconX
);
447 talloc_keep_secret(session_info
->session_key
.data
);
448 session_key_updated
= true;
451 conn
= make_connection(req
, now
, service
, client_devicetype
,
452 req
->vuid
, &nt_status
);
456 if (session_key_updated
) {
457 struct smbXsrv_session
*x
= session
;
458 struct auth_session_info
*session_info
=
459 session
->global
->auth_session_info
;
460 data_blob_clear_free(&x
->global
->application_key_blob
);
461 data_blob_clear_free(&session_info
->session_key
);
463 reply_nterror(req
, nt_status
);
464 END_PROFILE(SMBtconX
);
469 server_devicetype
= "IPC";
470 else if ( IS_PRINT(conn
) )
471 server_devicetype
= "LPT1:";
473 server_devicetype
= "A:";
475 if (xconn
->protocol
< PROTOCOL_NT1
) {
476 reply_smb1_outbuf(req
, 2, 0);
477 if (message_push_string(&req
->outbuf
, server_devicetype
,
478 STR_TERMINATE
|STR_ASCII
) == -1) {
479 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
480 END_PROFILE(SMBtconX
);
484 /* NT sets the fstype of IPC$ to the null string */
485 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
487 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
488 /* Return permissions. */
492 reply_smb1_outbuf(req
, 7, 0);
495 perm1
= FILE_ALL_ACCESS
;
496 perm2
= FILE_ALL_ACCESS
;
498 perm1
= conn
->share_access
;
501 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
502 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
504 reply_smb1_outbuf(req
, 3, 0);
507 if ((message_push_string(&req
->outbuf
, server_devicetype
,
508 STR_TERMINATE
|STR_ASCII
) == -1)
509 || (message_push_string(&req
->outbuf
, fstype
,
510 STR_TERMINATE
) == -1)) {
511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
512 END_PROFILE(SMBtconX
);
516 /* what does setting this bit do? It is set by NT4 and
517 may affect the ability to autorun mounted cdroms */
518 optional_support
|= SMB_SUPPORT_SEARCH_BITS
;
520 (lp_csc_policy(SNUM(conn
)) << SMB_CSC_POLICY_SHIFT
);
522 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
523 DEBUG(2,("Serving %s as a Dfs root\n",
524 lp_servicename(ctx
, lp_sub
, SNUM(conn
)) ));
525 optional_support
|= SMB_SHARE_IN_DFS
;
528 SSVAL(req
->outbuf
, smb_vwv2
, optional_support
);
531 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
532 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
534 DEBUG(3,("tconX service=%s \n",
537 /* set the incoming and outgoing tid to the just created one */
538 SSVAL(discard_const_p(uint8_t, req
->inbuf
),smb_tid
,conn
->cnum
);
539 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
541 END_PROFILE(SMBtconX
);
543 req
->tid
= conn
->cnum
;
546 /****************************************************************************
547 Reply to an unknown type.
548 ****************************************************************************/
550 void reply_unknown_new(struct smb_request
*req
, uint8_t type
)
552 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
553 smb_fn_name(type
), type
, type
));
554 reply_force_doserror(req
, ERRSRV
, ERRunknownsmb
);
558 /****************************************************************************
560 conn POINTER CAN BE NULL HERE !
561 ****************************************************************************/
563 void reply_ioctl(struct smb_request
*req
)
565 const struct loadparm_substitution
*lp_sub
=
566 loadparm_s3_global_substitution();
567 connection_struct
*conn
= req
->conn
;
574 START_PROFILE(SMBioctl
);
577 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
578 END_PROFILE(SMBioctl
);
582 device
= SVAL(req
->vwv
+1, 0);
583 function
= SVAL(req
->vwv
+2, 0);
584 ioctl_code
= (device
<< 16) + function
;
586 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
588 switch (ioctl_code
) {
589 case IOCTL_QUERY_JOB_INFO
:
593 reply_force_doserror(req
, ERRSRV
, ERRnosupport
);
594 END_PROFILE(SMBioctl
);
598 reply_smb1_outbuf(req
, 8, replysize
+1);
599 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
600 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
601 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
602 p
= smb_buf(req
->outbuf
);
603 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
604 p
+= 1; /* Allow for alignment */
606 switch (ioctl_code
) {
607 case IOCTL_QUERY_JOB_INFO
:
611 files_struct
*fsp
= file_fsp(
612 req
, SVAL(req
->vwv
+0, 0));
614 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
615 END_PROFILE(SMBioctl
);
619 SSVAL(p
, 0, print_spool_rap_jobid(fsp
->print_file
));
621 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
622 lp_netbios_name(), 15,
623 STR_TERMINATE
|STR_ASCII
, &len
);
624 if (!NT_STATUS_IS_OK(status
)) {
625 reply_nterror(req
, status
);
626 END_PROFILE(SMBioctl
);
630 status
= srvstr_push((char *)req
->outbuf
, req
->flags2
,
632 lp_servicename(talloc_tos(),
635 13, STR_TERMINATE
|STR_ASCII
, &len
);
636 if (!NT_STATUS_IS_OK(status
)) {
637 reply_nterror(req
, status
);
638 END_PROFILE(SMBioctl
);
648 END_PROFILE(SMBioctl
);
652 /****************************************************************************
653 Strange checkpath NTSTATUS mapping.
654 ****************************************************************************/
656 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
658 /* Strange DOS error code semantics only for checkpath... */
659 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
660 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
661 /* We need to map to ERRbadpath */
662 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
668 /****************************************************************************
669 Reply to a checkpath.
670 ****************************************************************************/
672 void reply_checkpath(struct smb_request
*req
)
674 connection_struct
*conn
= req
->conn
;
675 struct smb_filename
*smb_fname
= NULL
;
678 struct files_struct
*dirfsp
= NULL
;
679 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
681 TALLOC_CTX
*ctx
= talloc_tos();
683 START_PROFILE(SMBcheckpath
);
685 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
686 STR_TERMINATE
, &status
);
688 if (!NT_STATUS_IS_OK(status
)) {
689 status
= map_checkpath_error(req
->flags2
, status
);
690 reply_nterror(req
, status
);
691 END_PROFILE(SMBcheckpath
);
695 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
697 if (ucf_flags
& UCF_GMT_PATHNAME
) {
698 extract_snapshot_token(name
, &twrp
);
700 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &name
);
701 if (!NT_STATUS_IS_OK(status
)) {
702 reply_nterror(req
, status
);
706 status
= filename_convert_dirfsp(ctx
,
713 if (!NT_STATUS_IS_OK(status
)) {
714 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
715 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
717 END_PROFILE(SMBcheckpath
);
723 if (!VALID_STAT(smb_fname
->st
) &&
724 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
725 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
726 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
727 status
= map_nt_error_from_unix(errno
);
731 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
732 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
737 reply_smb1_outbuf(req
, 0, 0);
740 /* We special case this - as when a Windows machine
741 is parsing a path is steps through the components
742 one at a time - if a component fails it expects
743 ERRbadpath, not ERRbadfile.
745 status
= map_checkpath_error(req
->flags2
, status
);
746 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
748 * Windows returns different error codes if
749 * the parent directory is valid but not the
750 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
751 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
752 * if the path is invalid.
754 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
759 reply_nterror(req
, status
);
762 TALLOC_FREE(smb_fname
);
763 END_PROFILE(SMBcheckpath
);
767 /****************************************************************************
769 ****************************************************************************/
771 void reply_getatr(struct smb_request
*req
)
773 struct smbXsrv_connection
*xconn
= req
->xconn
;
774 connection_struct
*conn
= req
->conn
;
775 struct smb_filename
*smb_fname
= NULL
;
782 TALLOC_CTX
*ctx
= talloc_tos();
784 START_PROFILE(SMBgetatr
);
786 p
= (const char *)req
->buf
+ 1;
787 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
788 if (!NT_STATUS_IS_OK(status
)) {
789 reply_nterror(req
, status
);
794 * dos sometimes asks for a stat of "" - it returns a "hidden
795 * directory" under WfWg - weird!
797 if (*fname
== '\0') {
798 mode
= FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
799 if (!CAN_WRITE(conn
)) {
800 mode
|= FILE_ATTRIBUTE_READONLY
;
805 struct files_struct
*dirfsp
= NULL
;
806 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
810 if (ucf_flags
& UCF_GMT_PATHNAME
) {
811 extract_snapshot_token(fname
, &twrp
);
813 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
814 if (!NT_STATUS_IS_OK(status
)) {
815 reply_nterror(req
, status
);
818 status
= filename_convert_dirfsp(ctx
,
825 if (!NT_STATUS_IS_OK(status
)) {
826 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
827 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
831 reply_nterror(req
, status
);
834 if (!VALID_STAT(smb_fname
->st
) &&
835 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
836 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
837 smb_fname_str_dbg(smb_fname
),
839 reply_nterror(req
, map_nt_error_from_unix(errno
));
843 mode
= fdos_mode(smb_fname
->fsp
);
844 size
= smb_fname
->st
.st_ex_size
;
846 ask_sharemode
= fsp_search_ask_sharemode(smb_fname
->fsp
);
848 struct timespec write_time_ts
;
849 struct file_id fileid
;
851 ZERO_STRUCT(write_time_ts
);
852 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
853 get_file_infos(fileid
, 0, NULL
, &write_time_ts
);
854 if (!is_omit_timespec(&write_time_ts
)) {
855 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
859 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
860 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
865 reply_smb1_outbuf(req
, 10, 0);
867 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
868 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
869 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
871 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
873 SIVAL(req
->outbuf
,smb_vwv3
,(uint32_t)size
);
875 if (xconn
->protocol
>= PROTOCOL_NT1
) {
876 SSVAL(req
->outbuf
, smb_flg2
,
877 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
880 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
881 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
884 TALLOC_FREE(smb_fname
);
886 END_PROFILE(SMBgetatr
);
890 /****************************************************************************
892 ****************************************************************************/
894 void reply_setatr(struct smb_request
*req
)
896 struct smb_file_time ft
;
897 connection_struct
*conn
= req
->conn
;
898 struct smb_filename
*smb_fname
= NULL
;
899 struct files_struct
*dirfsp
= NULL
;
905 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
907 TALLOC_CTX
*ctx
= talloc_tos();
909 START_PROFILE(SMBsetatr
);
910 init_smb_file_time(&ft
);
913 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
917 p
= (const char *)req
->buf
+ 1;
918 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
919 if (!NT_STATUS_IS_OK(status
)) {
920 reply_nterror(req
, status
);
924 if (ucf_flags
& UCF_GMT_PATHNAME
) {
925 extract_snapshot_token(fname
, &twrp
);
927 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
928 if (!NT_STATUS_IS_OK(status
)) {
929 reply_nterror(req
, status
);
932 status
= filename_convert_dirfsp(ctx
,
939 if (!NT_STATUS_IS_OK(status
)) {
940 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
941 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
945 reply_nterror(req
, status
);
949 if (ISDOT(smb_fname
->base_name
)) {
951 * Not sure here is the right place to catch this
952 * condition. Might be moved to somewhere else later -- vl
954 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
958 if (smb_fname
->fsp
== NULL
) {
960 * filename_convert_dirfsp only returns a NULL fsp for
963 reply_nterror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
967 mode
= SVAL(req
->vwv
+0, 0);
968 mtime
= srv_make_unix_date3(req
->vwv
+1);
970 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
971 if (VALID_STAT_OF_DIR(smb_fname
->st
))
972 mode
|= FILE_ATTRIBUTE_DIRECTORY
;
974 mode
&= ~FILE_ATTRIBUTE_DIRECTORY
;
976 status
= smbd_check_access_rights_fsp(conn
->cwd_fsp
,
979 FILE_WRITE_ATTRIBUTES
);
980 if (!NT_STATUS_IS_OK(status
)) {
981 reply_nterror(req
, status
);
985 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
987 reply_nterror(req
, map_nt_error_from_unix(errno
));
992 ft
.mtime
= time_t_to_full_timespec(mtime
);
994 status
= smb_set_file_time(conn
, smb_fname
->fsp
, smb_fname
, &ft
, true);
995 if (!NT_STATUS_IS_OK(status
)) {
996 reply_nterror(req
, status
);
1000 reply_smb1_outbuf(req
, 0, 0);
1002 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1005 TALLOC_FREE(smb_fname
);
1006 END_PROFILE(SMBsetatr
);
1010 /****************************************************************************
1012 ****************************************************************************/
1014 void reply_dskattr(struct smb_request
*req
)
1016 struct smbXsrv_connection
*xconn
= req
->xconn
;
1017 connection_struct
*conn
= req
->conn
;
1019 uint64_t dfree
,dsize
,bsize
;
1020 struct smb_filename smb_fname
;
1021 START_PROFILE(SMBdskattr
);
1023 ZERO_STRUCT(smb_fname
);
1024 smb_fname
.base_name
= discard_const_p(char, ".");
1026 if (SMB_VFS_STAT(conn
, &smb_fname
) != 0) {
1027 reply_nterror(req
, map_nt_error_from_unix(errno
));
1028 DBG_WARNING("stat of . failed (%s)\n", strerror(errno
));
1029 END_PROFILE(SMBdskattr
);
1033 ret
= get_dfree_info(conn
, &smb_fname
, &bsize
, &dfree
, &dsize
);
1034 if (ret
== (uint64_t)-1) {
1035 reply_nterror(req
, map_nt_error_from_unix(errno
));
1036 END_PROFILE(SMBdskattr
);
1041 * Force max to fit in 16 bit fields.
1043 while (dfree
> WORDMAX
|| dsize
> WORDMAX
|| bsize
< 512) {
1047 if (bsize
> (WORDMAX
*512)) {
1048 bsize
= (WORDMAX
*512);
1049 if (dsize
> WORDMAX
)
1051 if (dfree
> WORDMAX
)
1057 reply_smb1_outbuf(req
, 5, 0);
1059 if (xconn
->protocol
<= PROTOCOL_LANMAN2
) {
1060 double total_space
, free_space
;
1061 /* we need to scale this to a number that DOS6 can handle. We
1062 use floating point so we can handle large drives on systems
1063 that don't have 64 bit integers
1065 we end up displaying a maximum of 2G to DOS systems
1067 total_space
= dsize
* (double)bsize
;
1068 free_space
= dfree
* (double)bsize
;
1070 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1071 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1073 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1074 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1076 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1077 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1078 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1079 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1081 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1082 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1083 SSVAL(req
->outbuf
,smb_vwv2
,512);
1084 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1087 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1089 END_PROFILE(SMBdskattr
);
1093 /****************************************************************************
1095 ****************************************************************************/
1097 static void make_dir_struct(char *buf
,
1107 if ((mode
& FILE_ATTRIBUTE_DIRECTORY
) != 0) {
1111 memset(buf
+1,' ',11);
1112 if ((p
= strchr_m(mask
, '.')) != NULL
) {
1113 char name
[p
- mask
+ 1];
1114 strlcpy(name
, mask
, sizeof(name
));
1115 push_ascii(buf
+ 1, name
, 8, 0);
1116 push_ascii(buf
+9,p
+1,3, 0);
1118 push_ascii(buf
+ 1, mask
, 11, 0);
1121 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
1123 srv_put_dos_date(buf
,22,date
);
1124 SSVAL(buf
,26,size
& 0xFFFF);
1125 SSVAL(buf
,28,(size
>> 16)&0xFFFF);
1126 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1127 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1128 push_ascii(buf
+30,fname
,12, uc
? STR_UPPER
: 0);
1129 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf
+30, fname
));
1132 /*******************************************************************
1133 A wrapper that handles case sensitivity and the special handling
1135 *******************************************************************/
1137 static bool mask_match_search(const char *string
,
1138 const char *pattern
,
1139 bool is_case_sensitive
)
1141 if (ISDOTDOT(string
)) {
1144 if (ISDOT(pattern
)) {
1148 return ms_fnmatch(pattern
, string
, True
, is_case_sensitive
) == 0;
1151 static bool mangle_mask_match(connection_struct
*conn
,
1152 const char *filename
,
1157 if (!name_to_8_3(filename
, mname
, False
, conn
->params
)) {
1160 return mask_match_search(mname
, mask
, False
);
1163 /****************************************************************************
1164 Get an 8.3 directory entry.
1165 ****************************************************************************/
1167 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX
*ctx
,
1173 connection_struct
*conn
= (connection_struct
*)private_data
;
1175 if ((strcmp(mask
, "*.*") == 0) ||
1176 mask_match_search(dname
, mask
, false) ||
1177 mangle_mask_match(conn
, dname
, mask
)) {
1181 * Ensure we can push the original name as UCS2. If
1182 * not, then just don't return this name.
1186 size_t len
= (strlen(dname
) + 2) * 4; /* Allow enough space. */
1187 uint8_t *tmp
= talloc_array(talloc_tos(), uint8_t, len
);
1189 status
= srvstr_push(NULL
,
1190 FLAGS2_UNICODE_STRINGS
,
1199 if (!NT_STATUS_IS_OK(status
)) {
1203 if (!mangle_is_8_3(dname
, false, conn
->params
)) {
1205 name_to_8_3(dname
, mname
, false, conn
->params
);
1214 *_fname
= talloc_strdup(ctx
, fname
);
1215 if (*_fname
== NULL
) {
1225 static bool get_dir_entry(TALLOC_CTX
*ctx
,
1226 connection_struct
*conn
,
1227 struct dptr_struct
*dirptr
,
1233 struct timespec
*_date
,
1238 struct smb_filename
*smb_fname
= NULL
;
1243 ok
= smbd_dirptr_get_entry(ctx
,
1250 smbd_dirptr_8_3_match_fn
,
1258 if (mode
& FILE_ATTRIBUTE_REPARSE_POINT
) {
1259 /* hide reparse points from ancient clients */
1261 TALLOC_FREE(smb_fname
);
1265 *_fname
= talloc_move(ctx
, &fname
);
1266 *_size
= smb_fname
->st
.st_ex_size
;
1268 *_date
= smb_fname
->st
.st_ex_mtime
;
1269 TALLOC_FREE(smb_fname
);
1273 /****************************************************************************
1275 Can be called from SMBsearch, SMBffirst or SMBfunique.
1276 ****************************************************************************/
1278 void reply_search(struct smb_request
*req
)
1280 connection_struct
*conn
= req
->conn
;
1283 char *directory
= NULL
;
1284 struct smb_filename
*smb_fname
= NULL
;
1288 struct timespec date
;
1290 unsigned int numentries
= 0;
1291 unsigned int maxentries
= 0;
1292 bool finished
= False
;
1297 bool check_descend
= False
;
1298 bool expect_close
= False
;
1300 bool mask_contains_wcard
= False
;
1301 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1302 TALLOC_CTX
*ctx
= talloc_tos();
1303 struct smbXsrv_connection
*xconn
= req
->xconn
;
1304 struct smbd_server_connection
*sconn
= req
->sconn
;
1305 files_struct
*fsp
= NULL
;
1306 const struct loadparm_substitution
*lp_sub
=
1307 loadparm_s3_global_substitution();
1309 START_PROFILE(SMBsearch
);
1312 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1316 if (req
->posix_pathnames
) {
1317 reply_unknown_new(req
, req
->cmd
);
1321 /* If we were called as SMBffirst then we must expect close. */
1322 if(req
->cmd
== SMBffirst
) {
1323 expect_close
= True
;
1326 reply_smb1_outbuf(req
, 1, 3);
1327 maxentries
= SVAL(req
->vwv
+0, 0);
1328 dirtype
= SVAL(req
->vwv
+1, 0);
1329 p
= (const char *)req
->buf
+ 1;
1330 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1332 if (!NT_STATUS_IS_OK(nt_status
)) {
1333 reply_nterror(req
, nt_status
);
1337 if (smbreq_bufrem(req
, p
) < 3) {
1338 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1343 status_len
= SVAL(p
, 0);
1346 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1348 if (status_len
== 0) {
1349 const char *dirpath
;
1350 struct files_struct
*dirfsp
= NULL
;
1351 struct smb_filename
*smb_dname
= NULL
;
1352 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
1354 nt_status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &path
);
1355 if (!NT_STATUS_IS_OK(nt_status
)) {
1356 reply_nterror(req
, nt_status
);
1360 nt_status
= filename_convert_smb1_search_path(ctx
,
1368 if (!NT_STATUS_IS_OK(nt_status
)) {
1369 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1370 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1371 ERRSRV
, ERRbadpath
);
1374 reply_nterror(req
, nt_status
);
1378 memset((char *)status
,'\0',21);
1379 SCVAL(status
,0,(dirtype
& 0x1F));
1382 * Open an fsp on this directory for the dptr.
1384 nt_status
= SMB_VFS_CREATE_FILE(
1387 dirfsp
, /* dirfsp */
1388 smb_dname
, /* dname */
1389 FILE_LIST_DIRECTORY
, /* access_mask */
1391 FILE_SHARE_WRITE
, /* share_access */
1392 FILE_OPEN
, /* create_disposition*/
1393 FILE_DIRECTORY_FILE
, /* create_options */
1394 FILE_ATTRIBUTE_DIRECTORY
,/* file_attributes */
1395 NO_OPLOCK
, /* oplock_request */
1397 0, /* allocation_size */
1398 0, /* private_flags */
1403 NULL
, /* in_context */
1404 NULL
);/* out_context */
1406 if (!NT_STATUS_IS_OK(nt_status
)) {
1407 DBG_ERR("failed to open directory %s\n",
1408 smb_fname_str_dbg(smb_dname
));
1409 reply_nterror(req
, nt_status
);
1413 nt_status
= dptr_create(conn
,
1421 TALLOC_FREE(smb_dname
);
1423 if (!NT_STATUS_IS_OK(nt_status
)) {
1425 * Use NULL here for the first parameter (req)
1426 * as this is not a client visible handle so
1427 * can't be part of an SMB1 chain.
1429 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1430 reply_nterror(req
, nt_status
);
1434 dptr_num
= dptr_dnum(fsp
->dptr
);
1435 dirpath
= dptr_path(sconn
, dptr_num
);
1436 directory
= talloc_strdup(ctx
, dirpath
);
1438 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1444 const char *dirpath
;
1445 unsigned int dptr_filenum
;
1446 uint32_t resume_key_index
;
1448 if (smbreq_bufrem(req
, p
) < 21) {
1449 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1453 memcpy(status
,p
,21);
1454 status_dirtype
= CVAL(status
,0) & 0x1F;
1455 if (status_dirtype
!= (dirtype
& 0x1F)) {
1456 dirtype
= status_dirtype
;
1459 dptr_num
= CVAL(status
, 12);
1460 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
1465 resume_key_index
= PULL_LE_U32(status
, 13);
1466 dptr_filenum
= dptr_FileNumber(fsp
->dptr
);
1468 if (resume_key_index
> dptr_filenum
) {
1470 * Haven't seen this resume key yet. Just stop
1476 if (resume_key_index
< dptr_filenum
) {
1478 * The resume key was not the last one we
1479 * sent, rewind and skip to what the client
1482 dptr_RewindDir(fsp
->dptr
);
1484 dptr_filenum
= dptr_FileNumber(fsp
->dptr
);
1485 SMB_ASSERT(dptr_filenum
== 0);
1487 while (dptr_filenum
< resume_key_index
) {
1488 bool ok
= get_dir_entry(
1492 dptr_wcard(sconn
, dptr_num
),
1505 dptr_filenum
= dptr_FileNumber(fsp
->dptr
);
1509 dirpath
= dptr_path(sconn
, dptr_num
);
1510 directory
= talloc_strdup(ctx
, dirpath
);
1512 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1516 mask
= talloc_strdup(ctx
, dptr_wcard(sconn
, dptr_num
));
1520 dirtype
= dptr_attr(sconn
, dptr_num
);
1523 mask_contains_wcard
= dptr_has_wild(fsp
->dptr
);
1525 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1527 if ((dirtype
&0x1F) == FILE_ATTRIBUTE_VOLUME
) {
1528 char buf
[DIR_STRUCT_SIZE
];
1529 memcpy(buf
,status
,21);
1530 make_dir_struct(buf
,
1532 volume_label(ctx
, SNUM(conn
)),
1534 FILE_ATTRIBUTE_VOLUME
,
1536 !allow_long_path_components
);
1537 SCVAL(buf
, 12, dptr_num
);
1539 if (message_push_blob(&req
->outbuf
,
1540 data_blob_const(buf
, sizeof(buf
)))
1542 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1547 size_t hdr_size
= ((uint8_t *)smb_buf(req
->outbuf
) + 3 - req
->outbuf
);
1548 size_t available_space
= xconn
->smb1
.sessions
.max_send
- hdr_size
;
1551 maxentries
= MIN(maxentries
, available_space
/DIR_STRUCT_SIZE
);
1553 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1554 directory
,lp_dont_descend(ctx
, lp_sub
, SNUM(conn
))));
1555 if (in_list(directory
, lp_dont_descend(ctx
, lp_sub
, SNUM(conn
)),True
)) {
1556 check_descend
= True
;
1559 ask_sharemode
= fsp_search_ask_sharemode(fsp
);
1561 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1562 finished
= !get_dir_entry(ctx
,
1574 char buf
[DIR_STRUCT_SIZE
];
1575 memcpy(buf
,status
,21);
1576 make_dir_struct(buf
,
1581 convert_timespec_to_time_t(
1583 !allow_long_path_components
);
1584 SCVAL(buf
, 12, dptr_num
);
1587 dptr_FileNumber(fsp
->dptr
));
1588 if (message_push_blob(&req
->outbuf
,
1589 data_blob_const(buf
, sizeof(buf
)))
1591 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1602 /* If we were called as SMBffirst with smb_search_id == NULL
1603 and no entries were found then return error and close fsp->dptr
1606 if (numentries
== 0) {
1609 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1611 } else if(expect_close
&& status_len
== 0) {
1612 /* Close the dptr - we know it's gone */
1615 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1619 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1620 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1622 /* fsp may have been closed above. */
1624 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1628 if ((numentries
== 0) && !mask_contains_wcard
) {
1629 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1633 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1634 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1635 SCVAL(smb_buf(req
->outbuf
),0,5);
1636 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1638 /* The replies here are never long name. */
1639 SSVAL(req
->outbuf
, smb_flg2
,
1640 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1641 if (!allow_long_path_components
) {
1642 SSVAL(req
->outbuf
, smb_flg2
,
1643 SVAL(req
->outbuf
, smb_flg2
)
1644 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1647 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1648 SSVAL(req
->outbuf
, smb_flg2
,
1649 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1651 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1652 smb_fn_name(req
->cmd
),
1659 TALLOC_FREE(directory
);
1661 TALLOC_FREE(smb_fname
);
1662 END_PROFILE(SMBsearch
);
1666 /****************************************************************************
1667 Reply to a fclose (stop directory search).
1668 ****************************************************************************/
1670 void reply_fclose(struct smb_request
*req
)
1677 TALLOC_CTX
*ctx
= talloc_tos();
1678 struct smbd_server_connection
*sconn
= req
->sconn
;
1679 files_struct
*fsp
= NULL
;
1681 START_PROFILE(SMBfclose
);
1683 if (req
->posix_pathnames
) {
1684 reply_unknown_new(req
, req
->cmd
);
1685 END_PROFILE(SMBfclose
);
1689 p
= (const char *)req
->buf
+ 1;
1690 p
+= srvstr_get_path_req(ctx
, req
, &path
, p
, STR_TERMINATE
,
1692 if (!NT_STATUS_IS_OK(err
)) {
1693 reply_nterror(req
, err
);
1694 END_PROFILE(SMBfclose
);
1698 if (smbreq_bufrem(req
, p
) < 3) {
1699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1700 END_PROFILE(SMBfclose
);
1705 status_len
= SVAL(p
,0);
1708 if (status_len
== 0) {
1709 reply_force_doserror(req
, ERRSRV
, ERRsrverror
);
1710 END_PROFILE(SMBfclose
);
1714 if (smbreq_bufrem(req
, p
) < 21) {
1715 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1716 END_PROFILE(SMBfclose
);
1720 dptr_num
= CVAL(p
, 12);
1722 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
1724 /* Close the file - we know it's gone */
1725 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
1729 reply_smb1_outbuf(req
, 1, 0);
1730 SSVAL(req
->outbuf
,smb_vwv0
,0);
1732 DEBUG(3,("search close\n"));
1734 END_PROFILE(SMBfclose
);
1738 /****************************************************************************
1740 ****************************************************************************/
1742 void reply_open(struct smb_request
*req
)
1744 connection_struct
*conn
= req
->conn
;
1745 struct smb_filename
*smb_fname
= NULL
;
1751 struct files_struct
*dirfsp
= NULL
;
1756 uint32_t access_mask
;
1757 uint32_t share_mode
;
1758 uint32_t create_disposition
;
1759 uint32_t create_options
= 0;
1760 uint32_t private_flags
= 0;
1764 TALLOC_CTX
*ctx
= talloc_tos();
1766 START_PROFILE(SMBopen
);
1769 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1773 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1774 deny_mode
= SVAL(req
->vwv
+0, 0);
1775 dos_attr
= SVAL(req
->vwv
+1, 0);
1777 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1778 STR_TERMINATE
, &status
);
1779 if (!NT_STATUS_IS_OK(status
)) {
1780 reply_nterror(req
, status
);
1784 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1785 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1786 &share_mode
, &create_disposition
,
1787 &create_options
, &private_flags
)) {
1788 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1792 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
1794 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1795 extract_snapshot_token(fname
, &twrp
);
1797 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
1798 if (!NT_STATUS_IS_OK(status
)) {
1799 reply_nterror(req
, status
);
1802 status
= filename_convert_dirfsp(ctx
,
1809 if (!NT_STATUS_IS_OK(status
)) {
1810 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1811 reply_botherror(req
,
1812 NT_STATUS_PATH_NOT_COVERED
,
1813 ERRSRV
, ERRbadpath
);
1816 reply_nterror(req
, status
);
1820 status
= SMB_VFS_CREATE_FILE(
1823 dirfsp
, /* dirfsp */
1824 smb_fname
, /* fname */
1825 access_mask
, /* access_mask */
1826 share_mode
, /* share_access */
1827 create_disposition
, /* create_disposition*/
1828 create_options
, /* create_options */
1829 dos_attr
, /* file_attributes */
1830 oplock_request
, /* oplock_request */
1832 0, /* allocation_size */
1838 NULL
, NULL
); /* create context */
1840 if (!NT_STATUS_IS_OK(status
)) {
1841 if (open_was_deferred(req
->xconn
, req
->mid
)) {
1842 /* We have re-scheduled this call. */
1846 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
1847 reply_openerror(req
, status
);
1851 fsp
= fcb_or_dos_open(
1858 bool ok
= defer_smb1_sharing_violation(req
);
1862 reply_openerror(req
, status
);
1867 /* Ensure we're pointing at the correct stat struct. */
1868 TALLOC_FREE(smb_fname
);
1869 smb_fname
= fsp
->fsp_name
;
1871 size
= smb_fname
->st
.st_ex_size
;
1872 fattr
= fdos_mode(fsp
);
1874 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1876 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
1877 DEBUG(3,("attempt to open a directory %s\n",
1879 close_file_free(req
, &fsp
, ERROR_CLOSE
);
1880 reply_botherror(req
, NT_STATUS_ACCESS_DENIED
,
1881 ERRDOS
, ERRnoaccess
);
1885 reply_smb1_outbuf(req
, 7, 0);
1886 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1887 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1888 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1889 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1891 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1893 SIVAL(req
->outbuf
,smb_vwv4
,(uint32_t)size
);
1894 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1896 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1897 SCVAL(req
->outbuf
,smb_flg
,
1898 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1901 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1902 SCVAL(req
->outbuf
,smb_flg
,
1903 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1906 END_PROFILE(SMBopen
);
1910 /****************************************************************************
1911 Reply to an open and X.
1912 ****************************************************************************/
1914 void reply_open_and_X(struct smb_request
*req
)
1916 connection_struct
*conn
= req
->conn
;
1917 struct smb_filename
*smb_fname
= NULL
;
1919 uint16_t open_flags
;
1922 /* Breakout the oplock request bits so we can set the
1923 reply bits separately. */
1924 int ex_oplock_request
;
1925 int core_oplock_request
;
1928 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1929 uint32_t smb_time
= make_unix_date3(req
->vwv
+6);
1935 struct files_struct
*dirfsp
= NULL
;
1938 uint64_t allocation_size
;
1939 ssize_t retval
= -1;
1940 uint32_t access_mask
;
1941 uint32_t share_mode
;
1942 uint32_t create_disposition
;
1943 uint32_t create_options
= 0;
1944 uint32_t private_flags
= 0;
1947 TALLOC_CTX
*ctx
= talloc_tos();
1949 START_PROFILE(SMBopenX
);
1951 if (req
->wct
< 15) {
1952 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1956 open_flags
= SVAL(req
->vwv
+2, 0);
1957 deny_mode
= SVAL(req
->vwv
+3, 0);
1958 smb_attr
= SVAL(req
->vwv
+5, 0);
1959 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1960 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1961 oplock_request
= ex_oplock_request
| core_oplock_request
;
1962 smb_ofun
= SVAL(req
->vwv
+8, 0);
1963 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1965 /* If it's an IPC, pass off the pipe handler. */
1967 if (lp_nt_pipe_support()) {
1968 reply_open_pipe_and_X(conn
, req
);
1970 reply_nterror(req
, NT_STATUS_NETWORK_ACCESS_DENIED
);
1975 /* XXXX we need to handle passed times, sattr and flags */
1976 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1977 STR_TERMINATE
, &status
);
1978 if (!NT_STATUS_IS_OK(status
)) {
1979 reply_nterror(req
, status
);
1983 if (!map_open_params_to_ntcreate(fname
, deny_mode
,
1985 &access_mask
, &share_mode
,
1986 &create_disposition
,
1989 reply_force_doserror(req
, ERRDOS
, ERRbadaccess
);
1993 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
1995 if (ucf_flags
& UCF_GMT_PATHNAME
) {
1996 extract_snapshot_token(fname
, &twrp
);
1998 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
1999 if (!NT_STATUS_IS_OK(status
)) {
2000 reply_nterror(req
, status
);
2004 status
= filename_convert_dirfsp(ctx
,
2011 if (!NT_STATUS_IS_OK(status
)) {
2012 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2013 reply_botherror(req
,
2014 NT_STATUS_PATH_NOT_COVERED
,
2015 ERRSRV
, ERRbadpath
);
2018 reply_nterror(req
, status
);
2022 status
= SMB_VFS_CREATE_FILE(
2025 dirfsp
, /* dirfsp */
2026 smb_fname
, /* fname */
2027 access_mask
, /* access_mask */
2028 share_mode
, /* share_access */
2029 create_disposition
, /* create_disposition*/
2030 create_options
, /* create_options */
2031 smb_attr
, /* file_attributes */
2032 oplock_request
, /* oplock_request */
2034 0, /* allocation_size */
2039 &smb_action
, /* pinfo */
2040 NULL
, NULL
); /* create context */
2042 if (!NT_STATUS_IS_OK(status
)) {
2043 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2044 /* We have re-scheduled this call. */
2048 if (!NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2049 reply_openerror(req
, status
);
2053 fsp
= fcb_or_dos_open(
2060 bool ok
= defer_smb1_sharing_violation(req
);
2064 reply_openerror(req
, status
);
2069 smb_action
= FILE_WAS_OPENED
;
2072 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2073 if the file is truncated or created. */
2074 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
2075 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
2076 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
2077 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2078 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2081 retval
= vfs_set_filelen(fsp
, (off_t
)allocation_size
);
2083 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2084 reply_nterror(req
, NT_STATUS_DISK_FULL
);
2087 status
= vfs_stat_fsp(fsp
);
2088 if (!NT_STATUS_IS_OK(status
)) {
2089 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2090 reply_nterror(req
, status
);
2095 fattr
= fdos_mode(fsp
);
2096 if (fattr
& FILE_ATTRIBUTE_DIRECTORY
) {
2097 close_file_free(req
, &fsp
, ERROR_CLOSE
);
2098 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
2101 mtime
= convert_timespec_to_time_t(fsp
->fsp_name
->st
.st_ex_mtime
);
2103 /* If the caller set the extended oplock request bit
2104 and we granted one (by whatever means) - set the
2105 correct bit for extended oplock reply.
2108 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2109 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2112 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2113 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
2116 /* If the caller set the core oplock request bit
2117 and we granted one (by whatever means) - set the
2118 correct bit for core oplock reply.
2121 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2122 reply_smb1_outbuf(req
, 19, 0);
2124 reply_smb1_outbuf(req
, 15, 0);
2127 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2128 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2130 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2131 SCVAL(req
->outbuf
, smb_flg
,
2132 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2135 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2136 SCVAL(req
->outbuf
, smb_flg
,
2137 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2140 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2141 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2142 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2143 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2145 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2147 SIVAL(req
->outbuf
,smb_vwv6
,(uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
2148 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2149 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2151 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2152 SIVAL(req
->outbuf
, smb_vwv15
, SEC_STD_ALL
);
2156 TALLOC_FREE(smb_fname
);
2157 END_PROFILE(SMBopenX
);
2161 /****************************************************************************
2162 Reply to a SMBulogoffX.
2163 ****************************************************************************/
2165 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2166 struct smbXsrv_session
*session
);
2167 static void reply_ulogoffX_done(struct tevent_req
*req
);
2169 void reply_ulogoffX(struct smb_request
*smb1req
)
2171 struct timeval now
= timeval_current();
2172 struct smbXsrv_session
*session
= NULL
;
2173 struct tevent_req
*req
;
2177 * Don't setup the profile charge here, take
2178 * it in reply_ulogoffX_done(). Not strictly correct
2179 * but better than the other SMB1 async
2180 * code that double-charges at the moment.
2183 status
= smb1srv_session_lookup(smb1req
->xconn
,
2185 timeval_to_nttime(&now
),
2187 if (!NT_STATUS_IS_OK(status
)) {
2188 /* Not going async, profile here. */
2189 START_PROFILE(SMBulogoffX
);
2190 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2191 (unsigned long long)smb1req
->vuid
);
2193 smb1req
->vuid
= UID_FIELD_INVALID
;
2194 reply_force_doserror(smb1req
, ERRSRV
, ERRbaduid
);
2195 END_PROFILE(SMBulogoffX
);
2199 req
= reply_ulogoffX_send(smb1req
, session
);
2201 /* Not going async, profile here. */
2202 START_PROFILE(SMBulogoffX
);
2203 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
2204 END_PROFILE(SMBulogoffX
);
2208 /* We're async. This will complete later. */
2209 tevent_req_set_callback(req
, reply_ulogoffX_done
, smb1req
);
2213 struct reply_ulogoffX_state
{
2214 struct tevent_queue
*wait_queue
;
2215 struct smbXsrv_session
*session
;
2218 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
);
2220 /****************************************************************************
2221 Async SMB1 ulogoffX.
2222 Note, on failure here we deallocate and return NULL to allow the caller to
2223 SMB1 return an error of ERRnomem immediately.
2224 ****************************************************************************/
2226 static struct tevent_req
*reply_ulogoffX_send(struct smb_request
*smb1req
,
2227 struct smbXsrv_session
*session
)
2229 struct tevent_req
*req
;
2230 struct reply_ulogoffX_state
*state
;
2231 struct tevent_req
*subreq
;
2233 struct smbd_server_connection
*sconn
= session
->client
->sconn
;
2234 uint64_t vuid
= session
->global
->session_wire_id
;
2236 req
= tevent_req_create(smb1req
, &state
,
2237 struct reply_ulogoffX_state
);
2241 state
->wait_queue
= tevent_queue_create(state
,
2242 "reply_ulogoffX_wait_queue");
2243 if (tevent_req_nomem(state
->wait_queue
, req
)) {
2247 state
->session
= session
;
2250 * Make sure that no new request will be able to use this session.
2251 * This ensures that once all outstanding fsp->aio_requests
2252 * on this session are done, we are safe to close it.
2254 session
->status
= NT_STATUS_USER_SESSION_DELETED
;
2256 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
2257 if (fsp
->vuid
!= vuid
) {
2261 * Flag the file as close in progress.
2262 * This will prevent any more IO being
2265 fsp
->fsp_flags
.closing
= true;
2267 if (fsp
->num_aio_requests
> 0) {
2269 * Now wait until all aio requests on this fsp are
2272 * We don't set a callback, as we just want to block the
2273 * wait queue and the talloc_free() of fsp->aio_request
2274 * will remove the item from the wait queue.
2276 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
2279 if (tevent_req_nomem(subreq
, req
)) {
2287 * Now we add our own waiter to the end of the queue,
2288 * this way we get notified when all pending requests are finished
2289 * and reply to the outstanding SMB1 request.
2291 subreq
= tevent_queue_wait_send(state
,
2294 if (tevent_req_nomem(subreq
, req
)) {
2300 * We're really going async - move the SMB1 request from
2301 * a talloc stackframe above us to the sconn talloc-context.
2302 * We need this to stick around until the wait_done
2303 * callback is invoked.
2305 smb1req
= talloc_move(sconn
, &smb1req
);
2307 tevent_req_set_callback(subreq
, reply_ulogoffX_wait_done
, req
);
2312 static void reply_ulogoffX_wait_done(struct tevent_req
*subreq
)
2314 struct tevent_req
*req
= tevent_req_callback_data(
2315 subreq
, struct tevent_req
);
2317 tevent_queue_wait_recv(subreq
);
2318 TALLOC_FREE(subreq
);
2319 tevent_req_done(req
);
2322 static NTSTATUS
reply_ulogoffX_recv(struct tevent_req
*req
)
2324 return tevent_req_simple_recv_ntstatus(req
);
2327 static void reply_ulogoffX_done(struct tevent_req
*req
)
2329 struct smb_request
*smb1req
= tevent_req_callback_data(
2330 req
, struct smb_request
);
2331 struct reply_ulogoffX_state
*state
= tevent_req_data(req
,
2332 struct reply_ulogoffX_state
);
2333 struct smbXsrv_session
*session
= state
->session
;
2337 * Take the profile charge here. Not strictly
2338 * correct but better than the other SMB1 async
2339 * code that double-charges at the moment.
2341 START_PROFILE(SMBulogoffX
);
2343 status
= reply_ulogoffX_recv(req
);
2345 if (!NT_STATUS_IS_OK(status
)) {
2346 TALLOC_FREE(smb1req
);
2347 END_PROFILE(SMBulogoffX
);
2348 exit_server(__location__
": reply_ulogoffX_recv failed");
2352 status
= smbXsrv_session_logoff(session
);
2353 if (!NT_STATUS_IS_OK(status
)) {
2354 TALLOC_FREE(smb1req
);
2355 END_PROFILE(SMBulogoffX
);
2356 exit_server(__location__
": smbXsrv_session_logoff failed");
2360 TALLOC_FREE(session
);
2362 reply_smb1_outbuf(smb1req
, 2, 0);
2363 SSVAL(smb1req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
2364 SSVAL(smb1req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
2366 DBG_NOTICE("ulogoffX vuid=%llu\n",
2367 (unsigned long long)smb1req
->vuid
);
2369 smb1req
->vuid
= UID_FIELD_INVALID
;
2371 * The following call is needed to push the
2372 * reply data back out the socket after async
2373 * return. Plus it frees smb1req.
2375 smb_request_done(smb1req
);
2376 END_PROFILE(SMBulogoffX
);
2379 /****************************************************************************
2380 Reply to a mknew or a create.
2381 ****************************************************************************/
2383 void reply_mknew(struct smb_request
*req
)
2385 connection_struct
*conn
= req
->conn
;
2386 struct smb_filename
*smb_fname
= NULL
;
2389 struct smb_file_time ft
;
2390 struct files_struct
*dirfsp
= NULL
;
2392 int oplock_request
= 0;
2394 uint32_t access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2395 uint32_t share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2396 uint32_t create_disposition
;
2397 uint32_t create_options
= 0;
2400 TALLOC_CTX
*ctx
= talloc_tos();
2402 START_PROFILE(SMBcreate
);
2403 init_smb_file_time(&ft
);
2406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2410 fattr
= SVAL(req
->vwv
+0, 0);
2411 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2413 if (req
->cmd
== SMBmknew
) {
2414 /* We should fail if file exists. */
2415 create_disposition
= FILE_CREATE
;
2417 /* Create if file doesn't exist, truncate if it does. */
2418 create_disposition
= FILE_OVERWRITE_IF
;
2422 ft
.mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+1));
2424 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2425 STR_TERMINATE
, &status
);
2426 if (!NT_STATUS_IS_OK(status
)) {
2427 reply_nterror(req
, status
);
2431 ucf_flags
= filename_create_ucf_flags(req
, create_disposition
);
2432 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2433 extract_snapshot_token(fname
, &twrp
);
2435 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
2436 if (!NT_STATUS_IS_OK(status
)) {
2437 reply_nterror(req
, status
);
2441 status
= filename_convert_dirfsp(ctx
,
2448 if (!NT_STATUS_IS_OK(status
)) {
2449 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2450 reply_botherror(req
,
2451 NT_STATUS_PATH_NOT_COVERED
,
2452 ERRSRV
, ERRbadpath
);
2455 reply_nterror(req
, status
);
2459 if (fattr
& FILE_ATTRIBUTE_VOLUME
) {
2460 DEBUG(0,("Attempt to create file (%s) with volid set - "
2461 "please report this\n",
2462 smb_fname_str_dbg(smb_fname
)));
2465 status
= SMB_VFS_CREATE_FILE(
2468 dirfsp
, /* dirfsp */
2469 smb_fname
, /* fname */
2470 access_mask
, /* access_mask */
2471 share_mode
, /* share_access */
2472 create_disposition
, /* create_disposition*/
2473 create_options
, /* create_options */
2474 fattr
, /* file_attributes */
2475 oplock_request
, /* oplock_request */
2477 0, /* allocation_size */
2478 0, /* private_flags */
2483 NULL
, NULL
); /* create context */
2485 if (!NT_STATUS_IS_OK(status
)) {
2486 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2487 /* We have re-scheduled this call. */
2490 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2491 bool ok
= defer_smb1_sharing_violation(req
);
2496 reply_openerror(req
, status
);
2500 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2501 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2502 if (!NT_STATUS_IS_OK(status
)) {
2503 END_PROFILE(SMBcreate
);
2507 reply_smb1_outbuf(req
, 1, 0);
2508 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2510 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2511 SCVAL(req
->outbuf
,smb_flg
,
2512 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2515 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2516 SCVAL(req
->outbuf
,smb_flg
,
2517 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2520 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2521 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2522 smb_fname_str_dbg(smb_fname
), fsp_get_io_fd(fsp
),
2523 (unsigned int)fattr
));
2526 TALLOC_FREE(smb_fname
);
2527 END_PROFILE(SMBcreate
);
2531 /****************************************************************************
2532 Reply to a create temporary file.
2533 ****************************************************************************/
2535 void reply_ctemp(struct smb_request
*req
)
2537 connection_struct
*conn
= req
->conn
;
2538 struct smb_filename
*smb_fname
= NULL
;
2539 char *wire_name
= NULL
;
2542 struct files_struct
*dirfsp
= NULL
;
2550 TALLOC_CTX
*ctx
= talloc_tos();
2552 START_PROFILE(SMBctemp
);
2555 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2559 fattr
= SVAL(req
->vwv
+0, 0);
2560 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2562 srvstr_get_path_req(ctx
, req
, &wire_name
, (const char *)req
->buf
+1,
2563 STR_TERMINATE
, &status
);
2564 if (!NT_STATUS_IS_OK(status
)) {
2565 reply_nterror(req
, status
);
2569 for (i
= 0; i
< 10; i
++) {
2571 fname
= talloc_asprintf(ctx
,
2574 generate_random_str_list(ctx
, 5, "0123456789"));
2576 fname
= talloc_asprintf(ctx
,
2578 generate_random_str_list(ctx
, 5, "0123456789"));
2582 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2586 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
2587 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2588 extract_snapshot_token(fname
, &twrp
);
2590 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &fname
);
2591 if (!NT_STATUS_IS_OK(status
)) {
2592 reply_nterror(req
, status
);
2596 status
= filename_convert_dirfsp(ctx
,
2603 if (!NT_STATUS_IS_OK(status
)) {
2604 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2605 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2606 ERRSRV
, ERRbadpath
);
2609 reply_nterror(req
, status
);
2613 /* Create the file. */
2614 status
= SMB_VFS_CREATE_FILE(
2617 dirfsp
, /* dirfsp */
2618 smb_fname
, /* fname */
2619 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2620 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2621 FILE_CREATE
, /* create_disposition*/
2622 0, /* create_options */
2623 fattr
, /* file_attributes */
2624 oplock_request
, /* oplock_request */
2626 0, /* allocation_size */
2627 0, /* private_flags */
2632 NULL
, NULL
); /* create context */
2634 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_COLLISION
)) {
2636 TALLOC_FREE(dirfsp
);
2637 TALLOC_FREE(smb_fname
);
2641 if (!NT_STATUS_IS_OK(status
)) {
2642 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2643 /* We have re-scheduled this call. */
2646 if (NT_STATUS_EQUAL(
2647 status
, NT_STATUS_SHARING_VIOLATION
)) {
2648 bool ok
= defer_smb1_sharing_violation(req
);
2653 reply_openerror(req
, status
);
2661 /* Collision after 10 times... */
2662 reply_nterror(req
, status
);
2666 reply_smb1_outbuf(req
, 1, 0);
2667 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2669 /* the returned filename is relative to the directory */
2670 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2672 s
= fsp
->fsp_name
->base_name
;
2678 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2679 thing in the byte section. JRA */
2680 SSVALS(p
, 0, -1); /* what is this? not in spec */
2682 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2684 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2688 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2689 SCVAL(req
->outbuf
, smb_flg
,
2690 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2693 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2694 SCVAL(req
->outbuf
, smb_flg
,
2695 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2698 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2699 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2700 fsp_get_io_fd(fsp
), (unsigned int)smb_fname
->st
.st_ex_mode
));
2702 TALLOC_FREE(smb_fname
);
2703 TALLOC_FREE(wire_name
);
2704 END_PROFILE(SMBctemp
);
2708 /****************************************************************************
2710 ****************************************************************************/
2712 void reply_unlink(struct smb_request
*req
)
2714 connection_struct
*conn
= req
->conn
;
2716 struct files_struct
*dirfsp
= NULL
;
2717 struct smb_filename
*smb_fname
= NULL
;
2720 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
2722 TALLOC_CTX
*ctx
= talloc_tos();
2724 START_PROFILE(SMBunlink
);
2727 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2731 dirtype
= SVAL(req
->vwv
+0, 0);
2733 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2734 STR_TERMINATE
, &status
);
2735 if (!NT_STATUS_IS_OK(status
)) {
2736 reply_nterror(req
, status
);
2740 if (ucf_flags
& UCF_GMT_PATHNAME
) {
2741 extract_snapshot_token(name
, &twrp
);
2743 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &name
);
2744 if (!NT_STATUS_IS_OK(status
)) {
2745 reply_nterror(req
, status
);
2748 status
= filename_convert_dirfsp(ctx
,
2751 ucf_flags
| UCF_LCOMP_LNK_OK
,
2755 if (!NT_STATUS_IS_OK(status
)) {
2756 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2757 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2758 ERRSRV
, ERRbadpath
);
2761 reply_nterror(req
, status
);
2765 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2767 status
= unlink_internals(conn
, req
, dirtype
, dirfsp
, smb_fname
);
2768 if (!NT_STATUS_IS_OK(status
)) {
2769 if (open_was_deferred(req
->xconn
, req
->mid
)) {
2770 /* We have re-scheduled this call. */
2773 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
2774 bool ok
= defer_smb1_sharing_violation(req
);
2779 reply_nterror(req
, status
);
2783 reply_smb1_outbuf(req
, 0, 0);
2785 TALLOC_FREE(smb_fname
);
2786 END_PROFILE(SMBunlink
);
2790 /****************************************************************************
2792 ****************************************************************************/
2794 static void fail_readraw(void)
2796 const char *errstr
= talloc_asprintf(talloc_tos(),
2797 "FAIL ! reply_readbraw: socket write fail (%s)",
2802 exit_server_cleanly(errstr
);
2805 /****************************************************************************
2806 Return a readbraw error (4 bytes of zero).
2807 ****************************************************************************/
2809 static void reply_readbraw_error(struct smbXsrv_connection
*xconn
)
2815 smbd_lock_socket(xconn
);
2816 if (write_data(xconn
->transport
.sock
,header
,4) != 4) {
2817 int saved_errno
= errno
;
2819 * Try and give an error message saying what
2822 DEBUG(0, ("write_data failed for client %s. "
2824 smbXsrv_connection_dbg(xconn
),
2825 strerror(saved_errno
)));
2826 errno
= saved_errno
;
2830 smbd_unlock_socket(xconn
);
2833 /*******************************************************************
2834 Ensure we don't use sendfile if server smb signing is active.
2835 ********************************************************************/
2837 static bool lp_use_sendfile(struct smbXsrv_connection
*xconn
,
2839 struct smb1_signing_state
*signing_state
)
2841 bool sign_active
= false;
2843 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2844 if (xconn
->protocol
< PROTOCOL_NT1
) {
2847 if (signing_state
) {
2848 sign_active
= smb1_signing_is_active(signing_state
);
2850 return (lp__use_sendfile(snum
) &&
2851 (get_remote_arch() != RA_WIN95
) &&
2854 /****************************************************************************
2855 Use sendfile in readbraw.
2856 ****************************************************************************/
2858 static void send_file_readbraw(connection_struct
*conn
,
2859 struct smb_request
*req
,
2865 struct smbXsrv_connection
*xconn
= req
->xconn
;
2866 char *outbuf
= NULL
;
2870 * We can only use sendfile on a non-chained packet
2871 * but we can use on a non-oplocked file. tridge proved this
2872 * on a train in Germany :-). JRA.
2873 * reply_readbraw has already checked the length.
2876 if ( !req_is_in_chain(req
) &&
2878 !fsp_is_alternate_stream(fsp
) &&
2879 lp_use_sendfile(xconn
, SNUM(conn
), xconn
->smb1
.signing_state
) ) {
2880 ssize_t sendfile_read
= -1;
2882 DATA_BLOB header_blob
;
2884 _smb_setlen(header
,nread
);
2885 header_blob
= data_blob_const(header
, 4);
2887 sendfile_read
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
,
2888 &header_blob
, startpos
,
2890 if (sendfile_read
== -1) {
2891 /* Returning ENOSYS means no data at all was sent.
2892 * Do this as a normal read. */
2893 if (errno
== ENOSYS
) {
2894 goto normal_readbraw
;
2898 * Special hack for broken Linux with no working sendfile. If we
2899 * return EINTR we sent the header but not the rest of the data.
2900 * Fake this up by doing read/write calls.
2902 if (errno
== EINTR
) {
2903 /* Ensure we don't do this again. */
2904 set_use_sendfile(SNUM(conn
), False
);
2905 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2907 if (fake_sendfile(xconn
, fsp
, startpos
, nread
) == -1) {
2908 DEBUG(0,("send_file_readbraw: "
2909 "fake_sendfile failed for "
2913 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2918 DEBUG(0,("send_file_readbraw: sendfile failed for "
2919 "file %s (%s). Terminating\n",
2920 fsp_str_dbg(fsp
), strerror(errno
)));
2921 exit_server_cleanly("send_file_readbraw sendfile failed");
2922 } else if (sendfile_read
== 0) {
2924 * Some sendfile implementations return 0 to indicate
2925 * that there was a short read, but nothing was
2926 * actually written to the socket. In this case,
2927 * fallback to the normal read path so the header gets
2928 * the correct byte count.
2930 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2931 "bytes falling back to the normal read: "
2932 "%s\n", fsp_str_dbg(fsp
)));
2933 goto normal_readbraw
;
2936 /* Deal with possible short send. */
2937 if (sendfile_read
!= 4+nread
) {
2938 ret
= sendfile_short_send(xconn
, fsp
,
2939 sendfile_read
, 4, nread
);
2949 outbuf
= talloc_array(NULL
, char, nread
+4);
2951 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2952 (unsigned)(nread
+4)));
2953 reply_readbraw_error(xconn
);
2958 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2959 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2968 _smb_setlen(outbuf
,ret
);
2969 if (write_data(xconn
->transport
.sock
, outbuf
, 4+ret
) != 4+ret
) {
2970 int saved_errno
= errno
;
2972 * Try and give an error message saying what
2975 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2976 smbXsrv_connection_dbg(xconn
),
2977 strerror(saved_errno
)));
2978 errno
= saved_errno
;
2983 TALLOC_FREE(outbuf
);
2986 /****************************************************************************
2987 Reply to a readbraw (core+ protocol).
2988 ****************************************************************************/
2990 void reply_readbraw(struct smb_request
*req
)
2992 connection_struct
*conn
= req
->conn
;
2993 struct smbXsrv_connection
*xconn
= req
->xconn
;
2994 ssize_t maxcount
,mincount
;
2998 struct lock_struct lock
;
3002 START_PROFILE(SMBreadbraw
);
3004 if (smb1_srv_is_signing_active(xconn
) || req
->encrypted
) {
3005 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3006 "raw reads/writes are disallowed.");
3010 reply_readbraw_error(xconn
);
3011 END_PROFILE(SMBreadbraw
);
3015 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3016 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3017 "'async smb echo handler = yes'\n"));
3018 reply_readbraw_error(xconn
);
3019 END_PROFILE(SMBreadbraw
);
3024 * Special check if an oplock break has been issued
3025 * and the readraw request croses on the wire, we must
3026 * return a zero length response here.
3029 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3032 * We have to do a check_fsp by hand here, as
3033 * we must always return 4 zero bytes on error,
3039 conn
!= fsp
->conn
||
3040 req
->vuid
!= fsp
->vuid
||
3041 fsp
->fsp_flags
.is_directory
||
3042 fsp_get_io_fd(fsp
) == -1)
3045 * fsp could be NULL here so use the value from the packet. JRA.
3047 DEBUG(3,("reply_readbraw: fnum %d not valid "
3049 (int)SVAL(req
->vwv
+0, 0)));
3050 reply_readbraw_error(xconn
);
3051 END_PROFILE(SMBreadbraw
);
3055 /* Do a "by hand" version of CHECK_READ. */
3056 if (!(fsp
->fsp_flags
.can_read
||
3057 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3058 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3059 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3060 (int)SVAL(req
->vwv
+0, 0)));
3061 reply_readbraw_error(xconn
);
3062 END_PROFILE(SMBreadbraw
);
3066 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3067 if(req
->wct
== 10) {
3069 * This is a large offset (64 bit) read.
3072 startpos
|= (((off_t
)IVAL(req
->vwv
+8, 0)) << 32);
3075 DEBUG(0,("reply_readbraw: negative 64 bit "
3076 "readraw offset (%.0f) !\n",
3077 (double)startpos
));
3078 reply_readbraw_error(xconn
);
3079 END_PROFILE(SMBreadbraw
);
3084 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3085 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3087 /* ensure we don't overrun the packet size */
3088 maxcount
= MIN(65535,maxcount
);
3090 init_strict_lock_struct(fsp
,
3091 (uint64_t)req
->smbpid
,
3095 lp_posix_cifsu_locktype(fsp
),
3098 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3099 reply_readbraw_error(xconn
);
3100 END_PROFILE(SMBreadbraw
);
3104 status
= vfs_stat_fsp(fsp
);
3105 if (NT_STATUS_IS_OK(status
)) {
3106 size
= fsp
->fsp_name
->st
.st_ex_size
;
3109 if (startpos
>= size
) {
3112 nread
= MIN(maxcount
,(size
- startpos
));
3115 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3116 if (nread
< mincount
)
3120 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3121 "min=%lu nread=%lu\n",
3122 fsp_fnum_dbg(fsp
), (double)startpos
,
3123 (unsigned long)maxcount
,
3124 (unsigned long)mincount
,
3125 (unsigned long)nread
) );
3127 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3129 DEBUG(5,("reply_readbraw finished\n"));
3131 END_PROFILE(SMBreadbraw
);
3136 #define DBGC_CLASS DBGC_LOCKING
3138 /****************************************************************************
3139 Reply to a lockread (core+ protocol).
3140 ****************************************************************************/
3142 static void reply_lockread_locked(struct tevent_req
*subreq
);
3144 void reply_lockread(struct smb_request
*req
)
3146 struct tevent_req
*subreq
= NULL
;
3147 connection_struct
*conn
= req
->conn
;
3149 struct smbd_lock_element
*lck
= NULL
;
3151 START_PROFILE(SMBlockread
);
3154 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3155 END_PROFILE(SMBlockread
);
3159 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3161 if (!check_fsp(conn
, req
, fsp
)) {
3162 END_PROFILE(SMBlockread
);
3166 if (!CHECK_READ(fsp
,req
)) {
3167 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3168 END_PROFILE(SMBlockread
);
3172 lck
= talloc(req
, struct smbd_lock_element
);
3174 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3175 END_PROFILE(SMBlockread
);
3180 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3181 * protocol request that predates the read/write lock concept.
3182 * Thus instead of asking for a read lock here we need to ask
3183 * for a write lock. JRA.
3184 * Note that the requested lock size is unaffected by max_send.
3187 *lck
= (struct smbd_lock_element
) {
3188 .req_guid
= smbd_request_guid(req
, 0),
3189 .smblctx
= req
->smbpid
,
3190 .brltype
= WRITE_LOCK
,
3191 .lock_flav
= WINDOWS_LOCK
,
3192 .count
= SVAL(req
->vwv
+1, 0),
3193 .offset
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0),
3196 subreq
= smbd_smb1_do_locks_send(
3202 false, /* large_offset */
3205 if (subreq
== NULL
) {
3206 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
3207 END_PROFILE(SMBlockread
);
3210 tevent_req_set_callback(subreq
, reply_lockread_locked
, NULL
);
3211 END_PROFILE(SMBlockread
);
3214 static void reply_lockread_locked(struct tevent_req
*subreq
)
3216 struct smb_request
*req
= NULL
;
3222 size_t numtoread
, maxtoread
;
3223 struct files_struct
*fsp
= NULL
;
3226 START_PROFILE(SMBlockread
);
3228 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
3231 status
= smbd_smb1_do_locks_recv(subreq
);
3232 TALLOC_FREE(subreq
);
3234 if (!NT_STATUS_IS_OK(status
)) {
3235 reply_nterror(req
, status
);
3239 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3241 reply_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
3245 numtoread
= SVAL(req
->vwv
+1, 0);
3246 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3249 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3251 maxtoread
= req
->xconn
->smb1
.sessions
.max_send
- (MIN_SMB_SIZE
+ 5*2 + 3);
3253 if (numtoread
> maxtoread
) {
3254 DBG_WARNING("requested read size (%zu) is greater than "
3255 "maximum allowed (%zu/%d). "
3256 "Returning short read of maximum allowed for "
3257 "compatibility with Windows 2000.\n",
3260 req
->xconn
->smb1
.sessions
.max_send
);
3261 numtoread
= maxtoread
;
3264 reply_smb1_outbuf(req
, 5, numtoread
+ 3);
3266 data
= smb_buf(req
->outbuf
) + 3;
3268 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3271 reply_nterror(req
, map_nt_error_from_unix(errno
));
3275 srv_smb1_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3277 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3278 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3279 p
= smb_buf(req
->outbuf
);
3280 SCVAL(p
,0,0); /* pad byte. */
3283 DEBUG(3,("lockread %s num=%d nread=%d\n",
3284 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3287 ok
= smb1_srv_send(req
->xconn
,
3288 (char *)req
->outbuf
,
3291 IS_CONN_ENCRYPTED(req
->conn
));
3293 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
3296 END_PROFILE(SMBlockread
);
3301 #define DBGC_CLASS DBGC_ALL
3303 /****************************************************************************
3305 ****************************************************************************/
3307 void reply_read(struct smb_request
*req
)
3309 connection_struct
*conn
= req
->conn
;
3316 struct lock_struct lock
;
3317 struct smbXsrv_connection
*xconn
= req
->xconn
;
3319 START_PROFILE(SMBread
);
3322 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3323 END_PROFILE(SMBread
);
3327 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3329 if (!check_fsp(conn
, req
, fsp
)) {
3330 END_PROFILE(SMBread
);
3334 if (!CHECK_READ(fsp
,req
)) {
3335 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3336 END_PROFILE(SMBread
);
3340 numtoread
= SVAL(req
->vwv
+1, 0);
3341 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3344 * The requested read size cannot be greater than max_send. JRA.
3346 maxtoread
= xconn
->smb1
.sessions
.max_send
- (MIN_SMB_SIZE
+ 5*2 + 3);
3348 if (numtoread
> maxtoread
) {
3349 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3350 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3351 (unsigned int)numtoread
, (unsigned int)maxtoread
,
3352 (unsigned int)xconn
->smb1
.sessions
.max_send
));
3353 numtoread
= maxtoread
;
3356 reply_smb1_outbuf(req
, 5, numtoread
+3);
3358 data
= smb_buf(req
->outbuf
) + 3;
3360 init_strict_lock_struct(fsp
,
3361 (uint64_t)req
->smbpid
,
3363 (uint64_t)numtoread
,
3365 lp_posix_cifsu_locktype(fsp
),
3368 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3369 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3370 END_PROFILE(SMBread
);
3375 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3378 reply_nterror(req
, map_nt_error_from_unix(errno
));
3382 srv_smb1_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3384 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3385 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3386 SCVAL(smb_buf(req
->outbuf
),0,1);
3387 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3389 DEBUG(3, ("read %s num=%d nread=%d\n",
3390 fsp_fnum_dbg(fsp
), (int)numtoread
, (int)nread
));
3393 END_PROFILE(SMBread
);
3397 /****************************************************************************
3399 ****************************************************************************/
3401 size_t setup_readX_header(char *outbuf
, size_t smb_maxcnt
)
3405 outsize
= srv_smb1_set_message(outbuf
,12,smb_maxcnt
+ 1 /* padding byte */,
3408 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3410 SCVAL(outbuf
,smb_vwv0
,0xFF);
3411 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3412 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3413 SSVAL(outbuf
,smb_vwv6
,
3414 (smb_wct
- 4) /* offset from smb header to wct */
3415 + 1 /* the wct field */
3416 + 12 * sizeof(uint16_t) /* vwv */
3417 + 2 /* the buflen field */
3418 + 1); /* padding byte */
3419 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3420 SCVAL(smb_buf(outbuf
), 0, 0); /* padding byte */
3421 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3422 _smb_setlen_large(outbuf
,
3423 smb_size
+ 12*2 + smb_maxcnt
- 4 + 1 /* pad */);
3427 /****************************************************************************
3428 Reply to a read and X - possibly using sendfile.
3429 ****************************************************************************/
3431 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3432 files_struct
*fsp
, off_t startpos
,
3435 struct smbXsrv_connection
*xconn
= req
->xconn
;
3437 struct lock_struct lock
;
3438 int saved_errno
= 0;
3441 init_strict_lock_struct(fsp
,
3442 (uint64_t)req
->smbpid
,
3444 (uint64_t)smb_maxcnt
,
3446 lp_posix_cifsu_locktype(fsp
),
3449 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3450 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3455 * We can only use sendfile on a non-chained packet
3456 * but we can use on a non-oplocked file. tridge proved this
3457 * on a train in Germany :-). JRA.
3460 if (!req_is_in_chain(req
) &&
3462 !fsp_is_alternate_stream(fsp
) &&
3463 lp_use_sendfile(xconn
, SNUM(conn
), xconn
->smb1
.signing_state
) ) {
3464 uint8_t headerbuf
[smb_size
+ 12 * 2 + 1 /* padding byte */];
3467 status
= vfs_stat_fsp(fsp
);
3468 if (!NT_STATUS_IS_OK(status
)) {
3469 reply_nterror(req
, status
);
3473 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3474 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3475 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3477 * We already know that we would do a short read, so don't
3478 * try the sendfile() path.
3480 goto nosendfile_read
;
3484 * Set up the packet header before send. We
3485 * assume here the sendfile will work (get the
3486 * correct amount of data).
3489 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3491 construct_smb1_reply_common_req(req
, (char *)headerbuf
);
3492 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3494 nread
= SMB_VFS_SENDFILE(xconn
->transport
.sock
, fsp
, &header
,
3495 startpos
, smb_maxcnt
);
3497 saved_errno
= errno
;
3499 /* Returning ENOSYS means no data at all was sent.
3500 Do this as a normal read. */
3501 if (errno
== ENOSYS
) {
3506 * Special hack for broken Linux with no working sendfile. If we
3507 * return EINTR we sent the header but not the rest of the data.
3508 * Fake this up by doing read/write calls.
3511 if (errno
== EINTR
) {
3512 /* Ensure we don't do this again. */
3513 set_use_sendfile(SNUM(conn
), False
);
3514 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3515 nread
= fake_sendfile(xconn
, fsp
, startpos
,
3518 saved_errno
= errno
;
3519 DEBUG(0,("send_file_readX: "
3520 "fake_sendfile failed for "
3521 "file %s (%s) for client %s. "
3524 smbXsrv_connection_dbg(xconn
),
3525 strerror(saved_errno
)));
3526 errno
= saved_errno
;
3527 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3529 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3530 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3531 /* No outbuf here means successful sendfile. */
3535 DEBUG(0,("send_file_readX: sendfile failed for file "
3536 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3538 exit_server_cleanly("send_file_readX sendfile failed");
3539 } else if (nread
== 0) {
3541 * Some sendfile implementations return 0 to indicate
3542 * that there was a short read, but nothing was
3543 * actually written to the socket. In this case,
3544 * fallback to the normal read path so the header gets
3545 * the correct byte count.
3547 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3548 "falling back to the normal read: %s\n",
3553 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3554 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3556 /* Deal with possible short send. */
3557 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3560 ret
= sendfile_short_send(xconn
, fsp
, nread
,
3561 sizeof(headerbuf
), smb_maxcnt
);
3564 r
= "send_file_readX: sendfile_short_send failed";
3565 DEBUG(0,("%s for file %s (%s).\n",
3566 r
, fsp_str_dbg(fsp
), strerror(errno
)));
3567 exit_server_cleanly(r
);
3570 /* No outbuf here means successful sendfile. */
3576 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3577 uint8_t headerbuf
[smb_size
+ 2*12 + 1 /* padding byte */];
3580 if (!S_ISREG(fsp
->fsp_name
->st
.st_ex_mode
) ||
3581 (startpos
> fsp
->fsp_name
->st
.st_ex_size
) ||
3582 (smb_maxcnt
> (fsp
->fsp_name
->st
.st_ex_size
- startpos
))) {
3584 * We already know that we would do a short
3585 * read, so don't try the sendfile() path.
3587 goto nosendfile_read
;
3590 construct_smb1_reply_common_req(req
, (char *)headerbuf
);
3591 setup_readX_header((char *)headerbuf
, smb_maxcnt
);
3593 /* Send out the header. */
3594 ret
= write_data(xconn
->transport
.sock
, (char *)headerbuf
,
3596 if (ret
!= sizeof(headerbuf
)) {
3597 saved_errno
= errno
;
3599 * Try and give an error message saying what
3602 DEBUG(0,("send_file_readX: write_data failed for file "
3603 "%s (%s) for client %s. Terminating\n",
3605 smbXsrv_connection_dbg(xconn
),
3606 strerror(saved_errno
)));
3607 errno
= saved_errno
;
3608 exit_server_cleanly("send_file_readX sendfile failed");
3610 nread
= fake_sendfile(xconn
, fsp
, startpos
, smb_maxcnt
);
3612 saved_errno
= errno
;
3613 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3614 "%s (%s) for client %s. Terminating\n",
3616 smbXsrv_connection_dbg(xconn
),
3617 strerror(saved_errno
)));
3618 errno
= saved_errno
;
3619 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3626 reply_smb1_outbuf(req
, 12, smb_maxcnt
+ 1 /* padding byte */);
3627 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
3628 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
3630 nread
= read_file(fsp
, smb_buf(req
->outbuf
) + 1 /* padding byte */,
3631 startpos
, smb_maxcnt
);
3632 saved_errno
= errno
;
3635 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3639 setup_readX_header((char *)req
->outbuf
, nread
);
3641 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3642 fsp_fnum_dbg(fsp
), (int)smb_maxcnt
, (int)nread
));
3646 TALLOC_FREE(req
->outbuf
);
3650 /****************************************************************************
3651 Work out how much space we have for a read return.
3652 ****************************************************************************/
3654 static size_t calc_max_read_pdu(const struct smb_request
*req
)
3656 struct smbXsrv_connection
*xconn
= req
->xconn
;
3658 if (xconn
->protocol
< PROTOCOL_NT1
) {
3659 return xconn
->smb1
.sessions
.max_send
;
3662 if (!lp_large_readwrite()) {
3663 return xconn
->smb1
.sessions
.max_send
;
3666 if (req_is_in_chain(req
)) {
3667 return xconn
->smb1
.sessions
.max_send
;
3670 if (req
->encrypted
) {
3672 * Don't take encrypted traffic up to the
3673 * limit. There are padding considerations
3674 * that make that tricky.
3676 return xconn
->smb1
.sessions
.max_send
;
3679 if (smb1_srv_is_signing_active(xconn
)) {
3683 if (!lp_smb1_unix_extensions()) {
3688 * We can do ultra-large POSIX reads.
3693 /****************************************************************************
3694 Calculate how big a read can be. Copes with all clients. It's always
3695 safe to return a short read - Windows does this.
3696 ****************************************************************************/
3698 static size_t calc_read_size(const struct smb_request
*req
,
3702 struct smbXsrv_connection
*xconn
= req
->xconn
;
3703 size_t max_pdu
= calc_max_read_pdu(req
);
3704 size_t total_size
= 0;
3705 size_t hdr_len
= MIN_SMB_SIZE
+ VWV(12);
3706 size_t max_len
= max_pdu
- hdr_len
- 1 /* padding byte */;
3709 * Windows explicitly ignores upper size of 0xFFFF.
3710 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3711 * We must do the same as these will never fit even in
3712 * an extended size NetBIOS packet.
3714 if (upper_size
== 0xFFFF) {
3718 if (xconn
->protocol
< PROTOCOL_NT1
) {
3722 total_size
= ((upper_size
<<16) | lower_size
);
3725 * LARGE_READX test shows it's always safe to return
3726 * a short read. Windows does so.
3728 return MIN(total_size
, max_len
);
3731 /****************************************************************************
3732 Reply to a read and X.
3733 ****************************************************************************/
3735 void reply_read_and_X(struct smb_request
*req
)
3737 connection_struct
*conn
= req
->conn
;
3742 bool big_readX
= False
;
3744 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3747 START_PROFILE(SMBreadX
);
3749 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3750 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3754 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3755 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3756 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3758 /* If it's an IPC, pass off the pipe handler. */
3760 reply_pipe_read_and_X(req
);
3761 END_PROFILE(SMBreadX
);
3765 if (!check_fsp(conn
, req
, fsp
)) {
3766 END_PROFILE(SMBreadX
);
3770 if (!CHECK_READ(fsp
,req
)) {
3771 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
3772 END_PROFILE(SMBreadX
);
3776 upper_size
= SVAL(req
->vwv
+7, 0);
3777 smb_maxcnt
= calc_read_size(req
, upper_size
, smb_maxcnt
);
3778 if (smb_maxcnt
> (0x1FFFF - (MIN_SMB_SIZE
+ VWV(12)))) {
3780 * This is a heuristic to avoid keeping large
3781 * outgoing buffers around over long-lived aio
3787 if (req
->wct
== 12) {
3789 * This is a large offset (64 bit) read.
3791 startpos
|= (((off_t
)IVAL(req
->vwv
+10, 0)) << 32);
3796 NTSTATUS status
= schedule_aio_read_and_X(conn
,
3801 if (NT_STATUS_IS_OK(status
)) {
3802 /* Read scheduled - we're done. */
3805 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
3806 /* Real error - report to client. */
3807 END_PROFILE(SMBreadX
);
3808 reply_nterror(req
, status
);
3811 /* NT_STATUS_RETRY - fall back to sync read. */
3814 smbd_lock_socket(req
->xconn
);
3815 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3816 smbd_unlock_socket(req
->xconn
);
3819 END_PROFILE(SMBreadX
);
3823 /****************************************************************************
3824 Error replies to writebraw must have smb_wct == 1. Fix this up.
3825 ****************************************************************************/
3827 void error_to_writebrawerr(struct smb_request
*req
)
3829 uint8_t *old_outbuf
= req
->outbuf
;
3831 reply_smb1_outbuf(req
, 1, 0);
3833 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3834 TALLOC_FREE(old_outbuf
);
3837 /****************************************************************************
3838 Read 4 bytes of a smb packet and return the smb length of the packet.
3839 Store the result in the buffer. This version of the function will
3840 never return a session keepalive (length of zero).
3841 Timeout is in milliseconds.
3842 ****************************************************************************/
3844 static NTSTATUS
read_smb_length(int fd
, char *inbuf
, unsigned int timeout
,
3847 uint8_t msgtype
= NBSSkeepalive
;
3849 while (msgtype
== NBSSkeepalive
) {
3852 status
= read_smb_length_return_keepalive(fd
, inbuf
, timeout
,
3854 if (!NT_STATUS_IS_OK(status
)) {
3855 char addr
[INET6_ADDRSTRLEN
];
3856 /* Try and give an error message
3857 * saying what client failed. */
3858 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3859 "client %s read error = %s.\n",
3860 get_peer_addr(fd
,addr
,sizeof(addr
)),
3861 nt_errstr(status
)));
3865 msgtype
= CVAL(inbuf
, 0);
3868 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3869 (unsigned long)len
));
3871 return NT_STATUS_OK
;
3874 /****************************************************************************
3875 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3876 ****************************************************************************/
3878 void reply_writebraw(struct smb_request
*req
)
3880 connection_struct
*conn
= req
->conn
;
3881 struct smbXsrv_connection
*xconn
= req
->xconn
;
3884 ssize_t total_written
=0;
3885 size_t numtowrite
=0;
3888 const char *data
=NULL
;
3891 struct lock_struct lock
;
3894 START_PROFILE(SMBwritebraw
);
3897 * If we ever reply with an error, it must have the SMB command
3898 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3901 SCVAL(discard_const_p(uint8_t, req
->inbuf
),smb_com
,SMBwritec
);
3903 if (smb1_srv_is_signing_active(xconn
)) {
3904 END_PROFILE(SMBwritebraw
);
3905 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3906 "raw reads/writes are disallowed.");
3909 if (req
->wct
< 12) {
3910 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3911 error_to_writebrawerr(req
);
3912 END_PROFILE(SMBwritebraw
);
3916 if (xconn
->smb1
.echo_handler
.trusted_fde
) {
3917 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3918 "'async smb echo handler = yes'\n"));
3919 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3920 error_to_writebrawerr(req
);
3921 END_PROFILE(SMBwritebraw
);
3925 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3926 if (!check_fsp(conn
, req
, fsp
)) {
3927 error_to_writebrawerr(req
);
3928 END_PROFILE(SMBwritebraw
);
3932 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
3933 if (!NT_STATUS_IS_OK(status
)) {
3934 reply_nterror(req
, status
);
3935 error_to_writebrawerr(req
);
3936 END_PROFILE(SMBwritebraw
);
3940 tcount
= IVAL(req
->vwv
+1, 0);
3941 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3942 write_through
= BITSETW(req
->vwv
+7,0);
3944 /* We have to deal with slightly different formats depending
3945 on whether we are using the core+ or lanman1.0 protocol */
3947 if(xconn
->protocol
<= PROTOCOL_COREPLUS
) {
3948 numtowrite
= SVAL(smb_buf_const(req
->inbuf
),-2);
3949 data
= smb_buf_const(req
->inbuf
);
3951 numtowrite
= SVAL(req
->vwv
+10, 0);
3952 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3955 /* Ensure we don't write bytes past the end of this packet. */
3957 * This already protects us against CVE-2017-12163.
3959 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3960 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3961 error_to_writebrawerr(req
);
3962 END_PROFILE(SMBwritebraw
);
3966 if (!fsp
->print_file
) {
3967 init_strict_lock_struct(fsp
,
3968 (uint64_t)req
->smbpid
,
3972 lp_posix_cifsu_locktype(fsp
),
3975 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
3976 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
3977 error_to_writebrawerr(req
);
3978 END_PROFILE(SMBwritebraw
);
3984 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3987 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3988 "wrote=%d sync=%d\n",
3989 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
3990 (int)nwritten
, (int)write_through
));
3992 if (nwritten
< (ssize_t
)numtowrite
) {
3993 reply_nterror(req
, NT_STATUS_DISK_FULL
);
3994 error_to_writebrawerr(req
);
3998 total_written
= nwritten
;
4000 /* Allocate a buffer of 64k + length. */
4001 buf
= talloc_array(NULL
, char, 65540);
4003 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4004 error_to_writebrawerr(req
);
4008 /* Return a SMBwritebraw message to the redirector to tell
4009 * it to send more bytes */
4011 memcpy(buf
, req
->inbuf
, smb_size
);
4012 srv_smb1_set_message(buf
,xconn
->protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
4013 SCVAL(buf
,smb_com
,SMBwritebraw
);
4014 SSVALS(buf
,smb_vwv0
,0xFFFF);
4016 if (!smb1_srv_send(req
->xconn
,
4020 IS_CONN_ENCRYPTED(conn
))) {
4021 exit_server_cleanly("reply_writebraw: smb1_srv_send "
4025 /* Now read the raw data into the buffer and write it */
4026 status
= read_smb_length(xconn
->transport
.sock
, buf
, SMB_SECONDARY_WAIT
,
4028 if (!NT_STATUS_IS_OK(status
)) {
4029 exit_server_cleanly("secondary writebraw failed");
4032 /* Set up outbuf to return the correct size */
4033 reply_smb1_outbuf(req
, 1, 0);
4035 if (numtowrite
!= 0) {
4037 if (numtowrite
> 0xFFFF) {
4038 DEBUG(0,("reply_writebraw: Oversize secondary write "
4039 "raw requested (%u). Terminating\n",
4040 (unsigned int)numtowrite
));
4041 exit_server_cleanly("secondary writebraw failed");
4044 if (tcount
> nwritten
+numtowrite
) {
4045 DEBUG(3,("reply_writebraw: Client overestimated the "
4047 (int)tcount
,(int)nwritten
,(int)numtowrite
));
4050 status
= read_data_ntstatus(xconn
->transport
.sock
, buf
+4,
4053 if (!NT_STATUS_IS_OK(status
)) {
4054 /* Try and give an error message
4055 * saying what client failed. */
4056 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4057 "raw read failed (%s) for client %s. "
4058 "Terminating\n", nt_errstr(status
),
4059 smbXsrv_connection_dbg(xconn
)));
4060 exit_server_cleanly("secondary writebraw failed");
4064 * We are not vulnerable to CVE-2017-12163
4065 * here as we are guaranteed to have numtowrite
4066 * bytes available - we just read from the client.
4068 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
4069 if (nwritten
== -1) {
4071 reply_nterror(req
, map_nt_error_from_unix(errno
));
4072 error_to_writebrawerr(req
);
4076 if (nwritten
< (ssize_t
)numtowrite
) {
4077 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4078 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4082 total_written
+= nwritten
;
4087 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
4089 status
= sync_file(conn
, fsp
, write_through
);
4090 if (!NT_STATUS_IS_OK(status
)) {
4091 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4092 fsp_str_dbg(fsp
), nt_errstr(status
)));
4093 reply_nterror(req
, status
);
4094 error_to_writebrawerr(req
);
4098 DEBUG(3,("reply_writebraw: secondary write %s start=%.0f num=%d "
4100 fsp_fnum_dbg(fsp
), (double)startpos
, (int)numtowrite
,
4101 (int)total_written
));
4103 /* We won't return a status if write through is not selected - this
4104 * follows what WfWg does */
4105 END_PROFILE(SMBwritebraw
);
4107 if (!write_through
&& total_written
==tcount
) {
4109 #if RABBIT_PELLET_FIX
4111 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4112 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4115 if (!send_keepalive(xconn
->transport
.sock
)) {
4116 exit_server_cleanly("reply_writebraw: send of "
4117 "keepalive failed");
4120 TALLOC_FREE(req
->outbuf
);
4125 END_PROFILE(SMBwritebraw
);
4130 #define DBGC_CLASS DBGC_LOCKING
4132 /****************************************************************************
4133 Reply to a writeunlock (core+).
4134 ****************************************************************************/
4136 void reply_writeunlock(struct smb_request
*req
)
4138 connection_struct
*conn
= req
->conn
;
4139 ssize_t nwritten
= -1;
4144 NTSTATUS status
= NT_STATUS_OK
;
4146 struct lock_struct lock
;
4147 int saved_errno
= 0;
4149 START_PROFILE(SMBwriteunlock
);
4152 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4153 END_PROFILE(SMBwriteunlock
);
4157 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4159 if (!check_fsp(conn
, req
, fsp
)) {
4160 END_PROFILE(SMBwriteunlock
);
4164 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
4165 if (!NT_STATUS_IS_OK(status
)) {
4166 reply_nterror(req
, status
);
4167 END_PROFILE(SMBwriteunlock
);
4171 numtowrite
= SVAL(req
->vwv
+1, 0);
4172 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4173 data
= (const char *)req
->buf
+ 3;
4176 * Ensure client isn't asking us to write more than
4177 * they sent. CVE-2017-12163.
4179 remaining
= smbreq_bufrem(req
, data
);
4180 if (numtowrite
> remaining
) {
4181 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4182 END_PROFILE(SMBwriteunlock
);
4186 if (!fsp
->print_file
&& numtowrite
> 0) {
4187 init_strict_lock_struct(fsp
,
4188 (uint64_t)req
->smbpid
,
4190 (uint64_t)numtowrite
,
4192 lp_posix_cifsu_locktype(fsp
),
4195 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4196 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4197 END_PROFILE(SMBwriteunlock
);
4202 /* The special X/Open SMB protocol handling of
4203 zero length writes is *NOT* done for
4205 if(numtowrite
== 0) {
4208 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4209 saved_errno
= errno
;
4212 status
= sync_file(conn
, fsp
, False
/* write through */);
4213 if (!NT_STATUS_IS_OK(status
)) {
4214 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4215 fsp_str_dbg(fsp
), nt_errstr(status
)));
4216 reply_nterror(req
, status
);
4221 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4225 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4226 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4230 if (numtowrite
&& !fsp
->print_file
) {
4231 struct smbd_lock_element l
= {
4232 .req_guid
= smbd_request_guid(req
, 0),
4233 .smblctx
= req
->smbpid
,
4234 .brltype
= UNLOCK_LOCK
,
4235 .lock_flav
= WINDOWS_LOCK
,
4237 .count
= numtowrite
,
4239 status
= smbd_do_unlocking(req
, fsp
, 1, &l
);
4240 if (NT_STATUS_V(status
)) {
4241 reply_nterror(req
, status
);
4246 reply_smb1_outbuf(req
, 1, 0);
4248 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4250 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4251 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4254 END_PROFILE(SMBwriteunlock
);
4259 #define DBGC_CLASS DBGC_ALL
4261 /****************************************************************************
4263 ****************************************************************************/
4265 void reply_write(struct smb_request
*req
)
4267 connection_struct
*conn
= req
->conn
;
4270 ssize_t nwritten
= -1;
4274 struct lock_struct lock
;
4276 int saved_errno
= 0;
4278 START_PROFILE(SMBwrite
);
4281 END_PROFILE(SMBwrite
);
4282 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4286 /* If it's an IPC, pass off the pipe handler. */
4288 reply_pipe_write(req
);
4289 END_PROFILE(SMBwrite
);
4293 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4295 if (!check_fsp(conn
, req
, fsp
)) {
4296 END_PROFILE(SMBwrite
);
4300 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
4301 if (!NT_STATUS_IS_OK(status
)) {
4302 reply_nterror(req
, status
);
4303 END_PROFILE(SMBwrite
);
4307 numtowrite
= SVAL(req
->vwv
+1, 0);
4308 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4309 data
= (const char *)req
->buf
+ 3;
4312 * Ensure client isn't asking us to write more than
4313 * they sent. CVE-2017-12163.
4315 remaining
= smbreq_bufrem(req
, data
);
4316 if (numtowrite
> remaining
) {
4317 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4318 END_PROFILE(SMBwrite
);
4322 if (!fsp
->print_file
) {
4323 init_strict_lock_struct(fsp
,
4324 (uint64_t)req
->smbpid
,
4326 (uint64_t)numtowrite
,
4328 lp_posix_cifsu_locktype(fsp
),
4331 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4332 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4333 END_PROFILE(SMBwrite
);
4339 * X/Open SMB protocol says that if smb_vwv1 is
4340 * zero then the file size should be extended or
4341 * truncated to the size given in smb_vwv[2-3].
4344 if(numtowrite
== 0) {
4346 * This is actually an allocate call, and set EOF. JRA.
4348 nwritten
= vfs_allocate_file_space(fsp
, (off_t
)startpos
);
4350 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4353 nwritten
= vfs_set_filelen(fsp
, (off_t
)startpos
);
4355 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4358 trigger_write_time_update_immediate(fsp
);
4360 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4363 status
= sync_file(conn
, fsp
, False
);
4364 if (!NT_STATUS_IS_OK(status
)) {
4365 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4366 fsp_str_dbg(fsp
), nt_errstr(status
)));
4367 reply_nterror(req
, status
);
4372 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4376 if((nwritten
== 0) && (numtowrite
!= 0)) {
4377 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4381 reply_smb1_outbuf(req
, 1, 0);
4383 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4385 if (nwritten
< (ssize_t
)numtowrite
) {
4386 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4387 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4390 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4393 END_PROFILE(SMBwrite
);
4397 /****************************************************************************
4398 Ensure a buffer is a valid writeX for recvfile purposes.
4399 ****************************************************************************/
4401 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4402 (2*14) + /* word count (including bcc) */ \
4405 bool is_valid_writeX_buffer(struct smbXsrv_connection
*xconn
,
4406 const uint8_t *inbuf
)
4409 unsigned int doff
= 0;
4410 size_t len
= smb_len_large(inbuf
);
4412 struct smbXsrv_open
*op
= NULL
;
4413 struct files_struct
*fsp
= NULL
;
4416 if (is_encrypted_packet(inbuf
)) {
4417 /* Can't do this on encrypted
4422 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4426 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4427 CVAL(inbuf
,smb_wct
) != 14) {
4428 DEBUG(10,("is_valid_writeX_buffer: chained or "
4429 "invalid word length.\n"));
4433 fnum
= SVAL(inbuf
, smb_vwv2
);
4434 status
= smb1srv_open_lookup(xconn
,
4438 if (!NT_STATUS_IS_OK(status
)) {
4439 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4444 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4447 if (fsp
->conn
== NULL
) {
4448 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4452 if (IS_IPC(fsp
->conn
)) {
4453 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4456 if (IS_PRINT(fsp
->conn
)) {
4457 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4460 if (fsp_is_alternate_stream(fsp
)) {
4461 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4464 doff
= SVAL(inbuf
,smb_vwv11
);
4466 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4468 if (len
> doff
&& len
- doff
> 0xFFFF) {
4469 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4472 if (numtowrite
== 0) {
4473 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4477 /* Ensure the sizes match up. */
4478 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4479 /* no pad byte...old smbclient :-( */
4480 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4482 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4486 if (len
- doff
!= numtowrite
) {
4487 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4488 "len = %u, doff = %u, numtowrite = %u\n",
4491 (unsigned int)numtowrite
));
4495 DEBUG(10,("is_valid_writeX_buffer: true "
4496 "len = %u, doff = %u, numtowrite = %u\n",
4499 (unsigned int)numtowrite
));
4504 /****************************************************************************
4505 Reply to a write and X.
4506 ****************************************************************************/
4508 void reply_write_and_X(struct smb_request
*req
)
4510 connection_struct
*conn
= req
->conn
;
4511 struct smbXsrv_connection
*xconn
= req
->xconn
;
4513 struct lock_struct lock
;
4518 unsigned int smb_doff
;
4519 unsigned int smblen
;
4522 int saved_errno
= 0;
4524 START_PROFILE(SMBwriteX
);
4526 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4527 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4531 numtowrite
= SVAL(req
->vwv
+10, 0);
4532 smb_doff
= SVAL(req
->vwv
+11, 0);
4533 smblen
= smb_len(req
->inbuf
);
4535 if (req
->unread_bytes
> 0xFFFF ||
4536 (smblen
> smb_doff
&&
4537 smblen
- smb_doff
> 0xFFFF)) {
4538 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4541 if (req
->unread_bytes
) {
4542 /* Can't do a recvfile write on IPC$ */
4544 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4547 if (numtowrite
!= req
->unread_bytes
) {
4548 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4553 * This already protects us against CVE-2017-12163.
4555 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4556 smb_doff
+ numtowrite
> smblen
) {
4557 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4562 /* If it's an IPC, pass off the pipe handler. */
4564 if (req
->unread_bytes
) {
4565 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4568 reply_pipe_write_and_X(req
);
4572 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4573 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4574 write_through
= BITSETW(req
->vwv
+7,0);
4576 if (!check_fsp(conn
, req
, fsp
)) {
4580 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
4581 if (!NT_STATUS_IS_OK(status
)) {
4582 reply_nterror(req
, status
);
4586 data
= smb_base(req
->inbuf
) + smb_doff
;
4588 if(req
->wct
== 14) {
4590 * This is a large offset (64 bit) write.
4592 startpos
|= (((off_t
)IVAL(req
->vwv
+12, 0)) << 32);
4596 /* X/Open SMB protocol says that, unlike SMBwrite
4597 if the length is zero then NO truncation is
4598 done, just a write of zero. To truncate a file,
4601 if(numtowrite
== 0) {
4604 if (req
->unread_bytes
== 0) {
4605 status
= schedule_aio_write_and_X(conn
,
4612 if (NT_STATUS_IS_OK(status
)) {
4613 /* write scheduled - we're done. */
4616 if (!NT_STATUS_EQUAL(status
, NT_STATUS_RETRY
)) {
4617 /* Real error - report to client. */
4618 reply_nterror(req
, status
);
4621 /* NT_STATUS_RETRY - fall through to sync write. */
4624 init_strict_lock_struct(fsp
,
4625 (uint64_t)req
->smbpid
,
4627 (uint64_t)numtowrite
,
4629 lp_posix_cifsu_locktype(fsp
),
4632 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
4633 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
4637 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4638 saved_errno
= errno
;
4642 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4646 if((nwritten
== 0) && (numtowrite
!= 0)) {
4647 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4651 reply_smb1_outbuf(req
, 6, 0);
4652 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
4653 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
4654 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4655 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4657 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4658 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
));
4660 status
= sync_file(conn
, fsp
, write_through
);
4661 if (!NT_STATUS_IS_OK(status
)) {
4662 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4663 fsp_str_dbg(fsp
), nt_errstr(status
)));
4664 reply_nterror(req
, status
);
4668 END_PROFILE(SMBwriteX
);
4672 if (req
->unread_bytes
) {
4673 /* writeX failed. drain socket. */
4674 if (drain_socket(xconn
->transport
.sock
, req
->unread_bytes
) !=
4675 req
->unread_bytes
) {
4676 smb_panic("failed to drain pending bytes");
4678 req
->unread_bytes
= 0;
4681 END_PROFILE(SMBwriteX
);
4685 /****************************************************************************
4687 ****************************************************************************/
4689 void reply_lseek(struct smb_request
*req
)
4691 connection_struct
*conn
= req
->conn
;
4698 START_PROFILE(SMBlseek
);
4701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4702 END_PROFILE(SMBlseek
);
4706 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4708 if (!check_fsp(conn
, req
, fsp
)) {
4712 mode
= SVAL(req
->vwv
+1, 0) & 3;
4713 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4714 startpos
= (off_t
)IVALS(req
->vwv
+2, 0);
4723 res
= fh_get_pos(fsp
->fh
) + startpos
;
4734 if (umode
== SEEK_END
) {
4735 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4736 if(errno
== EINVAL
) {
4737 off_t current_pos
= startpos
;
4739 status
= vfs_stat_fsp(fsp
);
4740 if (!NT_STATUS_IS_OK(status
)) {
4741 reply_nterror(req
, status
);
4742 END_PROFILE(SMBlseek
);
4746 current_pos
+= fsp
->fsp_name
->st
.st_ex_size
;
4748 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4753 reply_nterror(req
, map_nt_error_from_unix(errno
));
4754 END_PROFILE(SMBlseek
);
4759 fh_set_pos(fsp
->fh
, res
);
4761 reply_smb1_outbuf(req
, 2, 0);
4762 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4764 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4765 fsp_fnum_dbg(fsp
), (double)startpos
, (double)res
, mode
));
4767 END_PROFILE(SMBlseek
);
4771 static struct files_struct
*file_sync_one_fn(struct files_struct
*fsp
,
4774 connection_struct
*conn
= talloc_get_type_abort(
4775 private_data
, connection_struct
);
4777 if (conn
!= fsp
->conn
) {
4780 if (fsp_get_io_fd(fsp
) == -1) {
4783 sync_file(conn
, fsp
, True
/* write through */);
4785 if (fsp
->fsp_flags
.modified
) {
4786 trigger_write_time_update_immediate(fsp
);
4792 /****************************************************************************
4794 ****************************************************************************/
4796 void reply_flush(struct smb_request
*req
)
4798 connection_struct
*conn
= req
->conn
;
4802 START_PROFILE(SMBflush
);
4805 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4809 fnum
= SVAL(req
->vwv
+0, 0);
4810 fsp
= file_fsp(req
, fnum
);
4812 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4817 files_forall(req
->sconn
, file_sync_one_fn
, conn
);
4819 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4820 if (!NT_STATUS_IS_OK(status
)) {
4821 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4822 fsp_str_dbg(fsp
), nt_errstr(status
)));
4823 reply_nterror(req
, status
);
4824 END_PROFILE(SMBflush
);
4827 if (fsp
->fsp_flags
.modified
) {
4828 trigger_write_time_update_immediate(fsp
);
4832 reply_smb1_outbuf(req
, 0, 0);
4834 DEBUG(3,("flush\n"));
4835 END_PROFILE(SMBflush
);
4839 /****************************************************************************
4841 conn POINTER CAN BE NULL HERE !
4842 ****************************************************************************/
4844 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
);
4845 static void reply_exit_done(struct tevent_req
*req
);
4847 void reply_exit(struct smb_request
*smb1req
)
4849 struct tevent_req
*req
;
4852 * Don't setup the profile charge here, take
4853 * it in reply_exit_done(). Not strictly correct
4854 * but better than the other SMB1 async
4855 * code that double-charges at the moment.
4857 req
= reply_exit_send(smb1req
);
4859 /* Not going async, profile here. */
4860 START_PROFILE(SMBexit
);
4861 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
4862 END_PROFILE(SMBexit
);
4866 /* We're async. This will complete later. */
4867 tevent_req_set_callback(req
, reply_exit_done
, smb1req
);
4871 struct reply_exit_state
{
4872 struct tevent_queue
*wait_queue
;
4875 static void reply_exit_wait_done(struct tevent_req
*subreq
);
4877 /****************************************************************************
4879 Note, on failure here we deallocate and return NULL to allow the caller to
4880 SMB1 return an error of ERRnomem immediately.
4881 ****************************************************************************/
4883 static struct tevent_req
*reply_exit_send(struct smb_request
*smb1req
)
4885 struct tevent_req
*req
;
4886 struct reply_exit_state
*state
;
4887 struct tevent_req
*subreq
;
4889 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4891 req
= tevent_req_create(smb1req
, &state
,
4892 struct reply_exit_state
);
4896 state
->wait_queue
= tevent_queue_create(state
,
4897 "reply_exit_wait_queue");
4898 if (tevent_req_nomem(state
->wait_queue
, req
)) {
4903 for (fsp
= sconn
->files
; fsp
; fsp
= fsp
->next
) {
4904 if (fsp
->file_pid
!= smb1req
->smbpid
) {
4907 if (fsp
->vuid
!= smb1req
->vuid
) {
4911 * Flag the file as close in progress.
4912 * This will prevent any more IO being
4915 fsp
->fsp_flags
.closing
= true;
4917 if (fsp
->num_aio_requests
> 0) {
4919 * Now wait until all aio requests on this fsp are
4922 * We don't set a callback, as we just want to block the
4923 * wait queue and the talloc_free() of fsp->aio_request
4924 * will remove the item from the wait queue.
4926 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
4929 if (tevent_req_nomem(subreq
, req
)) {
4937 * Now we add our own waiter to the end of the queue,
4938 * this way we get notified when all pending requests are finished
4939 * and reply to the outstanding SMB1 request.
4941 subreq
= tevent_queue_wait_send(state
,
4944 if (tevent_req_nomem(subreq
, req
)) {
4950 * We're really going async - move the SMB1 request from
4951 * a talloc stackframe above us to the conn talloc-context.
4952 * We need this to stick around until the wait_done
4953 * callback is invoked.
4955 smb1req
= talloc_move(sconn
, &smb1req
);
4957 tevent_req_set_callback(subreq
, reply_exit_wait_done
, req
);
4962 static void reply_exit_wait_done(struct tevent_req
*subreq
)
4964 struct tevent_req
*req
= tevent_req_callback_data(
4965 subreq
, struct tevent_req
);
4967 tevent_queue_wait_recv(subreq
);
4968 TALLOC_FREE(subreq
);
4969 tevent_req_done(req
);
4972 static NTSTATUS
reply_exit_recv(struct tevent_req
*req
)
4974 return tevent_req_simple_recv_ntstatus(req
);
4977 static void reply_exit_done(struct tevent_req
*req
)
4979 struct smb_request
*smb1req
= tevent_req_callback_data(
4980 req
, struct smb_request
);
4981 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
4982 struct smbXsrv_connection
*xconn
= smb1req
->xconn
;
4983 NTTIME now
= timeval_to_nttime(&smb1req
->request_time
);
4984 struct smbXsrv_session
*session
= NULL
;
4985 files_struct
*fsp
, *next
;
4989 * Take the profile charge here. Not strictly
4990 * correct but better than the other SMB1 async
4991 * code that double-charges at the moment.
4993 START_PROFILE(SMBexit
);
4995 status
= reply_exit_recv(req
);
4997 if (!NT_STATUS_IS_OK(status
)) {
4998 TALLOC_FREE(smb1req
);
4999 END_PROFILE(SMBexit
);
5000 exit_server(__location__
": reply_exit_recv failed");
5005 * Ensure the session is still valid.
5007 status
= smb1srv_session_lookup(xconn
,
5011 if (!NT_STATUS_IS_OK(status
)) {
5012 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5013 smb_request_done(smb1req
);
5014 END_PROFILE(SMBexit
);
5019 * Ensure the vuid is still valid - no one
5020 * called reply_ulogoffX() in the meantime.
5021 * reply_exit() doesn't have AS_USER set, so
5022 * use set_current_user_info() directly.
5023 * This is the same logic as in switch_message().
5025 if (session
->global
->auth_session_info
!= NULL
) {
5026 set_current_user_info(
5027 session
->global
->auth_session_info
->unix_info
->sanitized_username
,
5028 session
->global
->auth_session_info
->unix_info
->unix_name
,
5029 session
->global
->auth_session_info
->info
->domain_name
);
5032 /* No more aio - do the actual closes. */
5033 for (fsp
= sconn
->files
; fsp
; fsp
= next
) {
5037 if (fsp
->file_pid
!= smb1req
->smbpid
) {
5040 if (fsp
->vuid
!= smb1req
->vuid
) {
5043 if (!fsp
->fsp_flags
.closing
) {
5048 * reply_exit() has the DO_CHDIR flag set.
5050 ok
= chdir_current_service(fsp
->conn
);
5052 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5053 smb_request_done(smb1req
);
5054 END_PROFILE(SMBexit
);
5057 close_file_free(NULL
, &fsp
, SHUTDOWN_CLOSE
);
5060 reply_smb1_outbuf(smb1req
, 0, 0);
5062 * The following call is needed to push the
5063 * reply data back out the socket after async
5064 * return. Plus it frees smb1req.
5066 smb_request_done(smb1req
);
5067 DBG_INFO("reply_exit complete\n");
5068 END_PROFILE(SMBexit
);
5072 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
5074 static void reply_close_done(struct tevent_req
*req
);
5076 void reply_close(struct smb_request
*smb1req
)
5078 connection_struct
*conn
= smb1req
->conn
;
5079 NTSTATUS status
= NT_STATUS_OK
;
5080 files_struct
*fsp
= NULL
;
5081 START_PROFILE(SMBclose
);
5083 if (smb1req
->wct
< 3) {
5084 reply_nterror(smb1req
, NT_STATUS_INVALID_PARAMETER
);
5085 END_PROFILE(SMBclose
);
5089 fsp
= file_fsp(smb1req
, SVAL(smb1req
->vwv
+0, 0));
5092 * We can only use check_fsp if we know it's not a directory.
5095 if (!check_fsp_open(conn
, smb1req
, fsp
)) {
5096 END_PROFILE(SMBclose
);
5100 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5101 fsp
->fsp_flags
.is_directory
?
5102 "directory" : "file",
5103 fsp_get_pathref_fd(fsp
), fsp_fnum_dbg(fsp
),
5104 conn
->num_files_open
);
5106 if (!fsp
->fsp_flags
.is_directory
) {
5110 * Take care of any time sent in the close.
5113 t
= srv_make_unix_date3(smb1req
->vwv
+1);
5114 set_close_write_time(fsp
, time_t_to_full_timespec(t
));
5117 if (fsp
->num_aio_requests
!= 0) {
5118 struct tevent_req
*req
;
5120 req
= reply_close_send(smb1req
, fsp
);
5122 status
= NT_STATUS_NO_MEMORY
;
5125 /* We're async. This will complete later. */
5126 tevent_req_set_callback(req
, reply_close_done
, smb1req
);
5127 END_PROFILE(SMBclose
);
5132 * close_file_free() returns the unix errno if an error was detected on
5133 * close - normally this is due to a disk full error. If not then it
5134 * was probably an I/O error.
5137 status
= close_file_free(smb1req
, &fsp
, NORMAL_CLOSE
);
5139 if (!NT_STATUS_IS_OK(status
)) {
5140 reply_nterror(smb1req
, status
);
5141 END_PROFILE(SMBclose
);
5145 reply_smb1_outbuf(smb1req
, 0, 0);
5146 END_PROFILE(SMBclose
);
5150 struct reply_close_state
{
5152 struct tevent_queue
*wait_queue
;
5155 static void reply_close_wait_done(struct tevent_req
*subreq
);
5157 /****************************************************************************
5159 Note, on failure here we deallocate and return NULL to allow the caller to
5160 SMB1 return an error of ERRnomem immediately.
5161 ****************************************************************************/
5163 static struct tevent_req
*reply_close_send(struct smb_request
*smb1req
,
5166 struct tevent_req
*req
;
5167 struct reply_close_state
*state
;
5168 struct tevent_req
*subreq
;
5169 struct smbd_server_connection
*sconn
= smb1req
->sconn
;
5171 req
= tevent_req_create(smb1req
, &state
,
5172 struct reply_close_state
);
5176 state
->wait_queue
= tevent_queue_create(state
,
5177 "reply_close_wait_queue");
5178 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5184 * Flag the file as close in progress.
5185 * This will prevent any more IO being
5188 fsp
->fsp_flags
.closing
= true;
5191 * Now wait until all aio requests on this fsp are
5194 * We don't set a callback, as we just want to block the
5195 * wait queue and the talloc_free() of fsp->aio_request
5196 * will remove the item from the wait queue.
5198 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5201 if (tevent_req_nomem(subreq
, req
)) {
5207 * Now we add our own waiter to the end of the queue,
5208 * this way we get notified when all pending requests are finished
5209 * and reply to the outstanding SMB1 request.
5211 subreq
= tevent_queue_wait_send(state
,
5214 if (tevent_req_nomem(subreq
, req
)) {
5220 * We're really going async - move the SMB1 request from
5221 * a talloc stackframe above us to the conn talloc-context.
5222 * We need this to stick around until the wait_done
5223 * callback is invoked.
5225 smb1req
= talloc_move(sconn
, &smb1req
);
5227 tevent_req_set_callback(subreq
, reply_close_wait_done
, req
);
5232 static void reply_close_wait_done(struct tevent_req
*subreq
)
5234 struct tevent_req
*req
= tevent_req_callback_data(
5235 subreq
, struct tevent_req
);
5237 tevent_queue_wait_recv(subreq
);
5238 TALLOC_FREE(subreq
);
5239 tevent_req_done(req
);
5242 static NTSTATUS
reply_close_recv(struct tevent_req
*req
)
5244 return tevent_req_simple_recv_ntstatus(req
);
5247 static void reply_close_done(struct tevent_req
*req
)
5249 struct smb_request
*smb1req
= tevent_req_callback_data(
5250 req
, struct smb_request
);
5251 struct reply_close_state
*state
= tevent_req_data(req
,
5252 struct reply_close_state
);
5255 status
= reply_close_recv(req
);
5257 if (!NT_STATUS_IS_OK(status
)) {
5258 TALLOC_FREE(smb1req
);
5259 exit_server(__location__
": reply_close_recv failed");
5263 status
= close_file_free(smb1req
, &state
->fsp
, NORMAL_CLOSE
);
5264 if (NT_STATUS_IS_OK(status
)) {
5265 reply_smb1_outbuf(smb1req
, 0, 0);
5267 reply_nterror(smb1req
, status
);
5270 * The following call is needed to push the
5271 * reply data back out the socket after async
5272 * return. Plus it frees smb1req.
5274 smb_request_done(smb1req
);
5277 /****************************************************************************
5278 Reply to a writeclose (Core+ protocol).
5279 ****************************************************************************/
5281 void reply_writeclose(struct smb_request
*req
)
5283 connection_struct
*conn
= req
->conn
;
5286 ssize_t nwritten
= -1;
5287 NTSTATUS close_status
= NT_STATUS_OK
;
5290 struct timespec mtime
;
5292 struct lock_struct lock
;
5295 START_PROFILE(SMBwriteclose
);
5298 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5299 END_PROFILE(SMBwriteclose
);
5303 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5305 if (!check_fsp(conn
, req
, fsp
)) {
5306 END_PROFILE(SMBwriteclose
);
5309 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
5310 if (!NT_STATUS_IS_OK(status
)) {
5311 reply_nterror(req
, status
);
5312 END_PROFILE(SMBwriteclose
);
5316 numtowrite
= SVAL(req
->vwv
+1, 0);
5317 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
5318 mtime
= time_t_to_full_timespec(srv_make_unix_date3(req
->vwv
+4));
5319 data
= (const char *)req
->buf
+ 1;
5322 * Ensure client isn't asking us to write more than
5323 * they sent. CVE-2017-12163.
5325 remaining
= smbreq_bufrem(req
, data
);
5326 if (numtowrite
> remaining
) {
5327 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5328 END_PROFILE(SMBwriteclose
);
5332 if (fsp
->print_file
== NULL
) {
5333 init_strict_lock_struct(fsp
,
5334 (uint64_t)req
->smbpid
,
5336 (uint64_t)numtowrite
,
5338 lp_posix_cifsu_locktype(fsp
),
5341 if (!SMB_VFS_STRICT_LOCK_CHECK(conn
, fsp
, &lock
)) {
5342 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
5343 END_PROFILE(SMBwriteclose
);
5348 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
5350 set_close_write_time(fsp
, mtime
);
5353 * More insanity. W2K only closes the file if writelen > 0.
5357 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5358 fsp_fnum_dbg(fsp
), (int)numtowrite
, (int)nwritten
,
5359 (numtowrite
) ? conn
->num_files_open
- 1 : conn
->num_files_open
));
5362 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5363 "file %s\n", fsp_str_dbg(fsp
)));
5364 close_status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5367 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
5368 reply_nterror(req
, NT_STATUS_DISK_FULL
);
5372 if(!NT_STATUS_IS_OK(close_status
)) {
5373 reply_nterror(req
, close_status
);
5377 reply_smb1_outbuf(req
, 1, 0);
5379 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
5383 END_PROFILE(SMBwriteclose
);
5388 #define DBGC_CLASS DBGC_LOCKING
5390 /****************************************************************************
5392 ****************************************************************************/
5394 static void reply_lock_done(struct tevent_req
*subreq
);
5396 void reply_lock(struct smb_request
*req
)
5398 struct tevent_req
*subreq
= NULL
;
5399 connection_struct
*conn
= req
->conn
;
5401 struct smbd_lock_element
*lck
= NULL
;
5403 START_PROFILE(SMBlock
);
5406 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5407 END_PROFILE(SMBlock
);
5411 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5413 if (!check_fsp(conn
, req
, fsp
)) {
5414 END_PROFILE(SMBlock
);
5418 lck
= talloc(req
, struct smbd_lock_element
);
5420 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5421 END_PROFILE(SMBlock
);
5425 *lck
= (struct smbd_lock_element
) {
5426 .req_guid
= smbd_request_guid(req
, 0),
5427 .smblctx
= req
->smbpid
,
5428 .brltype
= WRITE_LOCK
,
5429 .lock_flav
= WINDOWS_LOCK
,
5430 .count
= IVAL(req
->vwv
+1, 0),
5431 .offset
= IVAL(req
->vwv
+3, 0),
5434 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5440 subreq
= smbd_smb1_do_locks_send(
5446 false, /* large_offset */
5449 if (subreq
== NULL
) {
5450 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5451 END_PROFILE(SMBlock
);
5454 tevent_req_set_callback(subreq
, reply_lock_done
, NULL
);
5455 END_PROFILE(SMBlock
);
5458 static void reply_lock_done(struct tevent_req
*subreq
)
5460 struct smb_request
*req
= NULL
;
5464 START_PROFILE(SMBlock
);
5466 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
5469 status
= smbd_smb1_do_locks_recv(subreq
);
5470 TALLOC_FREE(subreq
);
5472 if (NT_STATUS_IS_OK(status
)) {
5473 reply_smb1_outbuf(req
, 0, 0);
5475 reply_nterror(req
, status
);
5478 ok
= smb1_srv_send(req
->xconn
,
5479 (char *)req
->outbuf
,
5482 IS_CONN_ENCRYPTED(req
->conn
));
5484 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5487 END_PROFILE(SMBlock
);
5490 /****************************************************************************
5492 ****************************************************************************/
5494 void reply_unlock(struct smb_request
*req
)
5496 connection_struct
*conn
= req
->conn
;
5499 struct smbd_lock_element lck
;
5501 START_PROFILE(SMBunlock
);
5504 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5505 END_PROFILE(SMBunlock
);
5509 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5511 if (!check_fsp(conn
, req
, fsp
)) {
5512 END_PROFILE(SMBunlock
);
5516 lck
= (struct smbd_lock_element
) {
5517 .req_guid
= smbd_request_guid(req
, 0),
5518 .smblctx
= req
->smbpid
,
5519 .brltype
= UNLOCK_LOCK
,
5520 .lock_flav
= WINDOWS_LOCK
,
5521 .offset
= IVAL(req
->vwv
+3, 0),
5522 .count
= IVAL(req
->vwv
+1, 0),
5525 status
= smbd_do_unlocking(req
, fsp
, 1, &lck
);
5527 if (!NT_STATUS_IS_OK(status
)) {
5528 reply_nterror(req
, status
);
5529 END_PROFILE(SMBunlock
);
5533 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64
" count=%"PRIu64
"\n",
5539 reply_smb1_outbuf(req
, 0, 0);
5541 END_PROFILE(SMBunlock
);
5546 #define DBGC_CLASS DBGC_ALL
5548 /****************************************************************************
5550 conn POINTER CAN BE NULL HERE !
5551 ****************************************************************************/
5553 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
);
5554 static void reply_tdis_done(struct tevent_req
*req
);
5556 void reply_tdis(struct smb_request
*smb1req
)
5558 connection_struct
*conn
= smb1req
->conn
;
5559 struct tevent_req
*req
;
5562 * Don't setup the profile charge here, take
5563 * it in reply_tdis_done(). Not strictly correct
5564 * but better than the other SMB1 async
5565 * code that double-charges at the moment.
5569 /* Not going async, profile here. */
5570 START_PROFILE(SMBtdis
);
5571 DBG_INFO("Invalid connection in tdis\n");
5572 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5573 END_PROFILE(SMBtdis
);
5577 req
= reply_tdis_send(smb1req
);
5579 /* Not going async, profile here. */
5580 START_PROFILE(SMBtdis
);
5581 reply_force_doserror(smb1req
, ERRDOS
, ERRnomem
);
5582 END_PROFILE(SMBtdis
);
5585 /* We're async. This will complete later. */
5586 tevent_req_set_callback(req
, reply_tdis_done
, smb1req
);
5590 struct reply_tdis_state
{
5591 struct tevent_queue
*wait_queue
;
5594 static void reply_tdis_wait_done(struct tevent_req
*subreq
);
5596 /****************************************************************************
5598 Note, on failure here we deallocate and return NULL to allow the caller to
5599 SMB1 return an error of ERRnomem immediately.
5600 ****************************************************************************/
5602 static struct tevent_req
*reply_tdis_send(struct smb_request
*smb1req
)
5604 struct tevent_req
*req
;
5605 struct reply_tdis_state
*state
;
5606 struct tevent_req
*subreq
;
5607 connection_struct
*conn
= smb1req
->conn
;
5610 req
= tevent_req_create(smb1req
, &state
,
5611 struct reply_tdis_state
);
5615 state
->wait_queue
= tevent_queue_create(state
, "reply_tdis_wait_queue");
5616 if (tevent_req_nomem(state
->wait_queue
, req
)) {
5622 * Make sure that no new request will be able to use this tcon.
5623 * This ensures that once all outstanding fsp->aio_requests
5624 * on this tcon are done, we are safe to close it.
5626 conn
->tcon
->status
= NT_STATUS_NETWORK_NAME_DELETED
;
5628 for (fsp
= conn
->sconn
->files
; fsp
; fsp
= fsp
->next
) {
5629 if (fsp
->conn
!= conn
) {
5633 * Flag the file as close in progress.
5634 * This will prevent any more IO being
5635 * done on it. Not strictly needed, but
5636 * doesn't hurt to flag it as closing.
5638 fsp
->fsp_flags
.closing
= true;
5640 if (fsp
->num_aio_requests
> 0) {
5642 * Now wait until all aio requests on this fsp are
5645 * We don't set a callback, as we just want to block the
5646 * wait queue and the talloc_free() of fsp->aio_request
5647 * will remove the item from the wait queue.
5649 subreq
= tevent_queue_wait_send(fsp
->aio_requests
,
5650 conn
->sconn
->ev_ctx
,
5652 if (tevent_req_nomem(subreq
, req
)) {
5660 * Now we add our own waiter to the end of the queue,
5661 * this way we get notified when all pending requests are finished
5662 * and reply to the outstanding SMB1 request.
5664 subreq
= tevent_queue_wait_send(state
,
5665 conn
->sconn
->ev_ctx
,
5667 if (tevent_req_nomem(subreq
, req
)) {
5673 * We're really going async - move the SMB1 request from
5674 * a talloc stackframe above us to the sconn talloc-context.
5675 * We need this to stick around until the wait_done
5676 * callback is invoked.
5678 smb1req
= talloc_move(smb1req
->sconn
, &smb1req
);
5680 tevent_req_set_callback(subreq
, reply_tdis_wait_done
, req
);
5685 static void reply_tdis_wait_done(struct tevent_req
*subreq
)
5687 struct tevent_req
*req
= tevent_req_callback_data(
5688 subreq
, struct tevent_req
);
5690 tevent_queue_wait_recv(subreq
);
5691 TALLOC_FREE(subreq
);
5692 tevent_req_done(req
);
5695 static NTSTATUS
reply_tdis_recv(struct tevent_req
*req
)
5697 return tevent_req_simple_recv_ntstatus(req
);
5700 static void reply_tdis_done(struct tevent_req
*req
)
5702 struct smb_request
*smb1req
= tevent_req_callback_data(
5703 req
, struct smb_request
);
5705 struct smbXsrv_tcon
*tcon
= smb1req
->conn
->tcon
;
5709 * Take the profile charge here. Not strictly
5710 * correct but better than the other SMB1 async
5711 * code that double-charges at the moment.
5713 START_PROFILE(SMBtdis
);
5715 status
= reply_tdis_recv(req
);
5717 if (!NT_STATUS_IS_OK(status
)) {
5718 TALLOC_FREE(smb1req
);
5719 END_PROFILE(SMBtdis
);
5720 exit_server(__location__
": reply_tdis_recv failed");
5725 * As we've been awoken, we may have changed
5726 * directory in the meantime.
5727 * reply_tdis() has the DO_CHDIR flag set.
5729 ok
= chdir_current_service(smb1req
->conn
);
5731 reply_force_doserror(smb1req
, ERRSRV
, ERRinvnid
);
5732 smb_request_done(smb1req
);
5733 END_PROFILE(SMBtdis
);
5736 status
= smbXsrv_tcon_disconnect(tcon
,
5738 if (!NT_STATUS_IS_OK(status
)) {
5739 TALLOC_FREE(smb1req
);
5740 END_PROFILE(SMBtdis
);
5741 exit_server(__location__
": smbXsrv_tcon_disconnect failed");
5745 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5746 smb1req
->conn
= NULL
;
5750 reply_smb1_outbuf(smb1req
, 0, 0);
5752 * The following call is needed to push the
5753 * reply data back out the socket after async
5754 * return. Plus it frees smb1req.
5756 smb_request_done(smb1req
);
5757 END_PROFILE(SMBtdis
);
5760 /****************************************************************************
5762 conn POINTER CAN BE NULL HERE !
5763 ****************************************************************************/
5765 void reply_echo(struct smb_request
*req
)
5767 connection_struct
*conn
= req
->conn
;
5771 START_PROFILE(SMBecho
);
5774 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5775 END_PROFILE(SMBecho
);
5779 smb_reverb
= SVAL(req
->vwv
+0, 0);
5781 reply_smb1_outbuf(req
, 1, req
->buflen
);
5783 /* copy any incoming data back out */
5784 if (req
->buflen
> 0) {
5785 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
5788 if (smb_reverb
> 100) {
5789 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
5793 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
5795 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
5797 show_msg((char *)req
->outbuf
);
5798 if (!smb1_srv_send(req
->xconn
,
5799 (char *)req
->outbuf
,
5802 IS_CONN_ENCRYPTED(conn
) || req
->encrypted
))
5803 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5806 DEBUG(3,("echo %d times\n", smb_reverb
));
5808 TALLOC_FREE(req
->outbuf
);
5810 END_PROFILE(SMBecho
);
5814 /****************************************************************************
5815 Reply to a printopen.
5816 ****************************************************************************/
5818 void reply_printopen(struct smb_request
*req
)
5820 connection_struct
*conn
= req
->conn
;
5824 START_PROFILE(SMBsplopen
);
5827 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5828 END_PROFILE(SMBsplopen
);
5832 if (!CAN_PRINT(conn
)) {
5833 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5834 END_PROFILE(SMBsplopen
);
5838 status
= file_new(req
, conn
, &fsp
);
5839 if(!NT_STATUS_IS_OK(status
)) {
5840 reply_nterror(req
, status
);
5841 END_PROFILE(SMBsplopen
);
5845 /* Open for exclusive use, write only. */
5846 status
= print_spool_open(fsp
, NULL
, req
->vuid
);
5848 if (!NT_STATUS_IS_OK(status
)) {
5849 file_free(req
, fsp
);
5850 reply_nterror(req
, status
);
5851 END_PROFILE(SMBsplopen
);
5855 reply_smb1_outbuf(req
, 1, 0);
5856 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5858 DEBUG(3,("openprint fd=%d %s\n",
5859 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
5861 END_PROFILE(SMBsplopen
);
5865 /****************************************************************************
5866 Reply to a printclose.
5867 ****************************************************************************/
5869 void reply_printclose(struct smb_request
*req
)
5871 connection_struct
*conn
= req
->conn
;
5875 START_PROFILE(SMBsplclose
);
5878 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5879 END_PROFILE(SMBsplclose
);
5883 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5885 if (!check_fsp(conn
, req
, fsp
)) {
5886 END_PROFILE(SMBsplclose
);
5890 if (!CAN_PRINT(conn
)) {
5891 reply_force_doserror(req
, ERRSRV
, ERRerror
);
5892 END_PROFILE(SMBsplclose
);
5896 DEBUG(3,("printclose fd=%d %s\n",
5897 fsp_get_io_fd(fsp
), fsp_fnum_dbg(fsp
)));
5899 status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
5901 if(!NT_STATUS_IS_OK(status
)) {
5902 reply_nterror(req
, status
);
5903 END_PROFILE(SMBsplclose
);
5907 reply_smb1_outbuf(req
, 0, 0);
5909 END_PROFILE(SMBsplclose
);
5913 /****************************************************************************
5914 Reply to a printqueue.
5915 ****************************************************************************/
5917 void reply_printqueue(struct smb_request
*req
)
5919 const struct loadparm_substitution
*lp_sub
=
5920 loadparm_s3_global_substitution();
5921 connection_struct
*conn
= req
->conn
;
5925 START_PROFILE(SMBsplretq
);
5928 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5929 END_PROFILE(SMBsplretq
);
5933 max_count
= SVAL(req
->vwv
+0, 0);
5934 start_index
= SVAL(req
->vwv
+1, 0);
5936 /* we used to allow the client to get the cnum wrong, but that
5937 is really quite gross and only worked when there was only
5938 one printer - I think we should now only accept it if they
5939 get it right (tridge) */
5940 if (!CAN_PRINT(conn
)) {
5941 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
5942 END_PROFILE(SMBsplretq
);
5946 reply_smb1_outbuf(req
, 2, 3);
5947 SSVAL(req
->outbuf
,smb_vwv0
,0);
5948 SSVAL(req
->outbuf
,smb_vwv1
,0);
5949 SCVAL(smb_buf(req
->outbuf
),0,1);
5950 SSVAL(smb_buf(req
->outbuf
),1,0);
5952 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5953 start_index
, max_count
));
5956 TALLOC_CTX
*mem_ctx
= talloc_tos();
5959 const char *sharename
= lp_servicename(mem_ctx
, lp_sub
, SNUM(conn
));
5960 struct rpc_pipe_client
*cli
= NULL
;
5961 struct dcerpc_binding_handle
*b
= NULL
;
5962 struct policy_handle handle
;
5963 struct spoolss_DevmodeContainer devmode_ctr
;
5964 union spoolss_JobInfo
*info
;
5966 uint32_t num_to_get
;
5970 ZERO_STRUCT(handle
);
5972 status
= rpc_pipe_open_interface(mem_ctx
,
5975 conn
->sconn
->remote_address
,
5976 conn
->sconn
->local_address
,
5977 conn
->sconn
->msg_ctx
,
5979 if (!NT_STATUS_IS_OK(status
)) {
5980 DEBUG(0, ("reply_printqueue: "
5981 "could not connect to spoolss: %s\n",
5982 nt_errstr(status
)));
5983 reply_nterror(req
, status
);
5986 b
= cli
->binding_handle
;
5988 ZERO_STRUCT(devmode_ctr
);
5990 status
= dcerpc_spoolss_OpenPrinter(b
, mem_ctx
,
5993 SEC_FLAG_MAXIMUM_ALLOWED
,
5996 if (!NT_STATUS_IS_OK(status
)) {
5997 reply_nterror(req
, status
);
6000 if (!W_ERROR_IS_OK(werr
)) {
6001 reply_nterror(req
, werror_to_ntstatus(werr
));
6005 werr
= rpccli_spoolss_enumjobs(cli
, mem_ctx
,
6013 if (!W_ERROR_IS_OK(werr
)) {
6014 reply_nterror(req
, werror_to_ntstatus(werr
));
6018 if (max_count
> 0) {
6019 first
= start_index
;
6021 first
= start_index
+ max_count
+ 1;
6024 if (first
>= count
) {
6027 num_to_get
= first
+ MIN(ABS(max_count
), count
- first
);
6030 for (i
= first
; i
< num_to_get
; i
++) {
6033 struct timespec qtime
= {
6034 .tv_sec
= spoolss_Time_to_time_t(
6035 &info
[i
].info2
.submitted
),
6039 uint16_t qrapjobid
= pjobid_to_rap(sharename
,
6040 info
[i
].info2
.job_id
);
6042 if (info
[i
].info2
.status
== JOB_STATUS_PRINTING
) {
6048 srv_put_dos_date2_ts(p
, 0, qtime
);
6049 SCVAL(p
, 4, qstatus
);
6050 SSVAL(p
, 5, qrapjobid
);
6051 SIVAL(p
, 7, info
[i
].info2
.size
);
6053 status
= srvstr_push(blob
, req
->flags2
, p
+12,
6054 info
[i
].info2
.notify_name
, 16, STR_ASCII
, &len
);
6055 if (!NT_STATUS_IS_OK(status
)) {
6056 reply_nterror(req
, status
);
6059 if (message_push_blob(
6062 blob
, sizeof(blob
))) == -1) {
6063 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6069 SSVAL(req
->outbuf
,smb_vwv0
,count
);
6070 SSVAL(req
->outbuf
,smb_vwv1
,
6071 (max_count
>0?first
+count
:first
-1));
6072 SCVAL(smb_buf(req
->outbuf
),0,1);
6073 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
6077 DEBUG(3, ("%u entries returned in queue\n",
6081 if (b
&& is_valid_policy_hnd(&handle
)) {
6082 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &handle
, &werr
);
6087 END_PROFILE(SMBsplretq
);
6091 /****************************************************************************
6092 Reply to a printwrite.
6093 ****************************************************************************/
6095 void reply_printwrite(struct smb_request
*req
)
6097 connection_struct
*conn
= req
->conn
;
6103 START_PROFILE(SMBsplwr
);
6106 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6107 END_PROFILE(SMBsplwr
);
6111 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6113 if (!check_fsp(conn
, req
, fsp
)) {
6114 END_PROFILE(SMBsplwr
);
6118 if (!fsp
->print_file
) {
6119 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6120 END_PROFILE(SMBsplwr
);
6124 status
= check_any_access_fsp(fsp
, FILE_WRITE_DATA
|FILE_APPEND_DATA
);
6125 if (!NT_STATUS_IS_OK(status
)) {
6126 reply_nterror(req
, status
);
6127 END_PROFILE(SMBsplwr
);
6131 numtowrite
= SVAL(req
->buf
, 1);
6134 * This already protects us against CVE-2017-12163.
6136 if (req
->buflen
< numtowrite
+ 3) {
6137 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6138 END_PROFILE(SMBsplwr
);
6142 data
= (const char *)req
->buf
+ 3;
6144 if (write_file(req
,fsp
,data
,(off_t
)-1,numtowrite
) != numtowrite
) {
6145 reply_nterror(req
, map_nt_error_from_unix(errno
));
6146 END_PROFILE(SMBsplwr
);
6150 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp
), numtowrite
));
6152 reply_smb1_outbuf(req
, 0, 0);
6154 END_PROFILE(SMBsplwr
);
6158 /****************************************************************************
6160 ****************************************************************************/
6162 void reply_mkdir(struct smb_request
*req
)
6164 connection_struct
*conn
= req
->conn
;
6165 struct files_struct
*dirfsp
= NULL
;
6166 struct smb_filename
*smb_dname
= NULL
;
6167 char *directory
= NULL
;
6171 TALLOC_CTX
*ctx
= talloc_tos();
6173 START_PROFILE(SMBmkdir
);
6175 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6176 STR_TERMINATE
, &status
);
6177 if (!NT_STATUS_IS_OK(status
)) {
6178 reply_nterror(req
, status
);
6182 ucf_flags
= filename_create_ucf_flags(req
, FILE_CREATE
);
6183 if (ucf_flags
& UCF_GMT_PATHNAME
) {
6184 extract_snapshot_token(directory
, &twrp
);
6186 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
6187 if (!NT_STATUS_IS_OK(status
)) {
6188 reply_nterror(req
, status
);
6192 status
= filename_convert_dirfsp(ctx
,
6199 if (!NT_STATUS_IS_OK(status
)) {
6200 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6201 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6202 ERRSRV
, ERRbadpath
);
6205 reply_nterror(req
, status
);
6209 status
= create_directory(conn
, req
, dirfsp
, smb_dname
);
6211 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
6213 if (!NT_STATUS_IS_OK(status
)) {
6215 if (!use_nt_status()
6216 && NT_STATUS_EQUAL(status
,
6217 NT_STATUS_OBJECT_NAME_COLLISION
)) {
6219 * Yes, in the DOS error code case we get a
6220 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6221 * samba4 torture test.
6223 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
6226 reply_nterror(req
, status
);
6230 reply_smb1_outbuf(req
, 0, 0);
6232 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
6234 TALLOC_FREE(smb_dname
);
6235 END_PROFILE(SMBmkdir
);
6239 /****************************************************************************
6241 ****************************************************************************/
6243 void reply_rmdir(struct smb_request
*req
)
6245 connection_struct
*conn
= req
->conn
;
6246 struct smb_filename
*smb_dname
= NULL
;
6247 char *directory
= NULL
;
6249 TALLOC_CTX
*ctx
= talloc_tos();
6250 struct files_struct
*dirfsp
= NULL
;
6251 files_struct
*fsp
= NULL
;
6254 uint32_t ucf_flags
= ucf_flags_from_smb_request(req
);
6256 START_PROFILE(SMBrmdir
);
6258 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
6259 STR_TERMINATE
, &status
);
6260 if (!NT_STATUS_IS_OK(status
)) {
6261 reply_nterror(req
, status
);
6265 if (ucf_flags
& UCF_GMT_PATHNAME
) {
6266 extract_snapshot_token(directory
, &twrp
);
6268 status
= smb1_strip_dfs_path(ctx
, &ucf_flags
, &directory
);
6269 if (!NT_STATUS_IS_OK(status
)) {
6270 reply_nterror(req
, status
);
6274 status
= filename_convert_dirfsp(ctx
,
6281 if (!NT_STATUS_IS_OK(status
)) {
6282 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6283 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6284 ERRSRV
, ERRbadpath
);
6287 reply_nterror(req
, status
);
6291 status
= SMB_VFS_CREATE_FILE(
6294 dirfsp
, /* dirfsp */
6295 smb_dname
, /* fname */
6296 DELETE_ACCESS
, /* access_mask */
6297 (FILE_SHARE_READ
| FILE_SHARE_WRITE
| /* share_access */
6299 FILE_OPEN
, /* create_disposition*/
6300 FILE_DIRECTORY_FILE
|
6301 FILE_OPEN_REPARSE_POINT
, /* create_options */
6302 FILE_ATTRIBUTE_DIRECTORY
, /* file_attributes */
6303 0, /* oplock_request */
6305 0, /* allocation_size */
6306 0, /* private_flags */
6311 NULL
, NULL
); /* create context */
6313 if (!NT_STATUS_IS_OK(status
)) {
6314 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6315 /* We have re-scheduled this call. */
6318 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6319 bool ok
= defer_smb1_sharing_violation(req
);
6324 reply_nterror(req
, status
);
6328 status
= can_set_delete_on_close(fsp
, FILE_ATTRIBUTE_DIRECTORY
);
6329 if (!NT_STATUS_IS_OK(status
)) {
6330 close_file_free(req
, &fsp
, ERROR_CLOSE
);
6331 reply_nterror(req
, status
);
6335 if (!set_delete_on_close(fsp
, true,
6336 conn
->session_info
->security_token
,
6337 conn
->session_info
->unix_token
)) {
6338 close_file_free(req
, &fsp
, ERROR_CLOSE
);
6339 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
6343 status
= close_file_free(req
, &fsp
, NORMAL_CLOSE
);
6344 if (!NT_STATUS_IS_OK(status
)) {
6345 reply_nterror(req
, status
);
6347 reply_smb1_outbuf(req
, 0, 0);
6350 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
6352 TALLOC_FREE(smb_dname
);
6353 END_PROFILE(SMBrmdir
);
6357 /****************************************************************************
6359 ****************************************************************************/
6361 void reply_mv(struct smb_request
*req
)
6363 connection_struct
*conn
= req
->conn
;
6365 char *newname
= NULL
;
6369 TALLOC_CTX
*ctx
= talloc_tos();
6370 struct files_struct
*src_dirfsp
= NULL
;
6371 struct smb_filename
*smb_fname_src
= NULL
;
6372 struct files_struct
*dst_dirfsp
= NULL
;
6373 struct smb_filename
*smb_fname_dst
= NULL
;
6374 const char *dst_original_lcomp
= NULL
;
6375 uint32_t src_ucf_flags
= ucf_flags_from_smb_request(req
);
6376 NTTIME src_twrp
= 0;
6377 uint32_t dst_ucf_flags
= ucf_flags_from_smb_request(req
);
6378 NTTIME dst_twrp
= 0;
6379 bool stream_rename
= false;
6381 START_PROFILE(SMBmv
);
6384 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6388 attrs
= SVAL(req
->vwv
+0, 0);
6390 p
= (const char *)req
->buf
+ 1;
6391 p
+= srvstr_get_path_req(ctx
, req
, &name
, p
, STR_TERMINATE
,
6393 if (!NT_STATUS_IS_OK(status
)) {
6394 reply_nterror(req
, status
);
6398 p
+= srvstr_get_path_req(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6400 if (!NT_STATUS_IS_OK(status
)) {
6401 reply_nterror(req
, status
);
6405 if (!req
->posix_pathnames
) {
6406 /* The newname must begin with a ':' if the
6407 name contains a ':'. */
6408 if (strchr_m(name
, ':')) {
6409 if (newname
[0] != ':') {
6410 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6413 stream_rename
= true;
6417 if (src_ucf_flags
& UCF_GMT_PATHNAME
) {
6418 extract_snapshot_token(name
, &src_twrp
);
6420 status
= smb1_strip_dfs_path(ctx
, &src_ucf_flags
, &name
);
6421 if (!NT_STATUS_IS_OK(status
)) {
6422 reply_nterror(req
, status
);
6425 status
= filename_convert_dirfsp(ctx
,
6433 if (!NT_STATUS_IS_OK(status
)) {
6434 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6435 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6436 ERRSRV
, ERRbadpath
);
6439 reply_nterror(req
, status
);
6443 if (dst_ucf_flags
& UCF_GMT_PATHNAME
) {
6444 extract_snapshot_token(newname
, &dst_twrp
);
6446 status
= smb1_strip_dfs_path(ctx
, &dst_ucf_flags
, &newname
);
6447 if (!NT_STATUS_IS_OK(status
)) {
6448 reply_nterror(req
, status
);
6451 status
= filename_convert_dirfsp(ctx
,
6459 if (!NT_STATUS_IS_OK(status
)) {
6460 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6461 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6462 ERRSRV
, ERRbadpath
);
6465 reply_nterror(req
, status
);
6469 /* Get the last component of the destination for rename_internals(). */
6470 dst_original_lcomp
= get_original_lcomp(ctx
,
6474 if (dst_original_lcomp
== NULL
) {
6475 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6479 if (stream_rename
) {
6480 /* smb_fname_dst->base_name must be the same as
6481 smb_fname_src->base_name. */
6482 TALLOC_FREE(smb_fname_dst
->base_name
);
6483 smb_fname_dst
->base_name
= talloc_strdup(smb_fname_dst
,
6484 smb_fname_src
->base_name
);
6485 if (!smb_fname_dst
->base_name
) {
6486 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6491 DBG_NOTICE("%s -> %s\n",
6492 smb_fname_str_dbg(smb_fname_src
),
6493 smb_fname_str_dbg(smb_fname_dst
));
6495 status
= rename_internals(ctx
,
6498 src_dirfsp
, /* src_dirfsp */
6505 if (!NT_STATUS_IS_OK(status
)) {
6506 if (open_was_deferred(req
->xconn
, req
->mid
)) {
6507 /* We have re-scheduled this call. */
6510 if (NT_STATUS_EQUAL(status
, NT_STATUS_SHARING_VIOLATION
)) {
6511 bool ok
= defer_smb1_sharing_violation(req
);
6516 reply_nterror(req
, status
);
6520 reply_smb1_outbuf(req
, 0, 0);
6522 TALLOC_FREE(smb_fname_src
);
6523 TALLOC_FREE(smb_fname_dst
);
6528 /****************************************************************************
6529 Reply to a file copy.
6533 This command was introduced in the LAN Manager 1.0 dialect
6534 It was rendered obsolete in the NT LAN Manager dialect.
6535 This command was used to perform server-side file copies, but
6536 is no longer used. Clients SHOULD
6537 NOT send requests using this command code.
6538 Servers receiving requests with this command code
6539 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6540 ****************************************************************************/
6542 void reply_copy(struct smb_request
*req
)
6544 START_PROFILE(SMBcopy
);
6545 reply_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
6546 END_PROFILE(SMBcopy
);
6551 #define DBGC_CLASS DBGC_LOCKING
6553 /****************************************************************************
6554 Get a lock pid, dealing with large count requests.
6555 ****************************************************************************/
6557 uint64_t get_lock_pid(const uint8_t *data
, int data_offset
,
6558 bool large_file_format
)
6560 if(!large_file_format
)
6561 return (uint64_t)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
6563 return (uint64_t)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
6566 /****************************************************************************
6567 Get a lock count, dealing with large count requests.
6568 ****************************************************************************/
6570 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
6571 bool large_file_format
)
6575 if(!large_file_format
) {
6576 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
6579 * No BVAL, this is reversed!
6581 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
6582 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
6588 /****************************************************************************
6589 Reply to a lockingX request.
6590 ****************************************************************************/
6592 static void reply_lockingx_done(struct tevent_req
*subreq
);
6594 void reply_lockingX(struct smb_request
*req
)
6596 connection_struct
*conn
= req
->conn
;
6598 unsigned char locktype
;
6599 enum brl_type brltype
;
6600 unsigned char oplocklevel
;
6601 uint16_t num_ulocks
;
6603 int32_t lock_timeout
;
6605 const uint8_t *data
;
6606 bool large_file_format
;
6607 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
6608 struct smbd_lock_element
*locks
= NULL
;
6609 struct tevent_req
*subreq
= NULL
;
6611 START_PROFILE(SMBlockingX
);
6614 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6615 END_PROFILE(SMBlockingX
);
6619 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
6620 locktype
= CVAL(req
->vwv
+3, 0);
6621 oplocklevel
= CVAL(req
->vwv
+3, 1);
6622 num_ulocks
= SVAL(req
->vwv
+6, 0);
6623 num_locks
= SVAL(req
->vwv
+7, 0);
6624 lock_timeout
= IVAL(req
->vwv
+4, 0);
6625 large_file_format
= ((locktype
& LOCKING_ANDX_LARGE_FILES
) != 0);
6627 if (!check_fsp(conn
, req
, fsp
)) {
6628 END_PROFILE(SMBlockingX
);
6634 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
6635 /* we don't support these - and CANCEL_LOCK makes w2k
6636 and XP reboot so I don't really want to be
6637 compatible! (tridge) */
6638 reply_force_doserror(req
, ERRDOS
, ERRnoatomiclocks
);
6639 END_PROFILE(SMBlockingX
);
6643 /* Check if this is an oplock break on a file
6644 we have granted an oplock on.
6646 if (locktype
& LOCKING_ANDX_OPLOCK_RELEASE
) {
6647 /* Client can insist on breaking to none. */
6648 bool break_to_none
= (oplocklevel
== 0);
6651 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6652 "for %s\n", (unsigned int)oplocklevel
,
6653 fsp_fnum_dbg(fsp
)));
6656 * Make sure we have granted an exclusive or batch oplock on
6660 if (fsp
->oplock_type
== 0) {
6662 /* The Samba4 nbench simulator doesn't understand
6663 the difference between break to level2 and break
6664 to none from level2 - it sends oplock break
6665 replies in both cases. Don't keep logging an error
6666 message here - just ignore it. JRA. */
6668 DEBUG(5,("reply_lockingX: Error : oplock break from "
6669 "client for %s (oplock=%d) and no "
6670 "oplock granted on this file (%s).\n",
6671 fsp_fnum_dbg(fsp
), fsp
->oplock_type
,
6674 /* if this is a pure oplock break request then don't
6676 if (num_locks
== 0 && num_ulocks
== 0) {
6677 END_PROFILE(SMBlockingX
);
6681 END_PROFILE(SMBlockingX
);
6682 reply_nterror(req
, NT_STATUS_FILE_LOCK_CONFLICT
);
6686 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
6688 result
= remove_oplock(fsp
);
6690 result
= downgrade_oplock(fsp
);
6694 DEBUG(0, ("reply_lockingX: error in removing "
6695 "oplock on file %s\n", fsp_str_dbg(fsp
)));
6696 /* Hmmm. Is this panic justified? */
6697 smb_panic("internal tdb error");
6700 /* if this is a pure oplock break request then don't send a
6702 if (num_locks
== 0 && num_ulocks
== 0) {
6703 /* Sanity check - ensure a pure oplock break is not a
6705 if (CVAL(req
->vwv
+0, 0) != 0xff) {
6706 DEBUG(0,("reply_lockingX: Error : pure oplock "
6707 "break is a chained %d request !\n",
6708 (unsigned int)CVAL(req
->vwv
+0, 0)));
6710 END_PROFILE(SMBlockingX
);
6716 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
6717 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6718 END_PROFILE(SMBlockingX
);
6722 if (num_ulocks
!= 0) {
6723 struct smbd_lock_element
*ulocks
= NULL
;
6726 ulocks
= talloc_array(
6727 req
, struct smbd_lock_element
, num_ulocks
);
6728 if (ulocks
== NULL
) {
6729 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6730 END_PROFILE(SMBlockingX
);
6735 * Data now points at the beginning of the list of
6736 * smb_unlkrng structs
6738 for (i
= 0; i
< num_ulocks
; i
++) {
6739 ulocks
[i
].req_guid
= smbd_request_guid(req
,
6741 ulocks
[i
].smblctx
= get_lock_pid(
6742 data
, i
, large_file_format
);
6743 ulocks
[i
].count
= get_lock_count(
6744 data
, i
, large_file_format
);
6745 ulocks
[i
].offset
= get_lock_offset(
6746 data
, i
, large_file_format
);
6747 ulocks
[i
].brltype
= UNLOCK_LOCK
;
6748 ulocks
[i
].lock_flav
= WINDOWS_LOCK
;
6752 * Unlock cancels pending locks
6755 ok
= smbd_smb1_brl_finish_by_lock(
6761 reply_smb1_outbuf(req
, 2, 0);
6762 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6763 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6764 END_PROFILE(SMBlockingX
);
6768 status
= smbd_do_unlocking(
6769 req
, fsp
, num_ulocks
, ulocks
);
6770 TALLOC_FREE(ulocks
);
6771 if (!NT_STATUS_IS_OK(status
)) {
6772 END_PROFILE(SMBlockingX
);
6773 reply_nterror(req
, status
);
6778 /* Now do any requested locks */
6779 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
6781 /* Data now points at the beginning of the list
6782 of smb_lkrng structs */
6784 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
6785 brltype
= READ_LOCK
;
6787 brltype
= WRITE_LOCK
;
6790 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
6791 if (locks
== NULL
) {
6792 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6793 END_PROFILE(SMBlockingX
);
6797 for (i
= 0; i
< num_locks
; i
++) {
6798 locks
[i
].req_guid
= smbd_request_guid(req
, i
),
6799 locks
[i
].smblctx
= get_lock_pid(data
, i
, large_file_format
);
6800 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
6801 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
);
6802 locks
[i
].brltype
= brltype
;
6803 locks
[i
].lock_flav
= WINDOWS_LOCK
;
6806 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
6810 if (num_locks
== 0) {
6811 /* See smbtorture3 lock11 test */
6812 reply_smb1_outbuf(req
, 2, 0);
6813 /* andx chain ends */
6814 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6815 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6816 END_PROFILE(SMBlockingX
);
6820 ok
= smbd_smb1_brl_finish_by_lock(
6823 locks
[0], /* Windows only cancels the first lock */
6824 NT_STATUS_FILE_LOCK_CONFLICT
);
6827 reply_force_doserror(req
, ERRDOS
, ERRcancelviolation
);
6828 END_PROFILE(SMBlockingX
);
6832 reply_smb1_outbuf(req
, 2, 0);
6833 SSVAL(req
->outbuf
, smb_vwv0
, 0xff);
6834 SSVAL(req
->outbuf
, smb_vwv1
, 0);
6835 END_PROFILE(SMBlockingX
);
6839 subreq
= smbd_smb1_do_locks_send(
6848 if (subreq
== NULL
) {
6849 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6850 END_PROFILE(SMBlockingX
);
6853 tevent_req_set_callback(subreq
, reply_lockingx_done
, NULL
);
6854 END_PROFILE(SMBlockingX
);
6857 static void reply_lockingx_done(struct tevent_req
*subreq
)
6859 struct smb_request
*req
= NULL
;
6863 START_PROFILE(SMBlockingX
);
6865 ok
= smbd_smb1_do_locks_extract_smbreq(subreq
, talloc_tos(), &req
);
6868 status
= smbd_smb1_do_locks_recv(subreq
);
6869 TALLOC_FREE(subreq
);
6871 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status
));
6873 if (NT_STATUS_IS_OK(status
)) {
6874 reply_smb1_outbuf(req
, 2, 0);
6875 SSVAL(req
->outbuf
, smb_vwv0
, 0xff); /* andx chain ends */
6876 SSVAL(req
->outbuf
, smb_vwv1
, 0); /* no andx offset */
6878 reply_nterror(req
, status
);
6881 ok
= smb1_srv_send(req
->xconn
,
6882 (char *)req
->outbuf
,
6885 IS_CONN_ENCRYPTED(req
->conn
));
6887 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6890 END_PROFILE(SMBlockingX
);
6894 #define DBGC_CLASS DBGC_ALL
6896 /****************************************************************************
6897 Reply to a SMBreadbmpx (read block multiplex) request.
6898 Always reply with an error, if someone has a platform really needs this,
6899 please contact vl@samba.org
6900 ****************************************************************************/
6902 void reply_readbmpx(struct smb_request
*req
)
6904 START_PROFILE(SMBreadBmpx
);
6905 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6906 END_PROFILE(SMBreadBmpx
);
6910 /****************************************************************************
6911 Reply to a SMBreadbs (read block multiplex secondary) request.
6912 Always reply with an error, if someone has a platform really needs this,
6913 please contact vl@samba.org
6914 ****************************************************************************/
6916 void reply_readbs(struct smb_request
*req
)
6918 START_PROFILE(SMBreadBs
);
6919 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
6920 END_PROFILE(SMBreadBs
);
6924 /****************************************************************************
6925 Reply to a SMBsetattrE.
6926 ****************************************************************************/
6928 void reply_setattrE(struct smb_request
*req
)
6930 connection_struct
*conn
= req
->conn
;
6931 struct smb_file_time ft
;
6935 START_PROFILE(SMBsetattrE
);
6936 init_smb_file_time(&ft
);
6939 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6943 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
6945 if(!fsp
|| (fsp
->conn
!= conn
)) {
6946 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
6951 * Convert the DOS times into unix times.
6954 ft
.atime
= time_t_to_full_timespec(
6955 srv_make_unix_date2(req
->vwv
+3));
6956 ft
.mtime
= time_t_to_full_timespec(
6957 srv_make_unix_date2(req
->vwv
+5));
6958 ft
.create_time
= time_t_to_full_timespec(
6959 srv_make_unix_date2(req
->vwv
+1));
6961 reply_smb1_outbuf(req
, 0, 0);
6963 /* Ensure we have a valid stat struct for the source. */
6964 status
= vfs_stat_fsp(fsp
);
6965 if (!NT_STATUS_IS_OK(status
)) {
6966 reply_nterror(req
, status
);
6970 status
= check_any_access_fsp(fsp
, FILE_WRITE_ATTRIBUTES
);
6971 if (!NT_STATUS_IS_OK(status
)) {
6972 reply_nterror(req
, status
);
6976 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
6977 if (!NT_STATUS_IS_OK(status
)) {
6978 reply_nterror(req
, status
);
6982 if (fsp
->fsp_flags
.modified
) {
6983 trigger_write_time_update_immediate(fsp
);
6986 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6989 (unsigned int)ft
.atime
.tv_sec
,
6990 (unsigned int)ft
.mtime
.tv_sec
,
6991 (unsigned int)ft
.create_time
.tv_sec
6994 END_PROFILE(SMBsetattrE
);
6999 /* Back from the dead for OS/2..... JRA. */
7001 /****************************************************************************
7002 Reply to a SMBwritebmpx (write block multiplex primary) request.
7003 Always reply with an error, if someone has a platform really needs this,
7004 please contact vl@samba.org
7005 ****************************************************************************/
7007 void reply_writebmpx(struct smb_request
*req
)
7009 START_PROFILE(SMBwriteBmpx
);
7010 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7011 END_PROFILE(SMBwriteBmpx
);
7015 /****************************************************************************
7016 Reply to a SMBwritebs (write block multiplex secondary) request.
7017 Always reply with an error, if someone has a platform really needs this,
7018 please contact vl@samba.org
7019 ****************************************************************************/
7021 void reply_writebs(struct smb_request
*req
)
7023 START_PROFILE(SMBwriteBs
);
7024 reply_force_doserror(req
, ERRSRV
, ERRuseSTD
);
7025 END_PROFILE(SMBwriteBs
);
7029 /****************************************************************************
7030 Reply to a SMBgetattrE.
7031 ****************************************************************************/
7033 void reply_getattrE(struct smb_request
*req
)
7035 connection_struct
*conn
= req
->conn
;
7038 struct timespec create_ts
;
7041 START_PROFILE(SMBgetattrE
);
7044 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7045 END_PROFILE(SMBgetattrE
);
7049 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7051 if(!fsp
|| (fsp
->conn
!= conn
)) {
7052 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
7053 END_PROFILE(SMBgetattrE
);
7057 /* Do an fstat on this file */
7058 status
= vfs_stat_fsp(fsp
);
7059 if (!NT_STATUS_IS_OK(status
)) {
7060 reply_nterror(req
, status
);
7061 END_PROFILE(SMBgetattrE
);
7065 mode
= fdos_mode(fsp
);
7068 * Convert the times into dos times. Set create
7069 * date to be last modify date as UNIX doesn't save
7073 reply_smb1_outbuf(req
, 11, 0);
7075 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
7076 srv_put_dos_date2_ts((char *)req
->outbuf
, smb_vwv0
, create_ts
);
7077 srv_put_dos_date2_ts((char *)req
->outbuf
,
7079 fsp
->fsp_name
->st
.st_ex_atime
);
7080 /* Should we check pending modtime here ? JRA */
7081 srv_put_dos_date2_ts((char *)req
->outbuf
,
7083 fsp
->fsp_name
->st
.st_ex_mtime
);
7085 if (mode
& FILE_ATTRIBUTE_DIRECTORY
) {
7086 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7087 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7089 uint32_t allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &fsp
->fsp_name
->st
);
7090 SIVAL(req
->outbuf
, smb_vwv6
, (uint32_t)fsp
->fsp_name
->st
.st_ex_size
);
7091 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7093 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7095 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp
)));
7097 END_PROFILE(SMBgetattrE
);
7101 /****************************************************************************
7102 Reply to a SMBfindclose (stop trans2 directory search).
7103 ****************************************************************************/
7105 void reply_findclose(struct smb_request
*req
)
7108 struct smbd_server_connection
*sconn
= req
->sconn
;
7109 files_struct
*fsp
= NULL
;
7111 START_PROFILE(SMBfindclose
);
7114 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7115 END_PROFILE(SMBfindclose
);
7119 dptr_num
= SVALS(req
->vwv
+0, 0);
7121 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num
));
7124 * OS/2 seems to use -1 to indicate "close all directories"
7125 * This has to mean on this specific connection struct.
7127 if (dptr_num
== -1) {
7128 dptr_closecnum(req
->conn
);
7130 fsp
= dptr_fetch_lanman2_fsp(sconn
, dptr_num
);
7133 close_file_free(NULL
, &fsp
, NORMAL_CLOSE
);
7137 reply_smb1_outbuf(req
, 0, 0);
7139 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num
));
7141 END_PROFILE(SMBfindclose
);
7145 /****************************************************************************
7146 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7147 ****************************************************************************/
7149 void reply_findnclose(struct smb_request
*req
)
7153 START_PROFILE(SMBfindnclose
);
7156 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7157 END_PROFILE(SMBfindnclose
);
7161 dptr_num
= SVAL(req
->vwv
+0, 0);
7163 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num
));
7165 /* We never give out valid handles for a
7166 findnotifyfirst - so any dptr_num is ok here.
7169 reply_smb1_outbuf(req
, 0, 0);
7171 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num
));
7173 END_PROFILE(SMBfindnclose
);