ctdb-common: Map ENOENT for a missing event script to ENOEXEC
[samba.git] / source3 / smbd / smb1_reply.c
blob3b71f5fb8ba17c28659a899037ea949fbb567a76
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 "source3/smbd/smbXsrv_session.h"
35 #include "smbd/smbXsrv_open.h"
36 #include "fake_file.h"
37 #include "rpc_client/rpc_client.h"
38 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
39 #include "rpc_client/cli_spoolss.h"
40 #include "rpc_client/init_spoolss.h"
41 #include "rpc_server/rpc_ncacn_np.h"
42 #include "libcli/security/security.h"
43 #include "libsmb/nmblib.h"
44 #include "auth.h"
45 #include "smbprofile.h"
46 #include "../lib/tsocket/tsocket.h"
47 #include "lib/util/tevent_ntstatus.h"
48 #include "libcli/smb/smb_signing.h"
49 #include "lib/util/sys_rw_data.h"
50 #include "librpc/gen_ndr/open_files.h"
51 #include "libcli/smb/smb2_posix.h"
52 #include "lib/util/string_wrappers.h"
53 #include "source3/printing/rap_jobid.h"
54 #include "source3/lib/substitute.h"
55 #include "source3/smbd/dir.h"
57 /****************************************************************************
58 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
59 ****************************************************************************/
61 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
62 files_struct *fsp)
64 if ((fsp == NULL) || (conn == NULL)) {
65 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
66 return false;
68 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
69 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
70 return false;
72 return true;
75 /****************************************************************************
76 SMB1 version of smb2_strip_dfs_path()
77 Differs from SMB2 in that all Windows path separator '\' characters
78 have already been converted to '/' by check_path_syntax().
79 ****************************************************************************/
81 NTSTATUS smb1_strip_dfs_path(TALLOC_CTX *mem_ctx,
82 uint32_t *_ucf_flags,
83 char **in_path)
85 uint32_t ucf_flags = *_ucf_flags;
86 char *path = *in_path;
87 char *return_path = NULL;
89 if (!(ucf_flags & UCF_DFS_PATHNAME)) {
90 return NT_STATUS_OK;
93 /* Strip any leading '/' characters - MacOSX client behavior. */
94 while (*path == '/') {
95 path++;
98 /* We should now be pointing at the server name. Go past it. */
99 for (;;) {
100 if (*path == '\0') {
101 /* End of complete path. Exit OK. */
102 goto done;
104 if (*path == '/') {
105 /* End of server name. Go past and break. */
106 path++;
107 break;
109 path++; /* Continue looking for end of server name or string. */
112 /* We should now be pointing at the share name. Go past it. */
113 for (;;) {
114 if (*path == '\0') {
115 /* End of complete path. Exit OK. */
116 goto done;
118 if (*path == '/') {
119 /* End of share name. Go past and break. */
120 path++;
121 break;
123 if (*path == ':') {
124 /* Only invalid character in sharename. */
125 return NT_STATUS_OBJECT_NAME_INVALID;
127 path++; /* Continue looking for end of share name or string. */
130 done:
131 /* path now points at the start of the real filename (if any). */
132 /* Duplicate it first. */
133 return_path = talloc_strdup(mem_ctx, path);
134 if (return_path == NULL) {
135 return NT_STATUS_NO_MEMORY;
138 /* Now we can free the original (path points to part of this). */
139 TALLOC_FREE(*in_path);
141 *in_path = return_path;
142 ucf_flags &= ~UCF_DFS_PATHNAME;
143 *_ucf_flags = ucf_flags;
144 return NT_STATUS_OK;
147 /****************************************************************************
148 Check if we have a correct fsp pointing to a file.
149 ****************************************************************************/
151 bool check_fsp(connection_struct *conn, struct smb_request *req,
152 files_struct *fsp)
154 if (!check_fsp_open(conn, req, fsp)) {
155 return false;
157 if (fsp->fsp_flags.is_directory) {
158 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
159 return false;
161 if (fsp_get_pathref_fd(fsp) == -1) {
162 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
163 return false;
165 fsp->num_smb_operations++;
166 return true;
169 /****************************************************************************
170 Reply to a tcon.
171 conn POINTER CAN BE NULL HERE !
172 ****************************************************************************/
174 void reply_tcon(struct smb_request *req)
176 connection_struct *conn = req->conn;
177 const char *service;
178 char *service_buf = NULL;
179 char *password = NULL;
180 char *dev = NULL;
181 int pwlen=0;
182 NTSTATUS nt_status;
183 const uint8_t *p;
184 const char *p2;
185 TALLOC_CTX *ctx = talloc_tos();
186 struct smbXsrv_connection *xconn = req->xconn;
187 NTTIME now = timeval_to_nttime(&req->request_time);
189 START_PROFILE(SMBtcon);
191 if (req->buflen < 4) {
192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
193 END_PROFILE(SMBtcon);
194 return;
197 p = req->buf + 1;
198 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
199 p += 1;
200 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
201 p += pwlen+1;
202 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
203 p += 1;
205 if (service_buf == NULL || password == NULL || dev == NULL) {
206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
207 END_PROFILE(SMBtcon);
208 return;
210 p2 = strrchr_m(service_buf,'\\');
211 if (p2) {
212 service = p2+1;
213 } else {
214 service = service_buf;
217 conn = make_connection(req, now, service, dev,
218 req->vuid,&nt_status);
219 req->conn = conn;
221 if (!conn) {
222 reply_nterror(req, nt_status);
223 END_PROFILE(SMBtcon);
224 return;
227 reply_smb1_outbuf(req, 2, 0);
228 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
229 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
230 SSVAL(req->outbuf,smb_tid,conn->cnum);
232 DEBUG(3,("tcon service=%s cnum=%d\n",
233 service, conn->cnum));
235 END_PROFILE(SMBtcon);
236 return;
239 /****************************************************************************
240 Reply to a tcon and X.
241 conn POINTER CAN BE NULL HERE !
242 ****************************************************************************/
244 void reply_tcon_and_X(struct smb_request *req)
246 const struct loadparm_substitution *lp_sub =
247 loadparm_s3_global_substitution();
248 connection_struct *conn = req->conn;
249 const char *service = NULL;
250 TALLOC_CTX *ctx = talloc_tos();
251 /* what the client thinks the device is */
252 char *client_devicetype = NULL;
253 /* what the server tells the client the share represents */
254 const char *server_devicetype;
255 NTSTATUS nt_status;
256 int passlen;
257 char *path = NULL;
258 const uint8_t *p;
259 const char *q;
260 uint16_t tcon_flags;
261 struct smbXsrv_session *session = NULL;
262 NTTIME now = timeval_to_nttime(&req->request_time);
263 bool session_key_updated = false;
264 uint16_t optional_support = 0;
265 struct smbXsrv_connection *xconn = req->xconn;
267 START_PROFILE(SMBtconX);
269 if (req->wct < 4) {
270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
271 END_PROFILE(SMBtconX);
272 return;
275 passlen = SVAL(req->vwv+3, 0);
276 tcon_flags = SVAL(req->vwv+2, 0);
278 /* we might have to close an old one */
279 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
280 struct smbXsrv_tcon *tcon;
281 NTSTATUS status;
283 tcon = conn->tcon;
284 req->conn = NULL;
285 conn = NULL;
288 * TODO: cancel all outstanding requests on the tcon
290 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
291 if (!NT_STATUS_IS_OK(status)) {
292 DEBUG(0, ("reply_tcon_and_X: "
293 "smbXsrv_tcon_disconnect() failed: %s\n",
294 nt_errstr(status)));
296 * If we hit this case, there is something completely
297 * wrong, so we better disconnect the transport connection.
299 END_PROFILE(SMBtconX);
300 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
301 return;
304 TALLOC_FREE(tcon);
306 * This tree id is gone. Make sure we can't re-use it
307 * by accident.
309 req->tid = 0;
312 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
313 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
314 END_PROFILE(SMBtconX);
315 return;
318 if (xconn->smb1.negprot.encrypted_passwords) {
319 p = req->buf + passlen;
320 } else {
321 p = req->buf + passlen + 1;
324 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
326 if (path == NULL) {
327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
328 END_PROFILE(SMBtconX);
329 return;
333 * the service name can be either: \\server\share
334 * or share directly like on the DELL PowerVault 705
336 if (*path=='\\') {
337 q = strchr_m(path+2,'\\');
338 if (!q) {
339 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
340 END_PROFILE(SMBtconX);
341 return;
343 service = q+1;
344 } else {
345 service = path;
348 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
349 &client_devicetype, p,
350 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
352 if (client_devicetype == NULL) {
353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
354 END_PROFILE(SMBtconX);
355 return;
358 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
360 nt_status = smb1srv_session_lookup(xconn,
361 req->vuid, now, &session);
362 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
363 reply_force_doserror(req, ERRSRV, ERRbaduid);
364 END_PROFILE(SMBtconX);
365 return;
367 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
368 reply_nterror(req, nt_status);
369 END_PROFILE(SMBtconX);
370 return;
372 if (!NT_STATUS_IS_OK(nt_status)) {
373 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
374 END_PROFILE(SMBtconX);
375 return;
378 if (session->global->auth_session_info == NULL) {
379 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
380 END_PROFILE(SMBtconX);
381 return;
385 * If there is no application key defined yet
386 * we create one.
388 * This means we setup the application key on the
389 * first tcon that happens via the given session.
391 * Once the application key is defined, it does not
392 * change any more.
394 if (session->global->application_key_blob.length == 0 &&
395 smb2_signing_key_valid(session->global->signing_key))
397 struct smbXsrv_session *x = session;
398 struct auth_session_info *session_info =
399 session->global->auth_session_info;
400 uint8_t session_key[16];
402 ZERO_STRUCT(session_key);
403 memcpy(session_key, x->global->signing_key->blob.data,
404 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
407 * The application key is truncated/padded to 16 bytes
409 x->global->application_key_blob = data_blob_talloc(x->global,
410 session_key,
411 sizeof(session_key));
412 ZERO_STRUCT(session_key);
413 if (x->global->application_key_blob.data == NULL) {
414 reply_nterror(req, NT_STATUS_NO_MEMORY);
415 END_PROFILE(SMBtconX);
416 return;
418 talloc_keep_secret(x->global->application_key_blob.data);
420 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
421 NTSTATUS status;
423 status = smb1_key_derivation(x->global->application_key_blob.data,
424 x->global->application_key_blob.length,
425 x->global->application_key_blob.data);
426 if (!NT_STATUS_IS_OK(status)) {
427 DBG_ERR("smb1_key_derivation failed: %s\n",
428 nt_errstr(status));
429 END_PROFILE(SMBtconX);
430 return;
432 optional_support |= SMB_EXTENDED_SIGNATURES;
436 * Place the application key into the session_info
438 data_blob_clear_free(&session_info->session_key);
439 session_info->session_key = data_blob_dup_talloc(session_info,
440 x->global->application_key_blob);
441 if (session_info->session_key.data == NULL) {
442 data_blob_clear_free(&x->global->application_key_blob);
443 reply_nterror(req, NT_STATUS_NO_MEMORY);
444 END_PROFILE(SMBtconX);
445 return;
447 talloc_keep_secret(session_info->session_key.data);
448 session_key_updated = true;
451 conn = make_connection(req, now, service, client_devicetype,
452 req->vuid, &nt_status);
453 req->conn =conn;
455 if (!conn) {
456 if (session_key_updated) {
457 struct smbXsrv_session *x = session;
458 struct auth_session_info *session_info =
459 session->global->auth_session_info;
460 data_blob_clear_free(&x->global->application_key_blob);
461 data_blob_clear_free(&session_info->session_key);
463 reply_nterror(req, nt_status);
464 END_PROFILE(SMBtconX);
465 return;
468 if ( IS_IPC(conn) )
469 server_devicetype = "IPC";
470 else if ( IS_PRINT(conn) )
471 server_devicetype = "LPT1:";
472 else
473 server_devicetype = "A:";
475 if (xconn->protocol < PROTOCOL_NT1) {
476 reply_smb1_outbuf(req, 2, 0);
477 if (message_push_string(&req->outbuf, server_devicetype,
478 STR_TERMINATE|STR_ASCII) == -1) {
479 reply_nterror(req, NT_STATUS_NO_MEMORY);
480 END_PROFILE(SMBtconX);
481 return;
483 } else {
484 /* NT sets the fstype of IPC$ to the null string */
485 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
487 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
488 /* Return permissions. */
489 uint32_t perm1 = 0;
490 uint32_t perm2 = 0;
492 reply_smb1_outbuf(req, 7, 0);
494 if (IS_IPC(conn)) {
495 perm1 = FILE_ALL_ACCESS;
496 perm2 = FILE_ALL_ACCESS;
497 } else {
498 perm1 = conn->share_access;
501 SIVAL(req->outbuf, smb_vwv3, perm1);
502 SIVAL(req->outbuf, smb_vwv5, perm2);
503 } else {
504 reply_smb1_outbuf(req, 3, 0);
507 if ((message_push_string(&req->outbuf, server_devicetype,
508 STR_TERMINATE|STR_ASCII) == -1)
509 || (message_push_string(&req->outbuf, fstype,
510 STR_TERMINATE) == -1)) {
511 reply_nterror(req, NT_STATUS_NO_MEMORY);
512 END_PROFILE(SMBtconX);
513 return;
516 /* what does setting this bit do? It is set by NT4 and
517 may affect the ability to autorun mounted cdroms */
518 optional_support |= SMB_SUPPORT_SEARCH_BITS;
519 optional_support |=
520 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
522 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
523 DEBUG(2,("Serving %s as a Dfs root\n",
524 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
525 optional_support |= SMB_SHARE_IN_DFS;
528 SSVAL(req->outbuf, smb_vwv2, optional_support);
531 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
532 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
534 DEBUG(3,("tconX service=%s \n",
535 service));
537 /* set the incoming and outgoing tid to the just created one */
538 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
539 SSVAL(req->outbuf,smb_tid,conn->cnum);
541 END_PROFILE(SMBtconX);
543 req->tid = conn->cnum;
546 /****************************************************************************
547 Reply to an unknown type.
548 ****************************************************************************/
550 void reply_unknown_new(struct smb_request *req, uint8_t type)
552 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
553 smb_fn_name(type), type, type));
554 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
555 return;
558 /****************************************************************************
559 Reply to an ioctl.
560 conn POINTER CAN BE NULL HERE !
561 ****************************************************************************/
563 void reply_ioctl(struct smb_request *req)
565 const struct loadparm_substitution *lp_sub =
566 loadparm_s3_global_substitution();
567 connection_struct *conn = req->conn;
568 uint16_t device;
569 uint16_t function;
570 uint32_t ioctl_code;
571 int replysize;
572 char *p;
574 START_PROFILE(SMBioctl);
576 if (req->wct < 3) {
577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
578 END_PROFILE(SMBioctl);
579 return;
582 device = SVAL(req->vwv+1, 0);
583 function = SVAL(req->vwv+2, 0);
584 ioctl_code = (device << 16) + function;
586 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
588 switch (ioctl_code) {
589 case IOCTL_QUERY_JOB_INFO:
590 replysize = 32;
591 break;
592 default:
593 reply_force_doserror(req, ERRSRV, ERRnosupport);
594 END_PROFILE(SMBioctl);
595 return;
598 reply_smb1_outbuf(req, 8, replysize+1);
599 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
600 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
601 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
602 p = smb_buf(req->outbuf);
603 memset(p, '\0', replysize+1); /* valgrind-safe. */
604 p += 1; /* Allow for alignment */
606 switch (ioctl_code) {
607 case IOCTL_QUERY_JOB_INFO:
609 NTSTATUS status;
610 size_t len = 0;
611 files_struct *fsp = file_fsp(
612 req, SVAL(req->vwv+0, 0));
613 if (!fsp) {
614 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
615 END_PROFILE(SMBioctl);
616 return;
618 /* Job number */
619 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
621 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
622 lp_netbios_name(), 15,
623 STR_TERMINATE|STR_ASCII, &len);
624 if (!NT_STATUS_IS_OK(status)) {
625 reply_nterror(req, status);
626 END_PROFILE(SMBioctl);
627 return;
629 if (conn) {
630 status = srvstr_push((char *)req->outbuf, req->flags2,
631 p+18,
632 lp_servicename(talloc_tos(),
633 lp_sub,
634 SNUM(conn)),
635 13, STR_TERMINATE|STR_ASCII, &len);
636 if (!NT_STATUS_IS_OK(status)) {
637 reply_nterror(req, status);
638 END_PROFILE(SMBioctl);
639 return;
641 } else {
642 memset(p+18, 0, 13);
644 break;
648 END_PROFILE(SMBioctl);
649 return;
652 /****************************************************************************
653 Strange checkpath NTSTATUS mapping.
654 ****************************************************************************/
656 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
658 /* Strange DOS error code semantics only for checkpath... */
659 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
660 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
661 /* We need to map to ERRbadpath */
662 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
665 return status;
668 /****************************************************************************
669 Reply to a checkpath.
670 ****************************************************************************/
672 void reply_checkpath(struct smb_request *req)
674 connection_struct *conn = req->conn;
675 struct smb_filename *smb_fname = NULL;
676 char *name = NULL;
677 NTSTATUS status;
678 struct files_struct *dirfsp = NULL;
679 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
680 NTTIME twrp = 0;
681 TALLOC_CTX *ctx = talloc_tos();
683 START_PROFILE(SMBcheckpath);
685 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
686 STR_TERMINATE, &status);
688 if (!NT_STATUS_IS_OK(status)) {
689 status = map_checkpath_error(req->flags2, status);
690 reply_nterror(req, status);
691 END_PROFILE(SMBcheckpath);
692 return;
695 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
697 if (ucf_flags & UCF_GMT_PATHNAME) {
698 extract_snapshot_token(name, &twrp);
700 status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
701 if (!NT_STATUS_IS_OK(status)) {
702 reply_nterror(req, status);
703 goto out;
706 status = filename_convert_dirfsp(ctx,
707 conn,
708 name,
709 ucf_flags,
710 twrp,
711 &dirfsp,
712 &smb_fname);
713 if (!NT_STATUS_IS_OK(status)) {
714 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
715 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
716 ERRSRV, ERRbadpath);
717 END_PROFILE(SMBcheckpath);
718 return;
720 goto path_err;
723 if (!VALID_STAT(smb_fname->st) &&
724 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
725 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
726 smb_fname_str_dbg(smb_fname), strerror(errno)));
727 status = map_nt_error_from_unix(errno);
728 goto path_err;
731 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
732 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
733 ERRDOS, ERRbadpath);
734 goto out;
737 reply_smb1_outbuf(req, 0, 0);
739 path_err:
740 /* We special case this - as when a Windows machine
741 is parsing a path is steps through the components
742 one at a time - if a component fails it expects
743 ERRbadpath, not ERRbadfile.
745 status = map_checkpath_error(req->flags2, status);
746 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
748 * Windows returns different error codes if
749 * the parent directory is valid but not the
750 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
751 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
752 * if the path is invalid.
754 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
755 ERRDOS, ERRbadpath);
756 goto out;
759 reply_nterror(req, status);
761 out:
762 TALLOC_FREE(smb_fname);
763 END_PROFILE(SMBcheckpath);
764 return;
767 /****************************************************************************
768 Reply to a getatr.
769 ****************************************************************************/
771 void reply_getatr(struct smb_request *req)
773 struct smbXsrv_connection *xconn = req->xconn;
774 connection_struct *conn = req->conn;
775 struct smb_filename *smb_fname = NULL;
776 char *fname = NULL;
777 int mode=0;
778 off_t size=0;
779 time_t mtime=0;
780 const char *p;
781 NTSTATUS status;
782 TALLOC_CTX *ctx = talloc_tos();
784 START_PROFILE(SMBgetatr);
786 p = (const char *)req->buf + 1;
787 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
788 if (!NT_STATUS_IS_OK(status)) {
789 reply_nterror(req, status);
790 goto out;
794 * dos sometimes asks for a stat of "" - it returns a "hidden
795 * directory" under WfWg - weird!
797 if (*fname == '\0') {
798 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
799 if (!CAN_WRITE(conn)) {
800 mode |= FILE_ATTRIBUTE_READONLY;
802 size = 0;
803 mtime = 0;
804 } else {
805 struct files_struct *dirfsp = NULL;
806 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
807 NTTIME twrp = 0;
808 bool ask_sharemode;
810 if (ucf_flags & UCF_GMT_PATHNAME) {
811 extract_snapshot_token(fname, &twrp);
813 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
814 if (!NT_STATUS_IS_OK(status)) {
815 reply_nterror(req, status);
816 goto out;
818 status = filename_convert_dirfsp(ctx,
819 conn,
820 fname,
821 ucf_flags,
822 twrp,
823 &dirfsp,
824 &smb_fname);
825 if (!NT_STATUS_IS_OK(status)) {
826 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
827 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
828 ERRSRV, ERRbadpath);
829 goto out;
831 reply_nterror(req, status);
832 goto out;
834 if (!VALID_STAT(smb_fname->st) &&
835 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
836 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
837 smb_fname_str_dbg(smb_fname),
838 strerror(errno)));
839 reply_nterror(req, map_nt_error_from_unix(errno));
840 goto out;
843 mode = fdos_mode(smb_fname->fsp);
844 size = smb_fname->st.st_ex_size;
846 ask_sharemode = fsp_search_ask_sharemode(smb_fname->fsp);
847 if (ask_sharemode) {
848 struct timespec write_time_ts;
849 struct file_id fileid;
851 ZERO_STRUCT(write_time_ts);
852 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
853 get_file_infos(fileid, 0, NULL, &write_time_ts);
854 if (!is_omit_timespec(&write_time_ts)) {
855 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
859 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
860 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
861 size = 0;
865 reply_smb1_outbuf(req, 10, 0);
867 SSVAL(req->outbuf,smb_vwv0,mode);
868 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
869 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
870 } else {
871 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
873 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
875 if (xconn->protocol >= PROTOCOL_NT1) {
876 SSVAL(req->outbuf, smb_flg2,
877 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
880 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
881 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
883 out:
884 TALLOC_FREE(smb_fname);
885 TALLOC_FREE(fname);
886 END_PROFILE(SMBgetatr);
887 return;
890 /****************************************************************************
891 Reply to a setatr.
892 ****************************************************************************/
894 void reply_setatr(struct smb_request *req)
896 struct smb_file_time ft;
897 connection_struct *conn = req->conn;
898 struct smb_filename *smb_fname = NULL;
899 struct files_struct *dirfsp = NULL;
900 char *fname = NULL;
901 int mode;
902 time_t mtime;
903 const char *p;
904 NTSTATUS status;
905 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
906 NTTIME twrp = 0;
907 TALLOC_CTX *ctx = talloc_tos();
909 START_PROFILE(SMBsetatr);
910 init_smb_file_time(&ft);
912 if (req->wct < 2) {
913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
914 goto out;
917 p = (const char *)req->buf + 1;
918 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
919 if (!NT_STATUS_IS_OK(status)) {
920 reply_nterror(req, status);
921 goto out;
924 if (ucf_flags & UCF_GMT_PATHNAME) {
925 extract_snapshot_token(fname, &twrp);
927 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
928 if (!NT_STATUS_IS_OK(status)) {
929 reply_nterror(req, status);
930 goto out;
932 status = filename_convert_dirfsp(ctx,
933 conn,
934 fname,
935 ucf_flags,
936 twrp,
937 &dirfsp,
938 &smb_fname);
939 if (!NT_STATUS_IS_OK(status)) {
940 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
941 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
942 ERRSRV, ERRbadpath);
943 goto out;
945 reply_nterror(req, status);
946 goto out;
949 if (ISDOT(smb_fname->base_name)) {
951 * Not sure here is the right place to catch this
952 * condition. Might be moved to somewhere else later -- vl
954 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
955 goto out;
958 if (smb_fname->fsp == NULL) {
960 * filename_convert_dirfsp only returns a NULL fsp for
961 * new files.
963 reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
964 goto out;
967 mode = SVAL(req->vwv+0, 0);
968 mtime = srv_make_unix_date3(req->vwv+1);
970 if (mode != FILE_ATTRIBUTE_NORMAL) {
971 if (VALID_STAT_OF_DIR(smb_fname->st))
972 mode |= FILE_ATTRIBUTE_DIRECTORY;
973 else
974 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
976 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
977 smb_fname->fsp,
978 false,
979 FILE_WRITE_ATTRIBUTES);
980 if (!NT_STATUS_IS_OK(status)) {
981 reply_nterror(req, status);
982 goto out;
985 if (file_set_dosmode(conn, smb_fname, mode, NULL,
986 false) != 0) {
987 reply_nterror(req, map_nt_error_from_unix(errno));
988 goto out;
992 ft.mtime = time_t_to_full_timespec(mtime);
994 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
995 if (!NT_STATUS_IS_OK(status)) {
996 reply_nterror(req, status);
997 goto out;
1000 reply_smb1_outbuf(req, 0, 0);
1002 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1003 mode));
1004 out:
1005 TALLOC_FREE(smb_fname);
1006 END_PROFILE(SMBsetatr);
1007 return;
1010 /****************************************************************************
1011 Reply to a dskattr.
1012 ****************************************************************************/
1014 void reply_dskattr(struct smb_request *req)
1016 struct smbXsrv_connection *xconn = req->xconn;
1017 connection_struct *conn = req->conn;
1018 uint64_t ret;
1019 uint64_t dfree,dsize,bsize;
1020 struct smb_filename smb_fname;
1021 START_PROFILE(SMBdskattr);
1023 ZERO_STRUCT(smb_fname);
1024 smb_fname.base_name = discard_const_p(char, ".");
1026 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1027 reply_nterror(req, map_nt_error_from_unix(errno));
1028 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1029 END_PROFILE(SMBdskattr);
1030 return;
1033 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1034 if (ret == (uint64_t)-1) {
1035 reply_nterror(req, map_nt_error_from_unix(errno));
1036 END_PROFILE(SMBdskattr);
1037 return;
1041 * Force max to fit in 16 bit fields.
1043 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1044 dfree /= 2;
1045 dsize /= 2;
1046 bsize *= 2;
1047 if (bsize > (WORDMAX*512)) {
1048 bsize = (WORDMAX*512);
1049 if (dsize > WORDMAX)
1050 dsize = WORDMAX;
1051 if (dfree > WORDMAX)
1052 dfree = WORDMAX;
1053 break;
1057 reply_smb1_outbuf(req, 5, 0);
1059 if (xconn->protocol <= PROTOCOL_LANMAN2) {
1060 double total_space, free_space;
1061 /* we need to scale this to a number that DOS6 can handle. We
1062 use floating point so we can handle large drives on systems
1063 that don't have 64 bit integers
1065 we end up displaying a maximum of 2G to DOS systems
1067 total_space = dsize * (double)bsize;
1068 free_space = dfree * (double)bsize;
1070 dsize = (uint64_t)((total_space+63*512) / (64*512));
1071 dfree = (uint64_t)((free_space+63*512) / (64*512));
1073 if (dsize > 0xFFFF) dsize = 0xFFFF;
1074 if (dfree > 0xFFFF) dfree = 0xFFFF;
1076 SSVAL(req->outbuf,smb_vwv0,dsize);
1077 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1078 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1079 SSVAL(req->outbuf,smb_vwv3,dfree);
1080 } else {
1081 SSVAL(req->outbuf,smb_vwv0,dsize);
1082 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1083 SSVAL(req->outbuf,smb_vwv2,512);
1084 SSVAL(req->outbuf,smb_vwv3,dfree);
1087 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1089 END_PROFILE(SMBdskattr);
1090 return;
1093 /****************************************************************************
1094 Make a dir struct.
1095 ****************************************************************************/
1097 static void make_dir_struct(char *buf,
1098 const char *mask,
1099 const char *fname,
1100 off_t size,
1101 uint32_t mode,
1102 time_t date,
1103 bool uc)
1105 char *p;
1107 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1108 size = 0;
1111 memset(buf+1,' ',11);
1112 if ((p = strchr_m(mask, '.')) != NULL) {
1113 char name[p - mask + 1];
1114 strlcpy(name, mask, sizeof(name));
1115 push_ascii(buf + 1, name, 8, 0);
1116 push_ascii(buf+9,p+1,3, 0);
1117 } else {
1118 push_ascii(buf + 1, mask, 11, 0);
1121 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1122 SCVAL(buf,21,mode);
1123 srv_put_dos_date(buf,22,date);
1124 SSVAL(buf,26,size & 0xFFFF);
1125 SSVAL(buf,28,(size >> 16)&0xFFFF);
1126 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1127 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1128 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1129 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1132 /*******************************************************************
1133 A wrapper that handles case sensitivity and the special handling
1134 of the ".." name.
1135 *******************************************************************/
1137 static bool mask_match_search(const char *string,
1138 const char *pattern,
1139 bool is_case_sensitive)
1141 if (ISDOTDOT(string)) {
1142 string = ".";
1144 if (ISDOT(pattern)) {
1145 return False;
1148 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1151 static bool mangle_mask_match(connection_struct *conn,
1152 const char *filename,
1153 const char *mask)
1155 char mname[13];
1157 if (!name_to_8_3(filename, mname, False, conn->params)) {
1158 return False;
1160 return mask_match_search(mname, mask, False);
1163 /****************************************************************************
1164 Get an 8.3 directory entry.
1165 ****************************************************************************/
1167 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1168 void *private_data,
1169 const char *dname,
1170 const char *mask,
1171 char **_fname)
1173 connection_struct *conn = (connection_struct *)private_data;
1175 if ((strcmp(mask, "*.*") == 0) ||
1176 mask_match_search(dname, mask, false) ||
1177 mangle_mask_match(conn, dname, mask)) {
1178 char mname[13];
1179 const char *fname;
1181 * Ensure we can push the original name as UCS2. If
1182 * not, then just don't return this name.
1184 NTSTATUS status;
1185 size_t ret_len = 0;
1186 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1187 uint8_t *tmp = talloc_array(talloc_tos(), uint8_t, len);
1189 status = srvstr_push(NULL,
1190 FLAGS2_UNICODE_STRINGS,
1191 tmp,
1192 dname,
1193 len,
1194 STR_TERMINATE,
1195 &ret_len);
1197 TALLOC_FREE(tmp);
1199 if (!NT_STATUS_IS_OK(status)) {
1200 return false;
1203 if (!mangle_is_8_3(dname, false, conn->params)) {
1204 bool ok =
1205 name_to_8_3(dname, mname, false, conn->params);
1206 if (!ok) {
1207 return false;
1209 fname = mname;
1210 } else {
1211 fname = dname;
1214 *_fname = talloc_strdup(ctx, fname);
1215 if (*_fname == NULL) {
1216 return false;
1219 return true;
1222 return false;
1225 static bool get_dir_entry(TALLOC_CTX *ctx,
1226 connection_struct *conn,
1227 struct dptr_struct *dirptr,
1228 const char *mask,
1229 uint32_t dirtype,
1230 char **_fname,
1231 off_t *_size,
1232 uint32_t *_mode,
1233 struct timespec *_date,
1234 bool check_descend,
1235 bool ask_sharemode)
1237 char *fname = NULL;
1238 struct smb_filename *smb_fname = NULL;
1239 uint32_t mode = 0;
1240 bool ok;
1242 again:
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 conn,
1252 &fname,
1253 &smb_fname,
1254 &mode);
1255 if (!ok) {
1256 return false;
1258 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1259 /* hide reparse points from ancient clients */
1260 TALLOC_FREE(fname);
1261 TALLOC_FREE(smb_fname);
1262 goto again;
1265 *_fname = talloc_move(ctx, &fname);
1266 *_size = smb_fname->st.st_ex_size;
1267 *_mode = mode;
1268 *_date = smb_fname->st.st_ex_mtime;
1269 TALLOC_FREE(smb_fname);
1270 return true;
1273 /****************************************************************************
1274 Reply to a search.
1275 Can be called from SMBsearch, SMBffirst or SMBfunique.
1276 ****************************************************************************/
1278 void reply_search(struct smb_request *req)
1280 connection_struct *conn = req->conn;
1281 char *path = NULL;
1282 char *mask = NULL;
1283 char *directory = NULL;
1284 struct smb_filename *smb_fname = NULL;
1285 char *fname = NULL;
1286 off_t size;
1287 uint32_t mode;
1288 struct timespec date;
1289 uint32_t dirtype;
1290 unsigned int numentries = 0;
1291 unsigned int maxentries = 0;
1292 bool finished = False;
1293 const char *p;
1294 int status_len;
1295 char status[21];
1296 int dptr_num= -1;
1297 bool check_descend = False;
1298 bool expect_close = False;
1299 NTSTATUS nt_status;
1300 bool mask_contains_wcard = False;
1301 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1302 TALLOC_CTX *ctx = talloc_tos();
1303 struct smbXsrv_connection *xconn = req->xconn;
1304 struct smbd_server_connection *sconn = req->sconn;
1305 files_struct *fsp = NULL;
1306 const struct loadparm_substitution *lp_sub =
1307 loadparm_s3_global_substitution();
1309 START_PROFILE(SMBsearch);
1311 if (req->wct < 2) {
1312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1313 goto out;
1316 if (req->posix_pathnames) {
1317 reply_unknown_new(req, req->cmd);
1318 goto out;
1321 /* If we were called as SMBffirst then we must expect close. */
1322 if(req->cmd == SMBffirst) {
1323 expect_close = True;
1326 reply_smb1_outbuf(req, 1, 3);
1327 maxentries = SVAL(req->vwv+0, 0);
1328 dirtype = SVAL(req->vwv+1, 0);
1329 p = (const char *)req->buf + 1;
1330 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1331 &nt_status);
1332 if (!NT_STATUS_IS_OK(nt_status)) {
1333 reply_nterror(req, nt_status);
1334 goto out;
1337 if (smbreq_bufrem(req, p) < 3) {
1338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1339 goto out;
1342 p++;
1343 status_len = SVAL(p, 0);
1344 p += 2;
1346 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1348 if (status_len == 0) {
1349 const char *dirpath;
1350 struct files_struct *dirfsp = NULL;
1351 struct smb_filename *smb_dname = NULL;
1352 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1354 nt_status = smb1_strip_dfs_path(ctx, &ucf_flags, &path);
1355 if (!NT_STATUS_IS_OK(nt_status)) {
1356 reply_nterror(req, nt_status);
1357 goto out;
1360 nt_status = filename_convert_smb1_search_path(ctx,
1361 conn,
1362 path,
1363 ucf_flags,
1364 &dirfsp,
1365 &smb_dname,
1366 &mask);
1368 if (!NT_STATUS_IS_OK(nt_status)) {
1369 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1370 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1371 ERRSRV, ERRbadpath);
1372 goto out;
1374 reply_nterror(req, nt_status);
1375 goto out;
1378 memset((char *)status,'\0',21);
1379 SCVAL(status,0,(dirtype & 0x1F));
1382 * Open an fsp on this directory for the dptr.
1384 nt_status = SMB_VFS_CREATE_FILE(
1385 conn, /* conn */
1386 req, /* req */
1387 dirfsp, /* dirfsp */
1388 smb_dname, /* dname */
1389 FILE_LIST_DIRECTORY, /* access_mask */
1390 FILE_SHARE_READ|
1391 FILE_SHARE_WRITE, /* share_access */
1392 FILE_OPEN, /* create_disposition*/
1393 FILE_DIRECTORY_FILE, /* create_options */
1394 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1395 NO_OPLOCK, /* oplock_request */
1396 NULL, /* lease */
1397 0, /* allocation_size */
1398 0, /* private_flags */
1399 NULL, /* sd */
1400 NULL, /* ea_list */
1401 &fsp, /* result */
1402 NULL, /* pinfo */
1403 NULL, /* in_context */
1404 NULL);/* out_context */
1406 if (!NT_STATUS_IS_OK(nt_status)) {
1407 DBG_ERR("failed to open directory %s\n",
1408 smb_fname_str_dbg(smb_dname));
1409 reply_nterror(req, nt_status);
1410 goto out;
1413 nt_status = dptr_create(conn,
1414 NULL, /* req */
1415 fsp, /* fsp */
1416 True,
1417 mask,
1418 dirtype,
1419 &fsp->dptr);
1421 TALLOC_FREE(smb_dname);
1423 if (!NT_STATUS_IS_OK(nt_status)) {
1425 * Use NULL here for the first parameter (req)
1426 * as this is not a client visible handle so
1427 * can't be part of an SMB1 chain.
1429 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1430 reply_nterror(req, nt_status);
1431 goto out;
1434 dptr_num = dptr_dnum(fsp->dptr);
1435 dirpath = dptr_path(sconn, dptr_num);
1436 directory = talloc_strdup(ctx, dirpath);
1437 if (!directory) {
1438 reply_nterror(req, NT_STATUS_NO_MEMORY);
1439 goto out;
1442 } else {
1443 int status_dirtype;
1444 const char *dirpath;
1445 unsigned int dptr_filenum;
1446 uint32_t resume_key_index;
1448 if (smbreq_bufrem(req, p) < 21) {
1449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1450 goto out;
1453 memcpy(status,p,21);
1454 status_dirtype = CVAL(status,0) & 0x1F;
1455 if (status_dirtype != (dirtype & 0x1F)) {
1456 dirtype = status_dirtype;
1459 dptr_num = CVAL(status, 12);
1460 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1461 if (fsp == NULL) {
1462 goto SearchEmpty;
1465 resume_key_index = PULL_LE_U32(status, 13);
1466 dptr_filenum = dptr_FileNumber(fsp->dptr);
1468 if (resume_key_index > dptr_filenum) {
1470 * Haven't seen this resume key yet. Just stop
1471 * the search.
1473 goto SearchEmpty;
1476 if (resume_key_index < dptr_filenum) {
1478 * The resume key was not the last one we
1479 * sent, rewind and skip to what the client
1480 * sent.
1482 dptr_RewindDir(fsp->dptr);
1484 dptr_filenum = dptr_FileNumber(fsp->dptr);
1485 SMB_ASSERT(dptr_filenum == 0);
1487 while (dptr_filenum < resume_key_index) {
1488 bool ok = get_dir_entry(
1489 ctx,
1490 conn,
1491 fsp->dptr,
1492 dptr_wcard(sconn, dptr_num),
1493 dirtype,
1494 &fname,
1495 &size,
1496 &mode,
1497 &date,
1498 check_descend,
1499 false);
1500 TALLOC_FREE(fname);
1501 if (!ok) {
1502 goto SearchEmpty;
1505 dptr_filenum = dptr_FileNumber(fsp->dptr);
1509 dirpath = dptr_path(sconn, dptr_num);
1510 directory = talloc_strdup(ctx, dirpath);
1511 if (!directory) {
1512 reply_nterror(req, NT_STATUS_NO_MEMORY);
1513 goto out;
1516 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1517 if (!mask) {
1518 goto SearchEmpty;
1520 dirtype = dptr_attr(sconn, dptr_num);
1523 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1525 DEBUG(4,("dptr_num is %d\n",dptr_num));
1527 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1528 char buf[DIR_STRUCT_SIZE];
1529 memcpy(buf,status,21);
1530 make_dir_struct(buf,
1531 "???????????",
1532 volume_label(ctx, SNUM(conn)),
1534 FILE_ATTRIBUTE_VOLUME,
1536 !allow_long_path_components);
1537 SCVAL(buf, 12, dptr_num);
1538 numentries = 1;
1539 if (message_push_blob(&req->outbuf,
1540 data_blob_const(buf, sizeof(buf)))
1541 == -1) {
1542 reply_nterror(req, NT_STATUS_NO_MEMORY);
1543 goto out;
1545 } else {
1546 unsigned int i;
1547 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1548 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1549 bool ask_sharemode;
1551 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1553 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1554 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1555 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1556 check_descend = True;
1559 ask_sharemode = fsp_search_ask_sharemode(fsp);
1561 for (i=numentries;(i<maxentries) && !finished;i++) {
1562 finished = !get_dir_entry(ctx,
1563 conn,
1564 fsp->dptr,
1565 mask,
1566 dirtype,
1567 &fname,
1568 &size,
1569 &mode,
1570 &date,
1571 check_descend,
1572 ask_sharemode);
1573 if (!finished) {
1574 char buf[DIR_STRUCT_SIZE];
1575 memcpy(buf,status,21);
1576 make_dir_struct(buf,
1577 mask,
1578 fname,
1579 size,
1580 mode,
1581 convert_timespec_to_time_t(
1582 date),
1583 !allow_long_path_components);
1584 SCVAL(buf, 12, dptr_num);
1585 PUSH_LE_U32(buf,
1587 dptr_FileNumber(fsp->dptr));
1588 if (message_push_blob(&req->outbuf,
1589 data_blob_const(buf, sizeof(buf)))
1590 == -1) {
1591 reply_nterror(req, NT_STATUS_NO_MEMORY);
1592 goto out;
1594 numentries++;
1596 TALLOC_FREE(fname);
1600 SearchEmpty:
1602 /* If we were called as SMBffirst with smb_search_id == NULL
1603 and no entries were found then return error and close fsp->dptr
1604 (X/Open spec) */
1606 if (numentries == 0) {
1607 dptr_num = -1;
1608 if (fsp != NULL) {
1609 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1611 } else if(expect_close && status_len == 0) {
1612 /* Close the dptr - we know it's gone */
1613 dptr_num = -1;
1614 if (fsp != NULL) {
1615 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1619 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1620 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1621 dptr_num = -1;
1622 /* fsp may have been closed above. */
1623 if (fsp != NULL) {
1624 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1628 if ((numentries == 0) && !mask_contains_wcard) {
1629 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1630 goto out;
1633 SSVAL(req->outbuf,smb_vwv0,numentries);
1634 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1635 SCVAL(smb_buf(req->outbuf),0,5);
1636 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1638 /* The replies here are never long name. */
1639 SSVAL(req->outbuf, smb_flg2,
1640 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1641 if (!allow_long_path_components) {
1642 SSVAL(req->outbuf, smb_flg2,
1643 SVAL(req->outbuf, smb_flg2)
1644 & (~FLAGS2_LONG_PATH_COMPONENTS));
1647 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1648 SSVAL(req->outbuf, smb_flg2,
1649 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1651 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1652 smb_fn_name(req->cmd),
1653 mask,
1654 directory,
1655 dirtype,
1656 numentries,
1657 maxentries ));
1658 out:
1659 TALLOC_FREE(directory);
1660 TALLOC_FREE(mask);
1661 TALLOC_FREE(smb_fname);
1662 END_PROFILE(SMBsearch);
1663 return;
1666 /****************************************************************************
1667 Reply to a fclose (stop directory search).
1668 ****************************************************************************/
1670 void reply_fclose(struct smb_request *req)
1672 int status_len;
1673 int dptr_num= -2;
1674 const char *p;
1675 char *path = NULL;
1676 NTSTATUS err;
1677 TALLOC_CTX *ctx = talloc_tos();
1678 struct smbd_server_connection *sconn = req->sconn;
1679 files_struct *fsp = NULL;
1681 START_PROFILE(SMBfclose);
1683 if (req->posix_pathnames) {
1684 reply_unknown_new(req, req->cmd);
1685 END_PROFILE(SMBfclose);
1686 return;
1689 p = (const char *)req->buf + 1;
1690 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1691 &err);
1692 if (!NT_STATUS_IS_OK(err)) {
1693 reply_nterror(req, err);
1694 END_PROFILE(SMBfclose);
1695 return;
1698 if (smbreq_bufrem(req, p) < 3) {
1699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1700 END_PROFILE(SMBfclose);
1701 return;
1704 p++;
1705 status_len = SVAL(p,0);
1706 p += 2;
1708 if (status_len == 0) {
1709 reply_force_doserror(req, ERRSRV, ERRsrverror);
1710 END_PROFILE(SMBfclose);
1711 return;
1714 if (smbreq_bufrem(req, p) < 21) {
1715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1716 END_PROFILE(SMBfclose);
1717 return;
1720 dptr_num = CVAL(p, 12);
1722 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
1723 if(fsp != NULL) {
1724 /* Close the file - we know it's gone */
1725 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1726 dptr_num = -1;
1729 reply_smb1_outbuf(req, 1, 0);
1730 SSVAL(req->outbuf,smb_vwv0,0);
1732 DEBUG(3,("search close\n"));
1734 END_PROFILE(SMBfclose);
1735 return;
1738 /****************************************************************************
1739 Reply to an open.
1740 ****************************************************************************/
1742 void reply_open(struct smb_request *req)
1744 connection_struct *conn = req->conn;
1745 struct smb_filename *smb_fname = NULL;
1746 char *fname = NULL;
1747 uint32_t fattr=0;
1748 off_t size = 0;
1749 time_t mtime=0;
1750 int info;
1751 struct files_struct *dirfsp = NULL;
1752 files_struct *fsp;
1753 int oplock_request;
1754 int deny_mode;
1755 uint32_t dos_attr;
1756 uint32_t access_mask;
1757 uint32_t share_mode;
1758 uint32_t create_disposition;
1759 uint32_t create_options = 0;
1760 uint32_t private_flags = 0;
1761 NTSTATUS status;
1762 uint32_t ucf_flags;
1763 NTTIME twrp = 0;
1764 TALLOC_CTX *ctx = talloc_tos();
1766 START_PROFILE(SMBopen);
1768 if (req->wct < 2) {
1769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1770 goto out;
1773 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1774 deny_mode = SVAL(req->vwv+0, 0);
1775 dos_attr = SVAL(req->vwv+1, 0);
1777 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1778 STR_TERMINATE, &status);
1779 if (!NT_STATUS_IS_OK(status)) {
1780 reply_nterror(req, status);
1781 goto out;
1784 if (!map_open_params_to_ntcreate(fname, deny_mode,
1785 OPENX_FILE_EXISTS_OPEN, &access_mask,
1786 &share_mode, &create_disposition,
1787 &create_options, &private_flags)) {
1788 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1789 goto out;
1792 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1794 if (ucf_flags & UCF_GMT_PATHNAME) {
1795 extract_snapshot_token(fname, &twrp);
1797 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1798 if (!NT_STATUS_IS_OK(status)) {
1799 reply_nterror(req, status);
1800 goto out;
1802 status = filename_convert_dirfsp(ctx,
1803 conn,
1804 fname,
1805 ucf_flags,
1806 twrp,
1807 &dirfsp,
1808 &smb_fname);
1809 if (!NT_STATUS_IS_OK(status)) {
1810 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1811 reply_botherror(req,
1812 NT_STATUS_PATH_NOT_COVERED,
1813 ERRSRV, ERRbadpath);
1814 goto out;
1816 reply_nterror(req, status);
1817 goto out;
1820 status = SMB_VFS_CREATE_FILE(
1821 conn, /* conn */
1822 req, /* req */
1823 dirfsp, /* dirfsp */
1824 smb_fname, /* fname */
1825 access_mask, /* access_mask */
1826 share_mode, /* share_access */
1827 create_disposition, /* create_disposition*/
1828 create_options, /* create_options */
1829 dos_attr, /* file_attributes */
1830 oplock_request, /* oplock_request */
1831 NULL, /* lease */
1832 0, /* allocation_size */
1833 private_flags,
1834 NULL, /* sd */
1835 NULL, /* ea_list */
1836 &fsp, /* result */
1837 &info, /* pinfo */
1838 NULL, NULL); /* create context */
1840 if (!NT_STATUS_IS_OK(status)) {
1841 if (open_was_deferred(req->xconn, req->mid)) {
1842 /* We have re-scheduled this call. */
1843 goto out;
1846 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1847 reply_openerror(req, status);
1848 goto out;
1851 fsp = fcb_or_dos_open(
1852 req,
1853 smb_fname,
1854 access_mask,
1855 create_options,
1856 private_flags);
1857 if (fsp == NULL) {
1858 bool ok = defer_smb1_sharing_violation(req);
1859 if (ok) {
1860 goto out;
1862 reply_openerror(req, status);
1863 goto out;
1867 /* Ensure we're pointing at the correct stat struct. */
1868 TALLOC_FREE(smb_fname);
1869 smb_fname = fsp->fsp_name;
1871 size = smb_fname->st.st_ex_size;
1872 fattr = fdos_mode(fsp);
1874 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1876 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1877 DEBUG(3,("attempt to open a directory %s\n",
1878 fsp_str_dbg(fsp)));
1879 close_file_free(req, &fsp, ERROR_CLOSE);
1880 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1881 ERRDOS, ERRnoaccess);
1882 goto out;
1885 reply_smb1_outbuf(req, 7, 0);
1886 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1887 SSVAL(req->outbuf,smb_vwv1,fattr);
1888 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1889 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1890 } else {
1891 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1893 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1894 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1896 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1897 SCVAL(req->outbuf,smb_flg,
1898 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1901 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1902 SCVAL(req->outbuf,smb_flg,
1903 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1905 out:
1906 END_PROFILE(SMBopen);
1907 return;
1910 /****************************************************************************
1911 Reply to an open and X.
1912 ****************************************************************************/
1914 void reply_open_and_X(struct smb_request *req)
1916 connection_struct *conn = req->conn;
1917 struct smb_filename *smb_fname = NULL;
1918 char *fname = NULL;
1919 uint16_t open_flags;
1920 int deny_mode;
1921 uint32_t smb_attr;
1922 /* Breakout the oplock request bits so we can set the
1923 reply bits separately. */
1924 int ex_oplock_request;
1925 int core_oplock_request;
1926 int oplock_request;
1927 #if 0
1928 int smb_sattr = SVAL(req->vwv+4, 0);
1929 uint32_t smb_time = make_unix_date3(req->vwv+6);
1930 #endif
1931 int smb_ofun;
1932 uint32_t fattr=0;
1933 int mtime=0;
1934 int smb_action = 0;
1935 struct files_struct *dirfsp = NULL;
1936 files_struct *fsp;
1937 NTSTATUS status;
1938 uint64_t allocation_size;
1939 ssize_t retval = -1;
1940 uint32_t access_mask;
1941 uint32_t share_mode;
1942 uint32_t create_disposition;
1943 uint32_t create_options = 0;
1944 uint32_t private_flags = 0;
1945 uint32_t ucf_flags;
1946 NTTIME twrp = 0;
1947 TALLOC_CTX *ctx = talloc_tos();
1949 START_PROFILE(SMBopenX);
1951 if (req->wct < 15) {
1952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1953 goto out;
1956 open_flags = SVAL(req->vwv+2, 0);
1957 deny_mode = SVAL(req->vwv+3, 0);
1958 smb_attr = SVAL(req->vwv+5, 0);
1959 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1960 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1961 oplock_request = ex_oplock_request | core_oplock_request;
1962 smb_ofun = SVAL(req->vwv+8, 0);
1963 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1965 /* If it's an IPC, pass off the pipe handler. */
1966 if (IS_IPC(conn)) {
1967 if (lp_nt_pipe_support()) {
1968 reply_open_pipe_and_X(conn, req);
1969 } else {
1970 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1972 goto out;
1975 /* XXXX we need to handle passed times, sattr and flags */
1976 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1977 STR_TERMINATE, &status);
1978 if (!NT_STATUS_IS_OK(status)) {
1979 reply_nterror(req, status);
1980 goto out;
1983 if (!map_open_params_to_ntcreate(fname, deny_mode,
1984 smb_ofun,
1985 &access_mask, &share_mode,
1986 &create_disposition,
1987 &create_options,
1988 &private_flags)) {
1989 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1990 goto out;
1993 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1995 if (ucf_flags & UCF_GMT_PATHNAME) {
1996 extract_snapshot_token(fname, &twrp);
1998 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 reply_nterror(req, status);
2001 goto out;
2004 status = filename_convert_dirfsp(ctx,
2005 conn,
2006 fname,
2007 ucf_flags,
2008 twrp,
2009 &dirfsp,
2010 &smb_fname);
2011 if (!NT_STATUS_IS_OK(status)) {
2012 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2013 reply_botherror(req,
2014 NT_STATUS_PATH_NOT_COVERED,
2015 ERRSRV, ERRbadpath);
2016 goto out;
2018 reply_nterror(req, status);
2019 goto out;
2022 status = SMB_VFS_CREATE_FILE(
2023 conn, /* conn */
2024 req, /* req */
2025 dirfsp, /* dirfsp */
2026 smb_fname, /* fname */
2027 access_mask, /* access_mask */
2028 share_mode, /* share_access */
2029 create_disposition, /* create_disposition*/
2030 create_options, /* create_options */
2031 smb_attr, /* file_attributes */
2032 oplock_request, /* oplock_request */
2033 NULL, /* lease */
2034 0, /* allocation_size */
2035 private_flags,
2036 NULL, /* sd */
2037 NULL, /* ea_list */
2038 &fsp, /* result */
2039 &smb_action, /* pinfo */
2040 NULL, NULL); /* create context */
2042 if (!NT_STATUS_IS_OK(status)) {
2043 if (open_was_deferred(req->xconn, req->mid)) {
2044 /* We have re-scheduled this call. */
2045 goto out;
2048 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2049 reply_openerror(req, status);
2050 goto out;
2053 fsp = fcb_or_dos_open(
2054 req,
2055 smb_fname,
2056 access_mask,
2057 create_options,
2058 private_flags);
2059 if (fsp == NULL) {
2060 bool ok = defer_smb1_sharing_violation(req);
2061 if (ok) {
2062 goto out;
2064 reply_openerror(req, status);
2065 goto out;
2069 smb_action = FILE_WAS_OPENED;
2072 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2073 if the file is truncated or created. */
2074 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2075 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2076 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2077 close_file_free(req, &fsp, ERROR_CLOSE);
2078 reply_nterror(req, NT_STATUS_DISK_FULL);
2079 goto out;
2081 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2082 if (retval < 0) {
2083 close_file_free(req, &fsp, ERROR_CLOSE);
2084 reply_nterror(req, NT_STATUS_DISK_FULL);
2085 goto out;
2087 status = vfs_stat_fsp(fsp);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 close_file_free(req, &fsp, ERROR_CLOSE);
2090 reply_nterror(req, status);
2091 goto out;
2095 fattr = fdos_mode(fsp);
2096 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2097 close_file_free(req, &fsp, ERROR_CLOSE);
2098 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2099 goto out;
2101 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2103 /* If the caller set the extended oplock request bit
2104 and we granted one (by whatever means) - set the
2105 correct bit for extended oplock reply.
2108 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2109 smb_action |= EXTENDED_OPLOCK_GRANTED;
2112 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2113 smb_action |= EXTENDED_OPLOCK_GRANTED;
2116 /* If the caller set the core oplock request bit
2117 and we granted one (by whatever means) - set the
2118 correct bit for core oplock reply.
2121 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2122 reply_smb1_outbuf(req, 19, 0);
2123 } else {
2124 reply_smb1_outbuf(req, 15, 0);
2127 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2128 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2130 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2131 SCVAL(req->outbuf, smb_flg,
2132 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2135 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2136 SCVAL(req->outbuf, smb_flg,
2137 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2140 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2141 SSVAL(req->outbuf,smb_vwv3,fattr);
2142 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2143 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2144 } else {
2145 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2147 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2148 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2149 SSVAL(req->outbuf,smb_vwv11,smb_action);
2151 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2152 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2155 out:
2156 TALLOC_FREE(smb_fname);
2157 END_PROFILE(SMBopenX);
2158 return;
2161 /****************************************************************************
2162 Reply to a SMBulogoffX.
2163 ****************************************************************************/
2165 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2166 struct smbXsrv_session *session);
2167 static void reply_ulogoffX_done(struct tevent_req *req);
2169 void reply_ulogoffX(struct smb_request *smb1req)
2171 struct timeval now = timeval_current();
2172 struct smbXsrv_session *session = NULL;
2173 struct tevent_req *req;
2174 NTSTATUS status;
2177 * Don't setup the profile charge here, take
2178 * it in reply_ulogoffX_done(). Not strictly correct
2179 * but better than the other SMB1 async
2180 * code that double-charges at the moment.
2183 status = smb1srv_session_lookup(smb1req->xconn,
2184 smb1req->vuid,
2185 timeval_to_nttime(&now),
2186 &session);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 /* Not going async, profile here. */
2189 START_PROFILE(SMBulogoffX);
2190 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2191 (unsigned long long)smb1req->vuid);
2193 smb1req->vuid = UID_FIELD_INVALID;
2194 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2195 END_PROFILE(SMBulogoffX);
2196 return;
2199 req = reply_ulogoffX_send(smb1req, session);
2200 if (req == NULL) {
2201 /* Not going async, profile here. */
2202 START_PROFILE(SMBulogoffX);
2203 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2204 END_PROFILE(SMBulogoffX);
2205 return;
2208 /* We're async. This will complete later. */
2209 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2210 return;
2213 struct reply_ulogoffX_state {
2214 struct tevent_queue *wait_queue;
2215 struct smbXsrv_session *session;
2218 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2220 /****************************************************************************
2221 Async SMB1 ulogoffX.
2222 Note, on failure here we deallocate and return NULL to allow the caller to
2223 SMB1 return an error of ERRnomem immediately.
2224 ****************************************************************************/
2226 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2227 struct smbXsrv_session *session)
2229 struct tevent_req *req;
2230 struct reply_ulogoffX_state *state;
2231 struct tevent_req *subreq;
2232 files_struct *fsp;
2233 struct smbd_server_connection *sconn = session->client->sconn;
2234 uint64_t vuid = session->global->session_wire_id;
2236 req = tevent_req_create(smb1req, &state,
2237 struct reply_ulogoffX_state);
2238 if (req == NULL) {
2239 return NULL;
2241 state->wait_queue = tevent_queue_create(state,
2242 "reply_ulogoffX_wait_queue");
2243 if (tevent_req_nomem(state->wait_queue, req)) {
2244 TALLOC_FREE(req);
2245 return NULL;
2247 state->session = session;
2250 * Make sure that no new request will be able to use this session.
2251 * This ensures that once all outstanding fsp->aio_requests
2252 * on this session are done, we are safe to close it.
2254 session->status = NT_STATUS_USER_SESSION_DELETED;
2256 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2257 if (fsp->vuid != vuid) {
2258 continue;
2261 * Flag the file as close in progress.
2262 * This will prevent any more IO being
2263 * done on it.
2265 fsp->fsp_flags.closing = true;
2267 if (fsp->num_aio_requests > 0) {
2269 * Now wait until all aio requests on this fsp are
2270 * finished.
2272 * We don't set a callback, as we just want to block the
2273 * wait queue and the talloc_free() of fsp->aio_request
2274 * will remove the item from the wait queue.
2276 subreq = tevent_queue_wait_send(fsp->aio_requests,
2277 sconn->ev_ctx,
2278 state->wait_queue);
2279 if (tevent_req_nomem(subreq, req)) {
2280 TALLOC_FREE(req);
2281 return NULL;
2287 * Now we add our own waiter to the end of the queue,
2288 * this way we get notified when all pending requests are finished
2289 * and reply to the outstanding SMB1 request.
2291 subreq = tevent_queue_wait_send(state,
2292 sconn->ev_ctx,
2293 state->wait_queue);
2294 if (tevent_req_nomem(subreq, req)) {
2295 TALLOC_FREE(req);
2296 return NULL;
2300 * We're really going async - move the SMB1 request from
2301 * a talloc stackframe above us to the sconn talloc-context.
2302 * We need this to stick around until the wait_done
2303 * callback is invoked.
2305 smb1req = talloc_move(sconn, &smb1req);
2307 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2309 return req;
2312 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2314 struct tevent_req *req = tevent_req_callback_data(
2315 subreq, struct tevent_req);
2317 tevent_queue_wait_recv(subreq);
2318 TALLOC_FREE(subreq);
2319 tevent_req_done(req);
2322 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2324 return tevent_req_simple_recv_ntstatus(req);
2327 static void reply_ulogoffX_done(struct tevent_req *req)
2329 struct smb_request *smb1req = tevent_req_callback_data(
2330 req, struct smb_request);
2331 struct reply_ulogoffX_state *state = tevent_req_data(req,
2332 struct reply_ulogoffX_state);
2333 struct smbXsrv_session *session = state->session;
2334 NTSTATUS status;
2337 * Take the profile charge here. Not strictly
2338 * correct but better than the other SMB1 async
2339 * code that double-charges at the moment.
2341 START_PROFILE(SMBulogoffX);
2343 status = reply_ulogoffX_recv(req);
2344 TALLOC_FREE(req);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 TALLOC_FREE(smb1req);
2347 END_PROFILE(SMBulogoffX);
2348 exit_server(__location__ ": reply_ulogoffX_recv failed");
2349 return;
2352 status = smbXsrv_session_logoff(session);
2353 if (!NT_STATUS_IS_OK(status)) {
2354 TALLOC_FREE(smb1req);
2355 END_PROFILE(SMBulogoffX);
2356 exit_server(__location__ ": smbXsrv_session_logoff failed");
2357 return;
2360 TALLOC_FREE(session);
2362 reply_smb1_outbuf(smb1req, 2, 0);
2363 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2364 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2366 DBG_NOTICE("ulogoffX vuid=%llu\n",
2367 (unsigned long long)smb1req->vuid);
2369 smb1req->vuid = UID_FIELD_INVALID;
2371 * The following call is needed to push the
2372 * reply data back out the socket after async
2373 * return. Plus it frees smb1req.
2375 smb_request_done(smb1req);
2376 END_PROFILE(SMBulogoffX);
2379 /****************************************************************************
2380 Reply to a mknew or a create.
2381 ****************************************************************************/
2383 void reply_mknew(struct smb_request *req)
2385 connection_struct *conn = req->conn;
2386 struct smb_filename *smb_fname = NULL;
2387 char *fname = NULL;
2388 uint32_t fattr = 0;
2389 struct smb_file_time ft;
2390 struct files_struct *dirfsp = NULL;
2391 files_struct *fsp;
2392 int oplock_request = 0;
2393 NTSTATUS status;
2394 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2395 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2396 uint32_t create_disposition;
2397 uint32_t create_options = 0;
2398 uint32_t ucf_flags;
2399 NTTIME twrp = 0;
2400 TALLOC_CTX *ctx = talloc_tos();
2402 START_PROFILE(SMBcreate);
2403 init_smb_file_time(&ft);
2405 if (req->wct < 3) {
2406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2407 goto out;
2410 fattr = SVAL(req->vwv+0, 0);
2411 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2413 if (req->cmd == SMBmknew) {
2414 /* We should fail if file exists. */
2415 create_disposition = FILE_CREATE;
2416 } else {
2417 /* Create if file doesn't exist, truncate if it does. */
2418 create_disposition = FILE_OVERWRITE_IF;
2421 /* mtime. */
2422 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2424 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2425 STR_TERMINATE, &status);
2426 if (!NT_STATUS_IS_OK(status)) {
2427 reply_nterror(req, status);
2428 goto out;
2431 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2432 if (ucf_flags & UCF_GMT_PATHNAME) {
2433 extract_snapshot_token(fname, &twrp);
2435 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 reply_nterror(req, status);
2438 goto out;
2441 status = filename_convert_dirfsp(ctx,
2442 conn,
2443 fname,
2444 ucf_flags,
2445 twrp,
2446 &dirfsp,
2447 &smb_fname);
2448 if (!NT_STATUS_IS_OK(status)) {
2449 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2450 reply_botherror(req,
2451 NT_STATUS_PATH_NOT_COVERED,
2452 ERRSRV, ERRbadpath);
2453 goto out;
2455 reply_nterror(req, status);
2456 goto out;
2459 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2460 DEBUG(0,("Attempt to create file (%s) with volid set - "
2461 "please report this\n",
2462 smb_fname_str_dbg(smb_fname)));
2465 status = SMB_VFS_CREATE_FILE(
2466 conn, /* conn */
2467 req, /* req */
2468 dirfsp, /* dirfsp */
2469 smb_fname, /* fname */
2470 access_mask, /* access_mask */
2471 share_mode, /* share_access */
2472 create_disposition, /* create_disposition*/
2473 create_options, /* create_options */
2474 fattr, /* file_attributes */
2475 oplock_request, /* oplock_request */
2476 NULL, /* lease */
2477 0, /* allocation_size */
2478 0, /* private_flags */
2479 NULL, /* sd */
2480 NULL, /* ea_list */
2481 &fsp, /* result */
2482 NULL, /* pinfo */
2483 NULL, NULL); /* create context */
2485 if (!NT_STATUS_IS_OK(status)) {
2486 if (open_was_deferred(req->xconn, req->mid)) {
2487 /* We have re-scheduled this call. */
2488 goto out;
2490 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2491 bool ok = defer_smb1_sharing_violation(req);
2492 if (ok) {
2493 goto out;
2496 reply_openerror(req, status);
2497 goto out;
2500 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2501 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2502 if (!NT_STATUS_IS_OK(status)) {
2503 END_PROFILE(SMBcreate);
2504 goto out;
2507 reply_smb1_outbuf(req, 1, 0);
2508 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2510 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2511 SCVAL(req->outbuf,smb_flg,
2512 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2515 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2516 SCVAL(req->outbuf,smb_flg,
2517 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2520 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2521 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2522 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2523 (unsigned int)fattr));
2525 out:
2526 TALLOC_FREE(smb_fname);
2527 END_PROFILE(SMBcreate);
2528 return;
2531 /****************************************************************************
2532 Reply to a create temporary file.
2533 ****************************************************************************/
2535 void reply_ctemp(struct smb_request *req)
2537 connection_struct *conn = req->conn;
2538 struct smb_filename *smb_fname = NULL;
2539 char *wire_name = NULL;
2540 char *fname = NULL;
2541 uint32_t fattr;
2542 struct files_struct *dirfsp = NULL;
2543 files_struct *fsp;
2544 int oplock_request;
2545 char *s;
2546 NTSTATUS status;
2547 int i;
2548 uint32_t ucf_flags;
2549 NTTIME twrp = 0;
2550 TALLOC_CTX *ctx = talloc_tos();
2552 START_PROFILE(SMBctemp);
2554 if (req->wct < 3) {
2555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2556 goto out;
2559 fattr = SVAL(req->vwv+0, 0);
2560 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2562 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2563 STR_TERMINATE, &status);
2564 if (!NT_STATUS_IS_OK(status)) {
2565 reply_nterror(req, status);
2566 goto out;
2569 for (i = 0; i < 10; i++) {
2570 if (*wire_name) {
2571 fname = talloc_asprintf(ctx,
2572 "%s/TMP%s",
2573 wire_name,
2574 generate_random_str_list(ctx, 5, "0123456789"));
2575 } else {
2576 fname = talloc_asprintf(ctx,
2577 "TMP%s",
2578 generate_random_str_list(ctx, 5, "0123456789"));
2581 if (!fname) {
2582 reply_nterror(req, NT_STATUS_NO_MEMORY);
2583 goto out;
2586 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2587 if (ucf_flags & UCF_GMT_PATHNAME) {
2588 extract_snapshot_token(fname, &twrp);
2590 status = smb1_strip_dfs_path(ctx, &ucf_flags, &fname);
2591 if (!NT_STATUS_IS_OK(status)) {
2592 reply_nterror(req, status);
2593 goto out;
2596 status = filename_convert_dirfsp(ctx,
2597 conn,
2598 fname,
2599 ucf_flags,
2600 twrp,
2601 &dirfsp,
2602 &smb_fname);
2603 if (!NT_STATUS_IS_OK(status)) {
2604 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2605 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2606 ERRSRV, ERRbadpath);
2607 goto out;
2609 reply_nterror(req, status);
2610 goto out;
2613 /* Create the file. */
2614 status = SMB_VFS_CREATE_FILE(
2615 conn, /* conn */
2616 req, /* req */
2617 dirfsp, /* dirfsp */
2618 smb_fname, /* fname */
2619 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2620 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2621 FILE_CREATE, /* create_disposition*/
2622 0, /* create_options */
2623 fattr, /* file_attributes */
2624 oplock_request, /* oplock_request */
2625 NULL, /* lease */
2626 0, /* allocation_size */
2627 0, /* private_flags */
2628 NULL, /* sd */
2629 NULL, /* ea_list */
2630 &fsp, /* result */
2631 NULL, /* pinfo */
2632 NULL, NULL); /* create context */
2634 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2635 TALLOC_FREE(fname);
2636 TALLOC_FREE(dirfsp);
2637 TALLOC_FREE(smb_fname);
2638 continue;
2641 if (!NT_STATUS_IS_OK(status)) {
2642 if (open_was_deferred(req->xconn, req->mid)) {
2643 /* We have re-scheduled this call. */
2644 goto out;
2646 if (NT_STATUS_EQUAL(
2647 status, NT_STATUS_SHARING_VIOLATION)) {
2648 bool ok = defer_smb1_sharing_violation(req);
2649 if (ok) {
2650 goto out;
2653 reply_openerror(req, status);
2654 goto out;
2657 break;
2660 if (i == 10) {
2661 /* Collision after 10 times... */
2662 reply_nterror(req, status);
2663 goto out;
2666 reply_smb1_outbuf(req, 1, 0);
2667 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2669 /* the returned filename is relative to the directory */
2670 s = strrchr_m(fsp->fsp_name->base_name, '/');
2671 if (!s) {
2672 s = fsp->fsp_name->base_name;
2673 } else {
2674 s++;
2677 #if 0
2678 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2679 thing in the byte section. JRA */
2680 SSVALS(p, 0, -1); /* what is this? not in spec */
2681 #endif
2682 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2683 == -1) {
2684 reply_nterror(req, NT_STATUS_NO_MEMORY);
2685 goto out;
2688 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2689 SCVAL(req->outbuf, smb_flg,
2690 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2693 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2694 SCVAL(req->outbuf, smb_flg,
2695 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2698 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2699 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2700 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2701 out:
2702 TALLOC_FREE(smb_fname);
2703 TALLOC_FREE(wire_name);
2704 END_PROFILE(SMBctemp);
2705 return;
2708 /****************************************************************************
2709 Reply to a unlink
2710 ****************************************************************************/
2712 void reply_unlink(struct smb_request *req)
2714 connection_struct *conn = req->conn;
2715 char *name = NULL;
2716 struct files_struct *dirfsp = NULL;
2717 struct smb_filename *smb_fname = NULL;
2718 uint32_t dirtype;
2719 NTSTATUS status;
2720 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2721 NTTIME twrp = 0;
2722 TALLOC_CTX *ctx = talloc_tos();
2724 START_PROFILE(SMBunlink);
2726 if (req->wct < 1) {
2727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2728 goto out;
2731 dirtype = SVAL(req->vwv+0, 0);
2733 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2734 STR_TERMINATE, &status);
2735 if (!NT_STATUS_IS_OK(status)) {
2736 reply_nterror(req, status);
2737 goto out;
2740 if (ucf_flags & UCF_GMT_PATHNAME) {
2741 extract_snapshot_token(name, &twrp);
2743 status = smb1_strip_dfs_path(ctx, &ucf_flags, &name);
2744 if (!NT_STATUS_IS_OK(status)) {
2745 reply_nterror(req, status);
2746 goto out;
2748 status = filename_convert_dirfsp(ctx,
2749 conn,
2750 name,
2751 ucf_flags | UCF_LCOMP_LNK_OK,
2752 twrp,
2753 &dirfsp,
2754 &smb_fname);
2755 if (!NT_STATUS_IS_OK(status)) {
2756 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2757 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2758 ERRSRV, ERRbadpath);
2759 goto out;
2761 reply_nterror(req, status);
2762 goto out;
2765 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2767 status = unlink_internals(conn, req, dirtype, dirfsp, smb_fname);
2768 if (!NT_STATUS_IS_OK(status)) {
2769 if (open_was_deferred(req->xconn, req->mid)) {
2770 /* We have re-scheduled this call. */
2771 goto out;
2773 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2774 bool ok = defer_smb1_sharing_violation(req);
2775 if (ok) {
2776 goto out;
2779 reply_nterror(req, status);
2780 goto out;
2783 reply_smb1_outbuf(req, 0, 0);
2784 out:
2785 TALLOC_FREE(smb_fname);
2786 END_PROFILE(SMBunlink);
2787 return;
2790 /****************************************************************************
2791 Fail for readbraw.
2792 ****************************************************************************/
2794 static void fail_readraw(void)
2796 const char *errstr = talloc_asprintf(talloc_tos(),
2797 "FAIL ! reply_readbraw: socket write fail (%s)",
2798 strerror(errno));
2799 if (!errstr) {
2800 errstr = "";
2802 exit_server_cleanly(errstr);
2805 /****************************************************************************
2806 Return a readbraw error (4 bytes of zero).
2807 ****************************************************************************/
2809 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2811 char header[4];
2813 SIVAL(header,0,0);
2815 smbd_lock_socket(xconn);
2816 if (write_data(xconn->transport.sock,header,4) != 4) {
2817 int saved_errno = errno;
2819 * Try and give an error message saying what
2820 * client failed.
2822 DEBUG(0, ("write_data failed for client %s. "
2823 "Error %s\n",
2824 smbXsrv_connection_dbg(xconn),
2825 strerror(saved_errno)));
2826 errno = saved_errno;
2828 fail_readraw();
2830 smbd_unlock_socket(xconn);
2833 /*******************************************************************
2834 Ensure we don't use sendfile if server smb signing is active.
2835 ********************************************************************/
2837 static bool lp_use_sendfile(struct smbXsrv_connection *xconn,
2838 int snum,
2839 struct smb1_signing_state *signing_state)
2841 bool sign_active = false;
2843 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2844 if (xconn->protocol < PROTOCOL_NT1) {
2845 return false;
2847 if (signing_state) {
2848 sign_active = smb1_signing_is_active(signing_state);
2850 return (lp__use_sendfile(snum) &&
2851 (get_remote_arch() != RA_WIN95) &&
2852 !sign_active);
2854 /****************************************************************************
2855 Use sendfile in readbraw.
2856 ****************************************************************************/
2858 static void send_file_readbraw(connection_struct *conn,
2859 struct smb_request *req,
2860 files_struct *fsp,
2861 off_t startpos,
2862 size_t nread,
2863 ssize_t mincount)
2865 struct smbXsrv_connection *xconn = req->xconn;
2866 char *outbuf = NULL;
2867 ssize_t ret=0;
2870 * We can only use sendfile on a non-chained packet
2871 * but we can use on a non-oplocked file. tridge proved this
2872 * on a train in Germany :-). JRA.
2873 * reply_readbraw has already checked the length.
2876 if ( !req_is_in_chain(req) &&
2877 (nread > 0) &&
2878 !fsp_is_alternate_stream(fsp) &&
2879 lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
2880 ssize_t sendfile_read = -1;
2881 char header[4];
2882 DATA_BLOB header_blob;
2884 _smb_setlen(header,nread);
2885 header_blob = data_blob_const(header, 4);
2887 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2888 &header_blob, startpos,
2889 nread);
2890 if (sendfile_read == -1) {
2891 /* Returning ENOSYS means no data at all was sent.
2892 * Do this as a normal read. */
2893 if (errno == ENOSYS) {
2894 goto normal_readbraw;
2898 * Special hack for broken Linux with no working sendfile. If we
2899 * return EINTR we sent the header but not the rest of the data.
2900 * Fake this up by doing read/write calls.
2902 if (errno == EINTR) {
2903 /* Ensure we don't do this again. */
2904 set_use_sendfile(SNUM(conn), False);
2905 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2907 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2908 DEBUG(0,("send_file_readbraw: "
2909 "fake_sendfile failed for "
2910 "file %s (%s).\n",
2911 fsp_str_dbg(fsp),
2912 strerror(errno)));
2913 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2915 return;
2918 DEBUG(0,("send_file_readbraw: sendfile failed for "
2919 "file %s (%s). Terminating\n",
2920 fsp_str_dbg(fsp), strerror(errno)));
2921 exit_server_cleanly("send_file_readbraw sendfile failed");
2922 } else if (sendfile_read == 0) {
2924 * Some sendfile implementations return 0 to indicate
2925 * that there was a short read, but nothing was
2926 * actually written to the socket. In this case,
2927 * fallback to the normal read path so the header gets
2928 * the correct byte count.
2930 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2931 "bytes falling back to the normal read: "
2932 "%s\n", fsp_str_dbg(fsp)));
2933 goto normal_readbraw;
2936 /* Deal with possible short send. */
2937 if (sendfile_read != 4+nread) {
2938 ret = sendfile_short_send(xconn, fsp,
2939 sendfile_read, 4, nread);
2940 if (ret == -1) {
2941 fail_readraw();
2944 return;
2947 normal_readbraw:
2949 outbuf = talloc_array(NULL, char, nread+4);
2950 if (!outbuf) {
2951 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2952 (unsigned)(nread+4)));
2953 reply_readbraw_error(xconn);
2954 return;
2957 if (nread > 0) {
2958 ret = read_file(fsp,outbuf+4,startpos,nread);
2959 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2960 if (ret < mincount)
2961 ret = 0;
2962 #else
2963 if (ret < nread)
2964 ret = 0;
2965 #endif
2968 _smb_setlen(outbuf,ret);
2969 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2970 int saved_errno = errno;
2972 * Try and give an error message saying what
2973 * client failed.
2975 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2976 smbXsrv_connection_dbg(xconn),
2977 strerror(saved_errno)));
2978 errno = saved_errno;
2980 fail_readraw();
2983 TALLOC_FREE(outbuf);
2986 /****************************************************************************
2987 Reply to a readbraw (core+ protocol).
2988 ****************************************************************************/
2990 void reply_readbraw(struct smb_request *req)
2992 connection_struct *conn = req->conn;
2993 struct smbXsrv_connection *xconn = req->xconn;
2994 ssize_t maxcount,mincount;
2995 size_t nread = 0;
2996 off_t startpos;
2997 files_struct *fsp;
2998 struct lock_struct lock;
2999 off_t size = 0;
3000 NTSTATUS status;
3002 START_PROFILE(SMBreadbraw);
3004 if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
3005 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3006 "raw reads/writes are disallowed.");
3009 if (req->wct < 8) {
3010 reply_readbraw_error(xconn);
3011 END_PROFILE(SMBreadbraw);
3012 return;
3015 if (xconn->smb1.echo_handler.trusted_fde) {
3016 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3017 "'async smb echo handler = yes'\n"));
3018 reply_readbraw_error(xconn);
3019 END_PROFILE(SMBreadbraw);
3020 return;
3024 * Special check if an oplock break has been issued
3025 * and the readraw request croses on the wire, we must
3026 * return a zero length response here.
3029 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3032 * We have to do a check_fsp by hand here, as
3033 * we must always return 4 zero bytes on error,
3034 * not a NTSTATUS.
3037 if (fsp == NULL ||
3038 conn == NULL ||
3039 conn != fsp->conn ||
3040 req->vuid != fsp->vuid ||
3041 fsp->fsp_flags.is_directory ||
3042 fsp_get_io_fd(fsp) == -1)
3045 * fsp could be NULL here so use the value from the packet. JRA.
3047 DEBUG(3,("reply_readbraw: fnum %d not valid "
3048 "- cache prime?\n",
3049 (int)SVAL(req->vwv+0, 0)));
3050 reply_readbraw_error(xconn);
3051 END_PROFILE(SMBreadbraw);
3052 return;
3055 /* Do a "by hand" version of CHECK_READ. */
3056 if (!(fsp->fsp_flags.can_read ||
3057 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3058 (fsp->access_mask & FILE_EXECUTE)))) {
3059 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3060 (int)SVAL(req->vwv+0, 0)));
3061 reply_readbraw_error(xconn);
3062 END_PROFILE(SMBreadbraw);
3063 return;
3066 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3067 if(req->wct == 10) {
3069 * This is a large offset (64 bit) read.
3072 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3074 if(startpos < 0) {
3075 DEBUG(0,("reply_readbraw: negative 64 bit "
3076 "readraw offset (%.0f) !\n",
3077 (double)startpos ));
3078 reply_readbraw_error(xconn);
3079 END_PROFILE(SMBreadbraw);
3080 return;
3084 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3085 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3087 /* ensure we don't overrun the packet size */
3088 maxcount = MIN(65535,maxcount);
3090 init_strict_lock_struct(fsp,
3091 (uint64_t)req->smbpid,
3092 (uint64_t)startpos,
3093 (uint64_t)maxcount,
3094 READ_LOCK,
3095 lp_posix_cifsu_locktype(fsp),
3096 &lock);
3098 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3099 reply_readbraw_error(xconn);
3100 END_PROFILE(SMBreadbraw);
3101 return;
3104 status = vfs_stat_fsp(fsp);
3105 if (NT_STATUS_IS_OK(status)) {
3106 size = fsp->fsp_name->st.st_ex_size;
3109 if (startpos >= size) {
3110 nread = 0;
3111 } else {
3112 nread = MIN(maxcount,(size - startpos));
3115 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3116 if (nread < mincount)
3117 nread = 0;
3118 #endif
3120 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3121 "min=%lu nread=%lu\n",
3122 fsp_fnum_dbg(fsp), (double)startpos,
3123 (unsigned long)maxcount,
3124 (unsigned long)mincount,
3125 (unsigned long)nread ) );
3127 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3129 DEBUG(5,("reply_readbraw finished\n"));
3131 END_PROFILE(SMBreadbraw);
3132 return;
3135 #undef DBGC_CLASS
3136 #define DBGC_CLASS DBGC_LOCKING
3138 /****************************************************************************
3139 Reply to a lockread (core+ protocol).
3140 ****************************************************************************/
3142 static void reply_lockread_locked(struct tevent_req *subreq);
3144 void reply_lockread(struct smb_request *req)
3146 struct tevent_req *subreq = NULL;
3147 connection_struct *conn = req->conn;
3148 files_struct *fsp;
3149 struct smbd_lock_element *lck = NULL;
3151 START_PROFILE(SMBlockread);
3153 if (req->wct < 5) {
3154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3155 END_PROFILE(SMBlockread);
3156 return;
3159 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3161 if (!check_fsp(conn, req, fsp)) {
3162 END_PROFILE(SMBlockread);
3163 return;
3166 if (!CHECK_READ(fsp,req)) {
3167 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3168 END_PROFILE(SMBlockread);
3169 return;
3172 lck = talloc(req, struct smbd_lock_element);
3173 if (lck == NULL) {
3174 reply_nterror(req, NT_STATUS_NO_MEMORY);
3175 END_PROFILE(SMBlockread);
3176 return;
3180 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3181 * protocol request that predates the read/write lock concept.
3182 * Thus instead of asking for a read lock here we need to ask
3183 * for a write lock. JRA.
3184 * Note that the requested lock size is unaffected by max_send.
3187 *lck = (struct smbd_lock_element) {
3188 .req_guid = smbd_request_guid(req, 0),
3189 .smblctx = req->smbpid,
3190 .brltype = WRITE_LOCK,
3191 .lock_flav = WINDOWS_LOCK,
3192 .count = SVAL(req->vwv+1, 0),
3193 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3196 subreq = smbd_smb1_do_locks_send(
3197 fsp,
3198 req->sconn->ev_ctx,
3199 &req,
3200 fsp,
3202 false, /* large_offset */
3204 lck);
3205 if (subreq == NULL) {
3206 reply_nterror(req, NT_STATUS_NO_MEMORY);
3207 END_PROFILE(SMBlockread);
3208 return;
3210 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3211 END_PROFILE(SMBlockread);
3214 static void reply_lockread_locked(struct tevent_req *subreq)
3216 struct smb_request *req = NULL;
3217 ssize_t nread = -1;
3218 char *data = NULL;
3219 NTSTATUS status;
3220 bool ok;
3221 off_t startpos;
3222 size_t numtoread, maxtoread;
3223 struct files_struct *fsp = NULL;
3224 char *p = NULL;
3226 START_PROFILE(SMBlockread);
3228 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3229 SMB_ASSERT(ok);
3231 status = smbd_smb1_do_locks_recv(subreq);
3232 TALLOC_FREE(subreq);
3234 if (!NT_STATUS_IS_OK(status)) {
3235 reply_nterror(req, status);
3236 goto send;
3239 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3240 if (fsp == NULL) {
3241 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3242 goto send;
3245 numtoread = SVAL(req->vwv+1, 0);
3246 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3249 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3251 maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3253 if (numtoread > maxtoread) {
3254 DBG_WARNING("requested read size (%zu) is greater than "
3255 "maximum allowed (%zu/%d). "
3256 "Returning short read of maximum allowed for "
3257 "compatibility with Windows 2000.\n",
3258 numtoread,
3259 maxtoread,
3260 req->xconn->smb1.sessions.max_send);
3261 numtoread = maxtoread;
3264 reply_smb1_outbuf(req, 5, numtoread + 3);
3266 data = smb_buf(req->outbuf) + 3;
3268 nread = read_file(fsp,data,startpos,numtoread);
3270 if (nread < 0) {
3271 reply_nterror(req, map_nt_error_from_unix(errno));
3272 goto send;
3275 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3277 SSVAL(req->outbuf,smb_vwv0,nread);
3278 SSVAL(req->outbuf,smb_vwv5,nread+3);
3279 p = smb_buf(req->outbuf);
3280 SCVAL(p,0,0); /* pad byte. */
3281 SSVAL(p,1,nread);
3283 DEBUG(3,("lockread %s num=%d nread=%d\n",
3284 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3286 send:
3287 ok = smb1_srv_send(req->xconn,
3288 (char *)req->outbuf,
3289 true,
3290 req->seqnum + 1,
3291 IS_CONN_ENCRYPTED(req->conn));
3292 if (!ok) {
3293 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
3295 TALLOC_FREE(req);
3296 END_PROFILE(SMBlockread);
3297 return;
3300 #undef DBGC_CLASS
3301 #define DBGC_CLASS DBGC_ALL
3303 /****************************************************************************
3304 Reply to a read.
3305 ****************************************************************************/
3307 void reply_read(struct smb_request *req)
3309 connection_struct *conn = req->conn;
3310 size_t numtoread;
3311 size_t maxtoread;
3312 ssize_t nread = 0;
3313 char *data;
3314 off_t startpos;
3315 files_struct *fsp;
3316 struct lock_struct lock;
3317 struct smbXsrv_connection *xconn = req->xconn;
3319 START_PROFILE(SMBread);
3321 if (req->wct < 3) {
3322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3323 END_PROFILE(SMBread);
3324 return;
3327 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3329 if (!check_fsp(conn, req, fsp)) {
3330 END_PROFILE(SMBread);
3331 return;
3334 if (!CHECK_READ(fsp,req)) {
3335 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3336 END_PROFILE(SMBread);
3337 return;
3340 numtoread = SVAL(req->vwv+1, 0);
3341 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3344 * The requested read size cannot be greater than max_send. JRA.
3346 maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
3348 if (numtoread > maxtoread) {
3349 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3350 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3351 (unsigned int)numtoread, (unsigned int)maxtoread,
3352 (unsigned int)xconn->smb1.sessions.max_send));
3353 numtoread = maxtoread;
3356 reply_smb1_outbuf(req, 5, numtoread+3);
3358 data = smb_buf(req->outbuf) + 3;
3360 init_strict_lock_struct(fsp,
3361 (uint64_t)req->smbpid,
3362 (uint64_t)startpos,
3363 (uint64_t)numtoread,
3364 READ_LOCK,
3365 lp_posix_cifsu_locktype(fsp),
3366 &lock);
3368 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3369 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3370 END_PROFILE(SMBread);
3371 return;
3374 if (numtoread > 0)
3375 nread = read_file(fsp,data,startpos,numtoread);
3377 if (nread < 0) {
3378 reply_nterror(req, map_nt_error_from_unix(errno));
3379 goto out;
3382 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3384 SSVAL(req->outbuf,smb_vwv0,nread);
3385 SSVAL(req->outbuf,smb_vwv5,nread+3);
3386 SCVAL(smb_buf(req->outbuf),0,1);
3387 SSVAL(smb_buf(req->outbuf),1,nread);
3389 DEBUG(3, ("read %s num=%d nread=%d\n",
3390 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3392 out:
3393 END_PROFILE(SMBread);
3394 return;
3397 /****************************************************************************
3398 Setup readX header.
3399 ****************************************************************************/
3401 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3403 size_t outsize;
3405 outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3406 False);
3408 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3410 SCVAL(outbuf,smb_vwv0,0xFF);
3411 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3412 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3413 SSVAL(outbuf,smb_vwv6,
3414 (smb_wct - 4) /* offset from smb header to wct */
3415 + 1 /* the wct field */
3416 + 12 * sizeof(uint16_t) /* vwv */
3417 + 2 /* the buflen field */
3418 + 1); /* padding byte */
3419 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3420 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3421 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3422 _smb_setlen_large(outbuf,
3423 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3424 return outsize;
3427 /****************************************************************************
3428 Reply to a read and X - possibly using sendfile.
3429 ****************************************************************************/
3431 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3432 files_struct *fsp, off_t startpos,
3433 size_t smb_maxcnt)
3435 struct smbXsrv_connection *xconn = req->xconn;
3436 ssize_t nread = -1;
3437 struct lock_struct lock;
3438 int saved_errno = 0;
3439 NTSTATUS status;
3441 init_strict_lock_struct(fsp,
3442 (uint64_t)req->smbpid,
3443 (uint64_t)startpos,
3444 (uint64_t)smb_maxcnt,
3445 READ_LOCK,
3446 lp_posix_cifsu_locktype(fsp),
3447 &lock);
3449 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3451 return;
3455 * We can only use sendfile on a non-chained packet
3456 * but we can use on a non-oplocked file. tridge proved this
3457 * on a train in Germany :-). JRA.
3460 if (!req_is_in_chain(req) &&
3461 !req->encrypted &&
3462 !fsp_is_alternate_stream(fsp) &&
3463 lp_use_sendfile(xconn, SNUM(conn), xconn->smb1.signing_state) ) {
3464 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3465 DATA_BLOB header;
3467 status = vfs_stat_fsp(fsp);
3468 if (!NT_STATUS_IS_OK(status)) {
3469 reply_nterror(req, status);
3470 goto out;
3473 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3474 (startpos > fsp->fsp_name->st.st_ex_size) ||
3475 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3477 * We already know that we would do a short read, so don't
3478 * try the sendfile() path.
3480 goto nosendfile_read;
3484 * Set up the packet header before send. We
3485 * assume here the sendfile will work (get the
3486 * correct amount of data).
3489 header = data_blob_const(headerbuf, sizeof(headerbuf));
3491 construct_smb1_reply_common_req(req, (char *)headerbuf);
3492 setup_readX_header((char *)headerbuf, smb_maxcnt);
3494 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3495 startpos, smb_maxcnt);
3496 if (nread == -1) {
3497 saved_errno = errno;
3499 /* Returning ENOSYS means no data at all was sent.
3500 Do this as a normal read. */
3501 if (errno == ENOSYS) {
3502 goto normal_read;
3506 * Special hack for broken Linux with no working sendfile. If we
3507 * return EINTR we sent the header but not the rest of the data.
3508 * Fake this up by doing read/write calls.
3511 if (errno == EINTR) {
3512 /* Ensure we don't do this again. */
3513 set_use_sendfile(SNUM(conn), False);
3514 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3515 nread = fake_sendfile(xconn, fsp, startpos,
3516 smb_maxcnt);
3517 if (nread == -1) {
3518 saved_errno = errno;
3519 DEBUG(0,("send_file_readX: "
3520 "fake_sendfile failed for "
3521 "file %s (%s) for client %s. "
3522 "Terminating\n",
3523 fsp_str_dbg(fsp),
3524 smbXsrv_connection_dbg(xconn),
3525 strerror(saved_errno)));
3526 errno = saved_errno;
3527 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3529 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3530 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3531 /* No outbuf here means successful sendfile. */
3532 goto out;
3535 DEBUG(0,("send_file_readX: sendfile failed for file "
3536 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3537 strerror(errno)));
3538 exit_server_cleanly("send_file_readX sendfile failed");
3539 } else if (nread == 0) {
3541 * Some sendfile implementations return 0 to indicate
3542 * that there was a short read, but nothing was
3543 * actually written to the socket. In this case,
3544 * fallback to the normal read path so the header gets
3545 * the correct byte count.
3547 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3548 "falling back to the normal read: %s\n",
3549 fsp_str_dbg(fsp)));
3550 goto normal_read;
3553 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3554 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3556 /* Deal with possible short send. */
3557 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3558 ssize_t ret;
3560 ret = sendfile_short_send(xconn, fsp, nread,
3561 sizeof(headerbuf), smb_maxcnt);
3562 if (ret == -1) {
3563 const char *r;
3564 r = "send_file_readX: sendfile_short_send failed";
3565 DEBUG(0,("%s for file %s (%s).\n",
3566 r, fsp_str_dbg(fsp), strerror(errno)));
3567 exit_server_cleanly(r);
3570 /* No outbuf here means successful sendfile. */
3571 goto out;
3574 normal_read:
3576 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3577 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3578 ssize_t ret;
3580 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3581 (startpos > fsp->fsp_name->st.st_ex_size) ||
3582 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3584 * We already know that we would do a short
3585 * read, so don't try the sendfile() path.
3587 goto nosendfile_read;
3590 construct_smb1_reply_common_req(req, (char *)headerbuf);
3591 setup_readX_header((char *)headerbuf, smb_maxcnt);
3593 /* Send out the header. */
3594 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3595 sizeof(headerbuf));
3596 if (ret != sizeof(headerbuf)) {
3597 saved_errno = errno;
3599 * Try and give an error message saying what
3600 * client failed.
3602 DEBUG(0,("send_file_readX: write_data failed for file "
3603 "%s (%s) for client %s. Terminating\n",
3604 fsp_str_dbg(fsp),
3605 smbXsrv_connection_dbg(xconn),
3606 strerror(saved_errno)));
3607 errno = saved_errno;
3608 exit_server_cleanly("send_file_readX sendfile failed");
3610 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3611 if (nread == -1) {
3612 saved_errno = errno;
3613 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3614 "%s (%s) for client %s. Terminating\n",
3615 fsp_str_dbg(fsp),
3616 smbXsrv_connection_dbg(xconn),
3617 strerror(saved_errno)));
3618 errno = saved_errno;
3619 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3621 goto out;
3624 nosendfile_read:
3626 reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3627 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3628 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3630 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3631 startpos, smb_maxcnt);
3632 saved_errno = errno;
3634 if (nread < 0) {
3635 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3636 return;
3639 setup_readX_header((char *)req->outbuf, nread);
3641 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3642 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3643 return;
3645 out:
3646 TALLOC_FREE(req->outbuf);
3647 return;
3650 /****************************************************************************
3651 Work out how much space we have for a read return.
3652 ****************************************************************************/
3654 static size_t calc_max_read_pdu(const struct smb_request *req)
3656 struct smbXsrv_connection *xconn = req->xconn;
3658 if (xconn->protocol < PROTOCOL_NT1) {
3659 return xconn->smb1.sessions.max_send;
3662 if (!lp_large_readwrite()) {
3663 return xconn->smb1.sessions.max_send;
3666 if (req_is_in_chain(req)) {
3667 return xconn->smb1.sessions.max_send;
3670 if (req->encrypted) {
3672 * Don't take encrypted traffic up to the
3673 * limit. There are padding considerations
3674 * that make that tricky.
3676 return xconn->smb1.sessions.max_send;
3679 if (smb1_srv_is_signing_active(xconn)) {
3680 return 0x1FFFF;
3683 if (!lp_smb1_unix_extensions()) {
3684 return 0x1FFFF;
3688 * We can do ultra-large POSIX reads.
3690 return 0xFFFFFF;
3693 /****************************************************************************
3694 Calculate how big a read can be. Copes with all clients. It's always
3695 safe to return a short read - Windows does this.
3696 ****************************************************************************/
3698 static size_t calc_read_size(const struct smb_request *req,
3699 size_t upper_size,
3700 size_t lower_size)
3702 struct smbXsrv_connection *xconn = req->xconn;
3703 size_t max_pdu = calc_max_read_pdu(req);
3704 size_t total_size = 0;
3705 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3706 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3709 * Windows explicitly ignores upper size of 0xFFFF.
3710 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3711 * We must do the same as these will never fit even in
3712 * an extended size NetBIOS packet.
3714 if (upper_size == 0xFFFF) {
3715 upper_size = 0;
3718 if (xconn->protocol < PROTOCOL_NT1) {
3719 upper_size = 0;
3722 total_size = ((upper_size<<16) | lower_size);
3725 * LARGE_READX test shows it's always safe to return
3726 * a short read. Windows does so.
3728 return MIN(total_size, max_len);
3731 /****************************************************************************
3732 Reply to a read and X.
3733 ****************************************************************************/
3735 void reply_read_and_X(struct smb_request *req)
3737 connection_struct *conn = req->conn;
3738 files_struct *fsp;
3739 off_t startpos;
3740 size_t smb_maxcnt;
3741 size_t upper_size;
3742 bool big_readX = False;
3743 #if 0
3744 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3745 #endif
3747 START_PROFILE(SMBreadX);
3749 if ((req->wct != 10) && (req->wct != 12)) {
3750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3751 return;
3754 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3755 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3756 smb_maxcnt = SVAL(req->vwv+5, 0);
3758 /* If it's an IPC, pass off the pipe handler. */
3759 if (IS_IPC(conn)) {
3760 reply_pipe_read_and_X(req);
3761 END_PROFILE(SMBreadX);
3762 return;
3765 if (!check_fsp(conn, req, fsp)) {
3766 END_PROFILE(SMBreadX);
3767 return;
3770 if (!CHECK_READ(fsp,req)) {
3771 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3772 END_PROFILE(SMBreadX);
3773 return;
3776 upper_size = SVAL(req->vwv+7, 0);
3777 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3778 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3780 * This is a heuristic to avoid keeping large
3781 * outgoing buffers around over long-lived aio
3782 * requests.
3784 big_readX = True;
3787 if (req->wct == 12) {
3789 * This is a large offset (64 bit) read.
3791 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3795 if (!big_readX) {
3796 NTSTATUS status = schedule_aio_read_and_X(conn,
3797 req,
3798 fsp,
3799 startpos,
3800 smb_maxcnt);
3801 if (NT_STATUS_IS_OK(status)) {
3802 /* Read scheduled - we're done. */
3803 goto out;
3805 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3806 /* Real error - report to client. */
3807 END_PROFILE(SMBreadX);
3808 reply_nterror(req, status);
3809 return;
3811 /* NT_STATUS_RETRY - fall back to sync read. */
3814 smbd_lock_socket(req->xconn);
3815 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3816 smbd_unlock_socket(req->xconn);
3818 out:
3819 END_PROFILE(SMBreadX);
3820 return;
3823 /****************************************************************************
3824 Error replies to writebraw must have smb_wct == 1. Fix this up.
3825 ****************************************************************************/
3827 void error_to_writebrawerr(struct smb_request *req)
3829 uint8_t *old_outbuf = req->outbuf;
3831 reply_smb1_outbuf(req, 1, 0);
3833 memcpy(req->outbuf, old_outbuf, smb_size);
3834 TALLOC_FREE(old_outbuf);
3837 /****************************************************************************
3838 Read 4 bytes of a smb packet and return the smb length of the packet.
3839 Store the result in the buffer. This version of the function will
3840 never return a session keepalive (length of zero).
3841 Timeout is in milliseconds.
3842 ****************************************************************************/
3844 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3845 size_t *len)
3847 uint8_t msgtype = NBSSkeepalive;
3849 while (msgtype == NBSSkeepalive) {
3850 NTSTATUS status;
3852 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3853 len);
3854 if (!NT_STATUS_IS_OK(status)) {
3855 char addr[INET6_ADDRSTRLEN];
3856 /* Try and give an error message
3857 * saying what client failed. */
3858 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3859 "client %s read error = %s.\n",
3860 get_peer_addr(fd,addr,sizeof(addr)),
3861 nt_errstr(status)));
3862 return status;
3865 msgtype = CVAL(inbuf, 0);
3868 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3869 (unsigned long)len));
3871 return NT_STATUS_OK;
3874 /****************************************************************************
3875 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3876 ****************************************************************************/
3878 void reply_writebraw(struct smb_request *req)
3880 connection_struct *conn = req->conn;
3881 struct smbXsrv_connection *xconn = req->xconn;
3882 char *buf = NULL;
3883 ssize_t nwritten=0;
3884 ssize_t total_written=0;
3885 size_t numtowrite=0;
3886 size_t tcount;
3887 off_t startpos;
3888 const char *data=NULL;
3889 bool write_through;
3890 files_struct *fsp;
3891 struct lock_struct lock;
3892 NTSTATUS status;
3894 START_PROFILE(SMBwritebraw);
3897 * If we ever reply with an error, it must have the SMB command
3898 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3899 * we're finished.
3901 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3903 if (smb1_srv_is_signing_active(xconn)) {
3904 END_PROFILE(SMBwritebraw);
3905 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3906 "raw reads/writes are disallowed.");
3909 if (req->wct < 12) {
3910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3911 error_to_writebrawerr(req);
3912 END_PROFILE(SMBwritebraw);
3913 return;
3916 if (xconn->smb1.echo_handler.trusted_fde) {
3917 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3918 "'async smb echo handler = yes'\n"));
3919 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3920 error_to_writebrawerr(req);
3921 END_PROFILE(SMBwritebraw);
3922 return;
3925 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3926 if (!check_fsp(conn, req, fsp)) {
3927 error_to_writebrawerr(req);
3928 END_PROFILE(SMBwritebraw);
3929 return;
3932 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 reply_nterror(req, status);
3935 error_to_writebrawerr(req);
3936 END_PROFILE(SMBwritebraw);
3937 return;
3940 tcount = IVAL(req->vwv+1, 0);
3941 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3942 write_through = BITSETW(req->vwv+7,0);
3944 /* We have to deal with slightly different formats depending
3945 on whether we are using the core+ or lanman1.0 protocol */
3947 if(xconn->protocol <= PROTOCOL_COREPLUS) {
3948 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3949 data = smb_buf_const(req->inbuf);
3950 } else {
3951 numtowrite = SVAL(req->vwv+10, 0);
3952 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3955 /* Ensure we don't write bytes past the end of this packet. */
3957 * This already protects us against CVE-2017-12163.
3959 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3960 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3961 error_to_writebrawerr(req);
3962 END_PROFILE(SMBwritebraw);
3963 return;
3966 if (!fsp->print_file) {
3967 init_strict_lock_struct(fsp,
3968 (uint64_t)req->smbpid,
3969 (uint64_t)startpos,
3970 (uint64_t)tcount,
3971 WRITE_LOCK,
3972 lp_posix_cifsu_locktype(fsp),
3973 &lock);
3975 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3976 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3977 error_to_writebrawerr(req);
3978 END_PROFILE(SMBwritebraw);
3979 return;
3983 if (numtowrite>0) {
3984 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3987 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3988 "wrote=%d sync=%d\n",
3989 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3990 (int)nwritten, (int)write_through));
3992 if (nwritten < (ssize_t)numtowrite) {
3993 reply_nterror(req, NT_STATUS_DISK_FULL);
3994 error_to_writebrawerr(req);
3995 goto out;
3998 total_written = nwritten;
4000 /* Allocate a buffer of 64k + length. */
4001 buf = talloc_array(NULL, char, 65540);
4002 if (!buf) {
4003 reply_nterror(req, NT_STATUS_NO_MEMORY);
4004 error_to_writebrawerr(req);
4005 goto out;
4008 /* Return a SMBwritebraw message to the redirector to tell
4009 * it to send more bytes */
4011 memcpy(buf, req->inbuf, smb_size);
4012 srv_smb1_set_message(buf,xconn->protocol>PROTOCOL_COREPLUS?1:0,0,True);
4013 SCVAL(buf,smb_com,SMBwritebraw);
4014 SSVALS(buf,smb_vwv0,0xFFFF);
4015 show_msg(buf);
4016 if (!smb1_srv_send(req->xconn,
4017 buf,
4018 false,
4019 0, /* no signing */
4020 IS_CONN_ENCRYPTED(conn))) {
4021 exit_server_cleanly("reply_writebraw: smb1_srv_send "
4022 "failed.");
4025 /* Now read the raw data into the buffer and write it */
4026 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4027 &numtowrite);
4028 if (!NT_STATUS_IS_OK(status)) {
4029 exit_server_cleanly("secondary writebraw failed");
4032 /* Set up outbuf to return the correct size */
4033 reply_smb1_outbuf(req, 1, 0);
4035 if (numtowrite != 0) {
4037 if (numtowrite > 0xFFFF) {
4038 DEBUG(0,("reply_writebraw: Oversize secondary write "
4039 "raw requested (%u). Terminating\n",
4040 (unsigned int)numtowrite ));
4041 exit_server_cleanly("secondary writebraw failed");
4044 if (tcount > nwritten+numtowrite) {
4045 DEBUG(3,("reply_writebraw: Client overestimated the "
4046 "write %d %d %d\n",
4047 (int)tcount,(int)nwritten,(int)numtowrite));
4050 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4051 numtowrite);
4053 if (!NT_STATUS_IS_OK(status)) {
4054 /* Try and give an error message
4055 * saying what client failed. */
4056 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4057 "raw read failed (%s) for client %s. "
4058 "Terminating\n", nt_errstr(status),
4059 smbXsrv_connection_dbg(xconn)));
4060 exit_server_cleanly("secondary writebraw failed");
4064 * We are not vulnerable to CVE-2017-12163
4065 * here as we are guaranteed to have numtowrite
4066 * bytes available - we just read from the client.
4068 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4069 if (nwritten == -1) {
4070 TALLOC_FREE(buf);
4071 reply_nterror(req, map_nt_error_from_unix(errno));
4072 error_to_writebrawerr(req);
4073 goto out;
4076 if (nwritten < (ssize_t)numtowrite) {
4077 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4078 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4081 if (nwritten > 0) {
4082 total_written += nwritten;
4086 TALLOC_FREE(buf);
4087 SSVAL(req->outbuf,smb_vwv0,total_written);
4089 status = sync_file(conn, fsp, write_through);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4092 fsp_str_dbg(fsp), nt_errstr(status)));
4093 reply_nterror(req, status);
4094 error_to_writebrawerr(req);
4095 goto out;
4098 DEBUG(3,("reply_writebraw: secondary write %s start=%.0f num=%d "
4099 "wrote=%d\n",
4100 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4101 (int)total_written));
4103 /* We won't return a status if write through is not selected - this
4104 * follows what WfWg does */
4105 END_PROFILE(SMBwritebraw);
4107 if (!write_through && total_written==tcount) {
4109 #if RABBIT_PELLET_FIX
4111 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4112 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4113 * JRA.
4115 if (!send_keepalive(xconn->transport.sock)) {
4116 exit_server_cleanly("reply_writebraw: send of "
4117 "keepalive failed");
4119 #endif
4120 TALLOC_FREE(req->outbuf);
4122 return;
4124 out:
4125 END_PROFILE(SMBwritebraw);
4126 return;
4129 #undef DBGC_CLASS
4130 #define DBGC_CLASS DBGC_LOCKING
4132 /****************************************************************************
4133 Reply to a writeunlock (core+).
4134 ****************************************************************************/
4136 void reply_writeunlock(struct smb_request *req)
4138 connection_struct *conn = req->conn;
4139 ssize_t nwritten = -1;
4140 size_t numtowrite;
4141 size_t remaining;
4142 off_t startpos;
4143 const char *data;
4144 NTSTATUS status = NT_STATUS_OK;
4145 files_struct *fsp;
4146 struct lock_struct lock;
4147 int saved_errno = 0;
4149 START_PROFILE(SMBwriteunlock);
4151 if (req->wct < 5) {
4152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4153 END_PROFILE(SMBwriteunlock);
4154 return;
4157 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4159 if (!check_fsp(conn, req, fsp)) {
4160 END_PROFILE(SMBwriteunlock);
4161 return;
4164 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4165 if (!NT_STATUS_IS_OK(status)) {
4166 reply_nterror(req, status);
4167 END_PROFILE(SMBwriteunlock);
4168 return;
4171 numtowrite = SVAL(req->vwv+1, 0);
4172 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4173 data = (const char *)req->buf + 3;
4176 * Ensure client isn't asking us to write more than
4177 * they sent. CVE-2017-12163.
4179 remaining = smbreq_bufrem(req, data);
4180 if (numtowrite > remaining) {
4181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4182 END_PROFILE(SMBwriteunlock);
4183 return;
4186 if (!fsp->print_file && numtowrite > 0) {
4187 init_strict_lock_struct(fsp,
4188 (uint64_t)req->smbpid,
4189 (uint64_t)startpos,
4190 (uint64_t)numtowrite,
4191 WRITE_LOCK,
4192 lp_posix_cifsu_locktype(fsp),
4193 &lock);
4195 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4196 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4197 END_PROFILE(SMBwriteunlock);
4198 return;
4202 /* The special X/Open SMB protocol handling of
4203 zero length writes is *NOT* done for
4204 this call */
4205 if(numtowrite == 0) {
4206 nwritten = 0;
4207 } else {
4208 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4209 saved_errno = errno;
4212 status = sync_file(conn, fsp, False /* write through */);
4213 if (!NT_STATUS_IS_OK(status)) {
4214 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4215 fsp_str_dbg(fsp), nt_errstr(status)));
4216 reply_nterror(req, status);
4217 goto out;
4220 if(nwritten < 0) {
4221 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4222 goto out;
4225 if((nwritten < numtowrite) && (numtowrite != 0)) {
4226 reply_nterror(req, NT_STATUS_DISK_FULL);
4227 goto out;
4230 if (numtowrite && !fsp->print_file) {
4231 struct smbd_lock_element l = {
4232 .req_guid = smbd_request_guid(req, 0),
4233 .smblctx = req->smbpid,
4234 .brltype = UNLOCK_LOCK,
4235 .lock_flav = WINDOWS_LOCK,
4236 .offset = startpos,
4237 .count = numtowrite,
4239 status = smbd_do_unlocking(req, fsp, 1, &l);
4240 if (NT_STATUS_V(status)) {
4241 reply_nterror(req, status);
4242 goto out;
4246 reply_smb1_outbuf(req, 1, 0);
4248 SSVAL(req->outbuf,smb_vwv0,nwritten);
4250 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4251 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4253 out:
4254 END_PROFILE(SMBwriteunlock);
4255 return;
4258 #undef DBGC_CLASS
4259 #define DBGC_CLASS DBGC_ALL
4261 /****************************************************************************
4262 Reply to a write.
4263 ****************************************************************************/
4265 void reply_write(struct smb_request *req)
4267 connection_struct *conn = req->conn;
4268 size_t numtowrite;
4269 size_t remaining;
4270 ssize_t nwritten = -1;
4271 off_t startpos;
4272 const char *data;
4273 files_struct *fsp;
4274 struct lock_struct lock;
4275 NTSTATUS status;
4276 int saved_errno = 0;
4278 START_PROFILE(SMBwrite);
4280 if (req->wct < 5) {
4281 END_PROFILE(SMBwrite);
4282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4283 return;
4286 /* If it's an IPC, pass off the pipe handler. */
4287 if (IS_IPC(conn)) {
4288 reply_pipe_write(req);
4289 END_PROFILE(SMBwrite);
4290 return;
4293 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4295 if (!check_fsp(conn, req, fsp)) {
4296 END_PROFILE(SMBwrite);
4297 return;
4300 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4301 if (!NT_STATUS_IS_OK(status)) {
4302 reply_nterror(req, status);
4303 END_PROFILE(SMBwrite);
4304 return;
4307 numtowrite = SVAL(req->vwv+1, 0);
4308 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4309 data = (const char *)req->buf + 3;
4312 * Ensure client isn't asking us to write more than
4313 * they sent. CVE-2017-12163.
4315 remaining = smbreq_bufrem(req, data);
4316 if (numtowrite > remaining) {
4317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4318 END_PROFILE(SMBwrite);
4319 return;
4322 if (!fsp->print_file) {
4323 init_strict_lock_struct(fsp,
4324 (uint64_t)req->smbpid,
4325 (uint64_t)startpos,
4326 (uint64_t)numtowrite,
4327 WRITE_LOCK,
4328 lp_posix_cifsu_locktype(fsp),
4329 &lock);
4331 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4332 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4333 END_PROFILE(SMBwrite);
4334 return;
4339 * X/Open SMB protocol says that if smb_vwv1 is
4340 * zero then the file size should be extended or
4341 * truncated to the size given in smb_vwv[2-3].
4344 if(numtowrite == 0) {
4346 * This is actually an allocate call, and set EOF. JRA.
4348 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4349 if (nwritten < 0) {
4350 reply_nterror(req, NT_STATUS_DISK_FULL);
4351 goto out;
4353 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4354 if (nwritten < 0) {
4355 reply_nterror(req, NT_STATUS_DISK_FULL);
4356 goto out;
4358 trigger_write_time_update_immediate(fsp);
4359 } else {
4360 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4363 status = sync_file(conn, fsp, False);
4364 if (!NT_STATUS_IS_OK(status)) {
4365 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4366 fsp_str_dbg(fsp), nt_errstr(status)));
4367 reply_nterror(req, status);
4368 goto out;
4371 if(nwritten < 0) {
4372 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4373 goto out;
4376 if((nwritten == 0) && (numtowrite != 0)) {
4377 reply_nterror(req, NT_STATUS_DISK_FULL);
4378 goto out;
4381 reply_smb1_outbuf(req, 1, 0);
4383 SSVAL(req->outbuf,smb_vwv0,nwritten);
4385 if (nwritten < (ssize_t)numtowrite) {
4386 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4387 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4390 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4392 out:
4393 END_PROFILE(SMBwrite);
4394 return;
4397 /****************************************************************************
4398 Ensure a buffer is a valid writeX for recvfile purposes.
4399 ****************************************************************************/
4401 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4402 (2*14) + /* word count (including bcc) */ \
4403 1 /* pad byte */)
4405 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4406 const uint8_t *inbuf)
4408 size_t numtowrite;
4409 unsigned int doff = 0;
4410 size_t len = smb_len_large(inbuf);
4411 uint16_t fnum;
4412 struct smbXsrv_open *op = NULL;
4413 struct files_struct *fsp = NULL;
4414 NTSTATUS status;
4416 if (is_encrypted_packet(inbuf)) {
4417 /* Can't do this on encrypted
4418 * connections. */
4419 return false;
4422 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4423 return false;
4426 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4427 CVAL(inbuf,smb_wct) != 14) {
4428 DEBUG(10,("is_valid_writeX_buffer: chained or "
4429 "invalid word length.\n"));
4430 return false;
4433 fnum = SVAL(inbuf, smb_vwv2);
4434 status = smb1srv_open_lookup(xconn,
4435 fnum,
4436 0, /* now */
4437 &op);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4440 return false;
4442 fsp = op->compat;
4443 if (fsp == NULL) {
4444 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4445 return false;
4447 if (fsp->conn == NULL) {
4448 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4449 return false;
4452 if (IS_IPC(fsp->conn)) {
4453 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4454 return false;
4456 if (IS_PRINT(fsp->conn)) {
4457 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4458 return false;
4460 if (fsp_is_alternate_stream(fsp)) {
4461 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4462 return false;
4464 doff = SVAL(inbuf,smb_vwv11);
4466 numtowrite = SVAL(inbuf,smb_vwv10);
4468 if (len > doff && len - doff > 0xFFFF) {
4469 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4472 if (numtowrite == 0) {
4473 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4474 return false;
4477 /* Ensure the sizes match up. */
4478 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4479 /* no pad byte...old smbclient :-( */
4480 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4481 (unsigned int)doff,
4482 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4483 return false;
4486 if (len - doff != numtowrite) {
4487 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4488 "len = %u, doff = %u, numtowrite = %u\n",
4489 (unsigned int)len,
4490 (unsigned int)doff,
4491 (unsigned int)numtowrite ));
4492 return false;
4495 DEBUG(10,("is_valid_writeX_buffer: true "
4496 "len = %u, doff = %u, numtowrite = %u\n",
4497 (unsigned int)len,
4498 (unsigned int)doff,
4499 (unsigned int)numtowrite ));
4501 return true;
4504 /****************************************************************************
4505 Reply to a write and X.
4506 ****************************************************************************/
4508 void reply_write_and_X(struct smb_request *req)
4510 connection_struct *conn = req->conn;
4511 struct smbXsrv_connection *xconn = req->xconn;
4512 files_struct *fsp;
4513 struct lock_struct lock;
4514 off_t startpos;
4515 size_t numtowrite;
4516 bool write_through;
4517 ssize_t nwritten;
4518 unsigned int smb_doff;
4519 unsigned int smblen;
4520 const char *data;
4521 NTSTATUS status;
4522 int saved_errno = 0;
4524 START_PROFILE(SMBwriteX);
4526 if ((req->wct != 12) && (req->wct != 14)) {
4527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4528 goto out;
4531 numtowrite = SVAL(req->vwv+10, 0);
4532 smb_doff = SVAL(req->vwv+11, 0);
4533 smblen = smb_len(req->inbuf);
4535 if (req->unread_bytes > 0xFFFF ||
4536 (smblen > smb_doff &&
4537 smblen - smb_doff > 0xFFFF)) {
4538 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4541 if (req->unread_bytes) {
4542 /* Can't do a recvfile write on IPC$ */
4543 if (IS_IPC(conn)) {
4544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4545 goto out;
4547 if (numtowrite != req->unread_bytes) {
4548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4549 goto out;
4551 } else {
4553 * This already protects us against CVE-2017-12163.
4555 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4556 smb_doff + numtowrite > smblen) {
4557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4558 goto out;
4562 /* If it's an IPC, pass off the pipe handler. */
4563 if (IS_IPC(conn)) {
4564 if (req->unread_bytes) {
4565 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4566 goto out;
4568 reply_pipe_write_and_X(req);
4569 goto out;
4572 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4573 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4574 write_through = BITSETW(req->vwv+7,0);
4576 if (!check_fsp(conn, req, fsp)) {
4577 goto out;
4580 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
4581 if (!NT_STATUS_IS_OK(status)) {
4582 reply_nterror(req, status);
4583 goto out;
4586 data = smb_base(req->inbuf) + smb_doff;
4588 if(req->wct == 14) {
4590 * This is a large offset (64 bit) write.
4592 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4596 /* X/Open SMB protocol says that, unlike SMBwrite
4597 if the length is zero then NO truncation is
4598 done, just a write of zero. To truncate a file,
4599 use SMBwrite. */
4601 if(numtowrite == 0) {
4602 nwritten = 0;
4603 } else {
4604 if (req->unread_bytes == 0) {
4605 status = schedule_aio_write_and_X(conn,
4606 req,
4607 fsp,
4608 data,
4609 startpos,
4610 numtowrite);
4612 if (NT_STATUS_IS_OK(status)) {
4613 /* write scheduled - we're done. */
4614 goto out;
4616 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4617 /* Real error - report to client. */
4618 reply_nterror(req, status);
4619 goto out;
4621 /* NT_STATUS_RETRY - fall through to sync write. */
4624 init_strict_lock_struct(fsp,
4625 (uint64_t)req->smbpid,
4626 (uint64_t)startpos,
4627 (uint64_t)numtowrite,
4628 WRITE_LOCK,
4629 lp_posix_cifsu_locktype(fsp),
4630 &lock);
4632 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4633 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4634 goto out;
4637 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4638 saved_errno = errno;
4641 if(nwritten < 0) {
4642 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4643 goto out;
4646 if((nwritten == 0) && (numtowrite != 0)) {
4647 reply_nterror(req, NT_STATUS_DISK_FULL);
4648 goto out;
4651 reply_smb1_outbuf(req, 6, 0);
4652 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4653 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4654 SSVAL(req->outbuf,smb_vwv2,nwritten);
4655 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4657 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4658 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4660 status = sync_file(conn, fsp, write_through);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4663 fsp_str_dbg(fsp), nt_errstr(status)));
4664 reply_nterror(req, status);
4665 goto out;
4668 END_PROFILE(SMBwriteX);
4669 return;
4671 out:
4672 if (req->unread_bytes) {
4673 /* writeX failed. drain socket. */
4674 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4675 req->unread_bytes) {
4676 smb_panic("failed to drain pending bytes");
4678 req->unread_bytes = 0;
4681 END_PROFILE(SMBwriteX);
4682 return;
4685 /****************************************************************************
4686 Reply to a lseek.
4687 ****************************************************************************/
4689 void reply_lseek(struct smb_request *req)
4691 connection_struct *conn = req->conn;
4692 off_t startpos;
4693 off_t res= -1;
4694 int mode,umode;
4695 files_struct *fsp;
4696 NTSTATUS status;
4698 START_PROFILE(SMBlseek);
4700 if (req->wct < 4) {
4701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4702 END_PROFILE(SMBlseek);
4703 return;
4706 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4708 if (!check_fsp(conn, req, fsp)) {
4709 return;
4712 mode = SVAL(req->vwv+1, 0) & 3;
4713 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4714 startpos = (off_t)IVALS(req->vwv+2, 0);
4716 switch (mode) {
4717 case 0:
4718 umode = SEEK_SET;
4719 res = startpos;
4720 break;
4721 case 1:
4722 umode = SEEK_CUR;
4723 res = fh_get_pos(fsp->fh) + startpos;
4724 break;
4725 case 2:
4726 umode = SEEK_END;
4727 break;
4728 default:
4729 umode = SEEK_SET;
4730 res = startpos;
4731 break;
4734 if (umode == SEEK_END) {
4735 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4736 if(errno == EINVAL) {
4737 off_t current_pos = startpos;
4739 status = vfs_stat_fsp(fsp);
4740 if (!NT_STATUS_IS_OK(status)) {
4741 reply_nterror(req, status);
4742 END_PROFILE(SMBlseek);
4743 return;
4746 current_pos += fsp->fsp_name->st.st_ex_size;
4747 if(current_pos < 0)
4748 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4752 if(res == -1) {
4753 reply_nterror(req, map_nt_error_from_unix(errno));
4754 END_PROFILE(SMBlseek);
4755 return;
4759 fh_set_pos(fsp->fh, res);
4761 reply_smb1_outbuf(req, 2, 0);
4762 SIVAL(req->outbuf,smb_vwv0,res);
4764 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4765 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4767 END_PROFILE(SMBlseek);
4768 return;
4771 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4772 void *private_data)
4774 connection_struct *conn = talloc_get_type_abort(
4775 private_data, connection_struct);
4777 if (conn != fsp->conn) {
4778 return NULL;
4780 if (fsp_get_io_fd(fsp) == -1) {
4781 return NULL;
4783 sync_file(conn, fsp, True /* write through */);
4785 if (fsp->fsp_flags.modified) {
4786 trigger_write_time_update_immediate(fsp);
4789 return NULL;
4792 /****************************************************************************
4793 Reply to a flush.
4794 ****************************************************************************/
4796 void reply_flush(struct smb_request *req)
4798 connection_struct *conn = req->conn;
4799 uint16_t fnum;
4800 files_struct *fsp;
4802 START_PROFILE(SMBflush);
4804 if (req->wct < 1) {
4805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4806 return;
4809 fnum = SVAL(req->vwv+0, 0);
4810 fsp = file_fsp(req, fnum);
4812 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4813 return;
4816 if (!fsp) {
4817 files_forall(req->sconn, file_sync_one_fn, conn);
4818 } else {
4819 NTSTATUS status = sync_file(conn, fsp, True);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4822 fsp_str_dbg(fsp), nt_errstr(status)));
4823 reply_nterror(req, status);
4824 END_PROFILE(SMBflush);
4825 return;
4827 if (fsp->fsp_flags.modified) {
4828 trigger_write_time_update_immediate(fsp);
4832 reply_smb1_outbuf(req, 0, 0);
4834 DEBUG(3,("flush\n"));
4835 END_PROFILE(SMBflush);
4836 return;
4839 /****************************************************************************
4840 Reply to a exit.
4841 conn POINTER CAN BE NULL HERE !
4842 ****************************************************************************/
4844 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4845 static void reply_exit_done(struct tevent_req *req);
4847 void reply_exit(struct smb_request *smb1req)
4849 struct tevent_req *req;
4852 * Don't setup the profile charge here, take
4853 * it in reply_exit_done(). Not strictly correct
4854 * but better than the other SMB1 async
4855 * code that double-charges at the moment.
4857 req = reply_exit_send(smb1req);
4858 if (req == NULL) {
4859 /* Not going async, profile here. */
4860 START_PROFILE(SMBexit);
4861 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4862 END_PROFILE(SMBexit);
4863 return;
4866 /* We're async. This will complete later. */
4867 tevent_req_set_callback(req, reply_exit_done, smb1req);
4868 return;
4871 struct reply_exit_state {
4872 struct tevent_queue *wait_queue;
4875 static void reply_exit_wait_done(struct tevent_req *subreq);
4877 /****************************************************************************
4878 Async SMB1 exit.
4879 Note, on failure here we deallocate and return NULL to allow the caller to
4880 SMB1 return an error of ERRnomem immediately.
4881 ****************************************************************************/
4883 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4885 struct tevent_req *req;
4886 struct reply_exit_state *state;
4887 struct tevent_req *subreq;
4888 files_struct *fsp;
4889 struct smbd_server_connection *sconn = smb1req->sconn;
4891 req = tevent_req_create(smb1req, &state,
4892 struct reply_exit_state);
4893 if (req == NULL) {
4894 return NULL;
4896 state->wait_queue = tevent_queue_create(state,
4897 "reply_exit_wait_queue");
4898 if (tevent_req_nomem(state->wait_queue, req)) {
4899 TALLOC_FREE(req);
4900 return NULL;
4903 for (fsp = sconn->files; fsp; fsp = fsp->next) {
4904 if (fsp->file_pid != smb1req->smbpid) {
4905 continue;
4907 if (fsp->vuid != smb1req->vuid) {
4908 continue;
4911 * Flag the file as close in progress.
4912 * This will prevent any more IO being
4913 * done on it.
4915 fsp->fsp_flags.closing = true;
4917 if (fsp->num_aio_requests > 0) {
4919 * Now wait until all aio requests on this fsp are
4920 * finished.
4922 * We don't set a callback, as we just want to block the
4923 * wait queue and the talloc_free() of fsp->aio_request
4924 * will remove the item from the wait queue.
4926 subreq = tevent_queue_wait_send(fsp->aio_requests,
4927 sconn->ev_ctx,
4928 state->wait_queue);
4929 if (tevent_req_nomem(subreq, req)) {
4930 TALLOC_FREE(req);
4931 return NULL;
4937 * Now we add our own waiter to the end of the queue,
4938 * this way we get notified when all pending requests are finished
4939 * and reply to the outstanding SMB1 request.
4941 subreq = tevent_queue_wait_send(state,
4942 sconn->ev_ctx,
4943 state->wait_queue);
4944 if (tevent_req_nomem(subreq, req)) {
4945 TALLOC_FREE(req);
4946 return NULL;
4950 * We're really going async - move the SMB1 request from
4951 * a talloc stackframe above us to the conn talloc-context.
4952 * We need this to stick around until the wait_done
4953 * callback is invoked.
4955 smb1req = talloc_move(sconn, &smb1req);
4957 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4959 return req;
4962 static void reply_exit_wait_done(struct tevent_req *subreq)
4964 struct tevent_req *req = tevent_req_callback_data(
4965 subreq, struct tevent_req);
4967 tevent_queue_wait_recv(subreq);
4968 TALLOC_FREE(subreq);
4969 tevent_req_done(req);
4972 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4974 return tevent_req_simple_recv_ntstatus(req);
4977 static void reply_exit_done(struct tevent_req *req)
4979 struct smb_request *smb1req = tevent_req_callback_data(
4980 req, struct smb_request);
4981 struct smbd_server_connection *sconn = smb1req->sconn;
4982 struct smbXsrv_connection *xconn = smb1req->xconn;
4983 NTTIME now = timeval_to_nttime(&smb1req->request_time);
4984 struct smbXsrv_session *session = NULL;
4985 files_struct *fsp, *next;
4986 NTSTATUS status;
4989 * Take the profile charge here. Not strictly
4990 * correct but better than the other SMB1 async
4991 * code that double-charges at the moment.
4993 START_PROFILE(SMBexit);
4995 status = reply_exit_recv(req);
4996 TALLOC_FREE(req);
4997 if (!NT_STATUS_IS_OK(status)) {
4998 TALLOC_FREE(smb1req);
4999 END_PROFILE(SMBexit);
5000 exit_server(__location__ ": reply_exit_recv failed");
5001 return;
5005 * Ensure the session is still valid.
5007 status = smb1srv_session_lookup(xconn,
5008 smb1req->vuid,
5009 now,
5010 &session);
5011 if (!NT_STATUS_IS_OK(status)) {
5012 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5013 smb_request_done(smb1req);
5014 END_PROFILE(SMBexit);
5015 return;
5019 * Ensure the vuid is still valid - no one
5020 * called reply_ulogoffX() in the meantime.
5021 * reply_exit() doesn't have AS_USER set, so
5022 * use set_current_user_info() directly.
5023 * This is the same logic as in switch_message().
5025 if (session->global->auth_session_info != NULL) {
5026 set_current_user_info(
5027 session->global->auth_session_info->unix_info->sanitized_username,
5028 session->global->auth_session_info->unix_info->unix_name,
5029 session->global->auth_session_info->info->domain_name);
5032 /* No more aio - do the actual closes. */
5033 for (fsp = sconn->files; fsp; fsp = next) {
5034 bool ok;
5035 next = fsp->next;
5037 if (fsp->file_pid != smb1req->smbpid) {
5038 continue;
5040 if (fsp->vuid != smb1req->vuid) {
5041 continue;
5043 if (!fsp->fsp_flags.closing) {
5044 continue;
5048 * reply_exit() has the DO_CHDIR flag set.
5050 ok = chdir_current_service(fsp->conn);
5051 if (!ok) {
5052 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5053 smb_request_done(smb1req);
5054 END_PROFILE(SMBexit);
5055 return;
5057 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
5060 reply_smb1_outbuf(smb1req, 0, 0);
5062 * The following call is needed to push the
5063 * reply data back out the socket after async
5064 * return. Plus it frees smb1req.
5066 smb_request_done(smb1req);
5067 DBG_INFO("reply_exit complete\n");
5068 END_PROFILE(SMBexit);
5069 return;
5072 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5073 files_struct *fsp);
5074 static void reply_close_done(struct tevent_req *req);
5076 void reply_close(struct smb_request *smb1req)
5078 connection_struct *conn = smb1req->conn;
5079 NTSTATUS status = NT_STATUS_OK;
5080 files_struct *fsp = NULL;
5081 START_PROFILE(SMBclose);
5083 if (smb1req->wct < 3) {
5084 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
5085 END_PROFILE(SMBclose);
5086 return;
5089 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5092 * We can only use check_fsp if we know it's not a directory.
5095 if (!check_fsp_open(conn, smb1req, fsp)) {
5096 END_PROFILE(SMBclose);
5097 return;
5100 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5101 fsp->fsp_flags.is_directory ?
5102 "directory" : "file",
5103 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5104 conn->num_files_open);
5106 if (!fsp->fsp_flags.is_directory) {
5107 time_t t;
5110 * Take care of any time sent in the close.
5113 t = srv_make_unix_date3(smb1req->vwv+1);
5114 set_close_write_time(fsp, time_t_to_full_timespec(t));
5117 if (fsp->num_aio_requests != 0) {
5118 struct tevent_req *req;
5120 req = reply_close_send(smb1req, fsp);
5121 if (req == NULL) {
5122 status = NT_STATUS_NO_MEMORY;
5123 goto done;
5125 /* We're async. This will complete later. */
5126 tevent_req_set_callback(req, reply_close_done, smb1req);
5127 END_PROFILE(SMBclose);
5128 return;
5132 * close_file_free() returns the unix errno if an error was detected on
5133 * close - normally this is due to a disk full error. If not then it
5134 * was probably an I/O error.
5137 status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
5138 done:
5139 if (!NT_STATUS_IS_OK(status)) {
5140 reply_nterror(smb1req, status);
5141 END_PROFILE(SMBclose);
5142 return;
5145 reply_smb1_outbuf(smb1req, 0, 0);
5146 END_PROFILE(SMBclose);
5147 return;
5150 struct reply_close_state {
5151 files_struct *fsp;
5152 struct tevent_queue *wait_queue;
5155 static void reply_close_wait_done(struct tevent_req *subreq);
5157 /****************************************************************************
5158 Async SMB1 close.
5159 Note, on failure here we deallocate and return NULL to allow the caller to
5160 SMB1 return an error of ERRnomem immediately.
5161 ****************************************************************************/
5163 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5164 files_struct *fsp)
5166 struct tevent_req *req;
5167 struct reply_close_state *state;
5168 struct tevent_req *subreq;
5169 struct smbd_server_connection *sconn = smb1req->sconn;
5171 req = tevent_req_create(smb1req, &state,
5172 struct reply_close_state);
5173 if (req == NULL) {
5174 return NULL;
5176 state->wait_queue = tevent_queue_create(state,
5177 "reply_close_wait_queue");
5178 if (tevent_req_nomem(state->wait_queue, req)) {
5179 TALLOC_FREE(req);
5180 return NULL;
5184 * Flag the file as close in progress.
5185 * This will prevent any more IO being
5186 * done on it.
5188 fsp->fsp_flags.closing = true;
5191 * Now wait until all aio requests on this fsp are
5192 * finished.
5194 * We don't set a callback, as we just want to block the
5195 * wait queue and the talloc_free() of fsp->aio_request
5196 * will remove the item from the wait queue.
5198 subreq = tevent_queue_wait_send(fsp->aio_requests,
5199 sconn->ev_ctx,
5200 state->wait_queue);
5201 if (tevent_req_nomem(subreq, req)) {
5202 TALLOC_FREE(req);
5203 return NULL;
5207 * Now we add our own waiter to the end of the queue,
5208 * this way we get notified when all pending requests are finished
5209 * and reply to the outstanding SMB1 request.
5211 subreq = tevent_queue_wait_send(state,
5212 sconn->ev_ctx,
5213 state->wait_queue);
5214 if (tevent_req_nomem(subreq, req)) {
5215 TALLOC_FREE(req);
5216 return NULL;
5220 * We're really going async - move the SMB1 request from
5221 * a talloc stackframe above us to the conn talloc-context.
5222 * We need this to stick around until the wait_done
5223 * callback is invoked.
5225 smb1req = talloc_move(sconn, &smb1req);
5227 tevent_req_set_callback(subreq, reply_close_wait_done, req);
5229 return req;
5232 static void reply_close_wait_done(struct tevent_req *subreq)
5234 struct tevent_req *req = tevent_req_callback_data(
5235 subreq, struct tevent_req);
5237 tevent_queue_wait_recv(subreq);
5238 TALLOC_FREE(subreq);
5239 tevent_req_done(req);
5242 static NTSTATUS reply_close_recv(struct tevent_req *req)
5244 return tevent_req_simple_recv_ntstatus(req);
5247 static void reply_close_done(struct tevent_req *req)
5249 struct smb_request *smb1req = tevent_req_callback_data(
5250 req, struct smb_request);
5251 struct reply_close_state *state = tevent_req_data(req,
5252 struct reply_close_state);
5253 NTSTATUS status;
5255 status = reply_close_recv(req);
5256 TALLOC_FREE(req);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 TALLOC_FREE(smb1req);
5259 exit_server(__location__ ": reply_close_recv failed");
5260 return;
5263 status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
5264 if (NT_STATUS_IS_OK(status)) {
5265 reply_smb1_outbuf(smb1req, 0, 0);
5266 } else {
5267 reply_nterror(smb1req, status);
5270 * The following call is needed to push the
5271 * reply data back out the socket after async
5272 * return. Plus it frees smb1req.
5274 smb_request_done(smb1req);
5277 /****************************************************************************
5278 Reply to a writeclose (Core+ protocol).
5279 ****************************************************************************/
5281 void reply_writeclose(struct smb_request *req)
5283 connection_struct *conn = req->conn;
5284 size_t numtowrite;
5285 size_t remaining;
5286 ssize_t nwritten = -1;
5287 NTSTATUS close_status = NT_STATUS_OK;
5288 off_t startpos;
5289 const char *data;
5290 struct timespec mtime;
5291 files_struct *fsp;
5292 struct lock_struct lock;
5293 NTSTATUS status;
5295 START_PROFILE(SMBwriteclose);
5297 if (req->wct < 6) {
5298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5299 END_PROFILE(SMBwriteclose);
5300 return;
5303 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5305 if (!check_fsp(conn, req, fsp)) {
5306 END_PROFILE(SMBwriteclose);
5307 return;
5309 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
5310 if (!NT_STATUS_IS_OK(status)) {
5311 reply_nterror(req, status);
5312 END_PROFILE(SMBwriteclose);
5313 return;
5316 numtowrite = SVAL(req->vwv+1, 0);
5317 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5318 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5319 data = (const char *)req->buf + 1;
5322 * Ensure client isn't asking us to write more than
5323 * they sent. CVE-2017-12163.
5325 remaining = smbreq_bufrem(req, data);
5326 if (numtowrite > remaining) {
5327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5328 END_PROFILE(SMBwriteclose);
5329 return;
5332 if (fsp->print_file == NULL) {
5333 init_strict_lock_struct(fsp,
5334 (uint64_t)req->smbpid,
5335 (uint64_t)startpos,
5336 (uint64_t)numtowrite,
5337 WRITE_LOCK,
5338 lp_posix_cifsu_locktype(fsp),
5339 &lock);
5341 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5342 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5343 END_PROFILE(SMBwriteclose);
5344 return;
5348 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5350 set_close_write_time(fsp, mtime);
5353 * More insanity. W2K only closes the file if writelen > 0.
5354 * JRA.
5357 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5358 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5359 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5361 if (numtowrite) {
5362 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5363 "file %s\n", fsp_str_dbg(fsp)));
5364 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5367 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5368 reply_nterror(req, NT_STATUS_DISK_FULL);
5369 goto out;
5372 if(!NT_STATUS_IS_OK(close_status)) {
5373 reply_nterror(req, close_status);
5374 goto out;
5377 reply_smb1_outbuf(req, 1, 0);
5379 SSVAL(req->outbuf,smb_vwv0,nwritten);
5381 out:
5383 END_PROFILE(SMBwriteclose);
5384 return;
5387 #undef DBGC_CLASS
5388 #define DBGC_CLASS DBGC_LOCKING
5390 /****************************************************************************
5391 Reply to a lock.
5392 ****************************************************************************/
5394 static void reply_lock_done(struct tevent_req *subreq);
5396 void reply_lock(struct smb_request *req)
5398 struct tevent_req *subreq = NULL;
5399 connection_struct *conn = req->conn;
5400 files_struct *fsp;
5401 struct smbd_lock_element *lck = NULL;
5403 START_PROFILE(SMBlock);
5405 if (req->wct < 5) {
5406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5407 END_PROFILE(SMBlock);
5408 return;
5411 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5413 if (!check_fsp(conn, req, fsp)) {
5414 END_PROFILE(SMBlock);
5415 return;
5418 lck = talloc(req, struct smbd_lock_element);
5419 if (lck == NULL) {
5420 reply_nterror(req, NT_STATUS_NO_MEMORY);
5421 END_PROFILE(SMBlock);
5422 return;
5425 *lck = (struct smbd_lock_element) {
5426 .req_guid = smbd_request_guid(req, 0),
5427 .smblctx = req->smbpid,
5428 .brltype = WRITE_LOCK,
5429 .lock_flav = WINDOWS_LOCK,
5430 .count = IVAL(req->vwv+1, 0),
5431 .offset = IVAL(req->vwv+3, 0),
5434 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5435 fsp_get_io_fd(fsp),
5436 fsp_fnum_dbg(fsp),
5437 lck->offset,
5438 lck->count);
5440 subreq = smbd_smb1_do_locks_send(
5441 fsp,
5442 req->sconn->ev_ctx,
5443 &req,
5444 fsp,
5446 false, /* large_offset */
5448 lck);
5449 if (subreq == NULL) {
5450 reply_nterror(req, NT_STATUS_NO_MEMORY);
5451 END_PROFILE(SMBlock);
5452 return;
5454 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5455 END_PROFILE(SMBlock);
5458 static void reply_lock_done(struct tevent_req *subreq)
5460 struct smb_request *req = NULL;
5461 NTSTATUS status;
5462 bool ok;
5464 START_PROFILE(SMBlock);
5466 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5467 SMB_ASSERT(ok);
5469 status = smbd_smb1_do_locks_recv(subreq);
5470 TALLOC_FREE(subreq);
5472 if (NT_STATUS_IS_OK(status)) {
5473 reply_smb1_outbuf(req, 0, 0);
5474 } else {
5475 reply_nterror(req, status);
5478 ok = smb1_srv_send(req->xconn,
5479 (char *)req->outbuf,
5480 true,
5481 req->seqnum + 1,
5482 IS_CONN_ENCRYPTED(req->conn));
5483 if (!ok) {
5484 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5486 TALLOC_FREE(req);
5487 END_PROFILE(SMBlock);
5490 /****************************************************************************
5491 Reply to a unlock.
5492 ****************************************************************************/
5494 void reply_unlock(struct smb_request *req)
5496 connection_struct *conn = req->conn;
5497 NTSTATUS status;
5498 files_struct *fsp;
5499 struct smbd_lock_element lck;
5501 START_PROFILE(SMBunlock);
5503 if (req->wct < 5) {
5504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5505 END_PROFILE(SMBunlock);
5506 return;
5509 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5511 if (!check_fsp(conn, req, fsp)) {
5512 END_PROFILE(SMBunlock);
5513 return;
5516 lck = (struct smbd_lock_element) {
5517 .req_guid = smbd_request_guid(req, 0),
5518 .smblctx = req->smbpid,
5519 .brltype = UNLOCK_LOCK,
5520 .lock_flav = WINDOWS_LOCK,
5521 .offset = IVAL(req->vwv+3, 0),
5522 .count = IVAL(req->vwv+1, 0),
5525 status = smbd_do_unlocking(req, fsp, 1, &lck);
5527 if (!NT_STATUS_IS_OK(status)) {
5528 reply_nterror(req, status);
5529 END_PROFILE(SMBunlock);
5530 return;
5533 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5534 fsp_get_io_fd(fsp),
5535 fsp_fnum_dbg(fsp),
5536 lck.offset,
5537 lck.count);
5539 reply_smb1_outbuf(req, 0, 0);
5541 END_PROFILE(SMBunlock);
5542 return;
5545 #undef DBGC_CLASS
5546 #define DBGC_CLASS DBGC_ALL
5548 /****************************************************************************
5549 Reply to a tdis.
5550 conn POINTER CAN BE NULL HERE !
5551 ****************************************************************************/
5553 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5554 static void reply_tdis_done(struct tevent_req *req);
5556 void reply_tdis(struct smb_request *smb1req)
5558 connection_struct *conn = smb1req->conn;
5559 struct tevent_req *req;
5562 * Don't setup the profile charge here, take
5563 * it in reply_tdis_done(). Not strictly correct
5564 * but better than the other SMB1 async
5565 * code that double-charges at the moment.
5568 if (conn == NULL) {
5569 /* Not going async, profile here. */
5570 START_PROFILE(SMBtdis);
5571 DBG_INFO("Invalid connection in tdis\n");
5572 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5573 END_PROFILE(SMBtdis);
5574 return;
5577 req = reply_tdis_send(smb1req);
5578 if (req == NULL) {
5579 /* Not going async, profile here. */
5580 START_PROFILE(SMBtdis);
5581 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5582 END_PROFILE(SMBtdis);
5583 return;
5585 /* We're async. This will complete later. */
5586 tevent_req_set_callback(req, reply_tdis_done, smb1req);
5587 return;
5590 struct reply_tdis_state {
5591 struct tevent_queue *wait_queue;
5594 static void reply_tdis_wait_done(struct tevent_req *subreq);
5596 /****************************************************************************
5597 Async SMB1 tdis.
5598 Note, on failure here we deallocate and return NULL to allow the caller to
5599 SMB1 return an error of ERRnomem immediately.
5600 ****************************************************************************/
5602 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5604 struct tevent_req *req;
5605 struct reply_tdis_state *state;
5606 struct tevent_req *subreq;
5607 connection_struct *conn = smb1req->conn;
5608 files_struct *fsp;
5610 req = tevent_req_create(smb1req, &state,
5611 struct reply_tdis_state);
5612 if (req == NULL) {
5613 return NULL;
5615 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5616 if (tevent_req_nomem(state->wait_queue, req)) {
5617 TALLOC_FREE(req);
5618 return NULL;
5622 * Make sure that no new request will be able to use this tcon.
5623 * This ensures that once all outstanding fsp->aio_requests
5624 * on this tcon are done, we are safe to close it.
5626 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5628 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5629 if (fsp->conn != conn) {
5630 continue;
5633 * Flag the file as close in progress.
5634 * This will prevent any more IO being
5635 * done on it. Not strictly needed, but
5636 * doesn't hurt to flag it as closing.
5638 fsp->fsp_flags.closing = true;
5640 if (fsp->num_aio_requests > 0) {
5642 * Now wait until all aio requests on this fsp are
5643 * finished.
5645 * We don't set a callback, as we just want to block the
5646 * wait queue and the talloc_free() of fsp->aio_request
5647 * will remove the item from the wait queue.
5649 subreq = tevent_queue_wait_send(fsp->aio_requests,
5650 conn->sconn->ev_ctx,
5651 state->wait_queue);
5652 if (tevent_req_nomem(subreq, req)) {
5653 TALLOC_FREE(req);
5654 return NULL;
5660 * Now we add our own waiter to the end of the queue,
5661 * this way we get notified when all pending requests are finished
5662 * and reply to the outstanding SMB1 request.
5664 subreq = tevent_queue_wait_send(state,
5665 conn->sconn->ev_ctx,
5666 state->wait_queue);
5667 if (tevent_req_nomem(subreq, req)) {
5668 TALLOC_FREE(req);
5669 return NULL;
5673 * We're really going async - move the SMB1 request from
5674 * a talloc stackframe above us to the sconn talloc-context.
5675 * We need this to stick around until the wait_done
5676 * callback is invoked.
5678 smb1req = talloc_move(smb1req->sconn, &smb1req);
5680 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5682 return req;
5685 static void reply_tdis_wait_done(struct tevent_req *subreq)
5687 struct tevent_req *req = tevent_req_callback_data(
5688 subreq, struct tevent_req);
5690 tevent_queue_wait_recv(subreq);
5691 TALLOC_FREE(subreq);
5692 tevent_req_done(req);
5695 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5697 return tevent_req_simple_recv_ntstatus(req);
5700 static void reply_tdis_done(struct tevent_req *req)
5702 struct smb_request *smb1req = tevent_req_callback_data(
5703 req, struct smb_request);
5704 NTSTATUS status;
5705 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5706 bool ok;
5709 * Take the profile charge here. Not strictly
5710 * correct but better than the other SMB1 async
5711 * code that double-charges at the moment.
5713 START_PROFILE(SMBtdis);
5715 status = reply_tdis_recv(req);
5716 TALLOC_FREE(req);
5717 if (!NT_STATUS_IS_OK(status)) {
5718 TALLOC_FREE(smb1req);
5719 END_PROFILE(SMBtdis);
5720 exit_server(__location__ ": reply_tdis_recv failed");
5721 return;
5725 * As we've been awoken, we may have changed
5726 * directory in the meantime.
5727 * reply_tdis() has the DO_CHDIR flag set.
5729 ok = chdir_current_service(smb1req->conn);
5730 if (!ok) {
5731 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5732 smb_request_done(smb1req);
5733 END_PROFILE(SMBtdis);
5736 status = smbXsrv_tcon_disconnect(tcon,
5737 smb1req->vuid);
5738 if (!NT_STATUS_IS_OK(status)) {
5739 TALLOC_FREE(smb1req);
5740 END_PROFILE(SMBtdis);
5741 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5742 return;
5745 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5746 smb1req->conn = NULL;
5748 TALLOC_FREE(tcon);
5750 reply_smb1_outbuf(smb1req, 0, 0);
5752 * The following call is needed to push the
5753 * reply data back out the socket after async
5754 * return. Plus it frees smb1req.
5756 smb_request_done(smb1req);
5757 END_PROFILE(SMBtdis);
5760 /****************************************************************************
5761 Reply to a echo.
5762 conn POINTER CAN BE NULL HERE !
5763 ****************************************************************************/
5765 void reply_echo(struct smb_request *req)
5767 connection_struct *conn = req->conn;
5768 int smb_reverb;
5769 int seq_num;
5771 START_PROFILE(SMBecho);
5773 if (req->wct < 1) {
5774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5775 END_PROFILE(SMBecho);
5776 return;
5779 smb_reverb = SVAL(req->vwv+0, 0);
5781 reply_smb1_outbuf(req, 1, req->buflen);
5783 /* copy any incoming data back out */
5784 if (req->buflen > 0) {
5785 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5788 if (smb_reverb > 100) {
5789 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5790 smb_reverb = 100;
5793 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5795 SSVAL(req->outbuf,smb_vwv0,seq_num);
5797 show_msg((char *)req->outbuf);
5798 if (!smb1_srv_send(req->xconn,
5799 (char *)req->outbuf,
5800 true,
5801 req->seqnum + 1,
5802 IS_CONN_ENCRYPTED(conn) || req->encrypted))
5803 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5806 DEBUG(3,("echo %d times\n", smb_reverb));
5808 TALLOC_FREE(req->outbuf);
5810 END_PROFILE(SMBecho);
5811 return;
5814 /****************************************************************************
5815 Reply to a printopen.
5816 ****************************************************************************/
5818 void reply_printopen(struct smb_request *req)
5820 connection_struct *conn = req->conn;
5821 files_struct *fsp;
5822 NTSTATUS status;
5824 START_PROFILE(SMBsplopen);
5826 if (req->wct < 2) {
5827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5828 END_PROFILE(SMBsplopen);
5829 return;
5832 if (!CAN_PRINT(conn)) {
5833 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5834 END_PROFILE(SMBsplopen);
5835 return;
5838 status = file_new(req, conn, &fsp);
5839 if(!NT_STATUS_IS_OK(status)) {
5840 reply_nterror(req, status);
5841 END_PROFILE(SMBsplopen);
5842 return;
5845 /* Open for exclusive use, write only. */
5846 status = print_spool_open(fsp, NULL, req->vuid);
5848 if (!NT_STATUS_IS_OK(status)) {
5849 file_free(req, fsp);
5850 reply_nterror(req, status);
5851 END_PROFILE(SMBsplopen);
5852 return;
5855 reply_smb1_outbuf(req, 1, 0);
5856 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5858 DEBUG(3,("openprint fd=%d %s\n",
5859 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5861 END_PROFILE(SMBsplopen);
5862 return;
5865 /****************************************************************************
5866 Reply to a printclose.
5867 ****************************************************************************/
5869 void reply_printclose(struct smb_request *req)
5871 connection_struct *conn = req->conn;
5872 files_struct *fsp;
5873 NTSTATUS status;
5875 START_PROFILE(SMBsplclose);
5877 if (req->wct < 1) {
5878 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5879 END_PROFILE(SMBsplclose);
5880 return;
5883 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5885 if (!check_fsp(conn, req, fsp)) {
5886 END_PROFILE(SMBsplclose);
5887 return;
5890 if (!CAN_PRINT(conn)) {
5891 reply_force_doserror(req, ERRSRV, ERRerror);
5892 END_PROFILE(SMBsplclose);
5893 return;
5896 DEBUG(3,("printclose fd=%d %s\n",
5897 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5899 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5901 if(!NT_STATUS_IS_OK(status)) {
5902 reply_nterror(req, status);
5903 END_PROFILE(SMBsplclose);
5904 return;
5907 reply_smb1_outbuf(req, 0, 0);
5909 END_PROFILE(SMBsplclose);
5910 return;
5913 /****************************************************************************
5914 Reply to a printqueue.
5915 ****************************************************************************/
5917 void reply_printqueue(struct smb_request *req)
5919 const struct loadparm_substitution *lp_sub =
5920 loadparm_s3_global_substitution();
5921 connection_struct *conn = req->conn;
5922 int max_count;
5923 int start_index;
5925 START_PROFILE(SMBsplretq);
5927 if (req->wct < 2) {
5928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5929 END_PROFILE(SMBsplretq);
5930 return;
5933 max_count = SVAL(req->vwv+0, 0);
5934 start_index = SVAL(req->vwv+1, 0);
5936 /* we used to allow the client to get the cnum wrong, but that
5937 is really quite gross and only worked when there was only
5938 one printer - I think we should now only accept it if they
5939 get it right (tridge) */
5940 if (!CAN_PRINT(conn)) {
5941 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5942 END_PROFILE(SMBsplretq);
5943 return;
5946 reply_smb1_outbuf(req, 2, 3);
5947 SSVAL(req->outbuf,smb_vwv0,0);
5948 SSVAL(req->outbuf,smb_vwv1,0);
5949 SCVAL(smb_buf(req->outbuf),0,1);
5950 SSVAL(smb_buf(req->outbuf),1,0);
5952 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5953 start_index, max_count));
5956 TALLOC_CTX *mem_ctx = talloc_tos();
5957 NTSTATUS status;
5958 WERROR werr;
5959 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5960 struct rpc_pipe_client *cli = NULL;
5961 struct dcerpc_binding_handle *b = NULL;
5962 struct policy_handle handle;
5963 struct spoolss_DevmodeContainer devmode_ctr;
5964 union spoolss_JobInfo *info;
5965 uint32_t count;
5966 uint32_t num_to_get;
5967 uint32_t first;
5968 uint32_t i;
5970 ZERO_STRUCT(handle);
5972 status = rpc_pipe_open_interface(mem_ctx,
5973 &ndr_table_spoolss,
5974 conn->session_info,
5975 conn->sconn->remote_address,
5976 conn->sconn->local_address,
5977 conn->sconn->msg_ctx,
5978 &cli);
5979 if (!NT_STATUS_IS_OK(status)) {
5980 DEBUG(0, ("reply_printqueue: "
5981 "could not connect to spoolss: %s\n",
5982 nt_errstr(status)));
5983 reply_nterror(req, status);
5984 goto out;
5986 b = cli->binding_handle;
5988 ZERO_STRUCT(devmode_ctr);
5990 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5991 sharename,
5992 NULL, devmode_ctr,
5993 SEC_FLAG_MAXIMUM_ALLOWED,
5994 &handle,
5995 &werr);
5996 if (!NT_STATUS_IS_OK(status)) {
5997 reply_nterror(req, status);
5998 goto out;
6000 if (!W_ERROR_IS_OK(werr)) {
6001 reply_nterror(req, werror_to_ntstatus(werr));
6002 goto out;
6005 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6006 &handle,
6007 0, /* firstjob */
6008 0xff, /* numjobs */
6009 2, /* level */
6010 0, /* offered */
6011 &count,
6012 &info);
6013 if (!W_ERROR_IS_OK(werr)) {
6014 reply_nterror(req, werror_to_ntstatus(werr));
6015 goto out;
6018 if (max_count > 0) {
6019 first = start_index;
6020 } else {
6021 first = start_index + max_count + 1;
6024 if (first >= count) {
6025 num_to_get = first;
6026 } else {
6027 num_to_get = first + MIN(ABS(max_count), count - first);
6030 for (i = first; i < num_to_get; i++) {
6031 char blob[28];
6032 char *p = blob;
6033 struct timespec qtime = {
6034 .tv_sec = spoolss_Time_to_time_t(
6035 &info[i].info2.submitted),
6037 int qstatus;
6038 size_t len = 0;
6039 uint16_t qrapjobid = pjobid_to_rap(sharename,
6040 info[i].info2.job_id);
6042 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6043 qstatus = 2;
6044 } else {
6045 qstatus = 3;
6048 srv_put_dos_date2_ts(p, 0, qtime);
6049 SCVAL(p, 4, qstatus);
6050 SSVAL(p, 5, qrapjobid);
6051 SIVAL(p, 7, info[i].info2.size);
6052 SCVAL(p, 11, 0);
6053 status = srvstr_push(blob, req->flags2, p+12,
6054 info[i].info2.notify_name, 16, STR_ASCII, &len);
6055 if (!NT_STATUS_IS_OK(status)) {
6056 reply_nterror(req, status);
6057 goto out;
6059 if (message_push_blob(
6060 &req->outbuf,
6061 data_blob_const(
6062 blob, sizeof(blob))) == -1) {
6063 reply_nterror(req, NT_STATUS_NO_MEMORY);
6064 goto out;
6068 if (count > 0) {
6069 SSVAL(req->outbuf,smb_vwv0,count);
6070 SSVAL(req->outbuf,smb_vwv1,
6071 (max_count>0?first+count:first-1));
6072 SCVAL(smb_buf(req->outbuf),0,1);
6073 SSVAL(smb_buf(req->outbuf),1,28*count);
6077 DEBUG(3, ("%u entries returned in queue\n",
6078 (unsigned)count));
6080 out:
6081 if (b && is_valid_policy_hnd(&handle)) {
6082 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6087 END_PROFILE(SMBsplretq);
6088 return;
6091 /****************************************************************************
6092 Reply to a printwrite.
6093 ****************************************************************************/
6095 void reply_printwrite(struct smb_request *req)
6097 connection_struct *conn = req->conn;
6098 int numtowrite;
6099 const char *data;
6100 files_struct *fsp;
6101 NTSTATUS status;
6103 START_PROFILE(SMBsplwr);
6105 if (req->wct < 1) {
6106 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6107 END_PROFILE(SMBsplwr);
6108 return;
6111 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6113 if (!check_fsp(conn, req, fsp)) {
6114 END_PROFILE(SMBsplwr);
6115 return;
6118 if (!fsp->print_file) {
6119 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6120 END_PROFILE(SMBsplwr);
6121 return;
6124 status = check_any_access_fsp(fsp, FILE_WRITE_DATA|FILE_APPEND_DATA);
6125 if (!NT_STATUS_IS_OK(status)) {
6126 reply_nterror(req, status);
6127 END_PROFILE(SMBsplwr);
6128 return;
6131 numtowrite = SVAL(req->buf, 1);
6134 * This already protects us against CVE-2017-12163.
6136 if (req->buflen < numtowrite + 3) {
6137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6138 END_PROFILE(SMBsplwr);
6139 return;
6142 data = (const char *)req->buf + 3;
6144 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6145 reply_nterror(req, map_nt_error_from_unix(errno));
6146 END_PROFILE(SMBsplwr);
6147 return;
6150 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6152 reply_smb1_outbuf(req, 0, 0);
6154 END_PROFILE(SMBsplwr);
6155 return;
6158 /****************************************************************************
6159 Reply to a mkdir.
6160 ****************************************************************************/
6162 void reply_mkdir(struct smb_request *req)
6164 connection_struct *conn = req->conn;
6165 struct files_struct *dirfsp = NULL;
6166 struct smb_filename *smb_dname = NULL;
6167 char *directory = NULL;
6168 NTSTATUS status;
6169 uint32_t ucf_flags;
6170 NTTIME twrp = 0;
6171 TALLOC_CTX *ctx = talloc_tos();
6173 START_PROFILE(SMBmkdir);
6175 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6176 STR_TERMINATE, &status);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 reply_nterror(req, status);
6179 goto out;
6182 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6183 if (ucf_flags & UCF_GMT_PATHNAME) {
6184 extract_snapshot_token(directory, &twrp);
6186 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6187 if (!NT_STATUS_IS_OK(status)) {
6188 reply_nterror(req, status);
6189 goto out;
6192 status = filename_convert_dirfsp(ctx,
6193 conn,
6194 directory,
6195 ucf_flags,
6196 twrp,
6197 &dirfsp,
6198 &smb_dname);
6199 if (!NT_STATUS_IS_OK(status)) {
6200 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6201 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6202 ERRSRV, ERRbadpath);
6203 goto out;
6205 reply_nterror(req, status);
6206 goto out;
6209 status = create_directory(conn, req, dirfsp, smb_dname);
6211 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6213 if (!NT_STATUS_IS_OK(status)) {
6215 if (!use_nt_status()
6216 && NT_STATUS_EQUAL(status,
6217 NT_STATUS_OBJECT_NAME_COLLISION)) {
6219 * Yes, in the DOS error code case we get a
6220 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6221 * samba4 torture test.
6223 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6226 reply_nterror(req, status);
6227 goto out;
6230 reply_smb1_outbuf(req, 0, 0);
6232 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6233 out:
6234 TALLOC_FREE(smb_dname);
6235 END_PROFILE(SMBmkdir);
6236 return;
6239 /****************************************************************************
6240 Reply to a rmdir.
6241 ****************************************************************************/
6243 void reply_rmdir(struct smb_request *req)
6245 connection_struct *conn = req->conn;
6246 struct smb_filename *smb_dname = NULL;
6247 char *directory = NULL;
6248 NTSTATUS status;
6249 TALLOC_CTX *ctx = talloc_tos();
6250 struct files_struct *dirfsp = NULL;
6251 files_struct *fsp = NULL;
6252 int info = 0;
6253 NTTIME twrp = 0;
6254 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6256 START_PROFILE(SMBrmdir);
6258 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6259 STR_TERMINATE, &status);
6260 if (!NT_STATUS_IS_OK(status)) {
6261 reply_nterror(req, status);
6262 goto out;
6265 if (ucf_flags & UCF_GMT_PATHNAME) {
6266 extract_snapshot_token(directory, &twrp);
6268 status = smb1_strip_dfs_path(ctx, &ucf_flags, &directory);
6269 if (!NT_STATUS_IS_OK(status)) {
6270 reply_nterror(req, status);
6271 goto out;
6274 status = filename_convert_dirfsp(ctx,
6275 conn,
6276 directory,
6277 ucf_flags,
6278 twrp,
6279 &dirfsp,
6280 &smb_dname);
6281 if (!NT_STATUS_IS_OK(status)) {
6282 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6283 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6284 ERRSRV, ERRbadpath);
6285 goto out;
6287 reply_nterror(req, status);
6288 goto out;
6291 status = SMB_VFS_CREATE_FILE(
6292 conn, /* conn */
6293 req, /* req */
6294 dirfsp, /* dirfsp */
6295 smb_dname, /* fname */
6296 DELETE_ACCESS, /* access_mask */
6297 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6298 FILE_SHARE_DELETE),
6299 FILE_OPEN, /* create_disposition*/
6300 FILE_DIRECTORY_FILE |
6301 FILE_OPEN_REPARSE_POINT, /* create_options */
6302 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6303 0, /* oplock_request */
6304 NULL, /* lease */
6305 0, /* allocation_size */
6306 0, /* private_flags */
6307 NULL, /* sd */
6308 NULL, /* ea_list */
6309 &fsp, /* result */
6310 &info, /* pinfo */
6311 NULL, NULL); /* create context */
6313 if (!NT_STATUS_IS_OK(status)) {
6314 if (open_was_deferred(req->xconn, req->mid)) {
6315 /* We have re-scheduled this call. */
6316 goto out;
6318 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6319 bool ok = defer_smb1_sharing_violation(req);
6320 if (ok) {
6321 goto out;
6324 reply_nterror(req, status);
6325 goto out;
6328 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6329 if (!NT_STATUS_IS_OK(status)) {
6330 close_file_free(req, &fsp, ERROR_CLOSE);
6331 reply_nterror(req, status);
6332 goto out;
6335 if (!set_delete_on_close(fsp, true,
6336 conn->session_info->security_token,
6337 conn->session_info->unix_token)) {
6338 close_file_free(req, &fsp, ERROR_CLOSE);
6339 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6340 goto out;
6343 status = close_file_free(req, &fsp, NORMAL_CLOSE);
6344 if (!NT_STATUS_IS_OK(status)) {
6345 reply_nterror(req, status);
6346 } else {
6347 reply_smb1_outbuf(req, 0, 0);
6350 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6351 out:
6352 TALLOC_FREE(smb_dname);
6353 END_PROFILE(SMBrmdir);
6354 return;
6357 /****************************************************************************
6358 Reply to a mv.
6359 ****************************************************************************/
6361 void reply_mv(struct smb_request *req)
6363 connection_struct *conn = req->conn;
6364 char *name = NULL;
6365 char *newname = NULL;
6366 const char *p;
6367 uint32_t attrs;
6368 NTSTATUS status;
6369 TALLOC_CTX *ctx = talloc_tos();
6370 struct files_struct *src_dirfsp = NULL;
6371 struct smb_filename *smb_fname_src = NULL;
6372 struct files_struct *dst_dirfsp = NULL;
6373 struct smb_filename *smb_fname_dst = NULL;
6374 const char *dst_original_lcomp = NULL;
6375 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
6376 NTTIME src_twrp = 0;
6377 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
6378 NTTIME dst_twrp = 0;
6379 bool stream_rename = false;
6381 START_PROFILE(SMBmv);
6383 if (req->wct < 1) {
6384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6385 goto out;
6388 attrs = SVAL(req->vwv+0, 0);
6390 p = (const char *)req->buf + 1;
6391 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
6392 &status);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 reply_nterror(req, status);
6395 goto out;
6397 p++;
6398 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
6399 &status);
6400 if (!NT_STATUS_IS_OK(status)) {
6401 reply_nterror(req, status);
6402 goto out;
6405 if (!req->posix_pathnames) {
6406 /* The newname must begin with a ':' if the
6407 name contains a ':'. */
6408 if (strchr_m(name, ':')) {
6409 if (newname[0] != ':') {
6410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6411 goto out;
6413 stream_rename = true;
6417 if (src_ucf_flags & UCF_GMT_PATHNAME) {
6418 extract_snapshot_token(name, &src_twrp);
6420 status = smb1_strip_dfs_path(ctx, &src_ucf_flags, &name);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 reply_nterror(req, status);
6423 goto out;
6425 status = filename_convert_dirfsp(ctx,
6426 conn,
6427 name,
6428 src_ucf_flags,
6429 src_twrp,
6430 &src_dirfsp,
6431 &smb_fname_src);
6433 if (!NT_STATUS_IS_OK(status)) {
6434 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6435 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6436 ERRSRV, ERRbadpath);
6437 goto out;
6439 reply_nterror(req, status);
6440 goto out;
6443 if (dst_ucf_flags & UCF_GMT_PATHNAME) {
6444 extract_snapshot_token(newname, &dst_twrp);
6446 status = smb1_strip_dfs_path(ctx, &dst_ucf_flags, &newname);
6447 if (!NT_STATUS_IS_OK(status)) {
6448 reply_nterror(req, status);
6449 goto out;
6451 status = filename_convert_dirfsp(ctx,
6452 conn,
6453 newname,
6454 dst_ucf_flags,
6455 dst_twrp,
6456 &dst_dirfsp,
6457 &smb_fname_dst);
6459 if (!NT_STATUS_IS_OK(status)) {
6460 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6461 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6462 ERRSRV, ERRbadpath);
6463 goto out;
6465 reply_nterror(req, status);
6466 goto out;
6469 /* Get the last component of the destination for rename_internals(). */
6470 dst_original_lcomp = get_original_lcomp(ctx,
6471 conn,
6472 newname,
6473 dst_ucf_flags);
6474 if (dst_original_lcomp == NULL) {
6475 reply_nterror(req, NT_STATUS_NO_MEMORY);
6476 goto out;
6479 if (stream_rename) {
6480 /* smb_fname_dst->base_name must be the same as
6481 smb_fname_src->base_name. */
6482 TALLOC_FREE(smb_fname_dst->base_name);
6483 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6484 smb_fname_src->base_name);
6485 if (!smb_fname_dst->base_name) {
6486 reply_nterror(req, NT_STATUS_NO_MEMORY);
6487 goto out;
6491 DBG_NOTICE("%s -> %s\n",
6492 smb_fname_str_dbg(smb_fname_src),
6493 smb_fname_str_dbg(smb_fname_dst));
6495 status = rename_internals(ctx,
6496 conn,
6497 req,
6498 src_dirfsp, /* src_dirfsp */
6499 smb_fname_src,
6500 smb_fname_dst,
6501 dst_original_lcomp,
6502 attrs,
6503 false,
6504 DELETE_ACCESS);
6505 if (!NT_STATUS_IS_OK(status)) {
6506 if (open_was_deferred(req->xconn, req->mid)) {
6507 /* We have re-scheduled this call. */
6508 goto out;
6510 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6511 bool ok = defer_smb1_sharing_violation(req);
6512 if (ok) {
6513 goto out;
6516 reply_nterror(req, status);
6517 goto out;
6520 reply_smb1_outbuf(req, 0, 0);
6521 out:
6522 TALLOC_FREE(smb_fname_src);
6523 TALLOC_FREE(smb_fname_dst);
6524 END_PROFILE(SMBmv);
6525 return;
6528 /****************************************************************************
6529 Reply to a file copy.
6531 From MS-CIFS.
6533 This command was introduced in the LAN Manager 1.0 dialect
6534 It was rendered obsolete in the NT LAN Manager dialect.
6535 This command was used to perform server-side file copies, but
6536 is no longer used. Clients SHOULD
6537 NOT send requests using this command code.
6538 Servers receiving requests with this command code
6539 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6540 ****************************************************************************/
6542 void reply_copy(struct smb_request *req)
6544 START_PROFILE(SMBcopy);
6545 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
6546 END_PROFILE(SMBcopy);
6547 return;
6550 #undef DBGC_CLASS
6551 #define DBGC_CLASS DBGC_LOCKING
6553 /****************************************************************************
6554 Get a lock pid, dealing with large count requests.
6555 ****************************************************************************/
6557 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6558 bool large_file_format)
6560 if(!large_file_format)
6561 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6562 else
6563 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6566 /****************************************************************************
6567 Get a lock count, dealing with large count requests.
6568 ****************************************************************************/
6570 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6571 bool large_file_format)
6573 uint64_t count = 0;
6575 if(!large_file_format) {
6576 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6577 } else {
6579 * No BVAL, this is reversed!
6581 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6582 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6585 return count;
6588 /****************************************************************************
6589 Reply to a lockingX request.
6590 ****************************************************************************/
6592 static void reply_lockingx_done(struct tevent_req *subreq);
6594 void reply_lockingX(struct smb_request *req)
6596 connection_struct *conn = req->conn;
6597 files_struct *fsp;
6598 unsigned char locktype;
6599 enum brl_type brltype;
6600 unsigned char oplocklevel;
6601 uint16_t num_ulocks;
6602 uint16_t num_locks;
6603 int32_t lock_timeout;
6604 uint16_t i;
6605 const uint8_t *data;
6606 bool large_file_format;
6607 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6608 struct smbd_lock_element *locks = NULL;
6609 struct tevent_req *subreq = NULL;
6611 START_PROFILE(SMBlockingX);
6613 if (req->wct < 8) {
6614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6615 END_PROFILE(SMBlockingX);
6616 return;
6619 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6620 locktype = CVAL(req->vwv+3, 0);
6621 oplocklevel = CVAL(req->vwv+3, 1);
6622 num_ulocks = SVAL(req->vwv+6, 0);
6623 num_locks = SVAL(req->vwv+7, 0);
6624 lock_timeout = IVAL(req->vwv+4, 0);
6625 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
6627 if (!check_fsp(conn, req, fsp)) {
6628 END_PROFILE(SMBlockingX);
6629 return;
6632 data = req->buf;
6634 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6635 /* we don't support these - and CANCEL_LOCK makes w2k
6636 and XP reboot so I don't really want to be
6637 compatible! (tridge) */
6638 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
6639 END_PROFILE(SMBlockingX);
6640 return;
6643 /* Check if this is an oplock break on a file
6644 we have granted an oplock on.
6646 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
6647 /* Client can insist on breaking to none. */
6648 bool break_to_none = (oplocklevel == 0);
6649 bool result;
6651 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6652 "for %s\n", (unsigned int)oplocklevel,
6653 fsp_fnum_dbg(fsp)));
6656 * Make sure we have granted an exclusive or batch oplock on
6657 * this file.
6660 if (fsp->oplock_type == 0) {
6662 /* The Samba4 nbench simulator doesn't understand
6663 the difference between break to level2 and break
6664 to none from level2 - it sends oplock break
6665 replies in both cases. Don't keep logging an error
6666 message here - just ignore it. JRA. */
6668 DEBUG(5,("reply_lockingX: Error : oplock break from "
6669 "client for %s (oplock=%d) and no "
6670 "oplock granted on this file (%s).\n",
6671 fsp_fnum_dbg(fsp), fsp->oplock_type,
6672 fsp_str_dbg(fsp)));
6674 /* if this is a pure oplock break request then don't
6675 * send a reply */
6676 if (num_locks == 0 && num_ulocks == 0) {
6677 END_PROFILE(SMBlockingX);
6678 return;
6681 END_PROFILE(SMBlockingX);
6682 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6683 return;
6686 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6687 (break_to_none)) {
6688 result = remove_oplock(fsp);
6689 } else {
6690 result = downgrade_oplock(fsp);
6693 if (!result) {
6694 DEBUG(0, ("reply_lockingX: error in removing "
6695 "oplock on file %s\n", fsp_str_dbg(fsp)));
6696 /* Hmmm. Is this panic justified? */
6697 smb_panic("internal tdb error");
6700 /* if this is a pure oplock break request then don't send a
6701 * reply */
6702 if (num_locks == 0 && num_ulocks == 0) {
6703 /* Sanity check - ensure a pure oplock break is not a
6704 chained request. */
6705 if (CVAL(req->vwv+0, 0) != 0xff) {
6706 DEBUG(0,("reply_lockingX: Error : pure oplock "
6707 "break is a chained %d request !\n",
6708 (unsigned int)CVAL(req->vwv+0, 0)));
6710 END_PROFILE(SMBlockingX);
6711 return;
6715 if (req->buflen <
6716 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6718 END_PROFILE(SMBlockingX);
6719 return;
6722 if (num_ulocks != 0) {
6723 struct smbd_lock_element *ulocks = NULL;
6724 bool ok;
6726 ulocks = talloc_array(
6727 req, struct smbd_lock_element, num_ulocks);
6728 if (ulocks == NULL) {
6729 reply_nterror(req, NT_STATUS_NO_MEMORY);
6730 END_PROFILE(SMBlockingX);
6731 return;
6735 * Data now points at the beginning of the list of
6736 * smb_unlkrng structs
6738 for (i = 0; i < num_ulocks; i++) {
6739 ulocks[i].req_guid = smbd_request_guid(req,
6740 UINT16_MAX - i),
6741 ulocks[i].smblctx = get_lock_pid(
6742 data, i, large_file_format);
6743 ulocks[i].count = get_lock_count(
6744 data, i, large_file_format);
6745 ulocks[i].offset = get_lock_offset(
6746 data, i, large_file_format);
6747 ulocks[i].brltype = UNLOCK_LOCK;
6748 ulocks[i].lock_flav = WINDOWS_LOCK;
6752 * Unlock cancels pending locks
6755 ok = smbd_smb1_brl_finish_by_lock(
6756 fsp,
6757 large_file_format,
6758 ulocks[0],
6759 NT_STATUS_OK);
6760 if (ok) {
6761 reply_smb1_outbuf(req, 2, 0);
6762 SSVAL(req->outbuf, smb_vwv0, 0xff);
6763 SSVAL(req->outbuf, smb_vwv1, 0);
6764 END_PROFILE(SMBlockingX);
6765 return;
6768 status = smbd_do_unlocking(
6769 req, fsp, num_ulocks, ulocks);
6770 TALLOC_FREE(ulocks);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 END_PROFILE(SMBlockingX);
6773 reply_nterror(req, status);
6774 return;
6778 /* Now do any requested locks */
6779 data += ((large_file_format ? 20 : 10)*num_ulocks);
6781 /* Data now points at the beginning of the list
6782 of smb_lkrng structs */
6784 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
6785 brltype = READ_LOCK;
6786 } else {
6787 brltype = WRITE_LOCK;
6790 locks = talloc_array(req, struct smbd_lock_element, num_locks);
6791 if (locks == NULL) {
6792 reply_nterror(req, NT_STATUS_NO_MEMORY);
6793 END_PROFILE(SMBlockingX);
6794 return;
6797 for (i = 0; i < num_locks; i++) {
6798 locks[i].req_guid = smbd_request_guid(req, i),
6799 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
6800 locks[i].count = get_lock_count(data, i, large_file_format);
6801 locks[i].offset = get_lock_offset(data, i, large_file_format);
6802 locks[i].brltype = brltype;
6803 locks[i].lock_flav = WINDOWS_LOCK;
6806 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6808 bool ok;
6810 if (num_locks == 0) {
6811 /* See smbtorture3 lock11 test */
6812 reply_smb1_outbuf(req, 2, 0);
6813 /* andx chain ends */
6814 SSVAL(req->outbuf, smb_vwv0, 0xff);
6815 SSVAL(req->outbuf, smb_vwv1, 0);
6816 END_PROFILE(SMBlockingX);
6817 return;
6820 ok = smbd_smb1_brl_finish_by_lock(
6821 fsp,
6822 large_file_format,
6823 locks[0], /* Windows only cancels the first lock */
6824 NT_STATUS_FILE_LOCK_CONFLICT);
6826 if (!ok) {
6827 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
6828 END_PROFILE(SMBlockingX);
6829 return;
6832 reply_smb1_outbuf(req, 2, 0);
6833 SSVAL(req->outbuf, smb_vwv0, 0xff);
6834 SSVAL(req->outbuf, smb_vwv1, 0);
6835 END_PROFILE(SMBlockingX);
6836 return;
6839 subreq = smbd_smb1_do_locks_send(
6840 fsp,
6841 req->sconn->ev_ctx,
6842 &req,
6843 fsp,
6844 lock_timeout,
6845 large_file_format,
6846 num_locks,
6847 locks);
6848 if (subreq == NULL) {
6849 reply_nterror(req, NT_STATUS_NO_MEMORY);
6850 END_PROFILE(SMBlockingX);
6851 return;
6853 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
6854 END_PROFILE(SMBlockingX);
6857 static void reply_lockingx_done(struct tevent_req *subreq)
6859 struct smb_request *req = NULL;
6860 NTSTATUS status;
6861 bool ok;
6863 START_PROFILE(SMBlockingX);
6865 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6866 SMB_ASSERT(ok);
6868 status = smbd_smb1_do_locks_recv(subreq);
6869 TALLOC_FREE(subreq);
6871 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
6873 if (NT_STATUS_IS_OK(status)) {
6874 reply_smb1_outbuf(req, 2, 0);
6875 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
6876 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
6877 } else {
6878 reply_nterror(req, status);
6881 ok = smb1_srv_send(req->xconn,
6882 (char *)req->outbuf,
6883 true,
6884 req->seqnum + 1,
6885 IS_CONN_ENCRYPTED(req->conn));
6886 if (!ok) {
6887 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6889 TALLOC_FREE(req);
6890 END_PROFILE(SMBlockingX);
6893 #undef DBGC_CLASS
6894 #define DBGC_CLASS DBGC_ALL
6896 /****************************************************************************
6897 Reply to a SMBreadbmpx (read block multiplex) request.
6898 Always reply with an error, if someone has a platform really needs this,
6899 please contact vl@samba.org
6900 ****************************************************************************/
6902 void reply_readbmpx(struct smb_request *req)
6904 START_PROFILE(SMBreadBmpx);
6905 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6906 END_PROFILE(SMBreadBmpx);
6907 return;
6910 /****************************************************************************
6911 Reply to a SMBreadbs (read block multiplex secondary) request.
6912 Always reply with an error, if someone has a platform really needs this,
6913 please contact vl@samba.org
6914 ****************************************************************************/
6916 void reply_readbs(struct smb_request *req)
6918 START_PROFILE(SMBreadBs);
6919 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6920 END_PROFILE(SMBreadBs);
6921 return;
6924 /****************************************************************************
6925 Reply to a SMBsetattrE.
6926 ****************************************************************************/
6928 void reply_setattrE(struct smb_request *req)
6930 connection_struct *conn = req->conn;
6931 struct smb_file_time ft;
6932 files_struct *fsp;
6933 NTSTATUS status;
6935 START_PROFILE(SMBsetattrE);
6936 init_smb_file_time(&ft);
6938 if (req->wct < 7) {
6939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6940 goto out;
6943 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6945 if(!fsp || (fsp->conn != conn)) {
6946 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6947 goto out;
6951 * Convert the DOS times into unix times.
6954 ft.atime = time_t_to_full_timespec(
6955 srv_make_unix_date2(req->vwv+3));
6956 ft.mtime = time_t_to_full_timespec(
6957 srv_make_unix_date2(req->vwv+5));
6958 ft.create_time = time_t_to_full_timespec(
6959 srv_make_unix_date2(req->vwv+1));
6961 reply_smb1_outbuf(req, 0, 0);
6963 /* Ensure we have a valid stat struct for the source. */
6964 status = vfs_stat_fsp(fsp);
6965 if (!NT_STATUS_IS_OK(status)) {
6966 reply_nterror(req, status);
6967 goto out;
6970 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
6971 if (!NT_STATUS_IS_OK(status)) {
6972 reply_nterror(req, status);
6973 goto out;
6976 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
6977 if (!NT_STATUS_IS_OK(status)) {
6978 reply_nterror(req, status);
6979 goto out;
6982 if (fsp->fsp_flags.modified) {
6983 trigger_write_time_update_immediate(fsp);
6986 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6987 " createtime=%u\n",
6988 fsp_fnum_dbg(fsp),
6989 (unsigned int)ft.atime.tv_sec,
6990 (unsigned int)ft.mtime.tv_sec,
6991 (unsigned int)ft.create_time.tv_sec
6993 out:
6994 END_PROFILE(SMBsetattrE);
6995 return;
6999 /* Back from the dead for OS/2..... JRA. */
7001 /****************************************************************************
7002 Reply to a SMBwritebmpx (write block multiplex primary) request.
7003 Always reply with an error, if someone has a platform really needs this,
7004 please contact vl@samba.org
7005 ****************************************************************************/
7007 void reply_writebmpx(struct smb_request *req)
7009 START_PROFILE(SMBwriteBmpx);
7010 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7011 END_PROFILE(SMBwriteBmpx);
7012 return;
7015 /****************************************************************************
7016 Reply to a SMBwritebs (write block multiplex secondary) request.
7017 Always reply with an error, if someone has a platform really needs this,
7018 please contact vl@samba.org
7019 ****************************************************************************/
7021 void reply_writebs(struct smb_request *req)
7023 START_PROFILE(SMBwriteBs);
7024 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7025 END_PROFILE(SMBwriteBs);
7026 return;
7029 /****************************************************************************
7030 Reply to a SMBgetattrE.
7031 ****************************************************************************/
7033 void reply_getattrE(struct smb_request *req)
7035 connection_struct *conn = req->conn;
7036 int mode;
7037 files_struct *fsp;
7038 struct timespec create_ts;
7039 NTSTATUS status;
7041 START_PROFILE(SMBgetattrE);
7043 if (req->wct < 1) {
7044 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7045 END_PROFILE(SMBgetattrE);
7046 return;
7049 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7051 if(!fsp || (fsp->conn != conn)) {
7052 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7053 END_PROFILE(SMBgetattrE);
7054 return;
7057 /* Do an fstat on this file */
7058 status = vfs_stat_fsp(fsp);
7059 if (!NT_STATUS_IS_OK(status)) {
7060 reply_nterror(req, status);
7061 END_PROFILE(SMBgetattrE);
7062 return;
7065 mode = fdos_mode(fsp);
7068 * Convert the times into dos times. Set create
7069 * date to be last modify date as UNIX doesn't save
7070 * this.
7073 reply_smb1_outbuf(req, 11, 0);
7075 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7076 srv_put_dos_date2_ts((char *)req->outbuf, smb_vwv0, create_ts);
7077 srv_put_dos_date2_ts((char *)req->outbuf,
7078 smb_vwv2,
7079 fsp->fsp_name->st.st_ex_atime);
7080 /* Should we check pending modtime here ? JRA */
7081 srv_put_dos_date2_ts((char *)req->outbuf,
7082 smb_vwv4,
7083 fsp->fsp_name->st.st_ex_mtime);
7085 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7086 SIVAL(req->outbuf, smb_vwv6, 0);
7087 SIVAL(req->outbuf, smb_vwv8, 0);
7088 } else {
7089 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7090 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
7091 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7093 SSVAL(req->outbuf,smb_vwv10, mode);
7095 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
7097 END_PROFILE(SMBgetattrE);
7098 return;
7101 /****************************************************************************
7102 Reply to a SMBfindclose (stop trans2 directory search).
7103 ****************************************************************************/
7105 void reply_findclose(struct smb_request *req)
7107 int dptr_num;
7108 struct smbd_server_connection *sconn = req->sconn;
7109 files_struct *fsp = NULL;
7111 START_PROFILE(SMBfindclose);
7113 if (req->wct < 1) {
7114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7115 END_PROFILE(SMBfindclose);
7116 return;
7119 dptr_num = SVALS(req->vwv+0, 0);
7121 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7124 * OS/2 seems to use -1 to indicate "close all directories"
7125 * This has to mean on this specific connection struct.
7127 if (dptr_num == -1) {
7128 dptr_closecnum(req->conn);
7129 } else {
7130 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
7131 dptr_num = -1;
7132 if (fsp != NULL) {
7133 close_file_free(NULL, &fsp, NORMAL_CLOSE);
7137 reply_smb1_outbuf(req, 0, 0);
7139 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7141 END_PROFILE(SMBfindclose);
7142 return;
7145 /****************************************************************************
7146 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7147 ****************************************************************************/
7149 void reply_findnclose(struct smb_request *req)
7151 int dptr_num;
7153 START_PROFILE(SMBfindnclose);
7155 if (req->wct < 1) {
7156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7157 END_PROFILE(SMBfindnclose);
7158 return;
7161 dptr_num = SVAL(req->vwv+0, 0);
7163 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7165 /* We never give out valid handles for a
7166 findnotifyfirst - so any dptr_num is ok here.
7167 Just ignore it. */
7169 reply_smb1_outbuf(req, 0, 0);
7171 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7173 END_PROFILE(SMBfindnclose);
7174 return;