smbd: use check_any_access_fsp() for all access checks
[Samba.git] / source3 / smbd / smb1_reply.c
blob9fbfc39c69fcc31464a4a11d79720b27a6a0838a
1 /*
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
27 #include "includes.h"
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "smbd/smbXsrv_open.h"
35 #include "fake_file.h"
36 #include "rpc_client/rpc_client.h"
37 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "rpc_client/cli_spoolss.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_server/rpc_ncacn_np.h"
41 #include "libcli/security/security.h"
42 #include "libsmb/nmblib.h"
43 #include "auth.h"
44 #include "smbprofile.h"
45 #include "../lib/tsocket/tsocket.h"
46 #include "lib/util/tevent_ntstatus.h"
47 #include "libcli/smb/smb_signing.h"
48 #include "lib/util/sys_rw_data.h"
49 #include "librpc/gen_ndr/open_files.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
53 #include "source3/lib/substitute.h"
55 /****************************************************************************
56 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
57 ****************************************************************************/
59 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
60 files_struct *fsp)
62 if ((fsp == NULL) || (conn == NULL)) {
63 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
64 return false;
66 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
67 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
68 return false;
70 return true;
73 /****************************************************************************
74 SMB1 version of smb2_strip_dfs_path()
75 Differs from SMB2 in that all Windows path separator '\' characters
76 have already been converted to '/' by check_path_syntax().
77 ****************************************************************************/
79 NTSTATUS smb1_strip_dfs_path(TALLOC_CTX *mem_ctx,
80 uint32_t *_ucf_flags,
81 char **in_path)
83 uint32_t ucf_flags = *_ucf_flags;
84 char *path = *in_path;
85 char *return_path = NULL;
87 if (!(ucf_flags & UCF_DFS_PATHNAME)) {
88 return NT_STATUS_OK;
91 /* Strip any leading '/' characters - MacOSX client behavior. */
92 while (*path == '/') {
93 path++;
96 /* We should now be pointing at the server name. Go past it. */
97 for (;;) {
98 if (*path == '\0') {
99 /* End of complete path. Exit OK. */
100 goto done;
102 if (*path == '/') {
103 /* End of server name. Go past and break. */
104 path++;
105 break;
107 path++; /* Continue looking for end of server name or string. */
110 /* We should now be pointing at the share name. Go past it. */
111 for (;;) {
112 if (*path == '\0') {
113 /* End of complete path. Exit OK. */
114 goto done;
116 if (*path == '/') {
117 /* End of share name. Go past and break. */
118 path++;
119 break;
121 if (*path == ':') {
122 /* Only invalid character in sharename. */
123 return NT_STATUS_OBJECT_NAME_INVALID;
125 path++; /* Continue looking for end of share name or string. */
128 done:
129 /* path now points at the start of the real filename (if any). */
130 /* Duplicate it first. */
131 return_path = talloc_strdup(mem_ctx, path);
132 if (return_path == NULL) {
133 return NT_STATUS_NO_MEMORY;
136 /* Now we can free the original (path points to part of this). */
137 TALLOC_FREE(*in_path);
139 *in_path = return_path;
140 ucf_flags &= ~UCF_DFS_PATHNAME;
141 *_ucf_flags = ucf_flags;
142 return NT_STATUS_OK;
145 /****************************************************************************
146 Check if we have a correct fsp pointing to a file.
147 ****************************************************************************/
149 bool check_fsp(connection_struct *conn, struct smb_request *req,
150 files_struct *fsp)
152 if (!check_fsp_open(conn, req, fsp)) {
153 return false;
155 if (fsp->fsp_flags.is_directory) {
156 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
157 return false;
159 if (fsp_get_pathref_fd(fsp) == -1) {
160 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
161 return false;
163 fsp->num_smb_operations++;
164 return true;
167 /****************************************************************************
168 Reply to a tcon.
169 conn POINTER CAN BE NULL HERE !
170 ****************************************************************************/
172 void reply_tcon(struct smb_request *req)
174 connection_struct *conn = req->conn;
175 const char *service;
176 char *service_buf = NULL;
177 char *password = NULL;
178 char *dev = NULL;
179 int pwlen=0;
180 NTSTATUS nt_status;
181 const uint8_t *p;
182 const char *p2;
183 TALLOC_CTX *ctx = talloc_tos();
184 struct smbXsrv_connection *xconn = req->xconn;
185 NTTIME now = timeval_to_nttime(&req->request_time);
187 START_PROFILE(SMBtcon);
189 if (req->buflen < 4) {
190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
191 END_PROFILE(SMBtcon);
192 return;
195 p = req->buf + 1;
196 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
197 p += 1;
198 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
199 p += pwlen+1;
200 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
201 p += 1;
203 if (service_buf == NULL || password == NULL || dev == NULL) {
204 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
205 END_PROFILE(SMBtcon);
206 return;
208 p2 = strrchr_m(service_buf,'\\');
209 if (p2) {
210 service = p2+1;
211 } else {
212 service = service_buf;
215 conn = make_connection(req, now, service, dev,
216 req->vuid,&nt_status);
217 req->conn = conn;
219 if (!conn) {
220 reply_nterror(req, nt_status);
221 END_PROFILE(SMBtcon);
222 return;
225 reply_smb1_outbuf(req, 2, 0);
226 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
227 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
228 SSVAL(req->outbuf,smb_tid,conn->cnum);
230 DEBUG(3,("tcon service=%s cnum=%d\n",
231 service, conn->cnum));
233 END_PROFILE(SMBtcon);
234 return;
237 /****************************************************************************
238 Reply to a tcon and X.
239 conn POINTER CAN BE NULL HERE !
240 ****************************************************************************/
242 void reply_tcon_and_X(struct smb_request *req)
244 const struct loadparm_substitution *lp_sub =
245 loadparm_s3_global_substitution();
246 connection_struct *conn = req->conn;
247 const char *service = NULL;
248 TALLOC_CTX *ctx = talloc_tos();
249 /* what the client thinks the device is */
250 char *client_devicetype = NULL;
251 /* what the server tells the client the share represents */
252 const char *server_devicetype;
253 NTSTATUS nt_status;
254 int passlen;
255 char *path = NULL;
256 const uint8_t *p;
257 const char *q;
258 uint16_t tcon_flags;
259 struct smbXsrv_session *session = NULL;
260 NTTIME now = timeval_to_nttime(&req->request_time);
261 bool session_key_updated = false;
262 uint16_t optional_support = 0;
263 struct smbXsrv_connection *xconn = req->xconn;
265 START_PROFILE(SMBtconX);
267 if (req->wct < 4) {
268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
269 END_PROFILE(SMBtconX);
270 return;
273 passlen = SVAL(req->vwv+3, 0);
274 tcon_flags = SVAL(req->vwv+2, 0);
276 /* we might have to close an old one */
277 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
278 struct smbXsrv_tcon *tcon;
279 NTSTATUS status;
281 tcon = conn->tcon;
282 req->conn = NULL;
283 conn = NULL;
286 * TODO: cancel all outstanding requests on the tcon
288 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
289 if (!NT_STATUS_IS_OK(status)) {
290 DEBUG(0, ("reply_tcon_and_X: "
291 "smbXsrv_tcon_disconnect() failed: %s\n",
292 nt_errstr(status)));
294 * If we hit this case, there is something completely
295 * wrong, so we better disconnect the transport connection.
297 END_PROFILE(SMBtconX);
298 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
299 return;
302 TALLOC_FREE(tcon);
304 * This tree id is gone. Make sure we can't re-use it
305 * by accident.
307 req->tid = 0;
310 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
311 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
312 END_PROFILE(SMBtconX);
313 return;
316 if (xconn->smb1.negprot.encrypted_passwords) {
317 p = req->buf + passlen;
318 } else {
319 p = req->buf + passlen + 1;
322 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
324 if (path == NULL) {
325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
326 END_PROFILE(SMBtconX);
327 return;
331 * the service name can be either: \\server\share
332 * or share directly like on the DELL PowerVault 705
334 if (*path=='\\') {
335 q = strchr_m(path+2,'\\');
336 if (!q) {
337 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
338 END_PROFILE(SMBtconX);
339 return;
341 service = q+1;
342 } else {
343 service = path;
346 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
347 &client_devicetype, p,
348 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
350 if (client_devicetype == NULL) {
351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
352 END_PROFILE(SMBtconX);
353 return;
356 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
358 nt_status = smb1srv_session_lookup(xconn,
359 req->vuid, now, &session);
360 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
361 reply_force_doserror(req, ERRSRV, ERRbaduid);
362 END_PROFILE(SMBtconX);
363 return;
365 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
366 reply_nterror(req, nt_status);
367 END_PROFILE(SMBtconX);
368 return;
370 if (!NT_STATUS_IS_OK(nt_status)) {
371 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
372 END_PROFILE(SMBtconX);
373 return;
376 if (session->global->auth_session_info == NULL) {
377 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
378 END_PROFILE(SMBtconX);
379 return;
383 * If there is no application key defined yet
384 * we create one.
386 * This means we setup the application key on the
387 * first tcon that happens via the given session.
389 * Once the application key is defined, it does not
390 * change any more.
392 if (session->global->application_key_blob.length == 0 &&
393 smb2_signing_key_valid(session->global->signing_key))
395 struct smbXsrv_session *x = session;
396 struct auth_session_info *session_info =
397 session->global->auth_session_info;
398 uint8_t session_key[16];
400 ZERO_STRUCT(session_key);
401 memcpy(session_key, x->global->signing_key->blob.data,
402 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
405 * The application key is truncated/padded to 16 bytes
407 x->global->application_key_blob = data_blob_talloc(x->global,
408 session_key,
409 sizeof(session_key));
410 ZERO_STRUCT(session_key);
411 if (x->global->application_key_blob.data == NULL) {
412 reply_nterror(req, NT_STATUS_NO_MEMORY);
413 END_PROFILE(SMBtconX);
414 return;
416 talloc_keep_secret(x->global->application_key_blob.data);
418 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
419 NTSTATUS status;
421 status = smb1_key_derivation(x->global->application_key_blob.data,
422 x->global->application_key_blob.length,
423 x->global->application_key_blob.data);
424 if (!NT_STATUS_IS_OK(status)) {
425 DBG_ERR("smb1_key_derivation failed: %s\n",
426 nt_errstr(status));
427 END_PROFILE(SMBtconX);
428 return;
430 optional_support |= SMB_EXTENDED_SIGNATURES;
434 * Place the application key into the session_info
436 data_blob_clear_free(&session_info->session_key);
437 session_info->session_key = data_blob_dup_talloc(session_info,
438 x->global->application_key_blob);
439 if (session_info->session_key.data == NULL) {
440 data_blob_clear_free(&x->global->application_key_blob);
441 reply_nterror(req, NT_STATUS_NO_MEMORY);
442 END_PROFILE(SMBtconX);
443 return;
445 talloc_keep_secret(session_info->session_key.data);
446 session_key_updated = true;
449 conn = make_connection(req, now, service, client_devicetype,
450 req->vuid, &nt_status);
451 req->conn =conn;
453 if (!conn) {
454 if (session_key_updated) {
455 struct smbXsrv_session *x = session;
456 struct auth_session_info *session_info =
457 session->global->auth_session_info;
458 data_blob_clear_free(&x->global->application_key_blob);
459 data_blob_clear_free(&session_info->session_key);
461 reply_nterror(req, nt_status);
462 END_PROFILE(SMBtconX);
463 return;
466 if ( IS_IPC(conn) )
467 server_devicetype = "IPC";
468 else if ( IS_PRINT(conn) )
469 server_devicetype = "LPT1:";
470 else
471 server_devicetype = "A:";
473 if (xconn->protocol < PROTOCOL_NT1) {
474 reply_smb1_outbuf(req, 2, 0);
475 if (message_push_string(&req->outbuf, server_devicetype,
476 STR_TERMINATE|STR_ASCII) == -1) {
477 reply_nterror(req, NT_STATUS_NO_MEMORY);
478 END_PROFILE(SMBtconX);
479 return;
481 } else {
482 /* NT sets the fstype of IPC$ to the null string */
483 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
485 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
486 /* Return permissions. */
487 uint32_t perm1 = 0;
488 uint32_t perm2 = 0;
490 reply_smb1_outbuf(req, 7, 0);
492 if (IS_IPC(conn)) {
493 perm1 = FILE_ALL_ACCESS;
494 perm2 = FILE_ALL_ACCESS;
495 } else {
496 perm1 = conn->share_access;
499 SIVAL(req->outbuf, smb_vwv3, perm1);
500 SIVAL(req->outbuf, smb_vwv5, perm2);
501 } else {
502 reply_smb1_outbuf(req, 3, 0);
505 if ((message_push_string(&req->outbuf, server_devicetype,
506 STR_TERMINATE|STR_ASCII) == -1)
507 || (message_push_string(&req->outbuf, fstype,
508 STR_TERMINATE) == -1)) {
509 reply_nterror(req, NT_STATUS_NO_MEMORY);
510 END_PROFILE(SMBtconX);
511 return;
514 /* what does setting this bit do? It is set by NT4 and
515 may affect the ability to autorun mounted cdroms */
516 optional_support |= SMB_SUPPORT_SEARCH_BITS;
517 optional_support |=
518 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
520 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
521 DEBUG(2,("Serving %s as a Dfs root\n",
522 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
523 optional_support |= SMB_SHARE_IN_DFS;
526 SSVAL(req->outbuf, smb_vwv2, optional_support);
529 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
530 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
532 DEBUG(3,("tconX service=%s \n",
533 service));
535 /* set the incoming and outgoing tid to the just created one */
536 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
537 SSVAL(req->outbuf,smb_tid,conn->cnum);
539 END_PROFILE(SMBtconX);
541 req->tid = conn->cnum;
544 /****************************************************************************
545 Reply to an unknown type.
546 ****************************************************************************/
548 void reply_unknown_new(struct smb_request *req, uint8_t type)
550 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
551 smb_fn_name(type), type, type));
552 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
553 return;
556 /****************************************************************************
557 Reply to an ioctl.
558 conn POINTER CAN BE NULL HERE !
559 ****************************************************************************/
561 void reply_ioctl(struct smb_request *req)
563 const struct loadparm_substitution *lp_sub =
564 loadparm_s3_global_substitution();
565 connection_struct *conn = req->conn;
566 uint16_t device;
567 uint16_t function;
568 uint32_t ioctl_code;
569 int replysize;
570 char *p;
572 START_PROFILE(SMBioctl);
574 if (req->wct < 3) {
575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
576 END_PROFILE(SMBioctl);
577 return;
580 device = SVAL(req->vwv+1, 0);
581 function = SVAL(req->vwv+2, 0);
582 ioctl_code = (device << 16) + function;
584 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
586 switch (ioctl_code) {
587 case IOCTL_QUERY_JOB_INFO:
588 replysize = 32;
589 break;
590 default:
591 reply_force_doserror(req, ERRSRV, ERRnosupport);
592 END_PROFILE(SMBioctl);
593 return;
596 reply_smb1_outbuf(req, 8, replysize+1);
597 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
598 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
599 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
600 p = smb_buf(req->outbuf);
601 memset(p, '\0', replysize+1); /* valgrind-safe. */
602 p += 1; /* Allow for alignment */
604 switch (ioctl_code) {
605 case IOCTL_QUERY_JOB_INFO:
607 NTSTATUS status;
608 size_t len = 0;
609 files_struct *fsp = file_fsp(
610 req, SVAL(req->vwv+0, 0));
611 if (!fsp) {
612 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
613 END_PROFILE(SMBioctl);
614 return;
616 /* Job number */
617 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
619 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
620 lp_netbios_name(), 15,
621 STR_TERMINATE|STR_ASCII, &len);
622 if (!NT_STATUS_IS_OK(status)) {
623 reply_nterror(req, status);
624 END_PROFILE(SMBioctl);
625 return;
627 if (conn) {
628 status = srvstr_push((char *)req->outbuf, req->flags2,
629 p+18,
630 lp_servicename(talloc_tos(),
631 lp_sub,
632 SNUM(conn)),
633 13, STR_TERMINATE|STR_ASCII, &len);
634 if (!NT_STATUS_IS_OK(status)) {
635 reply_nterror(req, status);
636 END_PROFILE(SMBioctl);
637 return;
639 } else {
640 memset(p+18, 0, 13);
642 break;
646 END_PROFILE(SMBioctl);
647 return;
650 /****************************************************************************
651 Strange checkpath NTSTATUS mapping.
652 ****************************************************************************/
654 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
656 /* Strange DOS error code semantics only for checkpath... */
657 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
658 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
659 /* We need to map to ERRbadpath */
660 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
663 return status;
666 /****************************************************************************
667 Reply to a checkpath.
668 ****************************************************************************/
670 void reply_checkpath(struct smb_request *req)
672 connection_struct *conn = req->conn;
673 struct smb_filename *smb_fname = NULL;
674 char *name = NULL;
675 NTSTATUS status;
676 struct files_struct *dirfsp = NULL;
677 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
678 NTTIME twrp = 0;
679 TALLOC_CTX *ctx = talloc_tos();
681 START_PROFILE(SMBcheckpath);
683 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
684 STR_TERMINATE, &status);
686 if (!NT_STATUS_IS_OK(status)) {
687 status = map_checkpath_error(req->flags2, status);
688 reply_nterror(req, status);
689 END_PROFILE(SMBcheckpath);
690 return;
693 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
695 if (ucf_flags & UCF_GMT_PATHNAME) {
696 extract_snapshot_token(name, &twrp);
698 status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
699 if (!NT_STATUS_IS_OK(status)) {
700 reply_nterror(req, status);
701 goto out;
704 status = filename_convert_dirfsp(ctx,
705 conn,
706 name,
707 ucf_flags,
708 twrp,
709 &dirfsp,
710 &smb_fname);
711 if (!NT_STATUS_IS_OK(status)) {
712 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
713 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
714 ERRSRV, ERRbadpath);
715 END_PROFILE(SMBcheckpath);
716 return;
718 goto path_err;
721 if (!VALID_STAT(smb_fname->st) &&
722 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
723 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
724 smb_fname_str_dbg(smb_fname), strerror(errno)));
725 status = map_nt_error_from_unix(errno);
726 goto path_err;
729 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
730 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
731 ERRDOS, ERRbadpath);
732 goto out;
735 reply_smb1_outbuf(req, 0, 0);
737 path_err:
738 /* We special case this - as when a Windows machine
739 is parsing a path is steps through the components
740 one at a time - if a component fails it expects
741 ERRbadpath, not ERRbadfile.
743 status = map_checkpath_error(req->flags2, status);
744 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
746 * Windows returns different error codes if
747 * the parent directory is valid but not the
748 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
749 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
750 * if the path is invalid.
752 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
753 ERRDOS, ERRbadpath);
754 goto out;
757 reply_nterror(req, status);
759 out:
760 TALLOC_FREE(smb_fname);
761 END_PROFILE(SMBcheckpath);
762 return;
765 /****************************************************************************
766 Reply to a getatr.
767 ****************************************************************************/
769 void reply_getatr(struct smb_request *req)
771 struct smbXsrv_connection *xconn = req->xconn;
772 connection_struct *conn = req->conn;
773 struct smb_filename *smb_fname = NULL;
774 char *fname = NULL;
775 int mode=0;
776 off_t size=0;
777 time_t mtime=0;
778 const char *p;
779 NTSTATUS status;
780 TALLOC_CTX *ctx = talloc_tos();
782 START_PROFILE(SMBgetatr);
784 p = (const char *)req->buf + 1;
785 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
786 if (!NT_STATUS_IS_OK(status)) {
787 reply_nterror(req, status);
788 goto out;
792 * dos sometimes asks for a stat of "" - it returns a "hidden
793 * directory" under WfWg - weird!
795 if (*fname == '\0') {
796 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
797 if (!CAN_WRITE(conn)) {
798 mode |= FILE_ATTRIBUTE_READONLY;
800 size = 0;
801 mtime = 0;
802 } else {
803 struct files_struct *dirfsp = NULL;
804 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
805 NTTIME twrp = 0;
806 bool ask_sharemode;
808 if (ucf_flags & UCF_GMT_PATHNAME) {
809 extract_snapshot_token(fname, &twrp);
811 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
812 if (!NT_STATUS_IS_OK(status)) {
813 reply_nterror(req, status);
814 goto out;
816 status = filename_convert_dirfsp(ctx,
817 conn,
818 fname,
819 ucf_flags,
820 twrp,
821 &dirfsp,
822 &smb_fname);
823 if (!NT_STATUS_IS_OK(status)) {
824 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
825 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
826 ERRSRV, ERRbadpath);
827 goto out;
829 reply_nterror(req, status);
830 goto out;
832 if (!VALID_STAT(smb_fname->st) &&
833 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
834 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
835 smb_fname_str_dbg(smb_fname),
836 strerror(errno)));
837 reply_nterror(req, map_nt_error_from_unix(errno));
838 goto out;
841 mode = fdos_mode(smb_fname->fsp);
842 size = smb_fname->st.st_ex_size;
844 ask_sharemode = fsp_search_ask_sharemode(smb_fname->fsp);
845 if (ask_sharemode) {
846 struct timespec write_time_ts;
847 struct file_id fileid;
849 ZERO_STRUCT(write_time_ts);
850 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
851 get_file_infos(fileid, 0, NULL, &write_time_ts);
852 if (!is_omit_timespec(&write_time_ts)) {
853 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
857 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
858 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
859 size = 0;
863 reply_smb1_outbuf(req, 10, 0);
865 SSVAL(req->outbuf,smb_vwv0,mode);
866 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
867 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
868 } else {
869 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
871 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
873 if (xconn->protocol >= PROTOCOL_NT1) {
874 SSVAL(req->outbuf, smb_flg2,
875 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
878 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
879 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
881 out:
882 TALLOC_FREE(smb_fname);
883 TALLOC_FREE(fname);
884 END_PROFILE(SMBgetatr);
885 return;
888 /****************************************************************************
889 Reply to a setatr.
890 ****************************************************************************/
892 void reply_setatr(struct smb_request *req)
894 struct smb_file_time ft;
895 connection_struct *conn = req->conn;
896 struct smb_filename *smb_fname = NULL;
897 struct files_struct *dirfsp = NULL;
898 char *fname = NULL;
899 int mode;
900 time_t mtime;
901 const char *p;
902 NTSTATUS status;
903 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
904 NTTIME twrp = 0;
905 TALLOC_CTX *ctx = talloc_tos();
907 START_PROFILE(SMBsetatr);
908 init_smb_file_time(&ft);
910 if (req->wct < 2) {
911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
912 goto out;
915 p = (const char *)req->buf + 1;
916 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
917 if (!NT_STATUS_IS_OK(status)) {
918 reply_nterror(req, status);
919 goto out;
922 if (ucf_flags & UCF_GMT_PATHNAME) {
923 extract_snapshot_token(fname, &twrp);
925 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
926 if (!NT_STATUS_IS_OK(status)) {
927 reply_nterror(req, status);
928 goto out;
930 status = filename_convert_dirfsp(ctx,
931 conn,
932 fname,
933 ucf_flags,
934 twrp,
935 &dirfsp,
936 &smb_fname);
937 if (!NT_STATUS_IS_OK(status)) {
938 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
939 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
940 ERRSRV, ERRbadpath);
941 goto out;
943 reply_nterror(req, status);
944 goto out;
947 if (ISDOT(smb_fname->base_name)) {
949 * Not sure here is the right place to catch this
950 * condition. Might be moved to somewhere else later -- vl
952 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
953 goto out;
956 if (smb_fname->fsp == NULL) {
957 /* Can't set access rights on a symlink. */
958 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
959 goto out;
962 mode = SVAL(req->vwv+0, 0);
963 mtime = srv_make_unix_date3(req->vwv+1);
965 if (mode != FILE_ATTRIBUTE_NORMAL) {
966 if (VALID_STAT_OF_DIR(smb_fname->st))
967 mode |= FILE_ATTRIBUTE_DIRECTORY;
968 else
969 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
971 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
972 smb_fname->fsp,
973 false,
974 FILE_WRITE_ATTRIBUTES);
975 if (!NT_STATUS_IS_OK(status)) {
976 reply_nterror(req, status);
977 goto out;
980 if (file_set_dosmode(conn, smb_fname, mode, NULL,
981 false) != 0) {
982 reply_nterror(req, map_nt_error_from_unix(errno));
983 goto out;
987 ft.mtime = time_t_to_full_timespec(mtime);
989 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
990 if (!NT_STATUS_IS_OK(status)) {
991 reply_nterror(req, status);
992 goto out;
995 reply_smb1_outbuf(req, 0, 0);
997 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
998 mode));
999 out:
1000 TALLOC_FREE(smb_fname);
1001 END_PROFILE(SMBsetatr);
1002 return;
1005 /****************************************************************************
1006 Reply to a dskattr.
1007 ****************************************************************************/
1009 void reply_dskattr(struct smb_request *req)
1011 struct smbXsrv_connection *xconn = req->xconn;
1012 connection_struct *conn = req->conn;
1013 uint64_t ret;
1014 uint64_t dfree,dsize,bsize;
1015 struct smb_filename smb_fname;
1016 START_PROFILE(SMBdskattr);
1018 ZERO_STRUCT(smb_fname);
1019 smb_fname.base_name = discard_const_p(char, ".");
1021 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1022 reply_nterror(req, map_nt_error_from_unix(errno));
1023 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1024 END_PROFILE(SMBdskattr);
1025 return;
1028 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1029 if (ret == (uint64_t)-1) {
1030 reply_nterror(req, map_nt_error_from_unix(errno));
1031 END_PROFILE(SMBdskattr);
1032 return;
1036 * Force max to fit in 16 bit fields.
1038 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1039 dfree /= 2;
1040 dsize /= 2;
1041 bsize *= 2;
1042 if (bsize > (WORDMAX*512)) {
1043 bsize = (WORDMAX*512);
1044 if (dsize > WORDMAX)
1045 dsize = WORDMAX;
1046 if (dfree > WORDMAX)
1047 dfree = WORDMAX;
1048 break;
1052 reply_smb1_outbuf(req, 5, 0);
1054 if (xconn->protocol <= PROTOCOL_LANMAN2) {
1055 double total_space, free_space;
1056 /* we need to scale this to a number that DOS6 can handle. We
1057 use floating point so we can handle large drives on systems
1058 that don't have 64 bit integers
1060 we end up displaying a maximum of 2G to DOS systems
1062 total_space = dsize * (double)bsize;
1063 free_space = dfree * (double)bsize;
1065 dsize = (uint64_t)((total_space+63*512) / (64*512));
1066 dfree = (uint64_t)((free_space+63*512) / (64*512));
1068 if (dsize > 0xFFFF) dsize = 0xFFFF;
1069 if (dfree > 0xFFFF) dfree = 0xFFFF;
1071 SSVAL(req->outbuf,smb_vwv0,dsize);
1072 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1073 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1074 SSVAL(req->outbuf,smb_vwv3,dfree);
1075 } else {
1076 SSVAL(req->outbuf,smb_vwv0,dsize);
1077 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1078 SSVAL(req->outbuf,smb_vwv2,512);
1079 SSVAL(req->outbuf,smb_vwv3,dfree);
1082 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1084 END_PROFILE(SMBdskattr);
1085 return;
1088 /****************************************************************************
1089 Make a dir struct.
1090 ****************************************************************************/
1092 static void make_dir_struct(TALLOC_CTX *ctx,
1093 char *buf,
1094 const char *mask,
1095 const char *fname,
1096 off_t size,
1097 uint32_t mode,
1098 time_t date,
1099 bool uc)
1101 char *p;
1103 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1104 size = 0;
1107 memset(buf+1,' ',11);
1108 if ((p = strchr_m(mask, '.')) != NULL) {
1109 char name[p - mask + 1];
1110 strlcpy(name, mask, sizeof(name));
1111 push_ascii(buf + 1, name, 8, 0);
1112 push_ascii(buf+9,p+1,3, 0);
1113 } else {
1114 push_ascii(buf + 1, mask, 11, 0);
1117 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1118 SCVAL(buf,21,mode);
1119 srv_put_dos_date(buf,22,date);
1120 SSVAL(buf,26,size & 0xFFFF);
1121 SSVAL(buf,28,(size >> 16)&0xFFFF);
1122 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1123 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1124 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1125 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1128 static bool mangle_mask_match(connection_struct *conn,
1129 const char *filename,
1130 const char *mask)
1132 char mname[13];
1134 if (!name_to_8_3(filename, mname, False, conn->params)) {
1135 return False;
1137 return mask_match_search(mname, mask, False);
1140 /****************************************************************************
1141 Get an 8.3 directory entry.
1142 ****************************************************************************/
1144 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1145 void *private_data,
1146 const char *dname,
1147 const char *mask,
1148 char **_fname)
1150 connection_struct *conn = (connection_struct *)private_data;
1152 if ((strcmp(mask, "*.*") == 0) ||
1153 mask_match_search(dname, mask, false) ||
1154 mangle_mask_match(conn, dname, mask)) {
1155 char mname[13];
1156 const char *fname;
1158 * Ensure we can push the original name as UCS2. If
1159 * not, then just don't return this name.
1161 NTSTATUS status;
1162 size_t ret_len = 0;
1163 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1164 uint8_t *tmp = talloc_array(talloc_tos(), uint8_t, len);
1166 status = srvstr_push(NULL,
1167 FLAGS2_UNICODE_STRINGS,
1168 tmp,
1169 dname,
1170 len,
1171 STR_TERMINATE,
1172 &ret_len);
1174 TALLOC_FREE(tmp);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 return false;
1180 if (!mangle_is_8_3(dname, false, conn->params)) {
1181 bool ok =
1182 name_to_8_3(dname, mname, false, conn->params);
1183 if (!ok) {
1184 return false;
1186 fname = mname;
1187 } else {
1188 fname = dname;
1191 *_fname = talloc_strdup(ctx, fname);
1192 if (*_fname == NULL) {
1193 return false;
1196 return true;
1199 return false;
1202 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1203 void *private_data,
1204 struct files_struct *dirfsp,
1205 struct smb_filename *smb_fname,
1206 bool get_dosmode,
1207 uint32_t *_mode)
1209 if (*_mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1211 * Don't show symlinks/special files to old clients
1213 return false;
1216 if (get_dosmode) {
1217 SMB_ASSERT(smb_fname != NULL);
1218 *_mode = fdos_mode(smb_fname->fsp);
1219 if (smb_fname->fsp != NULL) {
1220 smb_fname->st = smb_fname->fsp->fsp_name->st;
1223 return true;
1226 static bool get_dir_entry(TALLOC_CTX *ctx,
1227 connection_struct *conn,
1228 struct dptr_struct *dirptr,
1229 const char *mask,
1230 uint32_t dirtype,
1231 char **_fname,
1232 off_t *_size,
1233 uint32_t *_mode,
1234 struct timespec *_date,
1235 bool check_descend,
1236 bool ask_sharemode)
1238 char *fname = NULL;
1239 struct smb_filename *smb_fname = NULL;
1240 uint32_t mode = 0;
1241 bool ok;
1243 ok = smbd_dirptr_get_entry(ctx,
1244 dirptr,
1245 mask,
1246 dirtype,
1247 check_descend,
1248 ask_sharemode,
1249 true,
1250 smbd_dirptr_8_3_match_fn,
1251 smbd_dirptr_8_3_mode_fn,
1252 conn,
1253 &fname,
1254 &smb_fname,
1255 &mode);
1256 if (!ok) {
1257 return false;
1260 *_fname = talloc_move(ctx, &fname);
1261 *_size = smb_fname->st.st_ex_size;
1262 *_mode = mode;
1263 *_date = smb_fname->st.st_ex_mtime;
1264 TALLOC_FREE(smb_fname);
1265 return true;
1268 /****************************************************************************
1269 Reply to a search.
1270 Can be called from SMBsearch, SMBffirst or SMBfunique.
1271 ****************************************************************************/
1273 void reply_search(struct smb_request *req)
1275 connection_struct *conn = req->conn;
1276 char *path = NULL;
1277 char *mask = NULL;
1278 char *directory = NULL;
1279 struct smb_filename *smb_fname = NULL;
1280 char *fname = NULL;
1281 off_t size;
1282 uint32_t mode;
1283 struct timespec date;
1284 uint32_t dirtype;
1285 unsigned int numentries = 0;
1286 unsigned int maxentries = 0;
1287 bool finished = False;
1288 const char *p;
1289 int status_len;
1290 char status[21];
1291 int dptr_num= -1;
1292 bool check_descend = False;
1293 bool expect_close = False;
1294 NTSTATUS nt_status;
1295 bool mask_contains_wcard = False;
1296 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1297 TALLOC_CTX *ctx = talloc_tos();
1298 struct smbXsrv_connection *xconn = req->xconn;
1299 struct smbd_server_connection *sconn = req->sconn;
1300 files_struct *fsp = NULL;
1301 const struct loadparm_substitution *lp_sub =
1302 loadparm_s3_global_substitution();
1304 START_PROFILE(SMBsearch);
1306 if (req->wct < 2) {
1307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1308 goto out;
1311 if (req->posix_pathnames) {
1312 reply_unknown_new(req, req->cmd);
1313 goto out;
1316 /* If we were called as SMBffirst then we must expect close. */
1317 if(req->cmd == SMBffirst) {
1318 expect_close = True;
1321 reply_smb1_outbuf(req, 1, 3);
1322 maxentries = SVAL(req->vwv+0, 0);
1323 dirtype = SVAL(req->vwv+1, 0);
1324 p = (const char *)req->buf + 1;
1325 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1326 &nt_status);
1327 if (!NT_STATUS_IS_OK(nt_status)) {
1328 reply_nterror(req, nt_status);
1329 goto out;
1332 if (smbreq_bufrem(req, p) < 3) {
1333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1334 goto out;
1337 p++;
1338 status_len = SVAL(p, 0);
1339 p += 2;
1341 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1343 if (status_len == 0) {
1344 const char *dirpath;
1345 struct files_struct *dirfsp = NULL;
1346 struct smb_filename *smb_dname = NULL;
1347 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1349 nt_status = smb1_strip_dfs_path(ctx, &ucf_flags, &path);
1350 if (!NT_STATUS_IS_OK(nt_status)) {
1351 reply_nterror(req, nt_status);
1352 goto out;
1355 nt_status = filename_convert_smb1_search_path(ctx,
1356 conn,
1357 path,
1358 ucf_flags,
1359 &dirfsp,
1360 &smb_dname,
1361 &mask);
1363 if (!NT_STATUS_IS_OK(nt_status)) {
1364 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1365 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1366 ERRSRV, ERRbadpath);
1367 goto out;
1369 reply_nterror(req, nt_status);
1370 goto out;
1373 memset((char *)status,'\0',21);
1374 SCVAL(status,0,(dirtype & 0x1F));
1377 * Open an fsp on this directory for the dptr.
1379 nt_status = SMB_VFS_CREATE_FILE(
1380 conn, /* conn */
1381 req, /* req */
1382 dirfsp, /* dirfsp */
1383 smb_dname, /* dname */
1384 FILE_LIST_DIRECTORY, /* access_mask */
1385 FILE_SHARE_READ|
1386 FILE_SHARE_WRITE, /* share_access */
1387 FILE_OPEN, /* create_disposition*/
1388 FILE_DIRECTORY_FILE, /* create_options */
1389 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1390 NO_OPLOCK, /* oplock_request */
1391 NULL, /* lease */
1392 0, /* allocation_size */
1393 0, /* private_flags */
1394 NULL, /* sd */
1395 NULL, /* ea_list */
1396 &fsp, /* result */
1397 NULL, /* pinfo */
1398 NULL, /* in_context */
1399 NULL);/* out_context */
1401 if (!NT_STATUS_IS_OK(nt_status)) {
1402 DBG_ERR("failed to open directory %s\n",
1403 smb_fname_str_dbg(smb_dname));
1404 reply_nterror(req, nt_status);
1405 goto out;
1408 nt_status = dptr_create(conn,
1409 NULL, /* req */
1410 fsp, /* fsp */
1411 True,
1412 mask,
1413 dirtype,
1414 &fsp->dptr);
1416 TALLOC_FREE(smb_dname);
1418 if (!NT_STATUS_IS_OK(nt_status)) {
1420 * Use NULL here for the first parameter (req)
1421 * as this is not a client visible handle so
1422 * can't be part of an SMB1 chain.
1424 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1425 reply_nterror(req, nt_status);
1426 goto out;
1429 dptr_num = dptr_dnum(fsp->dptr);
1430 dirpath = dptr_path(sconn, dptr_num);
1431 directory = talloc_strdup(ctx, dirpath);
1432 if (!directory) {
1433 reply_nterror(req, NT_STATUS_NO_MEMORY);
1434 goto out;
1437 } else {
1438 int status_dirtype;
1439 const char *dirpath;
1440 unsigned int dptr_filenum;
1441 uint32_t resume_key_index;
1443 if (smbreq_bufrem(req, p) < 21) {
1444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1445 goto out;
1448 memcpy(status,p,21);
1449 status_dirtype = CVAL(status,0) & 0x1F;
1450 if (status_dirtype != (dirtype & 0x1F)) {
1451 dirtype = status_dirtype;
1454 dptr_num = CVAL(status, 12);
1455 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1456 if (fsp == NULL) {
1457 goto SearchEmpty;
1460 resume_key_index = PULL_LE_U32(status, 13);
1461 dptr_filenum = dptr_FileNumber(fsp->dptr);
1463 if (resume_key_index > dptr_filenum) {
1465 * Haven't seen this resume key yet. Just stop
1466 * the search.
1468 goto SearchEmpty;
1471 if (resume_key_index < dptr_filenum) {
1473 * The resume key was not the last one we
1474 * sent, rewind and skip to what the client
1475 * sent.
1477 dptr_RewindDir(fsp->dptr);
1479 dptr_filenum = dptr_FileNumber(fsp->dptr);
1480 SMB_ASSERT(dptr_filenum == 0);
1482 while (dptr_filenum < resume_key_index) {
1483 bool ok = get_dir_entry(
1484 ctx,
1485 conn,
1486 fsp->dptr,
1487 dptr_wcard(sconn, dptr_num),
1488 dirtype,
1489 &fname,
1490 &size,
1491 &mode,
1492 &date,
1493 check_descend,
1494 false);
1495 TALLOC_FREE(fname);
1496 if (!ok) {
1497 goto SearchEmpty;
1500 dptr_filenum = dptr_FileNumber(fsp->dptr);
1504 dirpath = dptr_path(sconn, dptr_num);
1505 directory = talloc_strdup(ctx, dirpath);
1506 if (!directory) {
1507 reply_nterror(req, NT_STATUS_NO_MEMORY);
1508 goto out;
1511 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1512 if (!mask) {
1513 goto SearchEmpty;
1515 dirtype = dptr_attr(sconn, dptr_num);
1518 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1520 DEBUG(4,("dptr_num is %d\n",dptr_num));
1522 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1523 char buf[DIR_STRUCT_SIZE];
1524 memcpy(buf,status,21);
1525 make_dir_struct(ctx,
1526 buf,
1527 "???????????",
1528 volume_label(ctx, SNUM(conn)),
1530 FILE_ATTRIBUTE_VOLUME,
1532 !allow_long_path_components);
1533 SCVAL(buf, 12, dptr_num);
1534 numentries = 1;
1535 if (message_push_blob(&req->outbuf,
1536 data_blob_const(buf, sizeof(buf)))
1537 == -1) {
1538 reply_nterror(req, NT_STATUS_NO_MEMORY);
1539 goto out;
1541 } else {
1542 unsigned int i;
1543 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1544 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1545 bool ask_sharemode;
1547 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1549 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1550 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1551 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1552 check_descend = True;
1555 ask_sharemode = fsp_search_ask_sharemode(fsp);
1557 for (i=numentries;(i<maxentries) && !finished;i++) {
1558 finished = !get_dir_entry(ctx,
1559 conn,
1560 fsp->dptr,
1561 mask,
1562 dirtype,
1563 &fname,
1564 &size,
1565 &mode,
1566 &date,
1567 check_descend,
1568 ask_sharemode);
1569 if (!finished) {
1570 char buf[DIR_STRUCT_SIZE];
1571 memcpy(buf,status,21);
1572 make_dir_struct(
1573 ctx,
1574 buf,
1575 mask,
1576 fname,
1577 size,
1578 mode,
1579 convert_timespec_to_time_t(date),
1580 !allow_long_path_components);
1581 SCVAL(buf, 12, dptr_num);
1582 PUSH_LE_U32(buf,
1584 dptr_FileNumber(fsp->dptr));
1585 if (message_push_blob(&req->outbuf,
1586 data_blob_const(buf, sizeof(buf)))
1587 == -1) {
1588 reply_nterror(req, NT_STATUS_NO_MEMORY);
1589 goto out;
1591 numentries++;
1593 TALLOC_FREE(fname);
1597 SearchEmpty:
1599 /* If we were called as SMBffirst with smb_search_id == NULL
1600 and no entries were found then return error and close fsp->dptr
1601 (X/Open spec) */
1603 if (numentries == 0) {
1604 dptr_num = -1;
1605 if (fsp != NULL) {
1606 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1608 } else if(expect_close && status_len == 0) {
1609 /* Close the dptr - we know it's gone */
1610 dptr_num = -1;
1611 if (fsp != NULL) {
1612 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1616 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1617 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1618 dptr_num = -1;
1619 /* fsp may have been closed above. */
1620 if (fsp != NULL) {
1621 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1625 if ((numentries == 0) && !mask_contains_wcard) {
1626 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1627 goto out;
1630 SSVAL(req->outbuf,smb_vwv0,numentries);
1631 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1632 SCVAL(smb_buf(req->outbuf),0,5);
1633 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1635 /* The replies here are never long name. */
1636 SSVAL(req->outbuf, smb_flg2,
1637 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1638 if (!allow_long_path_components) {
1639 SSVAL(req->outbuf, smb_flg2,
1640 SVAL(req->outbuf, smb_flg2)
1641 & (~FLAGS2_LONG_PATH_COMPONENTS));
1644 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1645 SSVAL(req->outbuf, smb_flg2,
1646 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1648 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1649 smb_fn_name(req->cmd),
1650 mask,
1651 directory,
1652 dirtype,
1653 numentries,
1654 maxentries ));
1655 out:
1656 TALLOC_FREE(directory);
1657 TALLOC_FREE(mask);
1658 TALLOC_FREE(smb_fname);
1659 END_PROFILE(SMBsearch);
1660 return;
1663 /****************************************************************************
1664 Reply to a fclose (stop directory search).
1665 ****************************************************************************/
1667 void reply_fclose(struct smb_request *req)
1669 int status_len;
1670 int dptr_num= -2;
1671 const char *p;
1672 char *path = NULL;
1673 NTSTATUS err;
1674 TALLOC_CTX *ctx = talloc_tos();
1675 struct smbd_server_connection *sconn = req->sconn;
1676 files_struct *fsp = NULL;
1678 START_PROFILE(SMBfclose);
1680 if (req->posix_pathnames) {
1681 reply_unknown_new(req, req->cmd);
1682 END_PROFILE(SMBfclose);
1683 return;
1686 p = (const char *)req->buf + 1;
1687 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1688 &err);
1689 if (!NT_STATUS_IS_OK(err)) {
1690 reply_nterror(req, err);
1691 END_PROFILE(SMBfclose);
1692 return;
1695 if (smbreq_bufrem(req, p) < 3) {
1696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1697 END_PROFILE(SMBfclose);
1698 return;
1701 p++;
1702 status_len = SVAL(p,0);
1703 p += 2;
1705 if (status_len == 0) {
1706 reply_force_doserror(req, ERRSRV, ERRsrverror);
1707 END_PROFILE(SMBfclose);
1708 return;
1711 if (smbreq_bufrem(req, p) < 21) {
1712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1713 END_PROFILE(SMBfclose);
1714 return;
1717 dptr_num = CVAL(p, 12);
1719 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1720 if(fsp != NULL) {
1721 /* Close the file - we know it's gone */
1722 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1723 dptr_num = -1;
1726 reply_smb1_outbuf(req, 1, 0);
1727 SSVAL(req->outbuf,smb_vwv0,0);
1729 DEBUG(3,("search close\n"));
1731 END_PROFILE(SMBfclose);
1732 return;
1735 /****************************************************************************
1736 Reply to an open.
1737 ****************************************************************************/
1739 void reply_open(struct smb_request *req)
1741 connection_struct *conn = req->conn;
1742 struct smb_filename *smb_fname = NULL;
1743 char *fname = NULL;
1744 uint32_t fattr=0;
1745 off_t size = 0;
1746 time_t mtime=0;
1747 int info;
1748 struct files_struct *dirfsp = NULL;
1749 files_struct *fsp;
1750 int oplock_request;
1751 int deny_mode;
1752 uint32_t dos_attr;
1753 uint32_t access_mask;
1754 uint32_t share_mode;
1755 uint32_t create_disposition;
1756 uint32_t create_options = 0;
1757 uint32_t private_flags = 0;
1758 NTSTATUS status;
1759 uint32_t ucf_flags;
1760 NTTIME twrp = 0;
1761 TALLOC_CTX *ctx = talloc_tos();
1763 START_PROFILE(SMBopen);
1765 if (req->wct < 2) {
1766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1767 goto out;
1770 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1771 deny_mode = SVAL(req->vwv+0, 0);
1772 dos_attr = SVAL(req->vwv+1, 0);
1774 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1775 STR_TERMINATE, &status);
1776 if (!NT_STATUS_IS_OK(status)) {
1777 reply_nterror(req, status);
1778 goto out;
1781 if (!map_open_params_to_ntcreate(fname, deny_mode,
1782 OPENX_FILE_EXISTS_OPEN, &access_mask,
1783 &share_mode, &create_disposition,
1784 &create_options, &private_flags)) {
1785 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1786 goto out;
1789 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1791 if (ucf_flags & UCF_GMT_PATHNAME) {
1792 extract_snapshot_token(fname, &twrp);
1794 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 reply_nterror(req, status);
1797 goto out;
1799 status = filename_convert_dirfsp(ctx,
1800 conn,
1801 fname,
1802 ucf_flags,
1803 twrp,
1804 &dirfsp,
1805 &smb_fname);
1806 if (!NT_STATUS_IS_OK(status)) {
1807 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1808 reply_botherror(req,
1809 NT_STATUS_PATH_NOT_COVERED,
1810 ERRSRV, ERRbadpath);
1811 goto out;
1813 reply_nterror(req, status);
1814 goto out;
1817 status = SMB_VFS_CREATE_FILE(
1818 conn, /* conn */
1819 req, /* req */
1820 dirfsp, /* dirfsp */
1821 smb_fname, /* fname */
1822 access_mask, /* access_mask */
1823 share_mode, /* share_access */
1824 create_disposition, /* create_disposition*/
1825 create_options, /* create_options */
1826 dos_attr, /* file_attributes */
1827 oplock_request, /* oplock_request */
1828 NULL, /* lease */
1829 0, /* allocation_size */
1830 private_flags,
1831 NULL, /* sd */
1832 NULL, /* ea_list */
1833 &fsp, /* result */
1834 &info, /* pinfo */
1835 NULL, NULL); /* create context */
1837 if (!NT_STATUS_IS_OK(status)) {
1838 if (open_was_deferred(req->xconn, req->mid)) {
1839 /* We have re-scheduled this call. */
1840 goto out;
1843 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1844 reply_openerror(req, status);
1845 goto out;
1848 fsp = fcb_or_dos_open(
1849 req,
1850 smb_fname,
1851 access_mask,
1852 create_options,
1853 private_flags);
1854 if (fsp == NULL) {
1855 bool ok = defer_smb1_sharing_violation(req);
1856 if (ok) {
1857 goto out;
1859 reply_openerror(req, status);
1860 goto out;
1864 /* Ensure we're pointing at the correct stat struct. */
1865 TALLOC_FREE(smb_fname);
1866 smb_fname = fsp->fsp_name;
1868 size = smb_fname->st.st_ex_size;
1869 fattr = fdos_mode(fsp);
1871 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1873 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1874 DEBUG(3,("attempt to open a directory %s\n",
1875 fsp_str_dbg(fsp)));
1876 close_file_free(req, &fsp, ERROR_CLOSE);
1877 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1878 ERRDOS, ERRnoaccess);
1879 goto out;
1882 reply_smb1_outbuf(req, 7, 0);
1883 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1884 SSVAL(req->outbuf,smb_vwv1,fattr);
1885 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1886 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1887 } else {
1888 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1890 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1891 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1893 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1894 SCVAL(req->outbuf,smb_flg,
1895 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1898 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1899 SCVAL(req->outbuf,smb_flg,
1900 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1902 out:
1903 END_PROFILE(SMBopen);
1904 return;
1907 /****************************************************************************
1908 Reply to an open and X.
1909 ****************************************************************************/
1911 void reply_open_and_X(struct smb_request *req)
1913 connection_struct *conn = req->conn;
1914 struct smb_filename *smb_fname = NULL;
1915 char *fname = NULL;
1916 uint16_t open_flags;
1917 int deny_mode;
1918 uint32_t smb_attr;
1919 /* Breakout the oplock request bits so we can set the
1920 reply bits separately. */
1921 int ex_oplock_request;
1922 int core_oplock_request;
1923 int oplock_request;
1924 #if 0
1925 int smb_sattr = SVAL(req->vwv+4, 0);
1926 uint32_t smb_time = make_unix_date3(req->vwv+6);
1927 #endif
1928 int smb_ofun;
1929 uint32_t fattr=0;
1930 int mtime=0;
1931 int smb_action = 0;
1932 struct files_struct *dirfsp = NULL;
1933 files_struct *fsp;
1934 NTSTATUS status;
1935 uint64_t allocation_size;
1936 ssize_t retval = -1;
1937 uint32_t access_mask;
1938 uint32_t share_mode;
1939 uint32_t create_disposition;
1940 uint32_t create_options = 0;
1941 uint32_t private_flags = 0;
1942 uint32_t ucf_flags;
1943 NTTIME twrp = 0;
1944 TALLOC_CTX *ctx = talloc_tos();
1946 START_PROFILE(SMBopenX);
1948 if (req->wct < 15) {
1949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1950 goto out;
1953 open_flags = SVAL(req->vwv+2, 0);
1954 deny_mode = SVAL(req->vwv+3, 0);
1955 smb_attr = SVAL(req->vwv+5, 0);
1956 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1957 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1958 oplock_request = ex_oplock_request | core_oplock_request;
1959 smb_ofun = SVAL(req->vwv+8, 0);
1960 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1962 /* If it's an IPC, pass off the pipe handler. */
1963 if (IS_IPC(conn)) {
1964 if (lp_nt_pipe_support()) {
1965 reply_open_pipe_and_X(conn, req);
1966 } else {
1967 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1969 goto out;
1972 /* XXXX we need to handle passed times, sattr and flags */
1973 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1974 STR_TERMINATE, &status);
1975 if (!NT_STATUS_IS_OK(status)) {
1976 reply_nterror(req, status);
1977 goto out;
1980 if (!map_open_params_to_ntcreate(fname, deny_mode,
1981 smb_ofun,
1982 &access_mask, &share_mode,
1983 &create_disposition,
1984 &create_options,
1985 &private_flags)) {
1986 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1987 goto out;
1990 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1992 if (ucf_flags & UCF_GMT_PATHNAME) {
1993 extract_snapshot_token(fname, &twrp);
1995 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1996 if (!NT_STATUS_IS_OK(status)) {
1997 reply_nterror(req, status);
1998 goto out;
2001 status = filename_convert_dirfsp(ctx,
2002 conn,
2003 fname,
2004 ucf_flags,
2005 twrp,
2006 &dirfsp,
2007 &smb_fname);
2008 if (!NT_STATUS_IS_OK(status)) {
2009 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2010 reply_botherror(req,
2011 NT_STATUS_PATH_NOT_COVERED,
2012 ERRSRV, ERRbadpath);
2013 goto out;
2015 reply_nterror(req, status);
2016 goto out;
2019 status = SMB_VFS_CREATE_FILE(
2020 conn, /* conn */
2021 req, /* req */
2022 dirfsp, /* dirfsp */
2023 smb_fname, /* fname */
2024 access_mask, /* access_mask */
2025 share_mode, /* share_access */
2026 create_disposition, /* create_disposition*/
2027 create_options, /* create_options */
2028 smb_attr, /* file_attributes */
2029 oplock_request, /* oplock_request */
2030 NULL, /* lease */
2031 0, /* allocation_size */
2032 private_flags,
2033 NULL, /* sd */
2034 NULL, /* ea_list */
2035 &fsp, /* result */
2036 &smb_action, /* pinfo */
2037 NULL, NULL); /* create context */
2039 if (!NT_STATUS_IS_OK(status)) {
2040 if (open_was_deferred(req->xconn, req->mid)) {
2041 /* We have re-scheduled this call. */
2042 goto out;
2045 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2046 reply_openerror(req, status);
2047 goto out;
2050 fsp = fcb_or_dos_open(
2051 req,
2052 smb_fname,
2053 access_mask,
2054 create_options,
2055 private_flags);
2056 if (fsp == NULL) {
2057 bool ok = defer_smb1_sharing_violation(req);
2058 if (ok) {
2059 goto out;
2061 reply_openerror(req, status);
2062 goto out;
2066 smb_action = FILE_WAS_OPENED;
2069 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2070 if the file is truncated or created. */
2071 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2072 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2073 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2074 close_file_free(req, &fsp, ERROR_CLOSE);
2075 reply_nterror(req, NT_STATUS_DISK_FULL);
2076 goto out;
2078 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2079 if (retval < 0) {
2080 close_file_free(req, &fsp, ERROR_CLOSE);
2081 reply_nterror(req, NT_STATUS_DISK_FULL);
2082 goto out;
2084 status = vfs_stat_fsp(fsp);
2085 if (!NT_STATUS_IS_OK(status)) {
2086 close_file_free(req, &fsp, ERROR_CLOSE);
2087 reply_nterror(req, status);
2088 goto out;
2092 fattr = fdos_mode(fsp);
2093 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2094 close_file_free(req, &fsp, ERROR_CLOSE);
2095 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2096 goto out;
2098 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2100 /* If the caller set the extended oplock request bit
2101 and we granted one (by whatever means) - set the
2102 correct bit for extended oplock reply.
2105 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2106 smb_action |= EXTENDED_OPLOCK_GRANTED;
2109 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2110 smb_action |= EXTENDED_OPLOCK_GRANTED;
2113 /* If the caller set the core oplock request bit
2114 and we granted one (by whatever means) - set the
2115 correct bit for core oplock reply.
2118 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2119 reply_smb1_outbuf(req, 19, 0);
2120 } else {
2121 reply_smb1_outbuf(req, 15, 0);
2124 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2125 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2127 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2128 SCVAL(req->outbuf, smb_flg,
2129 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2132 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2133 SCVAL(req->outbuf, smb_flg,
2134 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2137 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2138 SSVAL(req->outbuf,smb_vwv3,fattr);
2139 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2140 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2141 } else {
2142 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2144 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2145 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2146 SSVAL(req->outbuf,smb_vwv11,smb_action);
2148 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2149 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2152 out:
2153 TALLOC_FREE(smb_fname);
2154 END_PROFILE(SMBopenX);
2155 return;
2158 /****************************************************************************
2159 Reply to a SMBulogoffX.
2160 ****************************************************************************/
2162 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2163 struct smbXsrv_session *session);
2164 static void reply_ulogoffX_done(struct tevent_req *req);
2166 void reply_ulogoffX(struct smb_request *smb1req)
2168 struct timeval now = timeval_current();
2169 struct smbXsrv_session *session = NULL;
2170 struct tevent_req *req;
2171 NTSTATUS status;
2174 * Don't setup the profile charge here, take
2175 * it in reply_ulogoffX_done(). Not strictly correct
2176 * but better than the other SMB1 async
2177 * code that double-charges at the moment.
2180 status = smb1srv_session_lookup(smb1req->xconn,
2181 smb1req->vuid,
2182 timeval_to_nttime(&now),
2183 &session);
2184 if (!NT_STATUS_IS_OK(status)) {
2185 /* Not going async, profile here. */
2186 START_PROFILE(SMBulogoffX);
2187 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2188 (unsigned long long)smb1req->vuid);
2190 smb1req->vuid = UID_FIELD_INVALID;
2191 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2192 END_PROFILE(SMBulogoffX);
2193 return;
2196 req = reply_ulogoffX_send(smb1req, session);
2197 if (req == NULL) {
2198 /* Not going async, profile here. */
2199 START_PROFILE(SMBulogoffX);
2200 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2201 END_PROFILE(SMBulogoffX);
2202 return;
2205 /* We're async. This will complete later. */
2206 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2207 return;
2210 struct reply_ulogoffX_state {
2211 struct tevent_queue *wait_queue;
2212 struct smbXsrv_session *session;
2215 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2217 /****************************************************************************
2218 Async SMB1 ulogoffX.
2219 Note, on failure here we deallocate and return NULL to allow the caller to
2220 SMB1 return an error of ERRnomem immediately.
2221 ****************************************************************************/
2223 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2224 struct smbXsrv_session *session)
2226 struct tevent_req *req;
2227 struct reply_ulogoffX_state *state;
2228 struct tevent_req *subreq;
2229 files_struct *fsp;
2230 struct smbd_server_connection *sconn = session->client->sconn;
2231 uint64_t vuid = session->global->session_wire_id;
2233 req = tevent_req_create(smb1req, &state,
2234 struct reply_ulogoffX_state);
2235 if (req == NULL) {
2236 return NULL;
2238 state->wait_queue = tevent_queue_create(state,
2239 "reply_ulogoffX_wait_queue");
2240 if (tevent_req_nomem(state->wait_queue, req)) {
2241 TALLOC_FREE(req);
2242 return NULL;
2244 state->session = session;
2247 * Make sure that no new request will be able to use this session.
2248 * This ensures that once all outstanding fsp->aio_requests
2249 * on this session are done, we are safe to close it.
2251 session->status = NT_STATUS_USER_SESSION_DELETED;
2253 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2254 if (fsp->vuid != vuid) {
2255 continue;
2258 * Flag the file as close in progress.
2259 * This will prevent any more IO being
2260 * done on it.
2262 fsp->fsp_flags.closing = true;
2264 if (fsp->num_aio_requests > 0) {
2266 * Now wait until all aio requests on this fsp are
2267 * finished.
2269 * We don't set a callback, as we just want to block the
2270 * wait queue and the talloc_free() of fsp->aio_request
2271 * will remove the item from the wait queue.
2273 subreq = tevent_queue_wait_send(fsp->aio_requests,
2274 sconn->ev_ctx,
2275 state->wait_queue);
2276 if (tevent_req_nomem(subreq, req)) {
2277 TALLOC_FREE(req);
2278 return NULL;
2284 * Now we add our own waiter to the end of the queue,
2285 * this way we get notified when all pending requests are finished
2286 * and reply to the outstanding SMB1 request.
2288 subreq = tevent_queue_wait_send(state,
2289 sconn->ev_ctx,
2290 state->wait_queue);
2291 if (tevent_req_nomem(subreq, req)) {
2292 TALLOC_FREE(req);
2293 return NULL;
2297 * We're really going async - move the SMB1 request from
2298 * a talloc stackframe above us to the sconn talloc-context.
2299 * We need this to stick around until the wait_done
2300 * callback is invoked.
2302 smb1req = talloc_move(sconn, &smb1req);
2304 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2306 return req;
2309 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2311 struct tevent_req *req = tevent_req_callback_data(
2312 subreq, struct tevent_req);
2314 tevent_queue_wait_recv(subreq);
2315 TALLOC_FREE(subreq);
2316 tevent_req_done(req);
2319 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2321 return tevent_req_simple_recv_ntstatus(req);
2324 static void reply_ulogoffX_done(struct tevent_req *req)
2326 struct smb_request *smb1req = tevent_req_callback_data(
2327 req, struct smb_request);
2328 struct reply_ulogoffX_state *state = tevent_req_data(req,
2329 struct reply_ulogoffX_state);
2330 struct smbXsrv_session *session = state->session;
2331 NTSTATUS status;
2334 * Take the profile charge here. Not strictly
2335 * correct but better than the other SMB1 async
2336 * code that double-charges at the moment.
2338 START_PROFILE(SMBulogoffX);
2340 status = reply_ulogoffX_recv(req);
2341 TALLOC_FREE(req);
2342 if (!NT_STATUS_IS_OK(status)) {
2343 TALLOC_FREE(smb1req);
2344 END_PROFILE(SMBulogoffX);
2345 exit_server(__location__ ": reply_ulogoffX_recv failed");
2346 return;
2349 status = smbXsrv_session_logoff(session);
2350 if (!NT_STATUS_IS_OK(status)) {
2351 TALLOC_FREE(smb1req);
2352 END_PROFILE(SMBulogoffX);
2353 exit_server(__location__ ": smbXsrv_session_logoff failed");
2354 return;
2357 TALLOC_FREE(session);
2359 reply_smb1_outbuf(smb1req, 2, 0);
2360 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2361 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2363 DBG_NOTICE("ulogoffX vuid=%llu\n",
2364 (unsigned long long)smb1req->vuid);
2366 smb1req->vuid = UID_FIELD_INVALID;
2368 * The following call is needed to push the
2369 * reply data back out the socket after async
2370 * return. Plus it frees smb1req.
2372 smb_request_done(smb1req);
2373 END_PROFILE(SMBulogoffX);
2376 /****************************************************************************
2377 Reply to a mknew or a create.
2378 ****************************************************************************/
2380 void reply_mknew(struct smb_request *req)
2382 connection_struct *conn = req->conn;
2383 struct smb_filename *smb_fname = NULL;
2384 char *fname = NULL;
2385 uint32_t fattr = 0;
2386 struct smb_file_time ft;
2387 struct files_struct *dirfsp = NULL;
2388 files_struct *fsp;
2389 int oplock_request = 0;
2390 NTSTATUS status;
2391 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2392 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2393 uint32_t create_disposition;
2394 uint32_t create_options = 0;
2395 uint32_t ucf_flags;
2396 NTTIME twrp = 0;
2397 TALLOC_CTX *ctx = talloc_tos();
2399 START_PROFILE(SMBcreate);
2400 init_smb_file_time(&ft);
2402 if (req->wct < 3) {
2403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2404 goto out;
2407 fattr = SVAL(req->vwv+0, 0);
2408 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2410 if (req->cmd == SMBmknew) {
2411 /* We should fail if file exists. */
2412 create_disposition = FILE_CREATE;
2413 } else {
2414 /* Create if file doesn't exist, truncate if it does. */
2415 create_disposition = FILE_OVERWRITE_IF;
2418 /* mtime. */
2419 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2421 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2422 STR_TERMINATE, &status);
2423 if (!NT_STATUS_IS_OK(status)) {
2424 reply_nterror(req, status);
2425 goto out;
2428 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2429 if (ucf_flags & UCF_GMT_PATHNAME) {
2430 extract_snapshot_token(fname, &twrp);
2432 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2433 if (!NT_STATUS_IS_OK(status)) {
2434 reply_nterror(req, status);
2435 goto out;
2438 status = filename_convert_dirfsp(ctx,
2439 conn,
2440 fname,
2441 ucf_flags,
2442 twrp,
2443 &dirfsp,
2444 &smb_fname);
2445 if (!NT_STATUS_IS_OK(status)) {
2446 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2447 reply_botherror(req,
2448 NT_STATUS_PATH_NOT_COVERED,
2449 ERRSRV, ERRbadpath);
2450 goto out;
2452 reply_nterror(req, status);
2453 goto out;
2456 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2457 DEBUG(0,("Attempt to create file (%s) with volid set - "
2458 "please report this\n",
2459 smb_fname_str_dbg(smb_fname)));
2462 status = SMB_VFS_CREATE_FILE(
2463 conn, /* conn */
2464 req, /* req */
2465 dirfsp, /* dirfsp */
2466 smb_fname, /* fname */
2467 access_mask, /* access_mask */
2468 share_mode, /* share_access */
2469 create_disposition, /* create_disposition*/
2470 create_options, /* create_options */
2471 fattr, /* file_attributes */
2472 oplock_request, /* oplock_request */
2473 NULL, /* lease */
2474 0, /* allocation_size */
2475 0, /* private_flags */
2476 NULL, /* sd */
2477 NULL, /* ea_list */
2478 &fsp, /* result */
2479 NULL, /* pinfo */
2480 NULL, NULL); /* create context */
2482 if (!NT_STATUS_IS_OK(status)) {
2483 if (open_was_deferred(req->xconn, req->mid)) {
2484 /* We have re-scheduled this call. */
2485 goto out;
2487 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2488 bool ok = defer_smb1_sharing_violation(req);
2489 if (ok) {
2490 goto out;
2493 reply_openerror(req, status);
2494 goto out;
2497 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2498 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 END_PROFILE(SMBcreate);
2501 goto out;
2504 reply_smb1_outbuf(req, 1, 0);
2505 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2507 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2508 SCVAL(req->outbuf,smb_flg,
2509 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2512 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2513 SCVAL(req->outbuf,smb_flg,
2514 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2517 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2518 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2519 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2520 (unsigned int)fattr));
2522 out:
2523 TALLOC_FREE(smb_fname);
2524 END_PROFILE(SMBcreate);
2525 return;
2528 /****************************************************************************
2529 Reply to a create temporary file.
2530 ****************************************************************************/
2532 void reply_ctemp(struct smb_request *req)
2534 connection_struct *conn = req->conn;
2535 struct smb_filename *smb_fname = NULL;
2536 char *wire_name = NULL;
2537 char *fname = NULL;
2538 uint32_t fattr;
2539 struct files_struct *dirfsp = NULL;
2540 files_struct *fsp;
2541 int oplock_request;
2542 char *s;
2543 NTSTATUS status;
2544 int i;
2545 uint32_t ucf_flags;
2546 NTTIME twrp = 0;
2547 TALLOC_CTX *ctx = talloc_tos();
2549 START_PROFILE(SMBctemp);
2551 if (req->wct < 3) {
2552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2553 goto out;
2556 fattr = SVAL(req->vwv+0, 0);
2557 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2559 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2560 STR_TERMINATE, &status);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 reply_nterror(req, status);
2563 goto out;
2566 for (i = 0; i < 10; i++) {
2567 if (*wire_name) {
2568 fname = talloc_asprintf(ctx,
2569 "%s/TMP%s",
2570 wire_name,
2571 generate_random_str_list(ctx, 5, "0123456789"));
2572 } else {
2573 fname = talloc_asprintf(ctx,
2574 "TMP%s",
2575 generate_random_str_list(ctx, 5, "0123456789"));
2578 if (!fname) {
2579 reply_nterror(req, NT_STATUS_NO_MEMORY);
2580 goto out;
2583 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2584 if (ucf_flags & UCF_GMT_PATHNAME) {
2585 extract_snapshot_token(fname, &twrp);
2587 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2588 if (!NT_STATUS_IS_OK(status)) {
2589 reply_nterror(req, status);
2590 goto out;
2593 status = filename_convert_dirfsp(ctx,
2594 conn,
2595 fname,
2596 ucf_flags,
2597 twrp,
2598 &dirfsp,
2599 &smb_fname);
2600 if (!NT_STATUS_IS_OK(status)) {
2601 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2602 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2603 ERRSRV, ERRbadpath);
2604 goto out;
2606 reply_nterror(req, status);
2607 goto out;
2610 /* Create the file. */
2611 status = SMB_VFS_CREATE_FILE(
2612 conn, /* conn */
2613 req, /* req */
2614 dirfsp, /* dirfsp */
2615 smb_fname, /* fname */
2616 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2617 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2618 FILE_CREATE, /* create_disposition*/
2619 0, /* create_options */
2620 fattr, /* file_attributes */
2621 oplock_request, /* oplock_request */
2622 NULL, /* lease */
2623 0, /* allocation_size */
2624 0, /* private_flags */
2625 NULL, /* sd */
2626 NULL, /* ea_list */
2627 &fsp, /* result */
2628 NULL, /* pinfo */
2629 NULL, NULL); /* create context */
2631 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2632 TALLOC_FREE(fname);
2633 TALLOC_FREE(dirfsp);
2634 TALLOC_FREE(smb_fname);
2635 continue;
2638 if (!NT_STATUS_IS_OK(status)) {
2639 if (open_was_deferred(req->xconn, req->mid)) {
2640 /* We have re-scheduled this call. */
2641 goto out;
2643 if (NT_STATUS_EQUAL(
2644 status, NT_STATUS_SHARING_VIOLATION)) {
2645 bool ok = defer_smb1_sharing_violation(req);
2646 if (ok) {
2647 goto out;
2650 reply_openerror(req, status);
2651 goto out;
2654 break;
2657 if (i == 10) {
2658 /* Collision after 10 times... */
2659 reply_nterror(req, status);
2660 goto out;
2663 reply_smb1_outbuf(req, 1, 0);
2664 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2666 /* the returned filename is relative to the directory */
2667 s = strrchr_m(fsp->fsp_name->base_name, '/');
2668 if (!s) {
2669 s = fsp->fsp_name->base_name;
2670 } else {
2671 s++;
2674 #if 0
2675 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2676 thing in the byte section. JRA */
2677 SSVALS(p, 0, -1); /* what is this? not in spec */
2678 #endif
2679 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2680 == -1) {
2681 reply_nterror(req, NT_STATUS_NO_MEMORY);
2682 goto out;
2685 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2686 SCVAL(req->outbuf, smb_flg,
2687 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2690 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2691 SCVAL(req->outbuf, smb_flg,
2692 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2695 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2696 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2697 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2698 out:
2699 TALLOC_FREE(smb_fname);
2700 TALLOC_FREE(wire_name);
2701 END_PROFILE(SMBctemp);
2702 return;
2705 /****************************************************************************
2706 Reply to a unlink
2707 ****************************************************************************/
2709 void reply_unlink(struct smb_request *req)
2711 connection_struct *conn = req->conn;
2712 char *name = NULL;
2713 struct files_struct *dirfsp = NULL;
2714 struct smb_filename *smb_fname = NULL;
2715 uint32_t dirtype;
2716 NTSTATUS status;
2717 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2718 NTTIME twrp = 0;
2719 TALLOC_CTX *ctx = talloc_tos();
2721 START_PROFILE(SMBunlink);
2723 if (req->wct < 1) {
2724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2725 goto out;
2728 dirtype = SVAL(req->vwv+0, 0);
2730 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2731 STR_TERMINATE, &status);
2732 if (!NT_STATUS_IS_OK(status)) {
2733 reply_nterror(req, status);
2734 goto out;
2737 if (ucf_flags & UCF_GMT_PATHNAME) {
2738 extract_snapshot_token(name, &twrp);
2740 status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 reply_nterror(req, status);
2743 goto out;
2745 status = filename_convert_dirfsp(ctx,
2746 conn,
2747 name,
2748 ucf_flags,
2749 twrp,
2750 &dirfsp,
2751 &smb_fname);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2754 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2755 ERRSRV, ERRbadpath);
2756 goto out;
2758 reply_nterror(req, status);
2759 goto out;
2762 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2764 status = unlink_internals(conn, req, dirtype, dirfsp, smb_fname);
2765 if (!NT_STATUS_IS_OK(status)) {
2766 if (open_was_deferred(req->xconn, req->mid)) {
2767 /* We have re-scheduled this call. */
2768 goto out;
2770 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2771 bool ok = defer_smb1_sharing_violation(req);
2772 if (ok) {
2773 goto out;
2776 reply_nterror(req, status);
2777 goto out;
2780 reply_smb1_outbuf(req, 0, 0);
2781 out:
2782 TALLOC_FREE(smb_fname);
2783 END_PROFILE(SMBunlink);
2784 return;
2787 /****************************************************************************
2788 Fail for readbraw.
2789 ****************************************************************************/
2791 static void fail_readraw(void)
2793 const char *errstr = talloc_asprintf(talloc_tos(),
2794 "FAIL ! reply_readbraw: socket write fail (%s)",
2795 strerror(errno));
2796 if (!errstr) {
2797 errstr = "";
2799 exit_server_cleanly(errstr);
2802 /****************************************************************************
2803 Return a readbraw error (4 bytes of zero).
2804 ****************************************************************************/
2806 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2808 char header[4];
2810 SIVAL(header,0,0);
2812 smbd_lock_socket(xconn);
2813 if (write_data(xconn->transport.sock,header,4) != 4) {
2814 int saved_errno = errno;
2816 * Try and give an error message saying what
2817 * client failed.
2819 DEBUG(0, ("write_data failed for client %s. "
2820 "Error %s\n",
2821 smbXsrv_connection_dbg(xconn),
2822 strerror(saved_errno)));
2823 errno = saved_errno;
2825 fail_readraw();
2827 smbd_unlock_socket(xconn);
2830 /*******************************************************************
2831 Ensure we don't use sendfile if server smb signing is active.
2832 ********************************************************************/
2834 static bool lp_use_sendfile(struct smbXsrv_connection *xconn,
2835 int snum,
2836 struct smb1_signing_state *signing_state)
2838 bool sign_active = false;
2840 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2841 if (xconn->protocol < PROTOCOL_NT1) {
2842 return false;
2844 if (signing_state) {
2845 sign_active = smb1_signing_is_active(signing_state);
2847 return (lp__use_sendfile(snum) &&
2848 (get_remote_arch() != RA_WIN95) &&
2849 !sign_active);
2851 /****************************************************************************
2852 Use sendfile in readbraw.
2853 ****************************************************************************/
2855 static void send_file_readbraw(connection_struct *conn,
2856 struct smb_request *req,
2857 files_struct *fsp,
2858 off_t startpos,
2859 size_t nread,
2860 ssize_t mincount)
2862 struct smbXsrv_connection *xconn = req->xconn;
2863 char *outbuf = NULL;
2864 ssize_t ret=0;
2867 * We can only use sendfile on a non-chained packet
2868 * but we can use on a non-oplocked file. tridge proved this
2869 * on a train in Germany :-). JRA.
2870 * reply_readbraw has already checked the length.
2873 if ( !req_is_in_chain(req) &&
2874 (nread > 0) &&
2875 !fsp_is_alternate_stream(fsp) &&
2876 lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
2877 ssize_t sendfile_read = -1;
2878 char header[4];
2879 DATA_BLOB header_blob;
2881 _smb_setlen(header,nread);
2882 header_blob = data_blob_const(header, 4);
2884 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2885 &header_blob, startpos,
2886 nread);
2887 if (sendfile_read == -1) {
2888 /* Returning ENOSYS means no data at all was sent.
2889 * Do this as a normal read. */
2890 if (errno == ENOSYS) {
2891 goto normal_readbraw;
2895 * Special hack for broken Linux with no working sendfile. If we
2896 * return EINTR we sent the header but not the rest of the data.
2897 * Fake this up by doing read/write calls.
2899 if (errno == EINTR) {
2900 /* Ensure we don't do this again. */
2901 set_use_sendfile(SNUM(conn), False);
2902 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2904 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2905 DEBUG(0,("send_file_readbraw: "
2906 "fake_sendfile failed for "
2907 "file %s (%s).\n",
2908 fsp_str_dbg(fsp),
2909 strerror(errno)));
2910 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2912 return;
2915 DEBUG(0,("send_file_readbraw: sendfile failed for "
2916 "file %s (%s). Terminating\n",
2917 fsp_str_dbg(fsp), strerror(errno)));
2918 exit_server_cleanly("send_file_readbraw sendfile failed");
2919 } else if (sendfile_read == 0) {
2921 * Some sendfile implementations return 0 to indicate
2922 * that there was a short read, but nothing was
2923 * actually written to the socket. In this case,
2924 * fallback to the normal read path so the header gets
2925 * the correct byte count.
2927 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2928 "bytes falling back to the normal read: "
2929 "%s\n", fsp_str_dbg(fsp)));
2930 goto normal_readbraw;
2933 /* Deal with possible short send. */
2934 if (sendfile_read != 4+nread) {
2935 ret = sendfile_short_send(xconn, fsp,
2936 sendfile_read, 4, nread);
2937 if (ret == -1) {
2938 fail_readraw();
2941 return;
2944 normal_readbraw:
2946 outbuf = talloc_array(NULL, char, nread+4);
2947 if (!outbuf) {
2948 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2949 (unsigned)(nread+4)));
2950 reply_readbraw_error(xconn);
2951 return;
2954 if (nread > 0) {
2955 ret = read_file(fsp,outbuf+4,startpos,nread);
2956 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2957 if (ret < mincount)
2958 ret = 0;
2959 #else
2960 if (ret < nread)
2961 ret = 0;
2962 #endif
2965 _smb_setlen(outbuf,ret);
2966 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2967 int saved_errno = errno;
2969 * Try and give an error message saying what
2970 * client failed.
2972 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2973 smbXsrv_connection_dbg(xconn),
2974 strerror(saved_errno)));
2975 errno = saved_errno;
2977 fail_readraw();
2980 TALLOC_FREE(outbuf);
2983 /****************************************************************************
2984 Reply to a readbraw (core+ protocol).
2985 ****************************************************************************/
2987 void reply_readbraw(struct smb_request *req)
2989 connection_struct *conn = req->conn;
2990 struct smbXsrv_connection *xconn = req->xconn;
2991 ssize_t maxcount,mincount;
2992 size_t nread = 0;
2993 off_t startpos;
2994 files_struct *fsp;
2995 struct lock_struct lock;
2996 off_t size = 0;
2997 NTSTATUS status;
2999 START_PROFILE(SMBreadbraw);
3001 if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
3002 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3003 "raw reads/writes are disallowed.");
3006 if (req->wct < 8) {
3007 reply_readbraw_error(xconn);
3008 END_PROFILE(SMBreadbraw);
3009 return;
3012 if (xconn->smb1.echo_handler.trusted_fde) {
3013 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3014 "'async smb echo handler = yes'\n"));
3015 reply_readbraw_error(xconn);
3016 END_PROFILE(SMBreadbraw);
3017 return;
3021 * Special check if an oplock break has been issued
3022 * and the readraw request croses on the wire, we must
3023 * return a zero length response here.
3026 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3029 * We have to do a check_fsp by hand here, as
3030 * we must always return 4 zero bytes on error,
3031 * not a NTSTATUS.
3034 if (fsp == NULL ||
3035 conn == NULL ||
3036 conn != fsp->conn ||
3037 req->vuid != fsp->vuid ||
3038 fsp->fsp_flags.is_directory ||
3039 fsp_get_io_fd(fsp) == -1)
3042 * fsp could be NULL here so use the value from the packet. JRA.
3044 DEBUG(3,("reply_readbraw: fnum %d not valid "
3045 "- cache prime?\n",
3046 (int)SVAL(req->vwv+0, 0)));
3047 reply_readbraw_error(xconn);
3048 END_PROFILE(SMBreadbraw);
3049 return;
3052 /* Do a "by hand" version of CHECK_READ. */
3053 if (!(fsp->fsp_flags.can_read ||
3054 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3055 (fsp->access_mask & FILE_EXECUTE)))) {
3056 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3057 (int)SVAL(req->vwv+0, 0)));
3058 reply_readbraw_error(xconn);
3059 END_PROFILE(SMBreadbraw);
3060 return;
3063 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3064 if(req->wct == 10) {
3066 * This is a large offset (64 bit) read.
3069 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3071 if(startpos < 0) {
3072 DEBUG(0,("reply_readbraw: negative 64 bit "
3073 "readraw offset (%.0f) !\n",
3074 (double)startpos ));
3075 reply_readbraw_error(xconn);
3076 END_PROFILE(SMBreadbraw);
3077 return;
3081 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3082 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3084 /* ensure we don't overrun the packet size */
3085 maxcount = MIN(65535,maxcount);
3087 init_strict_lock_struct(fsp,
3088 (uint64_t)req->smbpid,
3089 (uint64_t)startpos,
3090 (uint64_t)maxcount,
3091 READ_LOCK,
3092 lp_posix_cifsu_locktype(fsp),
3093 &lock);
3095 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3096 reply_readbraw_error(xconn);
3097 END_PROFILE(SMBreadbraw);
3098 return;
3101 status = vfs_stat_fsp(fsp);
3102 if (NT_STATUS_IS_OK(status)) {
3103 size = fsp->fsp_name->st.st_ex_size;
3106 if (startpos >= size) {
3107 nread = 0;
3108 } else {
3109 nread = MIN(maxcount,(size - startpos));
3112 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3113 if (nread < mincount)
3114 nread = 0;
3115 #endif
3117 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3118 "min=%lu nread=%lu\n",
3119 fsp_fnum_dbg(fsp), (double)startpos,
3120 (unsigned long)maxcount,
3121 (unsigned long)mincount,
3122 (unsigned long)nread ) );
3124 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3126 DEBUG(5,("reply_readbraw finished\n"));
3128 END_PROFILE(SMBreadbraw);
3129 return;
3132 #undef DBGC_CLASS
3133 #define DBGC_CLASS DBGC_LOCKING
3135 /****************************************************************************
3136 Reply to a lockread (core+ protocol).
3137 ****************************************************************************/
3139 static void reply_lockread_locked(struct tevent_req *subreq);
3141 void reply_lockread(struct smb_request *req)
3143 struct tevent_req *subreq = NULL;
3144 connection_struct *conn = req->conn;
3145 files_struct *fsp;
3146 struct smbd_lock_element *lck = NULL;
3148 START_PROFILE(SMBlockread);
3150 if (req->wct < 5) {
3151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3152 END_PROFILE(SMBlockread);
3153 return;
3156 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3158 if (!check_fsp(conn, req, fsp)) {
3159 END_PROFILE(SMBlockread);
3160 return;
3163 if (!CHECK_READ(fsp,req)) {
3164 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3165 END_PROFILE(SMBlockread);
3166 return;
3169 lck = talloc(req, struct smbd_lock_element);
3170 if (lck == NULL) {
3171 reply_nterror(req, NT_STATUS_NO_MEMORY);
3172 END_PROFILE(SMBlockread);
3173 return;
3177 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3178 * protocol request that predates the read/write lock concept.
3179 * Thus instead of asking for a read lock here we need to ask
3180 * for a write lock. JRA.
3181 * Note that the requested lock size is unaffected by max_send.
3184 *lck = (struct smbd_lock_element) {
3185 .req_guid = smbd_request_guid(req, 0),
3186 .smblctx = req->smbpid,
3187 .brltype = WRITE_LOCK,
3188 .lock_flav = WINDOWS_LOCK,
3189 .count = SVAL(req->vwv+1, 0),
3190 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3193 subreq = smbd_smb1_do_locks_send(
3194 fsp,
3195 req->sconn->ev_ctx,
3196 &req,
3197 fsp,
3199 false, /* large_offset */
3201 lck);
3202 if (subreq == NULL) {
3203 reply_nterror(req, NT_STATUS_NO_MEMORY);
3204 END_PROFILE(SMBlockread);
3205 return;
3207 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3208 END_PROFILE(SMBlockread);
3211 static void reply_lockread_locked(struct tevent_req *subreq)
3213 struct smb_request *req = NULL;
3214 ssize_t nread = -1;
3215 char *data = NULL;
3216 NTSTATUS status;
3217 bool ok;
3218 off_t startpos;
3219 size_t numtoread, maxtoread;
3220 struct files_struct *fsp = NULL;
3221 char *p = NULL;
3223 START_PROFILE(SMBlockread);
3225 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3226 SMB_ASSERT(ok);
3228 status = smbd_smb1_do_locks_recv(subreq);
3229 TALLOC_FREE(subreq);
3231 if (!NT_STATUS_IS_OK(status)) {
3232 reply_nterror(req, status);
3233 goto send;
3236 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3237 if (fsp == NULL) {
3238 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3239 goto send;
3242 numtoread = SVAL(req->vwv+1, 0);
3243 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3246 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3248 maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3250 if (numtoread > maxtoread) {
3251 DBG_WARNING("requested read size (%zu) is greater than "
3252 "maximum allowed (%zu/%d). "
3253 "Returning short read of maximum allowed for "
3254 "compatibility with Windows 2000.\n",
3255 numtoread,
3256 maxtoread,
3257 req->xconn->smb1.sessions.max_send);
3258 numtoread = maxtoread;
3261 reply_smb1_outbuf(req, 5, numtoread + 3);
3263 data = smb_buf(req->outbuf) + 3;
3265 nread = read_file(fsp,data,startpos,numtoread);
3267 if (nread < 0) {
3268 reply_nterror(req, map_nt_error_from_unix(errno));
3269 goto send;
3272 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3274 SSVAL(req->outbuf,smb_vwv0,nread);
3275 SSVAL(req->outbuf,smb_vwv5,nread+3);
3276 p = smb_buf(req->outbuf);
3277 SCVAL(p,0,0); /* pad byte. */
3278 SSVAL(p,1,nread);
3280 DEBUG(3,("lockread %s num=%d nread=%d\n",
3281 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3283 send:
3284 ok = smb1_srv_send(req->xconn,
3285 (char *)req->outbuf,
3286 true,
3287 req->seqnum + 1,
3288 IS_CONN_ENCRYPTED(req->conn));
3289 if (!ok) {
3290 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
3292 TALLOC_FREE(req);
3293 END_PROFILE(SMBlockread);
3294 return;
3297 #undef DBGC_CLASS
3298 #define DBGC_CLASS DBGC_ALL
3300 /****************************************************************************
3301 Reply to a read.
3302 ****************************************************************************/
3304 void reply_read(struct smb_request *req)
3306 connection_struct *conn = req->conn;
3307 size_t numtoread;
3308 size_t maxtoread;
3309 ssize_t nread = 0;
3310 char *data;
3311 off_t startpos;
3312 files_struct *fsp;
3313 struct lock_struct lock;
3314 struct smbXsrv_connection *xconn = req->xconn;
3316 START_PROFILE(SMBread);
3318 if (req->wct < 3) {
3319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3320 END_PROFILE(SMBread);
3321 return;
3324 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3326 if (!check_fsp(conn, req, fsp)) {
3327 END_PROFILE(SMBread);
3328 return;
3331 if (!CHECK_READ(fsp,req)) {
3332 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3333 END_PROFILE(SMBread);
3334 return;
3337 numtoread = SVAL(req->vwv+1, 0);
3338 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3341 * The requested read size cannot be greater than max_send. JRA.
3343 maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3345 if (numtoread > maxtoread) {
3346 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3347 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3348 (unsigned int)numtoread, (unsigned int)maxtoread,
3349 (unsigned int)xconn->smb1.sessions.max_send));
3350 numtoread = maxtoread;
3353 reply_smb1_outbuf(req, 5, numtoread+3);
3355 data = smb_buf(req->outbuf) + 3;
3357 init_strict_lock_struct(fsp,
3358 (uint64_t)req->smbpid,
3359 (uint64_t)startpos,
3360 (uint64_t)numtoread,
3361 READ_LOCK,
3362 lp_posix_cifsu_locktype(fsp),
3363 &lock);
3365 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3366 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3367 END_PROFILE(SMBread);
3368 return;
3371 if (numtoread > 0)
3372 nread = read_file(fsp,data,startpos,numtoread);
3374 if (nread < 0) {
3375 reply_nterror(req, map_nt_error_from_unix(errno));
3376 goto out;
3379 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3381 SSVAL(req->outbuf,smb_vwv0,nread);
3382 SSVAL(req->outbuf,smb_vwv5,nread+3);
3383 SCVAL(smb_buf(req->outbuf),0,1);
3384 SSVAL(smb_buf(req->outbuf),1,nread);
3386 DEBUG(3, ("read %s num=%d nread=%d\n",
3387 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3389 out:
3390 END_PROFILE(SMBread);
3391 return;
3394 /****************************************************************************
3395 Setup readX header.
3396 ****************************************************************************/
3398 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3400 size_t outsize;
3402 outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3403 False);
3405 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3407 SCVAL(outbuf,smb_vwv0,0xFF);
3408 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3409 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3410 SSVAL(outbuf,smb_vwv6,
3411 (smb_wct - 4) /* offset from smb header to wct */
3412 + 1 /* the wct field */
3413 + 12 * sizeof(uint16_t) /* vwv */
3414 + 2 /* the buflen field */
3415 + 1); /* padding byte */
3416 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3417 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3418 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3419 _smb_setlen_large(outbuf,
3420 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3421 return outsize;
3424 /****************************************************************************
3425 Reply to a read and X - possibly using sendfile.
3426 ****************************************************************************/
3428 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3429 files_struct *fsp, off_t startpos,
3430 size_t smb_maxcnt)
3432 struct smbXsrv_connection *xconn = req->xconn;
3433 ssize_t nread = -1;
3434 struct lock_struct lock;
3435 int saved_errno = 0;
3436 NTSTATUS status;
3438 init_strict_lock_struct(fsp,
3439 (uint64_t)req->smbpid,
3440 (uint64_t)startpos,
3441 (uint64_t)smb_maxcnt,
3442 READ_LOCK,
3443 lp_posix_cifsu_locktype(fsp),
3444 &lock);
3446 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3447 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3448 return;
3452 * We can only use sendfile on a non-chained packet
3453 * but we can use on a non-oplocked file. tridge proved this
3454 * on a train in Germany :-). JRA.
3457 if (!req_is_in_chain(req) &&
3458 !req->encrypted &&
3459 !fsp_is_alternate_stream(fsp) &&
3460 lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
3461 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3462 DATA_BLOB header;
3464 status = vfs_stat_fsp(fsp);
3465 if (!NT_STATUS_IS_OK(status)) {
3466 reply_nterror(req, status);
3467 goto out;
3470 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3471 (startpos > fsp->fsp_name->st.st_ex_size) ||
3472 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3474 * We already know that we would do a short read, so don't
3475 * try the sendfile() path.
3477 goto nosendfile_read;
3481 * Set up the packet header before send. We
3482 * assume here the sendfile will work (get the
3483 * correct amount of data).
3486 header = data_blob_const(headerbuf, sizeof(headerbuf));
3488 construct_smb1_reply_common_req(req, (char *)headerbuf);
3489 setup_readX_header((char *)headerbuf, smb_maxcnt);
3491 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3492 startpos, smb_maxcnt);
3493 if (nread == -1) {
3494 saved_errno = errno;
3496 /* Returning ENOSYS means no data at all was sent.
3497 Do this as a normal read. */
3498 if (errno == ENOSYS) {
3499 goto normal_read;
3503 * Special hack for broken Linux with no working sendfile. If we
3504 * return EINTR we sent the header but not the rest of the data.
3505 * Fake this up by doing read/write calls.
3508 if (errno == EINTR) {
3509 /* Ensure we don't do this again. */
3510 set_use_sendfile(SNUM(conn), False);
3511 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3512 nread = fake_sendfile(xconn, fsp, startpos,
3513 smb_maxcnt);
3514 if (nread == -1) {
3515 saved_errno = errno;
3516 DEBUG(0,("send_file_readX: "
3517 "fake_sendfile failed for "
3518 "file %s (%s) for client %s. "
3519 "Terminating\n",
3520 fsp_str_dbg(fsp),
3521 smbXsrv_connection_dbg(xconn),
3522 strerror(saved_errno)));
3523 errno = saved_errno;
3524 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3526 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3527 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3528 /* No outbuf here means successful sendfile. */
3529 goto out;
3532 DEBUG(0,("send_file_readX: sendfile failed for file "
3533 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3534 strerror(errno)));
3535 exit_server_cleanly("send_file_readX sendfile failed");
3536 } else if (nread == 0) {
3538 * Some sendfile implementations return 0 to indicate
3539 * that there was a short read, but nothing was
3540 * actually written to the socket. In this case,
3541 * fallback to the normal read path so the header gets
3542 * the correct byte count.
3544 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3545 "falling back to the normal read: %s\n",
3546 fsp_str_dbg(fsp)));
3547 goto normal_read;
3550 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3551 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3553 /* Deal with possible short send. */
3554 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3555 ssize_t ret;
3557 ret = sendfile_short_send(xconn, fsp, nread,
3558 sizeof(headerbuf), smb_maxcnt);
3559 if (ret == -1) {
3560 const char *r;
3561 r = "send_file_readX: sendfile_short_send failed";
3562 DEBUG(0,("%s for file %s (%s).\n",
3563 r, fsp_str_dbg(fsp), strerror(errno)));
3564 exit_server_cleanly(r);
3567 /* No outbuf here means successful sendfile. */
3568 goto out;
3571 normal_read:
3573 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3574 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3575 ssize_t ret;
3577 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3578 (startpos > fsp->fsp_name->st.st_ex_size) ||
3579 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3581 * We already know that we would do a short
3582 * read, so don't try the sendfile() path.
3584 goto nosendfile_read;
3587 construct_smb1_reply_common_req(req, (char *)headerbuf);
3588 setup_readX_header((char *)headerbuf, smb_maxcnt);
3590 /* Send out the header. */
3591 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3592 sizeof(headerbuf));
3593 if (ret != sizeof(headerbuf)) {
3594 saved_errno = errno;
3596 * Try and give an error message saying what
3597 * client failed.
3599 DEBUG(0,("send_file_readX: write_data failed for file "
3600 "%s (%s) for client %s. Terminating\n",
3601 fsp_str_dbg(fsp),
3602 smbXsrv_connection_dbg(xconn),
3603 strerror(saved_errno)));
3604 errno = saved_errno;
3605 exit_server_cleanly("send_file_readX sendfile failed");
3607 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3608 if (nread == -1) {
3609 saved_errno = errno;
3610 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3611 "%s (%s) for client %s. Terminating\n",
3612 fsp_str_dbg(fsp),
3613 smbXsrv_connection_dbg(xconn),
3614 strerror(saved_errno)));
3615 errno = saved_errno;
3616 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3618 goto out;
3621 nosendfile_read:
3623 reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3624 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3625 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3627 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3628 startpos, smb_maxcnt);
3629 saved_errno = errno;
3631 if (nread < 0) {
3632 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3633 return;
3636 setup_readX_header((char *)req->outbuf, nread);
3638 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3639 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3640 return;
3642 out:
3643 TALLOC_FREE(req->outbuf);
3644 return;
3647 /****************************************************************************
3648 Work out how much space we have for a read return.
3649 ****************************************************************************/
3651 static size_t calc_max_read_pdu(const struct smb_request *req)
3653 struct smbXsrv_connection *xconn = req->xconn;
3655 if (xconn->protocol < PROTOCOL_NT1) {
3656 return xconn->smb1.sessions.max_send;
3659 if (!lp_large_readwrite()) {
3660 return xconn->smb1.sessions.max_send;
3663 if (req_is_in_chain(req)) {
3664 return xconn->smb1.sessions.max_send;
3667 if (req->encrypted) {
3669 * Don't take encrypted traffic up to the
3670 * limit. There are padding considerations
3671 * that make that tricky.
3673 return xconn->smb1.sessions.max_send;
3676 if (smb1_srv_is_signing_active(xconn)) {
3677 return 0x1FFFF;
3680 if (!lp_smb1_unix_extensions()) {
3681 return 0x1FFFF;
3685 * We can do ultra-large POSIX reads.
3687 return 0xFFFFFF;
3690 /****************************************************************************
3691 Calculate how big a read can be. Copes with all clients. It's always
3692 safe to return a short read - Windows does this.
3693 ****************************************************************************/
3695 static size_t calc_read_size(const struct smb_request *req,
3696 size_t upper_size,
3697 size_t lower_size)
3699 struct smbXsrv_connection *xconn = req->xconn;
3700 size_t max_pdu = calc_max_read_pdu(req);
3701 size_t total_size = 0;
3702 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3703 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3706 * Windows explicitly ignores upper size of 0xFFFF.
3707 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3708 * We must do the same as these will never fit even in
3709 * an extended size NetBIOS packet.
3711 if (upper_size == 0xFFFF) {
3712 upper_size = 0;
3715 if (xconn->protocol < PROTOCOL_NT1) {
3716 upper_size = 0;
3719 total_size = ((upper_size<<16) | lower_size);
3722 * LARGE_READX test shows it's always safe to return
3723 * a short read. Windows does so.
3725 return MIN(total_size, max_len);
3728 /****************************************************************************
3729 Reply to a read and X.
3730 ****************************************************************************/
3732 void reply_read_and_X(struct smb_request *req)
3734 connection_struct *conn = req->conn;
3735 files_struct *fsp;
3736 off_t startpos;
3737 size_t smb_maxcnt;
3738 size_t upper_size;
3739 bool big_readX = False;
3740 #if 0
3741 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3742 #endif
3744 START_PROFILE(SMBreadX);
3746 if ((req->wct != 10) && (req->wct != 12)) {
3747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 return;
3751 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3752 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3753 smb_maxcnt = SVAL(req->vwv+5, 0);
3755 /* If it's an IPC, pass off the pipe handler. */
3756 if (IS_IPC(conn)) {
3757 reply_pipe_read_and_X(req);
3758 END_PROFILE(SMBreadX);
3759 return;
3762 if (!check_fsp(conn, req, fsp)) {
3763 END_PROFILE(SMBreadX);
3764 return;
3767 if (!CHECK_READ(fsp,req)) {
3768 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3769 END_PROFILE(SMBreadX);
3770 return;
3773 upper_size = SVAL(req->vwv+7, 0);
3774 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3775 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3777 * This is a heuristic to avoid keeping large
3778 * outgoing buffers around over long-lived aio
3779 * requests.
3781 big_readX = True;
3784 if (req->wct == 12) {
3786 * This is a large offset (64 bit) read.
3788 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3792 if (!big_readX) {
3793 NTSTATUS status = schedule_aio_read_and_X(conn,
3794 req,
3795 fsp,
3796 startpos,
3797 smb_maxcnt);
3798 if (NT_STATUS_IS_OK(status)) {
3799 /* Read scheduled - we're done. */
3800 goto out;
3802 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3803 /* Real error - report to client. */
3804 END_PROFILE(SMBreadX);
3805 reply_nterror(req, status);
3806 return;
3808 /* NT_STATUS_RETRY - fall back to sync read. */
3811 smbd_lock_socket(req->xconn);
3812 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3813 smbd_unlock_socket(req->xconn);
3815 out:
3816 END_PROFILE(SMBreadX);
3817 return;
3820 /****************************************************************************
3821 Error replies to writebraw must have smb_wct == 1. Fix this up.
3822 ****************************************************************************/
3824 void error_to_writebrawerr(struct smb_request *req)
3826 uint8_t *old_outbuf = req->outbuf;
3828 reply_smb1_outbuf(req, 1, 0);
3830 memcpy(req->outbuf, old_outbuf, smb_size);
3831 TALLOC_FREE(old_outbuf);
3834 /****************************************************************************
3835 Read 4 bytes of a smb packet and return the smb length of the packet.
3836 Store the result in the buffer. This version of the function will
3837 never return a session keepalive (length of zero).
3838 Timeout is in milliseconds.
3839 ****************************************************************************/
3841 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3842 size_t *len)
3844 uint8_t msgtype = NBSSkeepalive;
3846 while (msgtype == NBSSkeepalive) {
3847 NTSTATUS status;
3849 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3850 len);
3851 if (!NT_STATUS_IS_OK(status)) {
3852 char addr[INET6_ADDRSTRLEN];
3853 /* Try and give an error message
3854 * saying what client failed. */
3855 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3856 "client %s read error = %s.\n",
3857 get_peer_addr(fd,addr,sizeof(addr)),
3858 nt_errstr(status)));
3859 return status;
3862 msgtype = CVAL(inbuf, 0);
3865 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3866 (unsigned long)len));
3868 return NT_STATUS_OK;
3871 /****************************************************************************
3872 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3873 ****************************************************************************/
3875 void reply_writebraw(struct smb_request *req)
3877 connection_struct *conn = req->conn;
3878 struct smbXsrv_connection *xconn = req->xconn;
3879 char *buf = NULL;
3880 ssize_t nwritten=0;
3881 ssize_t total_written=0;
3882 size_t numtowrite=0;
3883 size_t tcount;
3884 off_t startpos;
3885 const char *data=NULL;
3886 bool write_through;
3887 files_struct *fsp;
3888 struct lock_struct lock;
3889 NTSTATUS status;
3891 START_PROFILE(SMBwritebraw);
3894 * If we ever reply with an error, it must have the SMB command
3895 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3896 * we're finished.
3898 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3900 if (smb1_srv_is_signing_active(xconn)) {
3901 END_PROFILE(SMBwritebraw);
3902 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3903 "raw reads/writes are disallowed.");
3906 if (req->wct < 12) {
3907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3908 error_to_writebrawerr(req);
3909 END_PROFILE(SMBwritebraw);
3910 return;
3913 if (xconn->smb1.echo_handler.trusted_fde) {
3914 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3915 "'async smb echo handler = yes'\n"));
3916 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3917 error_to_writebrawerr(req);
3918 END_PROFILE(SMBwritebraw);
3919 return;
3922 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3923 if (!check_fsp(conn, req, fsp)) {
3924 error_to_writebrawerr(req);
3925 END_PROFILE(SMBwritebraw);
3926 return;
3929 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
3930 if (!NT_STATUS_IS_OK(status)) {
3931 reply_nterror(req, status);
3932 error_to_writebrawerr(req);
3933 END_PROFILE(SMBwritebraw);
3934 return;
3937 tcount = IVAL(req->vwv+1, 0);
3938 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3939 write_through = BITSETW(req->vwv+7,0);
3941 /* We have to deal with slightly different formats depending
3942 on whether we are using the core+ or lanman1.0 protocol */
3944 if(xconn->protocol <= PROTOCOL_COREPLUS) {
3945 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3946 data = smb_buf_const(req->inbuf);
3947 } else {
3948 numtowrite = SVAL(req->vwv+10, 0);
3949 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3952 /* Ensure we don't write bytes past the end of this packet. */
3954 * This already protects us against CVE-2017-12163.
3956 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3957 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3958 error_to_writebrawerr(req);
3959 END_PROFILE(SMBwritebraw);
3960 return;
3963 if (!fsp->print_file) {
3964 init_strict_lock_struct(fsp,
3965 (uint64_t)req->smbpid,
3966 (uint64_t)startpos,
3967 (uint64_t)tcount,
3968 WRITE_LOCK,
3969 lp_posix_cifsu_locktype(fsp),
3970 &lock);
3972 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3973 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3974 error_to_writebrawerr(req);
3975 END_PROFILE(SMBwritebraw);
3976 return;
3980 if (numtowrite>0) {
3981 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3984 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3985 "wrote=%d sync=%d\n",
3986 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3987 (int)nwritten, (int)write_through));
3989 if (nwritten < (ssize_t)numtowrite) {
3990 reply_nterror(req, NT_STATUS_DISK_FULL);
3991 error_to_writebrawerr(req);
3992 goto out;
3995 total_written = nwritten;
3997 /* Allocate a buffer of 64k + length. */
3998 buf = talloc_array(NULL, char, 65540);
3999 if (!buf) {
4000 reply_nterror(req, NT_STATUS_NO_MEMORY);
4001 error_to_writebrawerr(req);
4002 goto out;
4005 /* Return a SMBwritebraw message to the redirector to tell
4006 * it to send more bytes */
4008 memcpy(buf, req->inbuf, smb_size);
4009 srv_smb1_set_message(buf,xconn->protocol>PROTOCOL_COREPLUS?1:0,0,True);
4010 SCVAL(buf,smb_com,SMBwritebraw);
4011 SSVALS(buf,smb_vwv0,0xFFFF);
4012 show_msg(buf);
4013 if (!smb1_srv_send(req->xconn,
4014 buf,
4015 false,
4016 0, /* no signing */
4017 IS_CONN_ENCRYPTED(conn))) {
4018 exit_server_cleanly("reply_writebraw: smb1_srv_send "
4019 "failed.");
4022 /* Now read the raw data into the buffer and write it */
4023 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4024 &numtowrite);
4025 if (!NT_STATUS_IS_OK(status)) {
4026 exit_server_cleanly("secondary writebraw failed");
4029 /* Set up outbuf to return the correct size */
4030 reply_smb1_outbuf(req, 1, 0);
4032 if (numtowrite != 0) {
4034 if (numtowrite > 0xFFFF) {
4035 DEBUG(0,("reply_writebraw: Oversize secondary write "
4036 "raw requested (%u). Terminating\n",
4037 (unsigned int)numtowrite ));
4038 exit_server_cleanly("secondary writebraw failed");
4041 if (tcount > nwritten+numtowrite) {
4042 DEBUG(3,("reply_writebraw: Client overestimated the "
4043 "write %d %d %d\n",
4044 (int)tcount,(int)nwritten,(int)numtowrite));
4047 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4048 numtowrite);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 /* Try and give an error message
4052 * saying what client failed. */
4053 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4054 "raw read failed (%s) for client %s. "
4055 "Terminating\n", nt_errstr(status),
4056 smbXsrv_connection_dbg(xconn)));
4057 exit_server_cleanly("secondary writebraw failed");
4061 * We are not vulnerable to CVE-2017-12163
4062 * here as we are guaranteed to have numtowrite
4063 * bytes available - we just read from the client.
4065 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4066 if (nwritten == -1) {
4067 TALLOC_FREE(buf);
4068 reply_nterror(req, map_nt_error_from_unix(errno));
4069 error_to_writebrawerr(req);
4070 goto out;
4073 if (nwritten < (ssize_t)numtowrite) {
4074 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4075 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4078 if (nwritten > 0) {
4079 total_written += nwritten;
4083 TALLOC_FREE(buf);
4084 SSVAL(req->outbuf,smb_vwv0,total_written);
4086 status = sync_file(conn, fsp, write_through);
4087 if (!NT_STATUS_IS_OK(status)) {
4088 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4089 fsp_str_dbg(fsp), nt_errstr(status)));
4090 reply_nterror(req, status);
4091 error_to_writebrawerr(req);
4092 goto out;
4095 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4096 "wrote=%d\n",
4097 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4098 (int)total_written));
4100 /* We won't return a status if write through is not selected - this
4101 * follows what WfWg does */
4102 END_PROFILE(SMBwritebraw);
4104 if (!write_through && total_written==tcount) {
4106 #if RABBIT_PELLET_FIX
4108 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4109 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4110 * JRA.
4112 if (!send_keepalive(xconn->transport.sock)) {
4113 exit_server_cleanly("reply_writebraw: send of "
4114 "keepalive failed");
4116 #endif
4117 TALLOC_FREE(req->outbuf);
4119 return;
4121 out:
4122 END_PROFILE(SMBwritebraw);
4123 return;
4126 #undef DBGC_CLASS
4127 #define DBGC_CLASS DBGC_LOCKING
4129 /****************************************************************************
4130 Reply to a writeunlock (core+).
4131 ****************************************************************************/
4133 void reply_writeunlock(struct smb_request *req)
4135 connection_struct *conn = req->conn;
4136 ssize_t nwritten = -1;
4137 size_t numtowrite;
4138 size_t remaining;
4139 off_t startpos;
4140 const char *data;
4141 NTSTATUS status = NT_STATUS_OK;
4142 files_struct *fsp;
4143 struct lock_struct lock;
4144 int saved_errno = 0;
4146 START_PROFILE(SMBwriteunlock);
4148 if (req->wct < 5) {
4149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4150 END_PROFILE(SMBwriteunlock);
4151 return;
4154 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4156 if (!check_fsp(conn, req, fsp)) {
4157 END_PROFILE(SMBwriteunlock);
4158 return;
4161 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4162 if (!NT_STATUS_IS_OK(status)) {
4163 reply_nterror(req, status);
4164 END_PROFILE(SMBwriteunlock);
4165 return;
4168 numtowrite = SVAL(req->vwv+1, 0);
4169 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4170 data = (const char *)req->buf + 3;
4173 * Ensure client isn't asking us to write more than
4174 * they sent. CVE-2017-12163.
4176 remaining = smbreq_bufrem(req, data);
4177 if (numtowrite > remaining) {
4178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4179 END_PROFILE(SMBwriteunlock);
4180 return;
4183 if (!fsp->print_file && numtowrite > 0) {
4184 init_strict_lock_struct(fsp,
4185 (uint64_t)req->smbpid,
4186 (uint64_t)startpos,
4187 (uint64_t)numtowrite,
4188 WRITE_LOCK,
4189 lp_posix_cifsu_locktype(fsp),
4190 &lock);
4192 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4193 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4194 END_PROFILE(SMBwriteunlock);
4195 return;
4199 /* The special X/Open SMB protocol handling of
4200 zero length writes is *NOT* done for
4201 this call */
4202 if(numtowrite == 0) {
4203 nwritten = 0;
4204 } else {
4205 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4206 saved_errno = errno;
4209 status = sync_file(conn, fsp, False /* write through */);
4210 if (!NT_STATUS_IS_OK(status)) {
4211 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4212 fsp_str_dbg(fsp), nt_errstr(status)));
4213 reply_nterror(req, status);
4214 goto out;
4217 if(nwritten < 0) {
4218 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4219 goto out;
4222 if((nwritten < numtowrite) && (numtowrite != 0)) {
4223 reply_nterror(req, NT_STATUS_DISK_FULL);
4224 goto out;
4227 if (numtowrite && !fsp->print_file) {
4228 struct smbd_lock_element l = {
4229 .req_guid = smbd_request_guid(req, 0),
4230 .smblctx = req->smbpid,
4231 .brltype = UNLOCK_LOCK,
4232 .lock_flav = WINDOWS_LOCK,
4233 .offset = startpos,
4234 .count = numtowrite,
4236 status = smbd_do_unlocking(req, fsp, 1, &l);
4237 if (NT_STATUS_V(status)) {
4238 reply_nterror(req, status);
4239 goto out;
4243 reply_smb1_outbuf(req, 1, 0);
4245 SSVAL(req->outbuf,smb_vwv0,nwritten);
4247 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4248 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4250 out:
4251 END_PROFILE(SMBwriteunlock);
4252 return;
4255 #undef DBGC_CLASS
4256 #define DBGC_CLASS DBGC_ALL
4258 /****************************************************************************
4259 Reply to a write.
4260 ****************************************************************************/
4262 void reply_write(struct smb_request *req)
4264 connection_struct *conn = req->conn;
4265 size_t numtowrite;
4266 size_t remaining;
4267 ssize_t nwritten = -1;
4268 off_t startpos;
4269 const char *data;
4270 files_struct *fsp;
4271 struct lock_struct lock;
4272 NTSTATUS status;
4273 int saved_errno = 0;
4275 START_PROFILE(SMBwrite);
4277 if (req->wct < 5) {
4278 END_PROFILE(SMBwrite);
4279 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4280 return;
4283 /* If it's an IPC, pass off the pipe handler. */
4284 if (IS_IPC(conn)) {
4285 reply_pipe_write(req);
4286 END_PROFILE(SMBwrite);
4287 return;
4290 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4292 if (!check_fsp(conn, req, fsp)) {
4293 END_PROFILE(SMBwrite);
4294 return;
4297 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4298 if (!NT_STATUS_IS_OK(status)) {
4299 reply_nterror(req, status);
4300 END_PROFILE(SMBwrite);
4301 return;
4304 numtowrite = SVAL(req->vwv+1, 0);
4305 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4306 data = (const char *)req->buf + 3;
4309 * Ensure client isn't asking us to write more than
4310 * they sent. CVE-2017-12163.
4312 remaining = smbreq_bufrem(req, data);
4313 if (numtowrite > remaining) {
4314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4315 END_PROFILE(SMBwrite);
4316 return;
4319 if (!fsp->print_file) {
4320 init_strict_lock_struct(fsp,
4321 (uint64_t)req->smbpid,
4322 (uint64_t)startpos,
4323 (uint64_t)numtowrite,
4324 WRITE_LOCK,
4325 lp_posix_cifsu_locktype(fsp),
4326 &lock);
4328 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4329 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4330 END_PROFILE(SMBwrite);
4331 return;
4336 * X/Open SMB protocol says that if smb_vwv1 is
4337 * zero then the file size should be extended or
4338 * truncated to the size given in smb_vwv[2-3].
4341 if(numtowrite == 0) {
4343 * This is actually an allocate call, and set EOF. JRA.
4345 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4346 if (nwritten < 0) {
4347 reply_nterror(req, NT_STATUS_DISK_FULL);
4348 goto out;
4350 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4351 if (nwritten < 0) {
4352 reply_nterror(req, NT_STATUS_DISK_FULL);
4353 goto out;
4355 trigger_write_time_update_immediate(fsp);
4356 } else {
4357 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4360 status = sync_file(conn, fsp, False);
4361 if (!NT_STATUS_IS_OK(status)) {
4362 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4363 fsp_str_dbg(fsp), nt_errstr(status)));
4364 reply_nterror(req, status);
4365 goto out;
4368 if(nwritten < 0) {
4369 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4370 goto out;
4373 if((nwritten == 0) && (numtowrite != 0)) {
4374 reply_nterror(req, NT_STATUS_DISK_FULL);
4375 goto out;
4378 reply_smb1_outbuf(req, 1, 0);
4380 SSVAL(req->outbuf,smb_vwv0,nwritten);
4382 if (nwritten < (ssize_t)numtowrite) {
4383 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4384 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4387 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4389 out:
4390 END_PROFILE(SMBwrite);
4391 return;
4394 /****************************************************************************
4395 Ensure a buffer is a valid writeX for recvfile purposes.
4396 ****************************************************************************/
4398 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4399 (2*14) + /* word count (including bcc) */ \
4400 1 /* pad byte */)
4402 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4403 const uint8_t *inbuf)
4405 size_t numtowrite;
4406 unsigned int doff = 0;
4407 size_t len = smb_len_large(inbuf);
4408 uint16_t fnum;
4409 struct smbXsrv_open *op = NULL;
4410 struct files_struct *fsp = NULL;
4411 NTSTATUS status;
4413 if (is_encrypted_packet(inbuf)) {
4414 /* Can't do this on encrypted
4415 * connections. */
4416 return false;
4419 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4420 return false;
4423 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4424 CVAL(inbuf,smb_wct) != 14) {
4425 DEBUG(10,("is_valid_writeX_buffer: chained or "
4426 "invalid word length.\n"));
4427 return false;
4430 fnum = SVAL(inbuf, smb_vwv2);
4431 status = smb1srv_open_lookup(xconn,
4432 fnum,
4433 0, /* now */
4434 &op);
4435 if (!NT_STATUS_IS_OK(status)) {
4436 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4437 return false;
4439 fsp = op->compat;
4440 if (fsp == NULL) {
4441 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4442 return false;
4444 if (fsp->conn == NULL) {
4445 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4446 return false;
4449 if (IS_IPC(fsp->conn)) {
4450 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4451 return false;
4453 if (IS_PRINT(fsp->conn)) {
4454 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4455 return false;
4457 if (fsp_is_alternate_stream(fsp)) {
4458 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4459 return false;
4461 doff = SVAL(inbuf,smb_vwv11);
4463 numtowrite = SVAL(inbuf,smb_vwv10);
4465 if (len > doff && len - doff > 0xFFFF) {
4466 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4469 if (numtowrite == 0) {
4470 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4471 return false;
4474 /* Ensure the sizes match up. */
4475 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4476 /* no pad byte...old smbclient :-( */
4477 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4478 (unsigned int)doff,
4479 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4480 return false;
4483 if (len - doff != numtowrite) {
4484 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4485 "len = %u, doff = %u, numtowrite = %u\n",
4486 (unsigned int)len,
4487 (unsigned int)doff,
4488 (unsigned int)numtowrite ));
4489 return false;
4492 DEBUG(10,("is_valid_writeX_buffer: true "
4493 "len = %u, doff = %u, numtowrite = %u\n",
4494 (unsigned int)len,
4495 (unsigned int)doff,
4496 (unsigned int)numtowrite ));
4498 return true;
4501 /****************************************************************************
4502 Reply to a write and X.
4503 ****************************************************************************/
4505 void reply_write_and_X(struct smb_request *req)
4507 connection_struct *conn = req->conn;
4508 struct smbXsrv_connection *xconn = req->xconn;
4509 files_struct *fsp;
4510 struct lock_struct lock;
4511 off_t startpos;
4512 size_t numtowrite;
4513 bool write_through;
4514 ssize_t nwritten;
4515 unsigned int smb_doff;
4516 unsigned int smblen;
4517 const char *data;
4518 NTSTATUS status;
4519 int saved_errno = 0;
4521 START_PROFILE(SMBwriteX);
4523 if ((req->wct != 12) && (req->wct != 14)) {
4524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4525 goto out;
4528 numtowrite = SVAL(req->vwv+10, 0);
4529 smb_doff = SVAL(req->vwv+11, 0);
4530 smblen = smb_len(req->inbuf);
4532 if (req->unread_bytes > 0xFFFF ||
4533 (smblen > smb_doff &&
4534 smblen - smb_doff > 0xFFFF)) {
4535 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4538 if (req->unread_bytes) {
4539 /* Can't do a recvfile write on IPC$ */
4540 if (IS_IPC(conn)) {
4541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4542 goto out;
4544 if (numtowrite != req->unread_bytes) {
4545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4546 goto out;
4548 } else {
4550 * This already protects us against CVE-2017-12163.
4552 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4553 smb_doff + numtowrite > smblen) {
4554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4555 goto out;
4559 /* If it's an IPC, pass off the pipe handler. */
4560 if (IS_IPC(conn)) {
4561 if (req->unread_bytes) {
4562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4563 goto out;
4565 reply_pipe_write_and_X(req);
4566 goto out;
4569 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4570 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4571 write_through = BITSETW(req->vwv+7,0);
4573 if (!check_fsp(conn, req, fsp)) {
4574 goto out;
4577 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4578 if (!NT_STATUS_IS_OK(status)) {
4579 reply_nterror(req, status);
4580 goto out;
4583 data = smb_base(req->inbuf) + smb_doff;
4585 if(req->wct == 14) {
4587 * This is a large offset (64 bit) write.
4589 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4593 /* X/Open SMB protocol says that, unlike SMBwrite
4594 if the length is zero then NO truncation is
4595 done, just a write of zero. To truncate a file,
4596 use SMBwrite. */
4598 if(numtowrite == 0) {
4599 nwritten = 0;
4600 } else {
4601 if (req->unread_bytes == 0) {
4602 status = schedule_aio_write_and_X(conn,
4603 req,
4604 fsp,
4605 data,
4606 startpos,
4607 numtowrite);
4609 if (NT_STATUS_IS_OK(status)) {
4610 /* write scheduled - we're done. */
4611 goto out;
4613 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4614 /* Real error - report to client. */
4615 reply_nterror(req, status);
4616 goto out;
4618 /* NT_STATUS_RETRY - fall through to sync write. */
4621 init_strict_lock_struct(fsp,
4622 (uint64_t)req->smbpid,
4623 (uint64_t)startpos,
4624 (uint64_t)numtowrite,
4625 WRITE_LOCK,
4626 lp_posix_cifsu_locktype(fsp),
4627 &lock);
4629 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4630 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4631 goto out;
4634 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4635 saved_errno = errno;
4638 if(nwritten < 0) {
4639 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4640 goto out;
4643 if((nwritten == 0) && (numtowrite != 0)) {
4644 reply_nterror(req, NT_STATUS_DISK_FULL);
4645 goto out;
4648 reply_smb1_outbuf(req, 6, 0);
4649 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4650 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4651 SSVAL(req->outbuf,smb_vwv2,nwritten);
4652 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4654 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4655 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4657 status = sync_file(conn, fsp, write_through);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4660 fsp_str_dbg(fsp), nt_errstr(status)));
4661 reply_nterror(req, status);
4662 goto out;
4665 END_PROFILE(SMBwriteX);
4666 return;
4668 out:
4669 if (req->unread_bytes) {
4670 /* writeX failed. drain socket. */
4671 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4672 req->unread_bytes) {
4673 smb_panic("failed to drain pending bytes");
4675 req->unread_bytes = 0;
4678 END_PROFILE(SMBwriteX);
4679 return;
4682 /****************************************************************************
4683 Reply to a lseek.
4684 ****************************************************************************/
4686 void reply_lseek(struct smb_request *req)
4688 connection_struct *conn = req->conn;
4689 off_t startpos;
4690 off_t res= -1;
4691 int mode,umode;
4692 files_struct *fsp;
4693 NTSTATUS status;
4695 START_PROFILE(SMBlseek);
4697 if (req->wct < 4) {
4698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4699 END_PROFILE(SMBlseek);
4700 return;
4703 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4705 if (!check_fsp(conn, req, fsp)) {
4706 return;
4709 mode = SVAL(req->vwv+1, 0) & 3;
4710 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4711 startpos = (off_t)IVALS(req->vwv+2, 0);
4713 switch (mode) {
4714 case 0:
4715 umode = SEEK_SET;
4716 res = startpos;
4717 break;
4718 case 1:
4719 umode = SEEK_CUR;
4720 res = fh_get_pos(fsp->fh) + startpos;
4721 break;
4722 case 2:
4723 umode = SEEK_END;
4724 break;
4725 default:
4726 umode = SEEK_SET;
4727 res = startpos;
4728 break;
4731 if (umode == SEEK_END) {
4732 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4733 if(errno == EINVAL) {
4734 off_t current_pos = startpos;
4736 status = vfs_stat_fsp(fsp);
4737 if (!NT_STATUS_IS_OK(status)) {
4738 reply_nterror(req, status);
4739 END_PROFILE(SMBlseek);
4740 return;
4743 current_pos += fsp->fsp_name->st.st_ex_size;
4744 if(current_pos < 0)
4745 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4749 if(res == -1) {
4750 reply_nterror(req, map_nt_error_from_unix(errno));
4751 END_PROFILE(SMBlseek);
4752 return;
4756 fh_set_pos(fsp->fh, res);
4758 reply_smb1_outbuf(req, 2, 0);
4759 SIVAL(req->outbuf,smb_vwv0,res);
4761 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4762 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4764 END_PROFILE(SMBlseek);
4765 return;
4768 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4769 void *private_data)
4771 connection_struct *conn = talloc_get_type_abort(
4772 private_data, connection_struct);
4774 if (conn != fsp->conn) {
4775 return NULL;
4777 if (fsp_get_io_fd(fsp) == -1) {
4778 return NULL;
4780 sync_file(conn, fsp, True /* write through */);
4782 if (fsp->fsp_flags.modified) {
4783 trigger_write_time_update_immediate(fsp);
4786 return NULL;
4789 /****************************************************************************
4790 Reply to a flush.
4791 ****************************************************************************/
4793 void reply_flush(struct smb_request *req)
4795 connection_struct *conn = req->conn;
4796 uint16_t fnum;
4797 files_struct *fsp;
4799 START_PROFILE(SMBflush);
4801 if (req->wct < 1) {
4802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4803 return;
4806 fnum = SVAL(req->vwv+0, 0);
4807 fsp = file_fsp(req, fnum);
4809 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4810 return;
4813 if (!fsp) {
4814 files_forall(req->sconn, file_sync_one_fn, conn);
4815 } else {
4816 NTSTATUS status = sync_file(conn, fsp, True);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4819 fsp_str_dbg(fsp), nt_errstr(status)));
4820 reply_nterror(req, status);
4821 END_PROFILE(SMBflush);
4822 return;
4824 if (fsp->fsp_flags.modified) {
4825 trigger_write_time_update_immediate(fsp);
4829 reply_smb1_outbuf(req, 0, 0);
4831 DEBUG(3,("flush\n"));
4832 END_PROFILE(SMBflush);
4833 return;
4836 /****************************************************************************
4837 Reply to a exit.
4838 conn POINTER CAN BE NULL HERE !
4839 ****************************************************************************/
4841 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4842 static void reply_exit_done(struct tevent_req *req);
4844 void reply_exit(struct smb_request *smb1req)
4846 struct tevent_req *req;
4849 * Don't setup the profile charge here, take
4850 * it in reply_exit_done(). Not strictly correct
4851 * but better than the other SMB1 async
4852 * code that double-charges at the moment.
4854 req = reply_exit_send(smb1req);
4855 if (req == NULL) {
4856 /* Not going async, profile here. */
4857 START_PROFILE(SMBexit);
4858 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4859 END_PROFILE(SMBexit);
4860 return;
4863 /* We're async. This will complete later. */
4864 tevent_req_set_callback(req, reply_exit_done, smb1req);
4865 return;
4868 struct reply_exit_state {
4869 struct tevent_queue *wait_queue;
4872 static void reply_exit_wait_done(struct tevent_req *subreq);
4874 /****************************************************************************
4875 Async SMB1 exit.
4876 Note, on failure here we deallocate and return NULL to allow the caller to
4877 SMB1 return an error of ERRnomem immediately.
4878 ****************************************************************************/
4880 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4882 struct tevent_req *req;
4883 struct reply_exit_state *state;
4884 struct tevent_req *subreq;
4885 files_struct *fsp;
4886 struct smbd_server_connection *sconn = smb1req->sconn;
4888 req = tevent_req_create(smb1req, &state,
4889 struct reply_exit_state);
4890 if (req == NULL) {
4891 return NULL;
4893 state->wait_queue = tevent_queue_create(state,
4894 "reply_exit_wait_queue");
4895 if (tevent_req_nomem(state->wait_queue, req)) {
4896 TALLOC_FREE(req);
4897 return NULL;
4900 for (fsp = sconn->files; fsp; fsp = fsp->next) {
4901 if (fsp->file_pid != smb1req->smbpid) {
4902 continue;
4904 if (fsp->vuid != smb1req->vuid) {
4905 continue;
4908 * Flag the file as close in progress.
4909 * This will prevent any more IO being
4910 * done on it.
4912 fsp->fsp_flags.closing = true;
4914 if (fsp->num_aio_requests > 0) {
4916 * Now wait until all aio requests on this fsp are
4917 * finished.
4919 * We don't set a callback, as we just want to block the
4920 * wait queue and the talloc_free() of fsp->aio_request
4921 * will remove the item from the wait queue.
4923 subreq = tevent_queue_wait_send(fsp->aio_requests,
4924 sconn->ev_ctx,
4925 state->wait_queue);
4926 if (tevent_req_nomem(subreq, req)) {
4927 TALLOC_FREE(req);
4928 return NULL;
4934 * Now we add our own waiter to the end of the queue,
4935 * this way we get notified when all pending requests are finished
4936 * and reply to the outstanding SMB1 request.
4938 subreq = tevent_queue_wait_send(state,
4939 sconn->ev_ctx,
4940 state->wait_queue);
4941 if (tevent_req_nomem(subreq, req)) {
4942 TALLOC_FREE(req);
4943 return NULL;
4947 * We're really going async - move the SMB1 request from
4948 * a talloc stackframe above us to the conn talloc-context.
4949 * We need this to stick around until the wait_done
4950 * callback is invoked.
4952 smb1req = talloc_move(sconn, &smb1req);
4954 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4956 return req;
4959 static void reply_exit_wait_done(struct tevent_req *subreq)
4961 struct tevent_req *req = tevent_req_callback_data(
4962 subreq, struct tevent_req);
4964 tevent_queue_wait_recv(subreq);
4965 TALLOC_FREE(subreq);
4966 tevent_req_done(req);
4969 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4971 return tevent_req_simple_recv_ntstatus(req);
4974 static void reply_exit_done(struct tevent_req *req)
4976 struct smb_request *smb1req = tevent_req_callback_data(
4977 req, struct smb_request);
4978 struct smbd_server_connection *sconn = smb1req->sconn;
4979 struct smbXsrv_connection *xconn = smb1req->xconn;
4980 NTTIME now = timeval_to_nttime(&smb1req->request_time);
4981 struct smbXsrv_session *session = NULL;
4982 files_struct *fsp, *next;
4983 NTSTATUS status;
4986 * Take the profile charge here. Not strictly
4987 * correct but better than the other SMB1 async
4988 * code that double-charges at the moment.
4990 START_PROFILE(SMBexit);
4992 status = reply_exit_recv(req);
4993 TALLOC_FREE(req);
4994 if (!NT_STATUS_IS_OK(status)) {
4995 TALLOC_FREE(smb1req);
4996 END_PROFILE(SMBexit);
4997 exit_server(__location__ ": reply_exit_recv failed");
4998 return;
5002 * Ensure the session is still valid.
5004 status = smb1srv_session_lookup(xconn,
5005 smb1req->vuid,
5006 now,
5007 &session);
5008 if (!NT_STATUS_IS_OK(status)) {
5009 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5010 smb_request_done(smb1req);
5011 END_PROFILE(SMBexit);
5012 return;
5016 * Ensure the vuid is still valid - no one
5017 * called reply_ulogoffX() in the meantime.
5018 * reply_exit() doesn't have AS_USER set, so
5019 * use set_current_user_info() directly.
5020 * This is the same logic as in switch_message().
5022 if (session->global->auth_session_info != NULL) {
5023 set_current_user_info(
5024 session->global->auth_session_info->unix_info->sanitized_username,
5025 session->global->auth_session_info->unix_info->unix_name,
5026 session->global->auth_session_info->info->domain_name);
5029 /* No more aio - do the actual closes. */
5030 for (fsp = sconn->files; fsp; fsp = next) {
5031 bool ok;
5032 next = fsp->next;
5034 if (fsp->file_pid != smb1req->smbpid) {
5035 continue;
5037 if (fsp->vuid != smb1req->vuid) {
5038 continue;
5040 if (!fsp->fsp_flags.closing) {
5041 continue;
5045 * reply_exit() has the DO_CHDIR flag set.
5047 ok = chdir_current_service(fsp->conn);
5048 if (!ok) {
5049 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5050 smb_request_done(smb1req);
5051 END_PROFILE(SMBexit);
5052 return;
5054 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
5057 reply_smb1_outbuf(smb1req, 0, 0);
5059 * The following call is needed to push the
5060 * reply data back out the socket after async
5061 * return. Plus it frees smb1req.
5063 smb_request_done(smb1req);
5064 DBG_INFO("reply_exit complete\n");
5065 END_PROFILE(SMBexit);
5066 return;
5069 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5070 files_struct *fsp);
5071 static void reply_close_done(struct tevent_req *req);
5073 void reply_close(struct smb_request *smb1req)
5075 connection_struct *conn = smb1req->conn;
5076 NTSTATUS status = NT_STATUS_OK;
5077 files_struct *fsp = NULL;
5078 START_PROFILE(SMBclose);
5080 if (smb1req->wct < 3) {
5081 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5082 END_PROFILE(SMBclose);
5083 return;
5086 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5089 * We can only use check_fsp if we know it's not a directory.
5092 if (!check_fsp_open(conn, smb1req, fsp)) {
5093 END_PROFILE(SMBclose);
5094 return;
5097 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5098 fsp->fsp_flags.is_directory ?
5099 "directory" : "file",
5100 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5101 conn->num_files_open);
5103 if (!fsp->fsp_flags.is_directory) {
5104 time_t t;
5107 * Take care of any time sent in the close.
5110 t = srv_make_unix_date3(smb1req->vwv+1);
5111 set_close_write_time(fsp, time_t_to_full_timespec(t));
5114 if (fsp->num_aio_requests != 0) {
5115 struct tevent_req *req;
5117 req = reply_close_send(smb1req, fsp);
5118 if (req == NULL) {
5119 status = NT_STATUS_NO_MEMORY;
5120 goto done;
5122 /* We're async. This will complete later. */
5123 tevent_req_set_callback(req, reply_close_done, smb1req);
5124 END_PROFILE(SMBclose);
5125 return;
5129 * close_file_free() returns the unix errno if an error was detected on
5130 * close - normally this is due to a disk full error. If not then it
5131 * was probably an I/O error.
5134 status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
5135 done:
5136 if (!NT_STATUS_IS_OK(status)) {
5137 reply_nterror(smb1req, status);
5138 END_PROFILE(SMBclose);
5139 return;
5142 reply_smb1_outbuf(smb1req, 0, 0);
5143 END_PROFILE(SMBclose);
5144 return;
5147 struct reply_close_state {
5148 files_struct *fsp;
5149 struct tevent_queue *wait_queue;
5152 static void reply_close_wait_done(struct tevent_req *subreq);
5154 /****************************************************************************
5155 Async SMB1 close.
5156 Note, on failure here we deallocate and return NULL to allow the caller to
5157 SMB1 return an error of ERRnomem immediately.
5158 ****************************************************************************/
5160 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5161 files_struct *fsp)
5163 struct tevent_req *req;
5164 struct reply_close_state *state;
5165 struct tevent_req *subreq;
5166 struct smbd_server_connection *sconn = smb1req->sconn;
5168 req = tevent_req_create(smb1req, &state,
5169 struct reply_close_state);
5170 if (req == NULL) {
5171 return NULL;
5173 state->wait_queue = tevent_queue_create(state,
5174 "reply_close_wait_queue");
5175 if (tevent_req_nomem(state->wait_queue, req)) {
5176 TALLOC_FREE(req);
5177 return NULL;
5181 * Flag the file as close in progress.
5182 * This will prevent any more IO being
5183 * done on it.
5185 fsp->fsp_flags.closing = true;
5188 * Now wait until all aio requests on this fsp are
5189 * finished.
5191 * We don't set a callback, as we just want to block the
5192 * wait queue and the talloc_free() of fsp->aio_request
5193 * will remove the item from the wait queue.
5195 subreq = tevent_queue_wait_send(fsp->aio_requests,
5196 sconn->ev_ctx,
5197 state->wait_queue);
5198 if (tevent_req_nomem(subreq, req)) {
5199 TALLOC_FREE(req);
5200 return NULL;
5204 * Now we add our own waiter to the end of the queue,
5205 * this way we get notified when all pending requests are finished
5206 * and reply to the outstanding SMB1 request.
5208 subreq = tevent_queue_wait_send(state,
5209 sconn->ev_ctx,
5210 state->wait_queue);
5211 if (tevent_req_nomem(subreq, req)) {
5212 TALLOC_FREE(req);
5213 return NULL;
5217 * We're really going async - move the SMB1 request from
5218 * a talloc stackframe above us to the conn talloc-context.
5219 * We need this to stick around until the wait_done
5220 * callback is invoked.
5222 smb1req = talloc_move(sconn, &smb1req);
5224 tevent_req_set_callback(subreq, reply_close_wait_done, req);
5226 return req;
5229 static void reply_close_wait_done(struct tevent_req *subreq)
5231 struct tevent_req *req = tevent_req_callback_data(
5232 subreq, struct tevent_req);
5234 tevent_queue_wait_recv(subreq);
5235 TALLOC_FREE(subreq);
5236 tevent_req_done(req);
5239 static NTSTATUS reply_close_recv(struct tevent_req *req)
5241 return tevent_req_simple_recv_ntstatus(req);
5244 static void reply_close_done(struct tevent_req *req)
5246 struct smb_request *smb1req = tevent_req_callback_data(
5247 req, struct smb_request);
5248 struct reply_close_state *state = tevent_req_data(req,
5249 struct reply_close_state);
5250 NTSTATUS status;
5252 status = reply_close_recv(req);
5253 TALLOC_FREE(req);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 TALLOC_FREE(smb1req);
5256 exit_server(__location__ ": reply_close_recv failed");
5257 return;
5260 status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
5261 if (NT_STATUS_IS_OK(status)) {
5262 reply_smb1_outbuf(smb1req, 0, 0);
5263 } else {
5264 reply_nterror(smb1req, status);
5267 * The following call is needed to push the
5268 * reply data back out the socket after async
5269 * return. Plus it frees smb1req.
5271 smb_request_done(smb1req);
5274 /****************************************************************************
5275 Reply to a writeclose (Core+ protocol).
5276 ****************************************************************************/
5278 void reply_writeclose(struct smb_request *req)
5280 connection_struct *conn = req->conn;
5281 size_t numtowrite;
5282 size_t remaining;
5283 ssize_t nwritten = -1;
5284 NTSTATUS close_status = NT_STATUS_OK;
5285 off_t startpos;
5286 const char *data;
5287 struct timespec mtime;
5288 files_struct *fsp;
5289 struct lock_struct lock;
5290 NTSTATUS status;
5292 START_PROFILE(SMBwriteclose);
5294 if (req->wct < 6) {
5295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5296 END_PROFILE(SMBwriteclose);
5297 return;
5300 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5302 if (!check_fsp(conn, req, fsp)) {
5303 END_PROFILE(SMBwriteclose);
5304 return;
5306 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
5307 if (!NT_STATUS_IS_OK(status)) {
5308 reply_nterror(req, status);
5309 END_PROFILE(SMBwriteclose);
5310 return;
5313 numtowrite = SVAL(req->vwv+1, 0);
5314 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5315 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5316 data = (const char *)req->buf + 1;
5319 * Ensure client isn't asking us to write more than
5320 * they sent. CVE-2017-12163.
5322 remaining = smbreq_bufrem(req, data);
5323 if (numtowrite > remaining) {
5324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5325 END_PROFILE(SMBwriteclose);
5326 return;
5329 if (fsp->print_file == NULL) {
5330 init_strict_lock_struct(fsp,
5331 (uint64_t)req->smbpid,
5332 (uint64_t)startpos,
5333 (uint64_t)numtowrite,
5334 WRITE_LOCK,
5335 lp_posix_cifsu_locktype(fsp),
5336 &lock);
5338 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5339 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5340 END_PROFILE(SMBwriteclose);
5341 return;
5345 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5347 set_close_write_time(fsp, mtime);
5350 * More insanity. W2K only closes the file if writelen > 0.
5351 * JRA.
5354 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5355 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5356 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5358 if (numtowrite) {
5359 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5360 "file %s\n", fsp_str_dbg(fsp)));
5361 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5364 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5365 reply_nterror(req, NT_STATUS_DISK_FULL);
5366 goto out;
5369 if(!NT_STATUS_IS_OK(close_status)) {
5370 reply_nterror(req, close_status);
5371 goto out;
5374 reply_smb1_outbuf(req, 1, 0);
5376 SSVAL(req->outbuf,smb_vwv0,nwritten);
5378 out:
5380 END_PROFILE(SMBwriteclose);
5381 return;
5384 #undef DBGC_CLASS
5385 #define DBGC_CLASS DBGC_LOCKING
5387 /****************************************************************************
5388 Reply to a lock.
5389 ****************************************************************************/
5391 static void reply_lock_done(struct tevent_req *subreq);
5393 void reply_lock(struct smb_request *req)
5395 struct tevent_req *subreq = NULL;
5396 connection_struct *conn = req->conn;
5397 files_struct *fsp;
5398 struct smbd_lock_element *lck = NULL;
5400 START_PROFILE(SMBlock);
5402 if (req->wct < 5) {
5403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5404 END_PROFILE(SMBlock);
5405 return;
5408 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5410 if (!check_fsp(conn, req, fsp)) {
5411 END_PROFILE(SMBlock);
5412 return;
5415 lck = talloc(req, struct smbd_lock_element);
5416 if (lck == NULL) {
5417 reply_nterror(req, NT_STATUS_NO_MEMORY);
5418 END_PROFILE(SMBlock);
5419 return;
5422 *lck = (struct smbd_lock_element) {
5423 .req_guid = smbd_request_guid(req, 0),
5424 .smblctx = req->smbpid,
5425 .brltype = WRITE_LOCK,
5426 .lock_flav = WINDOWS_LOCK,
5427 .count = IVAL(req->vwv+1, 0),
5428 .offset = IVAL(req->vwv+3, 0),
5431 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5432 fsp_get_io_fd(fsp),
5433 fsp_fnum_dbg(fsp),
5434 lck->offset,
5435 lck->count);
5437 subreq = smbd_smb1_do_locks_send(
5438 fsp,
5439 req->sconn->ev_ctx,
5440 &req,
5441 fsp,
5443 false, /* large_offset */
5445 lck);
5446 if (subreq == NULL) {
5447 reply_nterror(req, NT_STATUS_NO_MEMORY);
5448 END_PROFILE(SMBlock);
5449 return;
5451 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5452 END_PROFILE(SMBlock);
5455 static void reply_lock_done(struct tevent_req *subreq)
5457 struct smb_request *req = NULL;
5458 NTSTATUS status;
5459 bool ok;
5461 START_PROFILE(SMBlock);
5463 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5464 SMB_ASSERT(ok);
5466 status = smbd_smb1_do_locks_recv(subreq);
5467 TALLOC_FREE(subreq);
5469 if (NT_STATUS_IS_OK(status)) {
5470 reply_smb1_outbuf(req, 0, 0);
5471 } else {
5472 reply_nterror(req, status);
5475 ok = smb1_srv_send(req->xconn,
5476 (char *)req->outbuf,
5477 true,
5478 req->seqnum + 1,
5479 IS_CONN_ENCRYPTED(req->conn));
5480 if (!ok) {
5481 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5483 TALLOC_FREE(req);
5484 END_PROFILE(SMBlock);
5487 /****************************************************************************
5488 Reply to a unlock.
5489 ****************************************************************************/
5491 void reply_unlock(struct smb_request *req)
5493 connection_struct *conn = req->conn;
5494 NTSTATUS status;
5495 files_struct *fsp;
5496 struct smbd_lock_element lck;
5498 START_PROFILE(SMBunlock);
5500 if (req->wct < 5) {
5501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5502 END_PROFILE(SMBunlock);
5503 return;
5506 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5508 if (!check_fsp(conn, req, fsp)) {
5509 END_PROFILE(SMBunlock);
5510 return;
5513 lck = (struct smbd_lock_element) {
5514 .req_guid = smbd_request_guid(req, 0),
5515 .smblctx = req->smbpid,
5516 .brltype = UNLOCK_LOCK,
5517 .lock_flav = WINDOWS_LOCK,
5518 .offset = IVAL(req->vwv+3, 0),
5519 .count = IVAL(req->vwv+1, 0),
5522 status = smbd_do_unlocking(req, fsp, 1, &lck);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 reply_nterror(req, status);
5526 END_PROFILE(SMBunlock);
5527 return;
5530 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5531 fsp_get_io_fd(fsp),
5532 fsp_fnum_dbg(fsp),
5533 lck.offset,
5534 lck.count);
5536 reply_smb1_outbuf(req, 0, 0);
5538 END_PROFILE(SMBunlock);
5539 return;
5542 #undef DBGC_CLASS
5543 #define DBGC_CLASS DBGC_ALL
5545 /****************************************************************************
5546 Reply to a tdis.
5547 conn POINTER CAN BE NULL HERE !
5548 ****************************************************************************/
5550 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5551 static void reply_tdis_done(struct tevent_req *req);
5553 void reply_tdis(struct smb_request *smb1req)
5555 connection_struct *conn = smb1req->conn;
5556 struct tevent_req *req;
5559 * Don't setup the profile charge here, take
5560 * it in reply_tdis_done(). Not strictly correct
5561 * but better than the other SMB1 async
5562 * code that double-charges at the moment.
5565 if (conn == NULL) {
5566 /* Not going async, profile here. */
5567 START_PROFILE(SMBtdis);
5568 DBG_INFO("Invalid connection in tdis\n");
5569 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5570 END_PROFILE(SMBtdis);
5571 return;
5574 req = reply_tdis_send(smb1req);
5575 if (req == NULL) {
5576 /* Not going async, profile here. */
5577 START_PROFILE(SMBtdis);
5578 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5579 END_PROFILE(SMBtdis);
5580 return;
5582 /* We're async. This will complete later. */
5583 tevent_req_set_callback(req, reply_tdis_done, smb1req);
5584 return;
5587 struct reply_tdis_state {
5588 struct tevent_queue *wait_queue;
5591 static void reply_tdis_wait_done(struct tevent_req *subreq);
5593 /****************************************************************************
5594 Async SMB1 tdis.
5595 Note, on failure here we deallocate and return NULL to allow the caller to
5596 SMB1 return an error of ERRnomem immediately.
5597 ****************************************************************************/
5599 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5601 struct tevent_req *req;
5602 struct reply_tdis_state *state;
5603 struct tevent_req *subreq;
5604 connection_struct *conn = smb1req->conn;
5605 files_struct *fsp;
5607 req = tevent_req_create(smb1req, &state,
5608 struct reply_tdis_state);
5609 if (req == NULL) {
5610 return NULL;
5612 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5613 if (tevent_req_nomem(state->wait_queue, req)) {
5614 TALLOC_FREE(req);
5615 return NULL;
5619 * Make sure that no new request will be able to use this tcon.
5620 * This ensures that once all outstanding fsp->aio_requests
5621 * on this tcon are done, we are safe to close it.
5623 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5625 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5626 if (fsp->conn != conn) {
5627 continue;
5630 * Flag the file as close in progress.
5631 * This will prevent any more IO being
5632 * done on it. Not strictly needed, but
5633 * doesn't hurt to flag it as closing.
5635 fsp->fsp_flags.closing = true;
5637 if (fsp->num_aio_requests > 0) {
5639 * Now wait until all aio requests on this fsp are
5640 * finished.
5642 * We don't set a callback, as we just want to block the
5643 * wait queue and the talloc_free() of fsp->aio_request
5644 * will remove the item from the wait queue.
5646 subreq = tevent_queue_wait_send(fsp->aio_requests,
5647 conn->sconn->ev_ctx,
5648 state->wait_queue);
5649 if (tevent_req_nomem(subreq, req)) {
5650 TALLOC_FREE(req);
5651 return NULL;
5657 * Now we add our own waiter to the end of the queue,
5658 * this way we get notified when all pending requests are finished
5659 * and reply to the outstanding SMB1 request.
5661 subreq = tevent_queue_wait_send(state,
5662 conn->sconn->ev_ctx,
5663 state->wait_queue);
5664 if (tevent_req_nomem(subreq, req)) {
5665 TALLOC_FREE(req);
5666 return NULL;
5670 * We're really going async - move the SMB1 request from
5671 * a talloc stackframe above us to the sconn talloc-context.
5672 * We need this to stick around until the wait_done
5673 * callback is invoked.
5675 smb1req = talloc_move(smb1req->sconn, &smb1req);
5677 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5679 return req;
5682 static void reply_tdis_wait_done(struct tevent_req *subreq)
5684 struct tevent_req *req = tevent_req_callback_data(
5685 subreq, struct tevent_req);
5687 tevent_queue_wait_recv(subreq);
5688 TALLOC_FREE(subreq);
5689 tevent_req_done(req);
5692 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5694 return tevent_req_simple_recv_ntstatus(req);
5697 static void reply_tdis_done(struct tevent_req *req)
5699 struct smb_request *smb1req = tevent_req_callback_data(
5700 req, struct smb_request);
5701 NTSTATUS status;
5702 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5703 bool ok;
5706 * Take the profile charge here. Not strictly
5707 * correct but better than the other SMB1 async
5708 * code that double-charges at the moment.
5710 START_PROFILE(SMBtdis);
5712 status = reply_tdis_recv(req);
5713 TALLOC_FREE(req);
5714 if (!NT_STATUS_IS_OK(status)) {
5715 TALLOC_FREE(smb1req);
5716 END_PROFILE(SMBtdis);
5717 exit_server(__location__ ": reply_tdis_recv failed");
5718 return;
5722 * As we've been awoken, we may have changed
5723 * directory in the meantime.
5724 * reply_tdis() has the DO_CHDIR flag set.
5726 ok = chdir_current_service(smb1req->conn);
5727 if (!ok) {
5728 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5729 smb_request_done(smb1req);
5730 END_PROFILE(SMBtdis);
5733 status = smbXsrv_tcon_disconnect(tcon,
5734 smb1req->vuid);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 TALLOC_FREE(smb1req);
5737 END_PROFILE(SMBtdis);
5738 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5739 return;
5742 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5743 smb1req->conn = NULL;
5745 TALLOC_FREE(tcon);
5747 reply_smb1_outbuf(smb1req, 0, 0);
5749 * The following call is needed to push the
5750 * reply data back out the socket after async
5751 * return. Plus it frees smb1req.
5753 smb_request_done(smb1req);
5754 END_PROFILE(SMBtdis);
5757 /****************************************************************************
5758 Reply to a echo.
5759 conn POINTER CAN BE NULL HERE !
5760 ****************************************************************************/
5762 void reply_echo(struct smb_request *req)
5764 connection_struct *conn = req->conn;
5765 int smb_reverb;
5766 int seq_num;
5768 START_PROFILE(SMBecho);
5770 if (req->wct < 1) {
5771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5772 END_PROFILE(SMBecho);
5773 return;
5776 smb_reverb = SVAL(req->vwv+0, 0);
5778 reply_smb1_outbuf(req, 1, req->buflen);
5780 /* copy any incoming data back out */
5781 if (req->buflen > 0) {
5782 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5785 if (smb_reverb > 100) {
5786 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5787 smb_reverb = 100;
5790 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5792 SSVAL(req->outbuf,smb_vwv0,seq_num);
5794 show_msg((char *)req->outbuf);
5795 if (!smb1_srv_send(req->xconn,
5796 (char *)req->outbuf,
5797 true,
5798 req->seqnum + 1,
5799 IS_CONN_ENCRYPTED(conn) || req->encrypted))
5800 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5803 DEBUG(3,("echo %d times\n", smb_reverb));
5805 TALLOC_FREE(req->outbuf);
5807 END_PROFILE(SMBecho);
5808 return;
5811 /****************************************************************************
5812 Reply to a printopen.
5813 ****************************************************************************/
5815 void reply_printopen(struct smb_request *req)
5817 connection_struct *conn = req->conn;
5818 files_struct *fsp;
5819 NTSTATUS status;
5821 START_PROFILE(SMBsplopen);
5823 if (req->wct < 2) {
5824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5825 END_PROFILE(SMBsplopen);
5826 return;
5829 if (!CAN_PRINT(conn)) {
5830 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5831 END_PROFILE(SMBsplopen);
5832 return;
5835 status = file_new(req, conn, &fsp);
5836 if(!NT_STATUS_IS_OK(status)) {
5837 reply_nterror(req, status);
5838 END_PROFILE(SMBsplopen);
5839 return;
5842 /* Open for exclusive use, write only. */
5843 status = print_spool_open(fsp, NULL, req->vuid);
5845 if (!NT_STATUS_IS_OK(status)) {
5846 file_free(req, fsp);
5847 reply_nterror(req, status);
5848 END_PROFILE(SMBsplopen);
5849 return;
5852 reply_smb1_outbuf(req, 1, 0);
5853 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5855 DEBUG(3,("openprint fd=%d %s\n",
5856 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5858 END_PROFILE(SMBsplopen);
5859 return;
5862 /****************************************************************************
5863 Reply to a printclose.
5864 ****************************************************************************/
5866 void reply_printclose(struct smb_request *req)
5868 connection_struct *conn = req->conn;
5869 files_struct *fsp;
5870 NTSTATUS status;
5872 START_PROFILE(SMBsplclose);
5874 if (req->wct < 1) {
5875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5876 END_PROFILE(SMBsplclose);
5877 return;
5880 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5882 if (!check_fsp(conn, req, fsp)) {
5883 END_PROFILE(SMBsplclose);
5884 return;
5887 if (!CAN_PRINT(conn)) {
5888 reply_force_doserror(req, ERRSRV, ERRerror);
5889 END_PROFILE(SMBsplclose);
5890 return;
5893 DEBUG(3,("printclose fd=%d %s\n",
5894 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5896 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5898 if(!NT_STATUS_IS_OK(status)) {
5899 reply_nterror(req, status);
5900 END_PROFILE(SMBsplclose);
5901 return;
5904 reply_smb1_outbuf(req, 0, 0);
5906 END_PROFILE(SMBsplclose);
5907 return;
5910 /****************************************************************************
5911 Reply to a printqueue.
5912 ****************************************************************************/
5914 void reply_printqueue(struct smb_request *req)
5916 const struct loadparm_substitution *lp_sub =
5917 loadparm_s3_global_substitution();
5918 connection_struct *conn = req->conn;
5919 int max_count;
5920 int start_index;
5922 START_PROFILE(SMBsplretq);
5924 if (req->wct < 2) {
5925 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5926 END_PROFILE(SMBsplretq);
5927 return;
5930 max_count = SVAL(req->vwv+0, 0);
5931 start_index = SVAL(req->vwv+1, 0);
5933 /* we used to allow the client to get the cnum wrong, but that
5934 is really quite gross and only worked when there was only
5935 one printer - I think we should now only accept it if they
5936 get it right (tridge) */
5937 if (!CAN_PRINT(conn)) {
5938 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5939 END_PROFILE(SMBsplretq);
5940 return;
5943 reply_smb1_outbuf(req, 2, 3);
5944 SSVAL(req->outbuf,smb_vwv0,0);
5945 SSVAL(req->outbuf,smb_vwv1,0);
5946 SCVAL(smb_buf(req->outbuf),0,1);
5947 SSVAL(smb_buf(req->outbuf),1,0);
5949 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5950 start_index, max_count));
5953 TALLOC_CTX *mem_ctx = talloc_tos();
5954 NTSTATUS status;
5955 WERROR werr;
5956 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5957 struct rpc_pipe_client *cli = NULL;
5958 struct dcerpc_binding_handle *b = NULL;
5959 struct policy_handle handle;
5960 struct spoolss_DevmodeContainer devmode_ctr;
5961 union spoolss_JobInfo *info;
5962 uint32_t count;
5963 uint32_t num_to_get;
5964 uint32_t first;
5965 uint32_t i;
5967 ZERO_STRUCT(handle);
5969 status = rpc_pipe_open_interface(mem_ctx,
5970 &ndr_table_spoolss,
5971 conn->session_info,
5972 conn->sconn->remote_address,
5973 conn->sconn->local_address,
5974 conn->sconn->msg_ctx,
5975 &cli);
5976 if (!NT_STATUS_IS_OK(status)) {
5977 DEBUG(0, ("reply_printqueue: "
5978 "could not connect to spoolss: %s\n",
5979 nt_errstr(status)));
5980 reply_nterror(req, status);
5981 goto out;
5983 b = cli->binding_handle;
5985 ZERO_STRUCT(devmode_ctr);
5987 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5988 sharename,
5989 NULL, devmode_ctr,
5990 SEC_FLAG_MAXIMUM_ALLOWED,
5991 &handle,
5992 &werr);
5993 if (!NT_STATUS_IS_OK(status)) {
5994 reply_nterror(req, status);
5995 goto out;
5997 if (!W_ERROR_IS_OK(werr)) {
5998 reply_nterror(req, werror_to_ntstatus(werr));
5999 goto out;
6002 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6003 &handle,
6004 0, /* firstjob */
6005 0xff, /* numjobs */
6006 2, /* level */
6007 0, /* offered */
6008 &count,
6009 &info);
6010 if (!W_ERROR_IS_OK(werr)) {
6011 reply_nterror(req, werror_to_ntstatus(werr));
6012 goto out;
6015 if (max_count > 0) {
6016 first = start_index;
6017 } else {
6018 first = start_index + max_count + 1;
6021 if (first >= count) {
6022 num_to_get = first;
6023 } else {
6024 num_to_get = first + MIN(ABS(max_count), count - first);
6027 for (i = first; i < num_to_get; i++) {
6028 char blob[28];
6029 char *p = blob;
6030 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6031 int qstatus;
6032 size_t len = 0;
6033 uint16_t qrapjobid = pjobid_to_rap(sharename,
6034 info[i].info2.job_id);
6036 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6037 qstatus = 2;
6038 } else {
6039 qstatus = 3;
6042 srv_put_dos_date2(p, 0, qtime);
6043 SCVAL(p, 4, qstatus);
6044 SSVAL(p, 5, qrapjobid);
6045 SIVAL(p, 7, info[i].info2.size);
6046 SCVAL(p, 11, 0);
6047 status = srvstr_push(blob, req->flags2, p+12,
6048 info[i].info2.notify_name, 16, STR_ASCII, &len);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 reply_nterror(req, status);
6051 goto out;
6053 if (message_push_blob(
6054 &req->outbuf,
6055 data_blob_const(
6056 blob, sizeof(blob))) == -1) {
6057 reply_nterror(req, NT_STATUS_NO_MEMORY);
6058 goto out;
6062 if (count > 0) {
6063 SSVAL(req->outbuf,smb_vwv0,count);
6064 SSVAL(req->outbuf,smb_vwv1,
6065 (max_count>0?first+count:first-1));
6066 SCVAL(smb_buf(req->outbuf),0,1);
6067 SSVAL(smb_buf(req->outbuf),1,28*count);
6071 DEBUG(3, ("%u entries returned in queue\n",
6072 (unsigned)count));
6074 out:
6075 if (b && is_valid_policy_hnd(&handle)) {
6076 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6081 END_PROFILE(SMBsplretq);
6082 return;
6085 /****************************************************************************
6086 Reply to a printwrite.
6087 ****************************************************************************/
6089 void reply_printwrite(struct smb_request *req)
6091 connection_struct *conn = req->conn;
6092 int numtowrite;
6093 const char *data;
6094 files_struct *fsp;
6095 NTSTATUS status;
6097 START_PROFILE(SMBsplwr);
6099 if (req->wct < 1) {
6100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6101 END_PROFILE(SMBsplwr);
6102 return;
6105 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6107 if (!check_fsp(conn, req, fsp)) {
6108 END_PROFILE(SMBsplwr);
6109 return;
6112 if (!fsp->print_file) {
6113 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6114 END_PROFILE(SMBsplwr);
6115 return;
6118 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
6119 if (!NT_STATUS_IS_OK(status)) {
6120 reply_nterror(req, status);
6121 END_PROFILE(SMBsplwr);
6122 return;
6125 numtowrite = SVAL(req->buf, 1);
6128 * This already protects us against CVE-2017-12163.
6130 if (req->buflen < numtowrite + 3) {
6131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6132 END_PROFILE(SMBsplwr);
6133 return;
6136 data = (const char *)req->buf + 3;
6138 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6139 reply_nterror(req, map_nt_error_from_unix(errno));
6140 END_PROFILE(SMBsplwr);
6141 return;
6144 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6146 reply_smb1_outbuf(req, 0, 0);
6148 END_PROFILE(SMBsplwr);
6149 return;
6152 /****************************************************************************
6153 Reply to a mkdir.
6154 ****************************************************************************/
6156 void reply_mkdir(struct smb_request *req)
6158 connection_struct *conn = req->conn;
6159 struct files_struct *dirfsp = NULL;
6160 struct smb_filename *smb_dname = NULL;
6161 char *directory = NULL;
6162 NTSTATUS status;
6163 uint32_t ucf_flags;
6164 NTTIME twrp = 0;
6165 TALLOC_CTX *ctx = talloc_tos();
6167 START_PROFILE(SMBmkdir);
6169 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6170 STR_TERMINATE, &status);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 reply_nterror(req, status);
6173 goto out;
6176 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6177 if (ucf_flags & UCF_GMT_PATHNAME) {
6178 extract_snapshot_token(directory, &twrp);
6180 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6181 if (!NT_STATUS_IS_OK(status)) {
6182 reply_nterror(req, status);
6183 goto out;
6186 status = filename_convert_dirfsp(ctx,
6187 conn,
6188 directory,
6189 ucf_flags,
6190 twrp,
6191 &dirfsp,
6192 &smb_dname);
6193 if (!NT_STATUS_IS_OK(status)) {
6194 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6195 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6196 ERRSRV, ERRbadpath);
6197 goto out;
6199 reply_nterror(req, status);
6200 goto out;
6203 status = create_directory(conn, req, dirfsp, smb_dname);
6205 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6207 if (!NT_STATUS_IS_OK(status)) {
6209 if (!use_nt_status()
6210 && NT_STATUS_EQUAL(status,
6211 NT_STATUS_OBJECT_NAME_COLLISION)) {
6213 * Yes, in the DOS error code case we get a
6214 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6215 * samba4 torture test.
6217 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6220 reply_nterror(req, status);
6221 goto out;
6224 reply_smb1_outbuf(req, 0, 0);
6226 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6227 out:
6228 TALLOC_FREE(smb_dname);
6229 END_PROFILE(SMBmkdir);
6230 return;
6233 /****************************************************************************
6234 Reply to a rmdir.
6235 ****************************************************************************/
6237 void reply_rmdir(struct smb_request *req)
6239 connection_struct *conn = req->conn;
6240 struct smb_filename *smb_dname = NULL;
6241 char *directory = NULL;
6242 NTSTATUS status;
6243 TALLOC_CTX *ctx = talloc_tos();
6244 struct files_struct *dirfsp = NULL;
6245 files_struct *fsp = NULL;
6246 int info = 0;
6247 NTTIME twrp = 0;
6248 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6250 START_PROFILE(SMBrmdir);
6252 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6253 STR_TERMINATE, &status);
6254 if (!NT_STATUS_IS_OK(status)) {
6255 reply_nterror(req, status);
6256 goto out;
6259 if (ucf_flags & UCF_GMT_PATHNAME) {
6260 extract_snapshot_token(directory, &twrp);
6262 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6263 if (!NT_STATUS_IS_OK(status)) {
6264 reply_nterror(req, status);
6265 goto out;
6268 status = filename_convert_dirfsp(ctx,
6269 conn,
6270 directory,
6271 ucf_flags,
6272 twrp,
6273 &dirfsp,
6274 &smb_dname);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6277 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6278 ERRSRV, ERRbadpath);
6279 goto out;
6281 reply_nterror(req, status);
6282 goto out;
6285 status = SMB_VFS_CREATE_FILE(
6286 conn, /* conn */
6287 req, /* req */
6288 dirfsp, /* dirfsp */
6289 smb_dname, /* fname */
6290 DELETE_ACCESS, /* access_mask */
6291 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6292 FILE_SHARE_DELETE),
6293 FILE_OPEN, /* create_disposition*/
6294 FILE_DIRECTORY_FILE, /* create_options */
6295 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6296 0, /* oplock_request */
6297 NULL, /* lease */
6298 0, /* allocation_size */
6299 0, /* private_flags */
6300 NULL, /* sd */
6301 NULL, /* ea_list */
6302 &fsp, /* result */
6303 &info, /* pinfo */
6304 NULL, NULL); /* create context */
6306 if (!NT_STATUS_IS_OK(status)) {
6307 if (open_was_deferred(req->xconn, req->mid)) {
6308 /* We have re-scheduled this call. */
6309 goto out;
6311 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6312 bool ok = defer_smb1_sharing_violation(req);
6313 if (ok) {
6314 goto out;
6317 reply_nterror(req, status);
6318 goto out;
6321 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 close_file_free(req, &fsp, ERROR_CLOSE);
6324 reply_nterror(req, status);
6325 goto out;
6328 if (!set_delete_on_close(fsp, true,
6329 conn->session_info->security_token,
6330 conn->session_info->unix_token)) {
6331 close_file_free(req, &fsp, ERROR_CLOSE);
6332 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6333 goto out;
6336 status = close_file_free(req, &fsp, NORMAL_CLOSE);
6337 if (!NT_STATUS_IS_OK(status)) {
6338 reply_nterror(req, status);
6339 } else {
6340 reply_smb1_outbuf(req, 0, 0);
6343 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6344 out:
6345 TALLOC_FREE(smb_dname);
6346 END_PROFILE(SMBrmdir);
6347 return;
6350 /****************************************************************************
6351 Reply to a mv.
6352 ****************************************************************************/
6354 void reply_mv(struct smb_request *req)
6356 connection_struct *conn = req->conn;
6357 char *name = NULL;
6358 char *newname = NULL;
6359 const char *p;
6360 uint32_t attrs;
6361 NTSTATUS status;
6362 TALLOC_CTX *ctx = talloc_tos();
6363 struct files_struct *src_dirfsp = NULL;
6364 struct smb_filename *smb_fname_src = NULL;
6365 struct files_struct *dst_dirfsp = NULL;
6366 struct smb_filename *smb_fname_dst = NULL;
6367 const char *dst_original_lcomp = NULL;
6368 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
6369 NTTIME src_twrp = 0;
6370 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
6371 NTTIME dst_twrp = 0;
6372 bool stream_rename = false;
6374 START_PROFILE(SMBmv);
6376 if (req->wct < 1) {
6377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6378 goto out;
6381 attrs = SVAL(req->vwv+0, 0);
6383 p = (const char *)req->buf + 1;
6384 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
6385 &status);
6386 if (!NT_STATUS_IS_OK(status)) {
6387 reply_nterror(req, status);
6388 goto out;
6390 p++;
6391 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
6392 &status);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 reply_nterror(req, status);
6395 goto out;
6398 if (!req->posix_pathnames) {
6399 /* The newname must begin with a ':' if the
6400 name contains a ':'. */
6401 if (strchr_m(name, ':')) {
6402 if (newname[0] != ':') {
6403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6404 goto out;
6406 stream_rename = true;
6410 if (src_ucf_flags & UCF_GMT_PATHNAME) {
6411 extract_snapshot_token(name, &src_twrp);
6413 status = smb1_strip_dfs_path(ctx, &src_ucf_flags, &name);
6414 if (!NT_STATUS_IS_OK(status)) {
6415 reply_nterror(req, status);
6416 goto out;
6418 status = filename_convert_dirfsp(ctx,
6419 conn,
6420 name,
6421 src_ucf_flags,
6422 src_twrp,
6423 &src_dirfsp,
6424 &smb_fname_src);
6426 if (!NT_STATUS_IS_OK(status)) {
6427 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6428 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6429 ERRSRV, ERRbadpath);
6430 goto out;
6432 reply_nterror(req, status);
6433 goto out;
6436 if (dst_ucf_flags & UCF_GMT_PATHNAME) {
6437 extract_snapshot_token(newname, &dst_twrp);
6439 status = smb1_strip_dfs_path(ctx, &dst_ucf_flags, &newname);
6440 if (!NT_STATUS_IS_OK(status)) {
6441 reply_nterror(req, status);
6442 goto out;
6444 status = filename_convert_dirfsp(ctx,
6445 conn,
6446 newname,
6447 dst_ucf_flags,
6448 dst_twrp,
6449 &dst_dirfsp,
6450 &smb_fname_dst);
6452 if (!NT_STATUS_IS_OK(status)) {
6453 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6454 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6455 ERRSRV, ERRbadpath);
6456 goto out;
6458 reply_nterror(req, status);
6459 goto out;
6462 /* Get the last component of the destination for rename_internals(). */
6463 dst_original_lcomp = get_original_lcomp(ctx,
6464 conn,
6465 newname,
6466 dst_ucf_flags);
6467 if (dst_original_lcomp == NULL) {
6468 reply_nterror(req, NT_STATUS_NO_MEMORY);
6469 goto out;
6472 if (stream_rename) {
6473 /* smb_fname_dst->base_name must be the same as
6474 smb_fname_src->base_name. */
6475 TALLOC_FREE(smb_fname_dst->base_name);
6476 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6477 smb_fname_src->base_name);
6478 if (!smb_fname_dst->base_name) {
6479 reply_nterror(req, NT_STATUS_NO_MEMORY);
6480 goto out;
6484 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6485 smb_fname_str_dbg(smb_fname_dst)));
6487 status = rename_internals(ctx,
6488 conn,
6489 req,
6490 src_dirfsp, /* src_dirfsp */
6491 smb_fname_src,
6492 dst_dirfsp, /* dst_dirfsp */
6493 smb_fname_dst,
6494 dst_original_lcomp,
6495 attrs,
6496 false,
6497 DELETE_ACCESS);
6498 if (!NT_STATUS_IS_OK(status)) {
6499 if (open_was_deferred(req->xconn, req->mid)) {
6500 /* We have re-scheduled this call. */
6501 goto out;
6503 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6504 bool ok = defer_smb1_sharing_violation(req);
6505 if (ok) {
6506 goto out;
6509 reply_nterror(req, status);
6510 goto out;
6513 reply_smb1_outbuf(req, 0, 0);
6514 out:
6515 TALLOC_FREE(smb_fname_src);
6516 TALLOC_FREE(smb_fname_dst);
6517 END_PROFILE(SMBmv);
6518 return;
6521 /****************************************************************************
6522 Reply to a file copy.
6524 From MS-CIFS.
6526 This command was introduced in the LAN Manager 1.0 dialect
6527 It was rendered obsolete in the NT LAN Manager dialect.
6528 This command was used to perform server-side file copies, but
6529 is no longer used. Clients SHOULD
6530 NOT send requests using this command code.
6531 Servers receiving requests with this command code
6532 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6533 ****************************************************************************/
6535 void reply_copy(struct smb_request *req)
6537 START_PROFILE(SMBcopy);
6538 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
6539 END_PROFILE(SMBcopy);
6540 return;
6543 #undef DBGC_CLASS
6544 #define DBGC_CLASS DBGC_LOCKING
6546 /****************************************************************************
6547 Get a lock pid, dealing with large count requests.
6548 ****************************************************************************/
6550 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6551 bool large_file_format)
6553 if(!large_file_format)
6554 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6555 else
6556 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6559 /****************************************************************************
6560 Get a lock count, dealing with large count requests.
6561 ****************************************************************************/
6563 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6564 bool large_file_format)
6566 uint64_t count = 0;
6568 if(!large_file_format) {
6569 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6570 } else {
6572 * No BVAL, this is reversed!
6574 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6575 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6578 return count;
6581 /****************************************************************************
6582 Reply to a lockingX request.
6583 ****************************************************************************/
6585 static void reply_lockingx_done(struct tevent_req *subreq);
6587 void reply_lockingX(struct smb_request *req)
6589 connection_struct *conn = req->conn;
6590 files_struct *fsp;
6591 unsigned char locktype;
6592 enum brl_type brltype;
6593 unsigned char oplocklevel;
6594 uint16_t num_ulocks;
6595 uint16_t num_locks;
6596 int32_t lock_timeout;
6597 uint16_t i;
6598 const uint8_t *data;
6599 bool large_file_format;
6600 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6601 struct smbd_lock_element *locks = NULL;
6602 struct tevent_req *subreq = NULL;
6604 START_PROFILE(SMBlockingX);
6606 if (req->wct < 8) {
6607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6608 END_PROFILE(SMBlockingX);
6609 return;
6612 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6613 locktype = CVAL(req->vwv+3, 0);
6614 oplocklevel = CVAL(req->vwv+3, 1);
6615 num_ulocks = SVAL(req->vwv+6, 0);
6616 num_locks = SVAL(req->vwv+7, 0);
6617 lock_timeout = IVAL(req->vwv+4, 0);
6618 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
6620 if (!check_fsp(conn, req, fsp)) {
6621 END_PROFILE(SMBlockingX);
6622 return;
6625 data = req->buf;
6627 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6628 /* we don't support these - and CANCEL_LOCK makes w2k
6629 and XP reboot so I don't really want to be
6630 compatible! (tridge) */
6631 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
6632 END_PROFILE(SMBlockingX);
6633 return;
6636 /* Check if this is an oplock break on a file
6637 we have granted an oplock on.
6639 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
6640 /* Client can insist on breaking to none. */
6641 bool break_to_none = (oplocklevel == 0);
6642 bool result;
6644 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6645 "for %s\n", (unsigned int)oplocklevel,
6646 fsp_fnum_dbg(fsp)));
6649 * Make sure we have granted an exclusive or batch oplock on
6650 * this file.
6653 if (fsp->oplock_type == 0) {
6655 /* The Samba4 nbench simulator doesn't understand
6656 the difference between break to level2 and break
6657 to none from level2 - it sends oplock break
6658 replies in both cases. Don't keep logging an error
6659 message here - just ignore it. JRA. */
6661 DEBUG(5,("reply_lockingX: Error : oplock break from "
6662 "client for %s (oplock=%d) and no "
6663 "oplock granted on this file (%s).\n",
6664 fsp_fnum_dbg(fsp), fsp->oplock_type,
6665 fsp_str_dbg(fsp)));
6667 /* if this is a pure oplock break request then don't
6668 * send a reply */
6669 if (num_locks == 0 && num_ulocks == 0) {
6670 END_PROFILE(SMBlockingX);
6671 return;
6674 END_PROFILE(SMBlockingX);
6675 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6676 return;
6679 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6680 (break_to_none)) {
6681 result = remove_oplock(fsp);
6682 } else {
6683 result = downgrade_oplock(fsp);
6686 if (!result) {
6687 DEBUG(0, ("reply_lockingX: error in removing "
6688 "oplock on file %s\n", fsp_str_dbg(fsp)));
6689 /* Hmmm. Is this panic justified? */
6690 smb_panic("internal tdb error");
6693 /* if this is a pure oplock break request then don't send a
6694 * reply */
6695 if (num_locks == 0 && num_ulocks == 0) {
6696 /* Sanity check - ensure a pure oplock break is not a
6697 chained request. */
6698 if (CVAL(req->vwv+0, 0) != 0xff) {
6699 DEBUG(0,("reply_lockingX: Error : pure oplock "
6700 "break is a chained %d request !\n",
6701 (unsigned int)CVAL(req->vwv+0, 0)));
6703 END_PROFILE(SMBlockingX);
6704 return;
6708 if (req->buflen <
6709 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6711 END_PROFILE(SMBlockingX);
6712 return;
6715 if (num_ulocks != 0) {
6716 struct smbd_lock_element *ulocks = NULL;
6717 bool ok;
6719 ulocks = talloc_array(
6720 req, struct smbd_lock_element, num_ulocks);
6721 if (ulocks == NULL) {
6722 reply_nterror(req, NT_STATUS_NO_MEMORY);
6723 END_PROFILE(SMBlockingX);
6724 return;
6728 * Data now points at the beginning of the list of
6729 * smb_unlkrng structs
6731 for (i = 0; i < num_ulocks; i++) {
6732 ulocks[i].req_guid = smbd_request_guid(req,
6733 UINT16_MAX - i),
6734 ulocks[i].smblctx = get_lock_pid(
6735 data, i, large_file_format);
6736 ulocks[i].count = get_lock_count(
6737 data, i, large_file_format);
6738 ulocks[i].offset = get_lock_offset(
6739 data, i, large_file_format);
6740 ulocks[i].brltype = UNLOCK_LOCK;
6741 ulocks[i].lock_flav = WINDOWS_LOCK;
6745 * Unlock cancels pending locks
6748 ok = smbd_smb1_brl_finish_by_lock(
6749 fsp,
6750 large_file_format,
6751 ulocks[0],
6752 NT_STATUS_OK);
6753 if (ok) {
6754 reply_smb1_outbuf(req, 2, 0);
6755 SSVAL(req->outbuf, smb_vwv0, 0xff);
6756 SSVAL(req->outbuf, smb_vwv1, 0);
6757 END_PROFILE(SMBlockingX);
6758 return;
6761 status = smbd_do_unlocking(
6762 req, fsp, num_ulocks, ulocks);
6763 TALLOC_FREE(ulocks);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 END_PROFILE(SMBlockingX);
6766 reply_nterror(req, status);
6767 return;
6771 /* Now do any requested locks */
6772 data += ((large_file_format ? 20 : 10)*num_ulocks);
6774 /* Data now points at the beginning of the list
6775 of smb_lkrng structs */
6777 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
6778 brltype = READ_LOCK;
6779 } else {
6780 brltype = WRITE_LOCK;
6783 locks = talloc_array(req, struct smbd_lock_element, num_locks);
6784 if (locks == NULL) {
6785 reply_nterror(req, NT_STATUS_NO_MEMORY);
6786 END_PROFILE(SMBlockingX);
6787 return;
6790 for (i = 0; i < num_locks; i++) {
6791 locks[i].req_guid = smbd_request_guid(req, i),
6792 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
6793 locks[i].count = get_lock_count(data, i, large_file_format);
6794 locks[i].offset = get_lock_offset(data, i, large_file_format);
6795 locks[i].brltype = brltype;
6796 locks[i].lock_flav = WINDOWS_LOCK;
6799 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6801 bool ok;
6803 if (num_locks == 0) {
6804 /* See smbtorture3 lock11 test */
6805 reply_smb1_outbuf(req, 2, 0);
6806 /* andx chain ends */
6807 SSVAL(req->outbuf, smb_vwv0, 0xff);
6808 SSVAL(req->outbuf, smb_vwv1, 0);
6809 END_PROFILE(SMBlockingX);
6810 return;
6813 ok = smbd_smb1_brl_finish_by_lock(
6814 fsp,
6815 large_file_format,
6816 locks[0], /* Windows only cancels the first lock */
6817 NT_STATUS_FILE_LOCK_CONFLICT);
6819 if (!ok) {
6820 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
6821 END_PROFILE(SMBlockingX);
6822 return;
6825 reply_smb1_outbuf(req, 2, 0);
6826 SSVAL(req->outbuf, smb_vwv0, 0xff);
6827 SSVAL(req->outbuf, smb_vwv1, 0);
6828 END_PROFILE(SMBlockingX);
6829 return;
6832 subreq = smbd_smb1_do_locks_send(
6833 fsp,
6834 req->sconn->ev_ctx,
6835 &req,
6836 fsp,
6837 lock_timeout,
6838 large_file_format,
6839 num_locks,
6840 locks);
6841 if (subreq == NULL) {
6842 reply_nterror(req, NT_STATUS_NO_MEMORY);
6843 END_PROFILE(SMBlockingX);
6844 return;
6846 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
6847 END_PROFILE(SMBlockingX);
6850 static void reply_lockingx_done(struct tevent_req *subreq)
6852 struct smb_request *req = NULL;
6853 NTSTATUS status;
6854 bool ok;
6856 START_PROFILE(SMBlockingX);
6858 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6859 SMB_ASSERT(ok);
6861 status = smbd_smb1_do_locks_recv(subreq);
6862 TALLOC_FREE(subreq);
6864 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
6866 if (NT_STATUS_IS_OK(status)) {
6867 reply_smb1_outbuf(req, 2, 0);
6868 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
6869 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
6870 } else {
6871 reply_nterror(req, status);
6874 ok = smb1_srv_send(req->xconn,
6875 (char *)req->outbuf,
6876 true,
6877 req->seqnum + 1,
6878 IS_CONN_ENCRYPTED(req->conn));
6879 if (!ok) {
6880 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6882 TALLOC_FREE(req);
6883 END_PROFILE(SMBlockingX);
6886 #undef DBGC_CLASS
6887 #define DBGC_CLASS DBGC_ALL
6889 /****************************************************************************
6890 Reply to a SMBreadbmpx (read block multiplex) request.
6891 Always reply with an error, if someone has a platform really needs this,
6892 please contact vl@samba.org
6893 ****************************************************************************/
6895 void reply_readbmpx(struct smb_request *req)
6897 START_PROFILE(SMBreadBmpx);
6898 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6899 END_PROFILE(SMBreadBmpx);
6900 return;
6903 /****************************************************************************
6904 Reply to a SMBreadbs (read block multiplex secondary) request.
6905 Always reply with an error, if someone has a platform really needs this,
6906 please contact vl@samba.org
6907 ****************************************************************************/
6909 void reply_readbs(struct smb_request *req)
6911 START_PROFILE(SMBreadBs);
6912 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6913 END_PROFILE(SMBreadBs);
6914 return;
6917 /****************************************************************************
6918 Reply to a SMBsetattrE.
6919 ****************************************************************************/
6921 void reply_setattrE(struct smb_request *req)
6923 connection_struct *conn = req->conn;
6924 struct smb_file_time ft;
6925 files_struct *fsp;
6926 NTSTATUS status;
6928 START_PROFILE(SMBsetattrE);
6929 init_smb_file_time(&ft);
6931 if (req->wct < 7) {
6932 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6933 goto out;
6936 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6938 if(!fsp || (fsp->conn != conn)) {
6939 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6940 goto out;
6944 * Convert the DOS times into unix times.
6947 ft.atime = time_t_to_full_timespec(
6948 srv_make_unix_date2(req->vwv+3));
6949 ft.mtime = time_t_to_full_timespec(
6950 srv_make_unix_date2(req->vwv+5));
6951 ft.create_time = time_t_to_full_timespec(
6952 srv_make_unix_date2(req->vwv+1));
6954 reply_smb1_outbuf(req, 0, 0);
6957 * Patch from Ray Frush <frush@engr.colostate.edu>
6958 * Sometimes times are sent as zero - ignore them.
6961 /* Ensure we have a valid stat struct for the source. */
6962 status = vfs_stat_fsp(fsp);
6963 if (!NT_STATUS_IS_OK(status)) {
6964 reply_nterror(req, status);
6965 goto out;
6968 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 reply_nterror(req, status);
6971 goto out;
6974 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
6975 if (!NT_STATUS_IS_OK(status)) {
6976 reply_nterror(req, status);
6977 goto out;
6980 if (fsp->fsp_flags.modified) {
6981 trigger_write_time_update_immediate(fsp);
6984 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6985 " createtime=%u\n",
6986 fsp_fnum_dbg(fsp),
6987 (unsigned int)ft.atime.tv_sec,
6988 (unsigned int)ft.mtime.tv_sec,
6989 (unsigned int)ft.create_time.tv_sec
6991 out:
6992 END_PROFILE(SMBsetattrE);
6993 return;
6997 /* Back from the dead for OS/2..... JRA. */
6999 /****************************************************************************
7000 Reply to a SMBwritebmpx (write block multiplex primary) request.
7001 Always reply with an error, if someone has a platform really needs this,
7002 please contact vl@samba.org
7003 ****************************************************************************/
7005 void reply_writebmpx(struct smb_request *req)
7007 START_PROFILE(SMBwriteBmpx);
7008 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7009 END_PROFILE(SMBwriteBmpx);
7010 return;
7013 /****************************************************************************
7014 Reply to a SMBwritebs (write block multiplex secondary) request.
7015 Always reply with an error, if someone has a platform really needs this,
7016 please contact vl@samba.org
7017 ****************************************************************************/
7019 void reply_writebs(struct smb_request *req)
7021 START_PROFILE(SMBwriteBs);
7022 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7023 END_PROFILE(SMBwriteBs);
7024 return;
7027 /****************************************************************************
7028 Reply to a SMBgetattrE.
7029 ****************************************************************************/
7031 void reply_getattrE(struct smb_request *req)
7033 connection_struct *conn = req->conn;
7034 int mode;
7035 files_struct *fsp;
7036 struct timespec create_ts;
7037 NTSTATUS status;
7039 START_PROFILE(SMBgetattrE);
7041 if (req->wct < 1) {
7042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7043 END_PROFILE(SMBgetattrE);
7044 return;
7047 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7049 if(!fsp || (fsp->conn != conn)) {
7050 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7051 END_PROFILE(SMBgetattrE);
7052 return;
7055 /* Do an fstat on this file */
7056 status = vfs_stat_fsp(fsp);
7057 if (!NT_STATUS_IS_OK(status)) {
7058 reply_nterror(req, status);
7059 END_PROFILE(SMBgetattrE);
7060 return;
7063 mode = fdos_mode(fsp);
7066 * Convert the times into dos times. Set create
7067 * date to be last modify date as UNIX doesn't save
7068 * this.
7071 reply_smb1_outbuf(req, 11, 0);
7073 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7074 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7075 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7076 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7077 /* Should we check pending modtime here ? JRA */
7078 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7079 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7081 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7082 SIVAL(req->outbuf, smb_vwv6, 0);
7083 SIVAL(req->outbuf, smb_vwv8, 0);
7084 } else {
7085 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7086 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
7087 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7089 SSVAL(req->outbuf,smb_vwv10, mode);
7091 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
7093 END_PROFILE(SMBgetattrE);
7094 return;
7097 /****************************************************************************
7098 Reply to a SMBfindclose (stop trans2 directory search).
7099 ****************************************************************************/
7101 void reply_findclose(struct smb_request *req)
7103 int dptr_num;
7104 struct smbd_server_connection *sconn = req->sconn;
7105 files_struct *fsp = NULL;
7107 START_PROFILE(SMBfindclose);
7109 if (req->wct < 1) {
7110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7111 END_PROFILE(SMBfindclose);
7112 return;
7115 dptr_num = SVALS(req->vwv+0, 0);
7117 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7120 * OS/2 seems to use -1 to indicate "close all directories"
7121 * This has to mean on this specific connection struct.
7123 if (dptr_num == -1) {
7124 dptr_closecnum(req->conn);
7125 } else {
7126 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
7127 dptr_num = -1;
7128 if (fsp != NULL) {
7129 close_file_free(NULL, &fsp, NORMAL_CLOSE);
7133 reply_smb1_outbuf(req, 0, 0);
7135 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7137 END_PROFILE(SMBfindclose);
7138 return;
7141 /****************************************************************************
7142 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7143 ****************************************************************************/
7145 void reply_findnclose(struct smb_request *req)
7147 int dptr_num;
7149 START_PROFILE(SMBfindnclose);
7151 if (req->wct < 1) {
7152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7153 END_PROFILE(SMBfindnclose);
7154 return;
7157 dptr_num = SVAL(req->vwv+0, 0);
7159 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7161 /* We never give out valid handles for a
7162 findnotifyfirst - so any dptr_num is ok here.
7163 Just ignore it. */
7165 reply_smb1_outbuf(req, 0, 0);
7167 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7169 END_PROFILE(SMBfindnclose);
7170 return;