s3: libsmb: In cli_qpathinfo_send() (SMBtrans2:TRANSACT2_QPATHINFO) check for DFS...
[Samba.git] / source3 / smbd / smb1_reply.c
blob343b7ee2b4913ebed865019b9280d9c7c6dbb0e3
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
28 #include "libsmb/namequery.h"
29 #include "system/filesys.h"
30 #include "printing.h"
31 #include "locking/share_mode_lock.h"
32 #include "smbd/smbd.h"
33 #include "smbd/globals.h"
34 #include "smbd/smbXsrv_open.h"
35 #include "fake_file.h"
36 #include "rpc_client/rpc_client.h"
37 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
38 #include "rpc_client/cli_spoolss.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_server/rpc_ncacn_np.h"
41 #include "libcli/security/security.h"
42 #include "libsmb/nmblib.h"
43 #include "auth.h"
44 #include "smbprofile.h"
45 #include "../lib/tsocket/tsocket.h"
46 #include "lib/util/tevent_ntstatus.h"
47 #include "libcli/smb/smb_signing.h"
48 #include "lib/util/sys_rw_data.h"
49 #include "librpc/gen_ndr/open_files.h"
50 #include "libcli/smb/smb2_posix.h"
51 #include "lib/util/string_wrappers.h"
52 #include "source3/printing/rap_jobid.h"
53 #include "source3/lib/substitute.h"
55 /****************************************************************************
56 Reply to a tcon.
57 conn POINTER CAN BE NULL HERE !
58 ****************************************************************************/
60 void reply_tcon(struct smb_request *req)
62 connection_struct *conn = req->conn;
63 const char *service;
64 char *service_buf = NULL;
65 char *password = NULL;
66 char *dev = NULL;
67 int pwlen=0;
68 NTSTATUS nt_status;
69 const uint8_t *p;
70 const char *p2;
71 TALLOC_CTX *ctx = talloc_tos();
72 struct smbXsrv_connection *xconn = req->xconn;
73 NTTIME now = timeval_to_nttime(&req->request_time);
75 START_PROFILE(SMBtcon);
77 if (req->buflen < 4) {
78 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
79 END_PROFILE(SMBtcon);
80 return;
83 p = req->buf + 1;
84 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
85 p += 1;
86 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
87 p += pwlen+1;
88 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
89 p += 1;
91 if (service_buf == NULL || password == NULL || dev == NULL) {
92 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
93 END_PROFILE(SMBtcon);
94 return;
96 p2 = strrchr_m(service_buf,'\\');
97 if (p2) {
98 service = p2+1;
99 } else {
100 service = service_buf;
103 conn = make_connection(req, now, service, dev,
104 req->vuid,&nt_status);
105 req->conn = conn;
107 if (!conn) {
108 reply_nterror(req, nt_status);
109 END_PROFILE(SMBtcon);
110 return;
113 reply_smb1_outbuf(req, 2, 0);
114 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
115 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
116 SSVAL(req->outbuf,smb_tid,conn->cnum);
118 DEBUG(3,("tcon service=%s cnum=%d\n",
119 service, conn->cnum));
121 END_PROFILE(SMBtcon);
122 return;
125 /****************************************************************************
126 Reply to a tcon and X.
127 conn POINTER CAN BE NULL HERE !
128 ****************************************************************************/
130 void reply_tcon_and_X(struct smb_request *req)
132 const struct loadparm_substitution *lp_sub =
133 loadparm_s3_global_substitution();
134 connection_struct *conn = req->conn;
135 const char *service = NULL;
136 TALLOC_CTX *ctx = talloc_tos();
137 /* what the client thinks the device is */
138 char *client_devicetype = NULL;
139 /* what the server tells the client the share represents */
140 const char *server_devicetype;
141 NTSTATUS nt_status;
142 int passlen;
143 char *path = NULL;
144 const uint8_t *p;
145 const char *q;
146 uint16_t tcon_flags;
147 struct smbXsrv_session *session = NULL;
148 NTTIME now = timeval_to_nttime(&req->request_time);
149 bool session_key_updated = false;
150 uint16_t optional_support = 0;
151 struct smbXsrv_connection *xconn = req->xconn;
153 START_PROFILE(SMBtconX);
155 if (req->wct < 4) {
156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
157 END_PROFILE(SMBtconX);
158 return;
161 passlen = SVAL(req->vwv+3, 0);
162 tcon_flags = SVAL(req->vwv+2, 0);
164 /* we might have to close an old one */
165 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
166 struct smbXsrv_tcon *tcon;
167 NTSTATUS status;
169 tcon = conn->tcon;
170 req->conn = NULL;
171 conn = NULL;
174 * TODO: cancel all outstanding requests on the tcon
176 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
177 if (!NT_STATUS_IS_OK(status)) {
178 DEBUG(0, ("reply_tcon_and_X: "
179 "smbXsrv_tcon_disconnect() failed: %s\n",
180 nt_errstr(status)));
182 * If we hit this case, there is something completely
183 * wrong, so we better disconnect the transport connection.
185 END_PROFILE(SMBtconX);
186 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
187 return;
190 TALLOC_FREE(tcon);
192 * This tree id is gone. Make sure we can't re-use it
193 * by accident.
195 req->tid = 0;
198 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
199 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
200 END_PROFILE(SMBtconX);
201 return;
204 if (xconn->smb1.negprot.encrypted_passwords) {
205 p = req->buf + passlen;
206 } else {
207 p = req->buf + passlen + 1;
210 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
212 if (path == NULL) {
213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
214 END_PROFILE(SMBtconX);
215 return;
219 * the service name can be either: \\server\share
220 * or share directly like on the DELL PowerVault 705
222 if (*path=='\\') {
223 q = strchr_m(path+2,'\\');
224 if (!q) {
225 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
226 END_PROFILE(SMBtconX);
227 return;
229 service = q+1;
230 } else {
231 service = path;
234 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
235 &client_devicetype, p,
236 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
238 if (client_devicetype == NULL) {
239 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
240 END_PROFILE(SMBtconX);
241 return;
244 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
246 nt_status = smb1srv_session_lookup(xconn,
247 req->vuid, now, &session);
248 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
249 reply_force_doserror(req, ERRSRV, ERRbaduid);
250 END_PROFILE(SMBtconX);
251 return;
253 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
254 reply_nterror(req, nt_status);
255 END_PROFILE(SMBtconX);
256 return;
258 if (!NT_STATUS_IS_OK(nt_status)) {
259 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
260 END_PROFILE(SMBtconX);
261 return;
264 if (session->global->auth_session_info == NULL) {
265 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
266 END_PROFILE(SMBtconX);
267 return;
271 * If there is no application key defined yet
272 * we create one.
274 * This means we setup the application key on the
275 * first tcon that happens via the given session.
277 * Once the application key is defined, it does not
278 * change any more.
280 if (session->global->application_key_blob.length == 0 &&
281 smb2_signing_key_valid(session->global->signing_key))
283 struct smbXsrv_session *x = session;
284 struct auth_session_info *session_info =
285 session->global->auth_session_info;
286 uint8_t session_key[16];
288 ZERO_STRUCT(session_key);
289 memcpy(session_key, x->global->signing_key->blob.data,
290 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
293 * The application key is truncated/padded to 16 bytes
295 x->global->application_key_blob = data_blob_talloc(x->global,
296 session_key,
297 sizeof(session_key));
298 ZERO_STRUCT(session_key);
299 if (x->global->application_key_blob.data == NULL) {
300 reply_nterror(req, NT_STATUS_NO_MEMORY);
301 END_PROFILE(SMBtconX);
302 return;
304 talloc_keep_secret(x->global->application_key_blob.data);
306 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
307 NTSTATUS status;
309 status = smb1_key_derivation(x->global->application_key_blob.data,
310 x->global->application_key_blob.length,
311 x->global->application_key_blob.data);
312 if (!NT_STATUS_IS_OK(status)) {
313 DBG_ERR("smb1_key_derivation failed: %s\n",
314 nt_errstr(status));
315 END_PROFILE(SMBtconX);
316 return;
318 optional_support |= SMB_EXTENDED_SIGNATURES;
322 * Place the application key into the session_info
324 data_blob_clear_free(&session_info->session_key);
325 session_info->session_key = data_blob_dup_talloc(session_info,
326 x->global->application_key_blob);
327 if (session_info->session_key.data == NULL) {
328 data_blob_clear_free(&x->global->application_key_blob);
329 reply_nterror(req, NT_STATUS_NO_MEMORY);
330 END_PROFILE(SMBtconX);
331 return;
333 talloc_keep_secret(session_info->session_key.data);
334 session_key_updated = true;
337 conn = make_connection(req, now, service, client_devicetype,
338 req->vuid, &nt_status);
339 req->conn =conn;
341 if (!conn) {
342 if (session_key_updated) {
343 struct smbXsrv_session *x = session;
344 struct auth_session_info *session_info =
345 session->global->auth_session_info;
346 data_blob_clear_free(&x->global->application_key_blob);
347 data_blob_clear_free(&session_info->session_key);
349 reply_nterror(req, nt_status);
350 END_PROFILE(SMBtconX);
351 return;
354 if ( IS_IPC(conn) )
355 server_devicetype = "IPC";
356 else if ( IS_PRINT(conn) )
357 server_devicetype = "LPT1:";
358 else
359 server_devicetype = "A:";
361 if (get_Protocol() < PROTOCOL_NT1) {
362 reply_smb1_outbuf(req, 2, 0);
363 if (message_push_string(&req->outbuf, server_devicetype,
364 STR_TERMINATE|STR_ASCII) == -1) {
365 reply_nterror(req, NT_STATUS_NO_MEMORY);
366 END_PROFILE(SMBtconX);
367 return;
369 } else {
370 /* NT sets the fstype of IPC$ to the null string */
371 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
373 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
374 /* Return permissions. */
375 uint32_t perm1 = 0;
376 uint32_t perm2 = 0;
378 reply_smb1_outbuf(req, 7, 0);
380 if (IS_IPC(conn)) {
381 perm1 = FILE_ALL_ACCESS;
382 perm2 = FILE_ALL_ACCESS;
383 } else {
384 perm1 = conn->share_access;
387 SIVAL(req->outbuf, smb_vwv3, perm1);
388 SIVAL(req->outbuf, smb_vwv5, perm2);
389 } else {
390 reply_smb1_outbuf(req, 3, 0);
393 if ((message_push_string(&req->outbuf, server_devicetype,
394 STR_TERMINATE|STR_ASCII) == -1)
395 || (message_push_string(&req->outbuf, fstype,
396 STR_TERMINATE) == -1)) {
397 reply_nterror(req, NT_STATUS_NO_MEMORY);
398 END_PROFILE(SMBtconX);
399 return;
402 /* what does setting this bit do? It is set by NT4 and
403 may affect the ability to autorun mounted cdroms */
404 optional_support |= SMB_SUPPORT_SEARCH_BITS;
405 optional_support |=
406 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
408 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
409 DEBUG(2,("Serving %s as a Dfs root\n",
410 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
411 optional_support |= SMB_SHARE_IN_DFS;
414 SSVAL(req->outbuf, smb_vwv2, optional_support);
417 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
418 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
420 DEBUG(3,("tconX service=%s \n",
421 service));
423 /* set the incoming and outgoing tid to the just created one */
424 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
425 SSVAL(req->outbuf,smb_tid,conn->cnum);
427 END_PROFILE(SMBtconX);
429 req->tid = conn->cnum;
432 /****************************************************************************
433 Reply to an unknown type.
434 ****************************************************************************/
436 void reply_unknown_new(struct smb_request *req, uint8_t type)
438 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
439 smb_fn_name(type), type, type));
440 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
441 return;
444 /****************************************************************************
445 Reply to an ioctl.
446 conn POINTER CAN BE NULL HERE !
447 ****************************************************************************/
449 void reply_ioctl(struct smb_request *req)
451 const struct loadparm_substitution *lp_sub =
452 loadparm_s3_global_substitution();
453 connection_struct *conn = req->conn;
454 uint16_t device;
455 uint16_t function;
456 uint32_t ioctl_code;
457 int replysize;
458 char *p;
460 START_PROFILE(SMBioctl);
462 if (req->wct < 3) {
463 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
464 END_PROFILE(SMBioctl);
465 return;
468 device = SVAL(req->vwv+1, 0);
469 function = SVAL(req->vwv+2, 0);
470 ioctl_code = (device << 16) + function;
472 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
474 switch (ioctl_code) {
475 case IOCTL_QUERY_JOB_INFO:
476 replysize = 32;
477 break;
478 default:
479 reply_force_doserror(req, ERRSRV, ERRnosupport);
480 END_PROFILE(SMBioctl);
481 return;
484 reply_smb1_outbuf(req, 8, replysize+1);
485 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
486 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
487 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
488 p = smb_buf(req->outbuf);
489 memset(p, '\0', replysize+1); /* valgrind-safe. */
490 p += 1; /* Allow for alignment */
492 switch (ioctl_code) {
493 case IOCTL_QUERY_JOB_INFO:
495 NTSTATUS status;
496 size_t len = 0;
497 files_struct *fsp = file_fsp(
498 req, SVAL(req->vwv+0, 0));
499 if (!fsp) {
500 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
501 END_PROFILE(SMBioctl);
502 return;
504 /* Job number */
505 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
507 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
508 lp_netbios_name(), 15,
509 STR_TERMINATE|STR_ASCII, &len);
510 if (!NT_STATUS_IS_OK(status)) {
511 reply_nterror(req, status);
512 END_PROFILE(SMBioctl);
513 return;
515 if (conn) {
516 status = srvstr_push((char *)req->outbuf, req->flags2,
517 p+18,
518 lp_servicename(talloc_tos(),
519 lp_sub,
520 SNUM(conn)),
521 13, STR_TERMINATE|STR_ASCII, &len);
522 if (!NT_STATUS_IS_OK(status)) {
523 reply_nterror(req, status);
524 END_PROFILE(SMBioctl);
525 return;
527 } else {
528 memset(p+18, 0, 13);
530 break;
534 END_PROFILE(SMBioctl);
535 return;
538 /****************************************************************************
539 Strange checkpath NTSTATUS mapping.
540 ****************************************************************************/
542 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
544 /* Strange DOS error code semantics only for checkpath... */
545 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
546 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
547 /* We need to map to ERRbadpath */
548 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
551 return status;
554 /****************************************************************************
555 Reply to a checkpath.
556 ****************************************************************************/
558 void reply_checkpath(struct smb_request *req)
560 connection_struct *conn = req->conn;
561 struct smb_filename *smb_fname = NULL;
562 char *name = NULL;
563 NTSTATUS status;
564 struct files_struct *dirfsp = NULL;
565 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
566 NTTIME twrp = 0;
567 TALLOC_CTX *ctx = talloc_tos();
569 START_PROFILE(SMBcheckpath);
571 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
572 STR_TERMINATE, &status);
574 if (!NT_STATUS_IS_OK(status)) {
575 status = map_checkpath_error(req->flags2, status);
576 reply_nterror(req, status);
577 END_PROFILE(SMBcheckpath);
578 return;
581 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
583 if (ucf_flags & UCF_GMT_PATHNAME) {
584 extract_snapshot_token(name, &twrp);
586 status = filename_convert_dirfsp(ctx,
587 conn,
588 name,
589 ucf_flags,
590 twrp,
591 &dirfsp,
592 &smb_fname);
593 if (!NT_STATUS_IS_OK(status)) {
594 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
595 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
596 ERRSRV, ERRbadpath);
597 END_PROFILE(SMBcheckpath);
598 return;
600 goto path_err;
603 if (!VALID_STAT(smb_fname->st) &&
604 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
605 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
606 smb_fname_str_dbg(smb_fname), strerror(errno)));
607 status = map_nt_error_from_unix(errno);
608 goto path_err;
611 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
612 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
613 ERRDOS, ERRbadpath);
614 goto out;
617 reply_smb1_outbuf(req, 0, 0);
619 path_err:
620 /* We special case this - as when a Windows machine
621 is parsing a path is steps through the components
622 one at a time - if a component fails it expects
623 ERRbadpath, not ERRbadfile.
625 status = map_checkpath_error(req->flags2, status);
626 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
628 * Windows returns different error codes if
629 * the parent directory is valid but not the
630 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
631 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
632 * if the path is invalid.
634 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
635 ERRDOS, ERRbadpath);
636 goto out;
639 reply_nterror(req, status);
641 out:
642 TALLOC_FREE(smb_fname);
643 END_PROFILE(SMBcheckpath);
644 return;
647 /****************************************************************************
648 Reply to a getatr.
649 ****************************************************************************/
651 void reply_getatr(struct smb_request *req)
653 connection_struct *conn = req->conn;
654 struct smb_filename *smb_fname = NULL;
655 char *fname = NULL;
656 int mode=0;
657 off_t size=0;
658 time_t mtime=0;
659 const char *p;
660 NTSTATUS status;
661 TALLOC_CTX *ctx = talloc_tos();
662 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
664 START_PROFILE(SMBgetatr);
666 p = (const char *)req->buf + 1;
667 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
668 if (!NT_STATUS_IS_OK(status)) {
669 reply_nterror(req, status);
670 goto out;
674 * dos sometimes asks for a stat of "" - it returns a "hidden
675 * directory" under WfWg - weird!
677 if (*fname == '\0') {
678 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
679 if (!CAN_WRITE(conn)) {
680 mode |= FILE_ATTRIBUTE_READONLY;
682 size = 0;
683 mtime = 0;
684 } else {
685 struct files_struct *dirfsp = NULL;
686 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
687 NTTIME twrp = 0;
688 if (ucf_flags & UCF_GMT_PATHNAME) {
689 extract_snapshot_token(fname, &twrp);
691 status = filename_convert_dirfsp(ctx,
692 conn,
693 fname,
694 ucf_flags,
695 twrp,
696 &dirfsp,
697 &smb_fname);
698 if (!NT_STATUS_IS_OK(status)) {
699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
700 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
701 ERRSRV, ERRbadpath);
702 goto out;
704 reply_nterror(req, status);
705 goto out;
707 if (!VALID_STAT(smb_fname->st) &&
708 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
709 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
710 smb_fname_str_dbg(smb_fname),
711 strerror(errno)));
712 reply_nterror(req, map_nt_error_from_unix(errno));
713 goto out;
716 mode = fdos_mode(smb_fname->fsp);
717 size = smb_fname->st.st_ex_size;
719 if (ask_sharemode) {
720 struct timespec write_time_ts;
721 struct file_id fileid;
723 ZERO_STRUCT(write_time_ts);
724 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
725 get_file_infos(fileid, 0, NULL, &write_time_ts);
726 if (!is_omit_timespec(&write_time_ts)) {
727 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
731 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
732 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
733 size = 0;
737 reply_smb1_outbuf(req, 10, 0);
739 SSVAL(req->outbuf,smb_vwv0,mode);
740 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
741 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
742 } else {
743 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
745 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
747 if (get_Protocol() >= PROTOCOL_NT1) {
748 SSVAL(req->outbuf, smb_flg2,
749 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
752 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
753 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
755 out:
756 TALLOC_FREE(smb_fname);
757 TALLOC_FREE(fname);
758 END_PROFILE(SMBgetatr);
759 return;
762 /****************************************************************************
763 Reply to a setatr.
764 ****************************************************************************/
766 void reply_setatr(struct smb_request *req)
768 struct smb_file_time ft;
769 connection_struct *conn = req->conn;
770 struct smb_filename *smb_fname = NULL;
771 struct files_struct *dirfsp = NULL;
772 char *fname = NULL;
773 int mode;
774 time_t mtime;
775 const char *p;
776 NTSTATUS status;
777 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
778 NTTIME twrp = 0;
779 TALLOC_CTX *ctx = talloc_tos();
781 START_PROFILE(SMBsetatr);
782 init_smb_file_time(&ft);
784 if (req->wct < 2) {
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 goto out;
789 p = (const char *)req->buf + 1;
790 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
791 if (!NT_STATUS_IS_OK(status)) {
792 reply_nterror(req, status);
793 goto out;
796 if (ucf_flags & UCF_GMT_PATHNAME) {
797 extract_snapshot_token(fname, &twrp);
799 status = filename_convert_dirfsp(ctx,
800 conn,
801 fname,
802 ucf_flags,
803 twrp,
804 &dirfsp,
805 &smb_fname);
806 if (!NT_STATUS_IS_OK(status)) {
807 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
808 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
809 ERRSRV, ERRbadpath);
810 goto out;
812 reply_nterror(req, status);
813 goto out;
816 if (ISDOT(smb_fname->base_name)) {
818 * Not sure here is the right place to catch this
819 * condition. Might be moved to somewhere else later -- vl
821 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
822 goto out;
825 if (smb_fname->fsp == NULL) {
826 /* Can't set access rights on a symlink. */
827 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
828 goto out;
831 mode = SVAL(req->vwv+0, 0);
832 mtime = srv_make_unix_date3(req->vwv+1);
834 if (mode != FILE_ATTRIBUTE_NORMAL) {
835 if (VALID_STAT_OF_DIR(smb_fname->st))
836 mode |= FILE_ATTRIBUTE_DIRECTORY;
837 else
838 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
840 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
841 smb_fname->fsp,
842 false,
843 FILE_WRITE_ATTRIBUTES);
844 if (!NT_STATUS_IS_OK(status)) {
845 reply_nterror(req, status);
846 goto out;
849 if (file_set_dosmode(conn, smb_fname, mode, NULL,
850 false) != 0) {
851 reply_nterror(req, map_nt_error_from_unix(errno));
852 goto out;
856 ft.mtime = time_t_to_full_timespec(mtime);
858 status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
859 if (!NT_STATUS_IS_OK(status)) {
860 reply_nterror(req, status);
861 goto out;
864 reply_smb1_outbuf(req, 0, 0);
866 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
867 mode));
868 out:
869 TALLOC_FREE(smb_fname);
870 END_PROFILE(SMBsetatr);
871 return;
874 /****************************************************************************
875 Reply to a dskattr.
876 ****************************************************************************/
878 void reply_dskattr(struct smb_request *req)
880 connection_struct *conn = req->conn;
881 uint64_t ret;
882 uint64_t dfree,dsize,bsize;
883 struct smb_filename smb_fname;
884 START_PROFILE(SMBdskattr);
886 ZERO_STRUCT(smb_fname);
887 smb_fname.base_name = discard_const_p(char, ".");
889 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
890 reply_nterror(req, map_nt_error_from_unix(errno));
891 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
892 END_PROFILE(SMBdskattr);
893 return;
896 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
897 if (ret == (uint64_t)-1) {
898 reply_nterror(req, map_nt_error_from_unix(errno));
899 END_PROFILE(SMBdskattr);
900 return;
904 * Force max to fit in 16 bit fields.
906 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
907 dfree /= 2;
908 dsize /= 2;
909 bsize *= 2;
910 if (bsize > (WORDMAX*512)) {
911 bsize = (WORDMAX*512);
912 if (dsize > WORDMAX)
913 dsize = WORDMAX;
914 if (dfree > WORDMAX)
915 dfree = WORDMAX;
916 break;
920 reply_smb1_outbuf(req, 5, 0);
922 if (get_Protocol() <= PROTOCOL_LANMAN2) {
923 double total_space, free_space;
924 /* we need to scale this to a number that DOS6 can handle. We
925 use floating point so we can handle large drives on systems
926 that don't have 64 bit integers
928 we end up displaying a maximum of 2G to DOS systems
930 total_space = dsize * (double)bsize;
931 free_space = dfree * (double)bsize;
933 dsize = (uint64_t)((total_space+63*512) / (64*512));
934 dfree = (uint64_t)((free_space+63*512) / (64*512));
936 if (dsize > 0xFFFF) dsize = 0xFFFF;
937 if (dfree > 0xFFFF) dfree = 0xFFFF;
939 SSVAL(req->outbuf,smb_vwv0,dsize);
940 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
941 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
942 SSVAL(req->outbuf,smb_vwv3,dfree);
943 } else {
944 SSVAL(req->outbuf,smb_vwv0,dsize);
945 SSVAL(req->outbuf,smb_vwv1,bsize/512);
946 SSVAL(req->outbuf,smb_vwv2,512);
947 SSVAL(req->outbuf,smb_vwv3,dfree);
950 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
952 END_PROFILE(SMBdskattr);
953 return;
956 /****************************************************************************
957 Make a dir struct.
958 ****************************************************************************/
960 static bool make_dir_struct(TALLOC_CTX *ctx,
961 char *buf,
962 const char *mask,
963 const char *fname,
964 off_t size,
965 uint32_t mode,
966 time_t date,
967 bool uc)
969 char *p;
970 char *mask2 = talloc_strdup(ctx, mask);
972 if (!mask2) {
973 return False;
976 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
977 size = 0;
980 memset(buf+1,' ',11);
981 if ((p = strchr_m(mask2,'.')) != NULL) {
982 *p = 0;
983 push_ascii(buf+1,mask2,8, 0);
984 push_ascii(buf+9,p+1,3, 0);
985 *p = '.';
986 } else {
987 push_ascii(buf+1,mask2,11, 0);
990 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
991 SCVAL(buf,21,mode);
992 srv_put_dos_date(buf,22,date);
993 SSVAL(buf,26,size & 0xFFFF);
994 SSVAL(buf,28,(size >> 16)&0xFFFF);
995 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
996 Strange, but verified on W2K3. Needed for OS/2. JRA. */
997 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
998 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
999 return True;
1002 /****************************************************************************
1003 Reply to a search.
1004 Can be called from SMBsearch, SMBffirst or SMBfunique.
1005 ****************************************************************************/
1007 void reply_search(struct smb_request *req)
1009 connection_struct *conn = req->conn;
1010 char *path = NULL;
1011 char *mask = NULL;
1012 char *directory = NULL;
1013 struct smb_filename *smb_fname = NULL;
1014 char *fname = NULL;
1015 off_t size;
1016 uint32_t mode;
1017 struct timespec date;
1018 uint32_t dirtype;
1019 unsigned int numentries = 0;
1020 unsigned int maxentries = 0;
1021 bool finished = False;
1022 const char *p;
1023 int status_len;
1024 char status[21];
1025 int dptr_num= -1;
1026 bool check_descend = False;
1027 bool expect_close = False;
1028 NTSTATUS nt_status;
1029 bool mask_contains_wcard = False;
1030 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1031 TALLOC_CTX *ctx = talloc_tos();
1032 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1033 struct smbXsrv_connection *xconn = req->xconn;
1034 struct smbd_server_connection *sconn = req->sconn;
1035 files_struct *fsp = NULL;
1036 const struct loadparm_substitution *lp_sub =
1037 loadparm_s3_global_substitution();
1039 START_PROFILE(SMBsearch);
1041 if (req->wct < 2) {
1042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1043 goto out;
1046 if (req->posix_pathnames) {
1047 reply_unknown_new(req, req->cmd);
1048 goto out;
1051 /* If we were called as SMBffirst then we must expect close. */
1052 if(req->cmd == SMBffirst) {
1053 expect_close = True;
1056 reply_smb1_outbuf(req, 1, 3);
1057 maxentries = SVAL(req->vwv+0, 0);
1058 dirtype = SVAL(req->vwv+1, 0);
1059 p = (const char *)req->buf + 1;
1060 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1061 &nt_status);
1062 if (!NT_STATUS_IS_OK(nt_status)) {
1063 reply_nterror(req, nt_status);
1064 goto out;
1067 if (smbreq_bufrem(req, p) < 3) {
1068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1069 goto out;
1072 p++;
1073 status_len = SVAL(p, 0);
1074 p += 2;
1076 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1078 if (status_len == 0) {
1079 const char *dirpath;
1080 struct files_struct *dirfsp = NULL;
1081 struct smb_filename *smb_dname = NULL;
1082 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1084 nt_status = filename_convert_smb1_search_path(ctx,
1085 conn,
1086 path,
1087 ucf_flags,
1088 &dirfsp,
1089 &smb_dname,
1090 &mask);
1092 if (!NT_STATUS_IS_OK(nt_status)) {
1093 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1094 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1095 ERRSRV, ERRbadpath);
1096 goto out;
1098 reply_nterror(req, nt_status);
1099 goto out;
1102 memset((char *)status,'\0',21);
1103 SCVAL(status,0,(dirtype & 0x1F));
1106 * Open an fsp on this directory for the dptr.
1108 nt_status = SMB_VFS_CREATE_FILE(
1109 conn, /* conn */
1110 req, /* req */
1111 dirfsp, /* dirfsp */
1112 smb_dname, /* dname */
1113 FILE_LIST_DIRECTORY, /* access_mask */
1114 FILE_SHARE_READ|
1115 FILE_SHARE_WRITE, /* share_access */
1116 FILE_OPEN, /* create_disposition*/
1117 FILE_DIRECTORY_FILE, /* create_options */
1118 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1119 NO_OPLOCK, /* oplock_request */
1120 NULL, /* lease */
1121 0, /* allocation_size */
1122 0, /* private_flags */
1123 NULL, /* sd */
1124 NULL, /* ea_list */
1125 &fsp, /* result */
1126 NULL, /* pinfo */
1127 NULL, /* in_context */
1128 NULL);/* out_context */
1130 if (!NT_STATUS_IS_OK(nt_status)) {
1131 DBG_ERR("failed to open directory %s\n",
1132 smb_fname_str_dbg(smb_dname));
1133 reply_nterror(req, nt_status);
1134 goto out;
1137 nt_status = dptr_create(conn,
1138 NULL, /* req */
1139 fsp, /* fsp */
1140 True,
1141 expect_close,
1142 req->smbpid,
1143 mask,
1144 dirtype,
1145 &fsp->dptr);
1147 TALLOC_FREE(smb_dname);
1149 if (!NT_STATUS_IS_OK(nt_status)) {
1151 * Use NULL here for the first parameter (req)
1152 * as this is not a client visible handle so
1153 * can'tbe part of an SMB1 chain.
1155 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1156 reply_nterror(req, nt_status);
1157 goto out;
1160 dptr_num = dptr_dnum(fsp->dptr);
1161 dirpath = dptr_path(sconn, dptr_num);
1162 directory = talloc_strdup(ctx, dirpath);
1163 if (!directory) {
1164 reply_nterror(req, NT_STATUS_NO_MEMORY);
1165 goto out;
1168 } else {
1169 int status_dirtype;
1170 const char *dirpath;
1172 if (smbreq_bufrem(req, p) < 21) {
1173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1174 goto out;
1177 memcpy(status,p,21);
1178 status_dirtype = CVAL(status,0) & 0x1F;
1179 if (status_dirtype != (dirtype & 0x1F)) {
1180 dirtype = status_dirtype;
1183 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1184 if (fsp == NULL) {
1185 goto SearchEmpty;
1187 dirpath = dptr_path(sconn, dptr_num);
1188 directory = talloc_strdup(ctx, dirpath);
1189 if (!directory) {
1190 reply_nterror(req, NT_STATUS_NO_MEMORY);
1191 goto out;
1194 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1195 if (!mask) {
1196 goto SearchEmpty;
1198 dirtype = dptr_attr(sconn, dptr_num);
1201 mask_contains_wcard = dptr_has_wild(fsp->dptr);
1203 DEBUG(4,("dptr_num is %d\n",dptr_num));
1205 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1206 char buf[DIR_STRUCT_SIZE];
1207 memcpy(buf,status,21);
1208 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1209 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1210 reply_nterror(req, NT_STATUS_NO_MEMORY);
1211 goto out;
1213 dptr_fill(sconn, buf+12,dptr_num);
1214 if (dptr_zero(buf+12) && (status_len==0)) {
1215 numentries = 1;
1216 } else {
1217 numentries = 0;
1219 if (message_push_blob(&req->outbuf,
1220 data_blob_const(buf, sizeof(buf)))
1221 == -1) {
1222 reply_nterror(req, NT_STATUS_NO_MEMORY);
1223 goto out;
1225 } else {
1226 unsigned int i;
1227 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1228 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1230 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1232 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1233 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1234 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1235 check_descend = True;
1238 for (i=numentries;(i<maxentries) && !finished;i++) {
1239 finished = !get_dir_entry(ctx,
1240 fsp->dptr,
1241 mask,
1242 dirtype,
1243 &fname,
1244 &size,
1245 &mode,
1246 &date,
1247 check_descend,
1248 ask_sharemode);
1249 if (!finished) {
1250 char buf[DIR_STRUCT_SIZE];
1251 memcpy(buf,status,21);
1252 if (!make_dir_struct(ctx,
1253 buf,
1254 mask,
1255 fname,
1256 size,
1257 mode,
1258 convert_timespec_to_time_t(date),
1259 !allow_long_path_components)) {
1260 reply_nterror(req, NT_STATUS_NO_MEMORY);
1261 goto out;
1263 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1264 break;
1266 if (message_push_blob(&req->outbuf,
1267 data_blob_const(buf, sizeof(buf)))
1268 == -1) {
1269 reply_nterror(req, NT_STATUS_NO_MEMORY);
1270 goto out;
1272 numentries++;
1277 SearchEmpty:
1279 /* If we were called as SMBffirst with smb_search_id == NULL
1280 and no entries were found then return error and close fsp->dptr
1281 (X/Open spec) */
1283 if (numentries == 0) {
1284 dptr_num = -1;
1285 if (fsp != NULL) {
1286 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1288 } else if(expect_close && status_len == 0) {
1289 /* Close the dptr - we know it's gone */
1290 dptr_num = -1;
1291 if (fsp != NULL) {
1292 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1296 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1297 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1298 dptr_num = -1;
1299 /* fsp may have been closed above. */
1300 if (fsp != NULL) {
1301 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1305 if ((numentries == 0) && !mask_contains_wcard) {
1306 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1307 goto out;
1310 SSVAL(req->outbuf,smb_vwv0,numentries);
1311 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1312 SCVAL(smb_buf(req->outbuf),0,5);
1313 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1315 /* The replies here are never long name. */
1316 SSVAL(req->outbuf, smb_flg2,
1317 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1318 if (!allow_long_path_components) {
1319 SSVAL(req->outbuf, smb_flg2,
1320 SVAL(req->outbuf, smb_flg2)
1321 & (~FLAGS2_LONG_PATH_COMPONENTS));
1324 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1325 SSVAL(req->outbuf, smb_flg2,
1326 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1328 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1329 smb_fn_name(req->cmd),
1330 mask,
1331 directory,
1332 dirtype,
1333 numentries,
1334 maxentries ));
1335 out:
1336 TALLOC_FREE(directory);
1337 TALLOC_FREE(mask);
1338 TALLOC_FREE(smb_fname);
1339 END_PROFILE(SMBsearch);
1340 return;
1343 /****************************************************************************
1344 Reply to a fclose (stop directory search).
1345 ****************************************************************************/
1347 void reply_fclose(struct smb_request *req)
1349 int status_len;
1350 char status[21];
1351 int dptr_num= -2;
1352 const char *p;
1353 char *path = NULL;
1354 NTSTATUS err;
1355 TALLOC_CTX *ctx = talloc_tos();
1356 struct smbd_server_connection *sconn = req->sconn;
1357 files_struct *fsp = NULL;
1359 START_PROFILE(SMBfclose);
1361 if (req->posix_pathnames) {
1362 reply_unknown_new(req, req->cmd);
1363 END_PROFILE(SMBfclose);
1364 return;
1367 p = (const char *)req->buf + 1;
1368 p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1369 &err);
1370 if (!NT_STATUS_IS_OK(err)) {
1371 reply_nterror(req, err);
1372 END_PROFILE(SMBfclose);
1373 return;
1376 if (smbreq_bufrem(req, p) < 3) {
1377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1378 END_PROFILE(SMBfclose);
1379 return;
1382 p++;
1383 status_len = SVAL(p,0);
1384 p += 2;
1386 if (status_len == 0) {
1387 reply_force_doserror(req, ERRSRV, ERRsrverror);
1388 END_PROFILE(SMBfclose);
1389 return;
1392 if (smbreq_bufrem(req, p) < 21) {
1393 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1394 END_PROFILE(SMBfclose);
1395 return;
1398 memcpy(status,p,21);
1400 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1401 if(fsp != NULL) {
1402 /* Close the file - we know it's gone */
1403 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1404 dptr_num = -1;
1407 reply_smb1_outbuf(req, 1, 0);
1408 SSVAL(req->outbuf,smb_vwv0,0);
1410 DEBUG(3,("search close\n"));
1412 END_PROFILE(SMBfclose);
1413 return;
1416 /****************************************************************************
1417 Reply to an open.
1418 ****************************************************************************/
1420 void reply_open(struct smb_request *req)
1422 connection_struct *conn = req->conn;
1423 struct smb_filename *smb_fname = NULL;
1424 char *fname = NULL;
1425 uint32_t fattr=0;
1426 off_t size = 0;
1427 time_t mtime=0;
1428 int info;
1429 struct files_struct *dirfsp = NULL;
1430 files_struct *fsp;
1431 int oplock_request;
1432 int deny_mode;
1433 uint32_t dos_attr;
1434 uint32_t access_mask;
1435 uint32_t share_mode;
1436 uint32_t create_disposition;
1437 uint32_t create_options = 0;
1438 uint32_t private_flags = 0;
1439 NTSTATUS status;
1440 uint32_t ucf_flags;
1441 NTTIME twrp = 0;
1442 TALLOC_CTX *ctx = talloc_tos();
1444 START_PROFILE(SMBopen);
1446 if (req->wct < 2) {
1447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1448 goto out;
1451 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1452 deny_mode = SVAL(req->vwv+0, 0);
1453 dos_attr = SVAL(req->vwv+1, 0);
1455 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1456 STR_TERMINATE, &status);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 reply_nterror(req, status);
1459 goto out;
1462 if (!map_open_params_to_ntcreate(fname, deny_mode,
1463 OPENX_FILE_EXISTS_OPEN, &access_mask,
1464 &share_mode, &create_disposition,
1465 &create_options, &private_flags)) {
1466 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1467 goto out;
1470 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1472 if (ucf_flags & UCF_GMT_PATHNAME) {
1473 extract_snapshot_token(fname, &twrp);
1475 status = filename_convert_dirfsp(ctx,
1476 conn,
1477 fname,
1478 ucf_flags,
1479 twrp,
1480 &dirfsp,
1481 &smb_fname);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1484 reply_botherror(req,
1485 NT_STATUS_PATH_NOT_COVERED,
1486 ERRSRV, ERRbadpath);
1487 goto out;
1489 reply_nterror(req, status);
1490 goto out;
1493 status = SMB_VFS_CREATE_FILE(
1494 conn, /* conn */
1495 req, /* req */
1496 dirfsp, /* dirfsp */
1497 smb_fname, /* fname */
1498 access_mask, /* access_mask */
1499 share_mode, /* share_access */
1500 create_disposition, /* create_disposition*/
1501 create_options, /* create_options */
1502 dos_attr, /* file_attributes */
1503 oplock_request, /* oplock_request */
1504 NULL, /* lease */
1505 0, /* allocation_size */
1506 private_flags,
1507 NULL, /* sd */
1508 NULL, /* ea_list */
1509 &fsp, /* result */
1510 &info, /* pinfo */
1511 NULL, NULL); /* create context */
1513 if (!NT_STATUS_IS_OK(status)) {
1514 if (open_was_deferred(req->xconn, req->mid)) {
1515 /* We have re-scheduled this call. */
1516 goto out;
1519 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1520 reply_openerror(req, status);
1521 goto out;
1524 fsp = fcb_or_dos_open(
1525 req,
1526 smb_fname,
1527 access_mask,
1528 create_options,
1529 private_flags);
1530 if (fsp == NULL) {
1531 bool ok = defer_smb1_sharing_violation(req);
1532 if (ok) {
1533 goto out;
1535 reply_openerror(req, status);
1536 goto out;
1540 /* Ensure we're pointing at the correct stat struct. */
1541 TALLOC_FREE(smb_fname);
1542 smb_fname = fsp->fsp_name;
1544 size = smb_fname->st.st_ex_size;
1545 fattr = fdos_mode(fsp);
1547 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1549 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1550 DEBUG(3,("attempt to open a directory %s\n",
1551 fsp_str_dbg(fsp)));
1552 close_file_free(req, &fsp, ERROR_CLOSE);
1553 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1554 ERRDOS, ERRnoaccess);
1555 goto out;
1558 reply_smb1_outbuf(req, 7, 0);
1559 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1560 SSVAL(req->outbuf,smb_vwv1,fattr);
1561 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1562 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1563 } else {
1564 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1566 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1567 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1569 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1570 SCVAL(req->outbuf,smb_flg,
1571 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1574 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1575 SCVAL(req->outbuf,smb_flg,
1576 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1578 out:
1579 END_PROFILE(SMBopen);
1580 return;
1583 /****************************************************************************
1584 Reply to an open and X.
1585 ****************************************************************************/
1587 void reply_open_and_X(struct smb_request *req)
1589 connection_struct *conn = req->conn;
1590 struct smb_filename *smb_fname = NULL;
1591 char *fname = NULL;
1592 uint16_t open_flags;
1593 int deny_mode;
1594 uint32_t smb_attr;
1595 /* Breakout the oplock request bits so we can set the
1596 reply bits separately. */
1597 int ex_oplock_request;
1598 int core_oplock_request;
1599 int oplock_request;
1600 #if 0
1601 int smb_sattr = SVAL(req->vwv+4, 0);
1602 uint32_t smb_time = make_unix_date3(req->vwv+6);
1603 #endif
1604 int smb_ofun;
1605 uint32_t fattr=0;
1606 int mtime=0;
1607 int smb_action = 0;
1608 struct files_struct *dirfsp = NULL;
1609 files_struct *fsp;
1610 NTSTATUS status;
1611 uint64_t allocation_size;
1612 ssize_t retval = -1;
1613 uint32_t access_mask;
1614 uint32_t share_mode;
1615 uint32_t create_disposition;
1616 uint32_t create_options = 0;
1617 uint32_t private_flags = 0;
1618 uint32_t ucf_flags;
1619 NTTIME twrp = 0;
1620 TALLOC_CTX *ctx = talloc_tos();
1622 START_PROFILE(SMBopenX);
1624 if (req->wct < 15) {
1625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1626 goto out;
1629 open_flags = SVAL(req->vwv+2, 0);
1630 deny_mode = SVAL(req->vwv+3, 0);
1631 smb_attr = SVAL(req->vwv+5, 0);
1632 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1633 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1634 oplock_request = ex_oplock_request | core_oplock_request;
1635 smb_ofun = SVAL(req->vwv+8, 0);
1636 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1638 /* If it's an IPC, pass off the pipe handler. */
1639 if (IS_IPC(conn)) {
1640 if (lp_nt_pipe_support()) {
1641 reply_open_pipe_and_X(conn, req);
1642 } else {
1643 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1645 goto out;
1648 /* XXXX we need to handle passed times, sattr and flags */
1649 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1650 STR_TERMINATE, &status);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 reply_nterror(req, status);
1653 goto out;
1656 if (!map_open_params_to_ntcreate(fname, deny_mode,
1657 smb_ofun,
1658 &access_mask, &share_mode,
1659 &create_disposition,
1660 &create_options,
1661 &private_flags)) {
1662 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1663 goto out;
1666 ucf_flags = filename_create_ucf_flags(req, create_disposition);
1668 if (ucf_flags & UCF_GMT_PATHNAME) {
1669 extract_snapshot_token(fname, &twrp);
1672 status = filename_convert_dirfsp(ctx,
1673 conn,
1674 fname,
1675 ucf_flags,
1676 twrp,
1677 &dirfsp,
1678 &smb_fname);
1679 if (!NT_STATUS_IS_OK(status)) {
1680 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1681 reply_botherror(req,
1682 NT_STATUS_PATH_NOT_COVERED,
1683 ERRSRV, ERRbadpath);
1684 goto out;
1686 reply_nterror(req, status);
1687 goto out;
1690 status = SMB_VFS_CREATE_FILE(
1691 conn, /* conn */
1692 req, /* req */
1693 dirfsp, /* dirfsp */
1694 smb_fname, /* fname */
1695 access_mask, /* access_mask */
1696 share_mode, /* share_access */
1697 create_disposition, /* create_disposition*/
1698 create_options, /* create_options */
1699 smb_attr, /* file_attributes */
1700 oplock_request, /* oplock_request */
1701 NULL, /* lease */
1702 0, /* allocation_size */
1703 private_flags,
1704 NULL, /* sd */
1705 NULL, /* ea_list */
1706 &fsp, /* result */
1707 &smb_action, /* pinfo */
1708 NULL, NULL); /* create context */
1710 if (!NT_STATUS_IS_OK(status)) {
1711 if (open_was_deferred(req->xconn, req->mid)) {
1712 /* We have re-scheduled this call. */
1713 goto out;
1716 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1717 reply_openerror(req, status);
1718 goto out;
1721 fsp = fcb_or_dos_open(
1722 req,
1723 smb_fname,
1724 access_mask,
1725 create_options,
1726 private_flags);
1727 if (fsp == NULL) {
1728 bool ok = defer_smb1_sharing_violation(req);
1729 if (ok) {
1730 goto out;
1732 reply_openerror(req, status);
1733 goto out;
1737 smb_action = FILE_WAS_OPENED;
1740 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1741 if the file is truncated or created. */
1742 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1743 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1744 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1745 close_file_free(req, &fsp, ERROR_CLOSE);
1746 reply_nterror(req, NT_STATUS_DISK_FULL);
1747 goto out;
1749 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1750 if (retval < 0) {
1751 close_file_free(req, &fsp, ERROR_CLOSE);
1752 reply_nterror(req, NT_STATUS_DISK_FULL);
1753 goto out;
1755 status = vfs_stat_fsp(fsp);
1756 if (!NT_STATUS_IS_OK(status)) {
1757 close_file_free(req, &fsp, ERROR_CLOSE);
1758 reply_nterror(req, status);
1759 goto out;
1763 fattr = fdos_mode(fsp);
1764 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1765 close_file_free(req, &fsp, ERROR_CLOSE);
1766 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1767 goto out;
1769 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
1771 /* If the caller set the extended oplock request bit
1772 and we granted one (by whatever means) - set the
1773 correct bit for extended oplock reply.
1776 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1777 smb_action |= EXTENDED_OPLOCK_GRANTED;
1780 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1781 smb_action |= EXTENDED_OPLOCK_GRANTED;
1784 /* If the caller set the core oplock request bit
1785 and we granted one (by whatever means) - set the
1786 correct bit for core oplock reply.
1789 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1790 reply_smb1_outbuf(req, 19, 0);
1791 } else {
1792 reply_smb1_outbuf(req, 15, 0);
1795 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1796 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1798 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1799 SCVAL(req->outbuf, smb_flg,
1800 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1803 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1804 SCVAL(req->outbuf, smb_flg,
1805 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1809 SSVAL(req->outbuf,smb_vwv3,fattr);
1810 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1811 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1812 } else {
1813 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1815 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
1816 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1817 SSVAL(req->outbuf,smb_vwv11,smb_action);
1819 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1820 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
1823 out:
1824 TALLOC_FREE(smb_fname);
1825 END_PROFILE(SMBopenX);
1826 return;
1829 /****************************************************************************
1830 Reply to a SMBulogoffX.
1831 ****************************************************************************/
1833 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1834 struct smbXsrv_session *session);
1835 static void reply_ulogoffX_done(struct tevent_req *req);
1837 void reply_ulogoffX(struct smb_request *smb1req)
1839 struct timeval now = timeval_current();
1840 struct smbXsrv_session *session = NULL;
1841 struct tevent_req *req;
1842 NTSTATUS status;
1845 * Don't setup the profile charge here, take
1846 * it in reply_ulogoffX_done(). Not strictly correct
1847 * but better than the other SMB1 async
1848 * code that double-charges at the moment.
1851 status = smb1srv_session_lookup(smb1req->xconn,
1852 smb1req->vuid,
1853 timeval_to_nttime(&now),
1854 &session);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 /* Not going async, profile here. */
1857 START_PROFILE(SMBulogoffX);
1858 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
1859 (unsigned long long)smb1req->vuid);
1861 smb1req->vuid = UID_FIELD_INVALID;
1862 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
1863 END_PROFILE(SMBulogoffX);
1864 return;
1867 req = reply_ulogoffX_send(smb1req, session);
1868 if (req == NULL) {
1869 /* Not going async, profile here. */
1870 START_PROFILE(SMBulogoffX);
1871 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
1872 END_PROFILE(SMBulogoffX);
1873 return;
1876 /* We're async. This will complete later. */
1877 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
1878 return;
1881 struct reply_ulogoffX_state {
1882 struct tevent_queue *wait_queue;
1883 struct smbXsrv_session *session;
1886 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
1888 /****************************************************************************
1889 Async SMB1 ulogoffX.
1890 Note, on failure here we deallocate and return NULL to allow the caller to
1891 SMB1 return an error of ERRnomem immediately.
1892 ****************************************************************************/
1894 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1895 struct smbXsrv_session *session)
1897 struct tevent_req *req;
1898 struct reply_ulogoffX_state *state;
1899 struct tevent_req *subreq;
1900 files_struct *fsp;
1901 struct smbd_server_connection *sconn = session->client->sconn;
1902 uint64_t vuid = session->global->session_wire_id;
1904 req = tevent_req_create(smb1req, &state,
1905 struct reply_ulogoffX_state);
1906 if (req == NULL) {
1907 return NULL;
1909 state->wait_queue = tevent_queue_create(state,
1910 "reply_ulogoffX_wait_queue");
1911 if (tevent_req_nomem(state->wait_queue, req)) {
1912 TALLOC_FREE(req);
1913 return NULL;
1915 state->session = session;
1918 * Make sure that no new request will be able to use this session.
1919 * This ensures that once all outstanding fsp->aio_requests
1920 * on this session are done, we are safe to close it.
1922 session->status = NT_STATUS_USER_SESSION_DELETED;
1924 for (fsp = sconn->files; fsp; fsp = fsp->next) {
1925 if (fsp->vuid != vuid) {
1926 continue;
1929 * Flag the file as close in progress.
1930 * This will prevent any more IO being
1931 * done on it.
1933 fsp->fsp_flags.closing = true;
1935 if (fsp->num_aio_requests > 0) {
1937 * Now wait until all aio requests on this fsp are
1938 * finished.
1940 * We don't set a callback, as we just want to block the
1941 * wait queue and the talloc_free() of fsp->aio_request
1942 * will remove the item from the wait queue.
1944 subreq = tevent_queue_wait_send(fsp->aio_requests,
1945 sconn->ev_ctx,
1946 state->wait_queue);
1947 if (tevent_req_nomem(subreq, req)) {
1948 TALLOC_FREE(req);
1949 return NULL;
1955 * Now we add our own waiter to the end of the queue,
1956 * this way we get notified when all pending requests are finished
1957 * and reply to the outstanding SMB1 request.
1959 subreq = tevent_queue_wait_send(state,
1960 sconn->ev_ctx,
1961 state->wait_queue);
1962 if (tevent_req_nomem(subreq, req)) {
1963 TALLOC_FREE(req);
1964 return NULL;
1968 * We're really going async - move the SMB1 request from
1969 * a talloc stackframe above us to the sconn talloc-context.
1970 * We need this to stick around until the wait_done
1971 * callback is invoked.
1973 smb1req = talloc_move(sconn, &smb1req);
1975 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
1977 return req;
1980 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
1982 struct tevent_req *req = tevent_req_callback_data(
1983 subreq, struct tevent_req);
1985 tevent_queue_wait_recv(subreq);
1986 TALLOC_FREE(subreq);
1987 tevent_req_done(req);
1990 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
1992 return tevent_req_simple_recv_ntstatus(req);
1995 static void reply_ulogoffX_done(struct tevent_req *req)
1997 struct smb_request *smb1req = tevent_req_callback_data(
1998 req, struct smb_request);
1999 struct reply_ulogoffX_state *state = tevent_req_data(req,
2000 struct reply_ulogoffX_state);
2001 struct smbXsrv_session *session = state->session;
2002 NTSTATUS status;
2005 * Take the profile charge here. Not strictly
2006 * correct but better than the other SMB1 async
2007 * code that double-charges at the moment.
2009 START_PROFILE(SMBulogoffX);
2011 status = reply_ulogoffX_recv(req);
2012 TALLOC_FREE(req);
2013 if (!NT_STATUS_IS_OK(status)) {
2014 TALLOC_FREE(smb1req);
2015 END_PROFILE(SMBulogoffX);
2016 exit_server(__location__ ": reply_ulogoffX_recv failed");
2017 return;
2020 status = smbXsrv_session_logoff(session);
2021 if (!NT_STATUS_IS_OK(status)) {
2022 TALLOC_FREE(smb1req);
2023 END_PROFILE(SMBulogoffX);
2024 exit_server(__location__ ": smbXsrv_session_logoff failed");
2025 return;
2028 TALLOC_FREE(session);
2030 reply_smb1_outbuf(smb1req, 2, 0);
2031 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2032 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2034 DBG_NOTICE("ulogoffX vuid=%llu\n",
2035 (unsigned long long)smb1req->vuid);
2037 smb1req->vuid = UID_FIELD_INVALID;
2039 * The following call is needed to push the
2040 * reply data back out the socket after async
2041 * return. Plus it frees smb1req.
2043 smb_request_done(smb1req);
2044 END_PROFILE(SMBulogoffX);
2047 /****************************************************************************
2048 Reply to a mknew or a create.
2049 ****************************************************************************/
2051 void reply_mknew(struct smb_request *req)
2053 connection_struct *conn = req->conn;
2054 struct smb_filename *smb_fname = NULL;
2055 char *fname = NULL;
2056 uint32_t fattr = 0;
2057 struct smb_file_time ft;
2058 struct files_struct *dirfsp = NULL;
2059 files_struct *fsp;
2060 int oplock_request = 0;
2061 NTSTATUS status;
2062 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2063 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2064 uint32_t create_disposition;
2065 uint32_t create_options = 0;
2066 uint32_t ucf_flags;
2067 NTTIME twrp = 0;
2068 TALLOC_CTX *ctx = talloc_tos();
2070 START_PROFILE(SMBcreate);
2071 init_smb_file_time(&ft);
2073 if (req->wct < 3) {
2074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2075 goto out;
2078 fattr = SVAL(req->vwv+0, 0);
2079 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2081 if (req->cmd == SMBmknew) {
2082 /* We should fail if file exists. */
2083 create_disposition = FILE_CREATE;
2084 } else {
2085 /* Create if file doesn't exist, truncate if it does. */
2086 create_disposition = FILE_OVERWRITE_IF;
2089 /* mtime. */
2090 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2092 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2093 STR_TERMINATE, &status);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 reply_nterror(req, status);
2096 goto out;
2099 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2100 if (ucf_flags & UCF_GMT_PATHNAME) {
2101 extract_snapshot_token(fname, &twrp);
2104 status = filename_convert_dirfsp(ctx,
2105 conn,
2106 fname,
2107 ucf_flags,
2108 twrp,
2109 &dirfsp,
2110 &smb_fname);
2111 if (!NT_STATUS_IS_OK(status)) {
2112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2113 reply_botherror(req,
2114 NT_STATUS_PATH_NOT_COVERED,
2115 ERRSRV, ERRbadpath);
2116 goto out;
2118 reply_nterror(req, status);
2119 goto out;
2122 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2123 DEBUG(0,("Attempt to create file (%s) with volid set - "
2124 "please report this\n",
2125 smb_fname_str_dbg(smb_fname)));
2128 status = SMB_VFS_CREATE_FILE(
2129 conn, /* conn */
2130 req, /* req */
2131 dirfsp, /* dirfsp */
2132 smb_fname, /* fname */
2133 access_mask, /* access_mask */
2134 share_mode, /* share_access */
2135 create_disposition, /* create_disposition*/
2136 create_options, /* create_options */
2137 fattr, /* file_attributes */
2138 oplock_request, /* oplock_request */
2139 NULL, /* lease */
2140 0, /* allocation_size */
2141 0, /* private_flags */
2142 NULL, /* sd */
2143 NULL, /* ea_list */
2144 &fsp, /* result */
2145 NULL, /* pinfo */
2146 NULL, NULL); /* create context */
2148 if (!NT_STATUS_IS_OK(status)) {
2149 if (open_was_deferred(req->xconn, req->mid)) {
2150 /* We have re-scheduled this call. */
2151 goto out;
2153 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2154 bool ok = defer_smb1_sharing_violation(req);
2155 if (ok) {
2156 goto out;
2159 reply_openerror(req, status);
2160 goto out;
2163 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2164 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2165 if (!NT_STATUS_IS_OK(status)) {
2166 END_PROFILE(SMBcreate);
2167 goto out;
2170 reply_smb1_outbuf(req, 1, 0);
2171 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2173 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2174 SCVAL(req->outbuf,smb_flg,
2175 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2178 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2179 SCVAL(req->outbuf,smb_flg,
2180 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2183 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2184 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2185 smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2186 (unsigned int)fattr));
2188 out:
2189 TALLOC_FREE(smb_fname);
2190 END_PROFILE(SMBcreate);
2191 return;
2194 /****************************************************************************
2195 Reply to a create temporary file.
2196 ****************************************************************************/
2198 void reply_ctemp(struct smb_request *req)
2200 connection_struct *conn = req->conn;
2201 struct smb_filename *smb_fname = NULL;
2202 char *wire_name = NULL;
2203 char *fname = NULL;
2204 uint32_t fattr;
2205 struct files_struct *dirfsp = NULL;
2206 files_struct *fsp;
2207 int oplock_request;
2208 char *s;
2209 NTSTATUS status;
2210 int i;
2211 uint32_t ucf_flags;
2212 NTTIME twrp = 0;
2213 TALLOC_CTX *ctx = talloc_tos();
2215 START_PROFILE(SMBctemp);
2217 if (req->wct < 3) {
2218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2219 goto out;
2222 fattr = SVAL(req->vwv+0, 0);
2223 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2225 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2226 STR_TERMINATE, &status);
2227 if (!NT_STATUS_IS_OK(status)) {
2228 reply_nterror(req, status);
2229 goto out;
2232 for (i = 0; i < 10; i++) {
2233 if (*wire_name) {
2234 fname = talloc_asprintf(ctx,
2235 "%s/TMP%s",
2236 wire_name,
2237 generate_random_str_list(ctx, 5, "0123456789"));
2238 } else {
2239 fname = talloc_asprintf(ctx,
2240 "TMP%s",
2241 generate_random_str_list(ctx, 5, "0123456789"));
2244 if (!fname) {
2245 reply_nterror(req, NT_STATUS_NO_MEMORY);
2246 goto out;
2249 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2250 if (ucf_flags & UCF_GMT_PATHNAME) {
2251 extract_snapshot_token(fname, &twrp);
2253 status = filename_convert_dirfsp(ctx,
2254 conn,
2255 fname,
2256 ucf_flags,
2257 twrp,
2258 &dirfsp,
2259 &smb_fname);
2260 if (!NT_STATUS_IS_OK(status)) {
2261 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2262 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2263 ERRSRV, ERRbadpath);
2264 goto out;
2266 reply_nterror(req, status);
2267 goto out;
2270 /* Create the file. */
2271 status = SMB_VFS_CREATE_FILE(
2272 conn, /* conn */
2273 req, /* req */
2274 dirfsp, /* dirfsp */
2275 smb_fname, /* fname */
2276 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2277 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2278 FILE_CREATE, /* create_disposition*/
2279 0, /* create_options */
2280 fattr, /* file_attributes */
2281 oplock_request, /* oplock_request */
2282 NULL, /* lease */
2283 0, /* allocation_size */
2284 0, /* private_flags */
2285 NULL, /* sd */
2286 NULL, /* ea_list */
2287 &fsp, /* result */
2288 NULL, /* pinfo */
2289 NULL, NULL); /* create context */
2291 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2292 TALLOC_FREE(fname);
2293 TALLOC_FREE(dirfsp);
2294 TALLOC_FREE(smb_fname);
2295 continue;
2298 if (!NT_STATUS_IS_OK(status)) {
2299 if (open_was_deferred(req->xconn, req->mid)) {
2300 /* We have re-scheduled this call. */
2301 goto out;
2303 if (NT_STATUS_EQUAL(
2304 status, NT_STATUS_SHARING_VIOLATION)) {
2305 bool ok = defer_smb1_sharing_violation(req);
2306 if (ok) {
2307 goto out;
2310 reply_openerror(req, status);
2311 goto out;
2314 break;
2317 if (i == 10) {
2318 /* Collision after 10 times... */
2319 reply_nterror(req, status);
2320 goto out;
2323 reply_smb1_outbuf(req, 1, 0);
2324 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2326 /* the returned filename is relative to the directory */
2327 s = strrchr_m(fsp->fsp_name->base_name, '/');
2328 if (!s) {
2329 s = fsp->fsp_name->base_name;
2330 } else {
2331 s++;
2334 #if 0
2335 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2336 thing in the byte section. JRA */
2337 SSVALS(p, 0, -1); /* what is this? not in spec */
2338 #endif
2339 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2340 == -1) {
2341 reply_nterror(req, NT_STATUS_NO_MEMORY);
2342 goto out;
2345 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2346 SCVAL(req->outbuf, smb_flg,
2347 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2350 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2351 SCVAL(req->outbuf, smb_flg,
2352 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2355 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2356 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2357 fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2358 out:
2359 TALLOC_FREE(smb_fname);
2360 TALLOC_FREE(wire_name);
2361 END_PROFILE(SMBctemp);
2362 return;
2365 /****************************************************************************
2366 Reply to a unlink
2367 ****************************************************************************/
2369 void reply_unlink(struct smb_request *req)
2371 connection_struct *conn = req->conn;
2372 char *name = NULL;
2373 struct files_struct *dirfsp = NULL;
2374 struct smb_filename *smb_fname = NULL;
2375 uint32_t dirtype;
2376 NTSTATUS status;
2377 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2378 NTTIME twrp = 0;
2379 TALLOC_CTX *ctx = talloc_tos();
2381 START_PROFILE(SMBunlink);
2383 if (req->wct < 1) {
2384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2385 goto out;
2388 dirtype = SVAL(req->vwv+0, 0);
2390 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2391 STR_TERMINATE, &status);
2392 if (!NT_STATUS_IS_OK(status)) {
2393 reply_nterror(req, status);
2394 goto out;
2397 if (ucf_flags & UCF_GMT_PATHNAME) {
2398 extract_snapshot_token(name, &twrp);
2400 status = filename_convert_dirfsp(ctx,
2401 conn,
2402 name,
2403 ucf_flags,
2404 twrp,
2405 &dirfsp,
2406 &smb_fname);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2409 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2410 ERRSRV, ERRbadpath);
2411 goto out;
2413 reply_nterror(req, status);
2414 goto out;
2417 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2419 status = unlink_internals(conn, req, dirtype, dirfsp, smb_fname);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 if (open_was_deferred(req->xconn, req->mid)) {
2422 /* We have re-scheduled this call. */
2423 goto out;
2425 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2426 bool ok = defer_smb1_sharing_violation(req);
2427 if (ok) {
2428 goto out;
2431 reply_nterror(req, status);
2432 goto out;
2435 reply_smb1_outbuf(req, 0, 0);
2436 out:
2437 TALLOC_FREE(smb_fname);
2438 END_PROFILE(SMBunlink);
2439 return;
2442 /****************************************************************************
2443 Fail for readbraw.
2444 ****************************************************************************/
2446 static void fail_readraw(void)
2448 const char *errstr = talloc_asprintf(talloc_tos(),
2449 "FAIL ! reply_readbraw: socket write fail (%s)",
2450 strerror(errno));
2451 if (!errstr) {
2452 errstr = "";
2454 exit_server_cleanly(errstr);
2457 /****************************************************************************
2458 Return a readbraw error (4 bytes of zero).
2459 ****************************************************************************/
2461 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2463 char header[4];
2465 SIVAL(header,0,0);
2467 smbd_lock_socket(xconn);
2468 if (write_data(xconn->transport.sock,header,4) != 4) {
2469 int saved_errno = errno;
2471 * Try and give an error message saying what
2472 * client failed.
2474 DEBUG(0, ("write_data failed for client %s. "
2475 "Error %s\n",
2476 smbXsrv_connection_dbg(xconn),
2477 strerror(saved_errno)));
2478 errno = saved_errno;
2480 fail_readraw();
2482 smbd_unlock_socket(xconn);
2485 /*******************************************************************
2486 Ensure we don't use sendfile if server smb signing is active.
2487 ********************************************************************/
2489 static bool lp_use_sendfile(int snum, struct smb1_signing_state *signing_state)
2491 bool sign_active = false;
2493 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2494 if (get_Protocol() < PROTOCOL_NT1) {
2495 return false;
2497 if (signing_state) {
2498 sign_active = smb1_signing_is_active(signing_state);
2500 return (lp__use_sendfile(snum) &&
2501 (get_remote_arch() != RA_WIN95) &&
2502 !sign_active);
2504 /****************************************************************************
2505 Use sendfile in readbraw.
2506 ****************************************************************************/
2508 static void send_file_readbraw(connection_struct *conn,
2509 struct smb_request *req,
2510 files_struct *fsp,
2511 off_t startpos,
2512 size_t nread,
2513 ssize_t mincount)
2515 struct smbXsrv_connection *xconn = req->xconn;
2516 char *outbuf = NULL;
2517 ssize_t ret=0;
2520 * We can only use sendfile on a non-chained packet
2521 * but we can use on a non-oplocked file. tridge proved this
2522 * on a train in Germany :-). JRA.
2523 * reply_readbraw has already checked the length.
2526 if ( !req_is_in_chain(req) &&
2527 (nread > 0) &&
2528 !fsp_is_alternate_stream(fsp) &&
2529 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
2530 ssize_t sendfile_read = -1;
2531 char header[4];
2532 DATA_BLOB header_blob;
2534 _smb_setlen(header,nread);
2535 header_blob = data_blob_const(header, 4);
2537 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2538 &header_blob, startpos,
2539 nread);
2540 if (sendfile_read == -1) {
2541 /* Returning ENOSYS means no data at all was sent.
2542 * Do this as a normal read. */
2543 if (errno == ENOSYS) {
2544 goto normal_readbraw;
2548 * Special hack for broken Linux with no working sendfile. If we
2549 * return EINTR we sent the header but not the rest of the data.
2550 * Fake this up by doing read/write calls.
2552 if (errno == EINTR) {
2553 /* Ensure we don't do this again. */
2554 set_use_sendfile(SNUM(conn), False);
2555 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2557 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2558 DEBUG(0,("send_file_readbraw: "
2559 "fake_sendfile failed for "
2560 "file %s (%s).\n",
2561 fsp_str_dbg(fsp),
2562 strerror(errno)));
2563 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2565 return;
2568 DEBUG(0,("send_file_readbraw: sendfile failed for "
2569 "file %s (%s). Terminating\n",
2570 fsp_str_dbg(fsp), strerror(errno)));
2571 exit_server_cleanly("send_file_readbraw sendfile failed");
2572 } else if (sendfile_read == 0) {
2574 * Some sendfile implementations return 0 to indicate
2575 * that there was a short read, but nothing was
2576 * actually written to the socket. In this case,
2577 * fallback to the normal read path so the header gets
2578 * the correct byte count.
2580 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2581 "bytes falling back to the normal read: "
2582 "%s\n", fsp_str_dbg(fsp)));
2583 goto normal_readbraw;
2586 /* Deal with possible short send. */
2587 if (sendfile_read != 4+nread) {
2588 ret = sendfile_short_send(xconn, fsp,
2589 sendfile_read, 4, nread);
2590 if (ret == -1) {
2591 fail_readraw();
2594 return;
2597 normal_readbraw:
2599 outbuf = talloc_array(NULL, char, nread+4);
2600 if (!outbuf) {
2601 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2602 (unsigned)(nread+4)));
2603 reply_readbraw_error(xconn);
2604 return;
2607 if (nread > 0) {
2608 ret = read_file(fsp,outbuf+4,startpos,nread);
2609 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2610 if (ret < mincount)
2611 ret = 0;
2612 #else
2613 if (ret < nread)
2614 ret = 0;
2615 #endif
2618 _smb_setlen(outbuf,ret);
2619 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2620 int saved_errno = errno;
2622 * Try and give an error message saying what
2623 * client failed.
2625 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2626 smbXsrv_connection_dbg(xconn),
2627 strerror(saved_errno)));
2628 errno = saved_errno;
2630 fail_readraw();
2633 TALLOC_FREE(outbuf);
2636 /****************************************************************************
2637 Reply to a readbraw (core+ protocol).
2638 ****************************************************************************/
2640 void reply_readbraw(struct smb_request *req)
2642 connection_struct *conn = req->conn;
2643 struct smbXsrv_connection *xconn = req->xconn;
2644 ssize_t maxcount,mincount;
2645 size_t nread = 0;
2646 off_t startpos;
2647 files_struct *fsp;
2648 struct lock_struct lock;
2649 off_t size = 0;
2650 NTSTATUS status;
2652 START_PROFILE(SMBreadbraw);
2654 if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
2655 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2656 "raw reads/writes are disallowed.");
2659 if (req->wct < 8) {
2660 reply_readbraw_error(xconn);
2661 END_PROFILE(SMBreadbraw);
2662 return;
2665 if (xconn->smb1.echo_handler.trusted_fde) {
2666 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
2667 "'async smb echo handler = yes'\n"));
2668 reply_readbraw_error(xconn);
2669 END_PROFILE(SMBreadbraw);
2670 return;
2674 * Special check if an oplock break has been issued
2675 * and the readraw request croses on the wire, we must
2676 * return a zero length response here.
2679 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2682 * We have to do a check_fsp by hand here, as
2683 * we must always return 4 zero bytes on error,
2684 * not a NTSTATUS.
2687 if (fsp == NULL ||
2688 conn == NULL ||
2689 conn != fsp->conn ||
2690 req->vuid != fsp->vuid ||
2691 fsp->fsp_flags.is_directory ||
2692 fsp_get_io_fd(fsp) == -1)
2695 * fsp could be NULL here so use the value from the packet. JRA.
2697 DEBUG(3,("reply_readbraw: fnum %d not valid "
2698 "- cache prime?\n",
2699 (int)SVAL(req->vwv+0, 0)));
2700 reply_readbraw_error(xconn);
2701 END_PROFILE(SMBreadbraw);
2702 return;
2705 /* Do a "by hand" version of CHECK_READ. */
2706 if (!(fsp->fsp_flags.can_read ||
2707 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2708 (fsp->access_mask & FILE_EXECUTE)))) {
2709 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2710 (int)SVAL(req->vwv+0, 0)));
2711 reply_readbraw_error(xconn);
2712 END_PROFILE(SMBreadbraw);
2713 return;
2716 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2717 if(req->wct == 10) {
2719 * This is a large offset (64 bit) read.
2722 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
2724 if(startpos < 0) {
2725 DEBUG(0,("reply_readbraw: negative 64 bit "
2726 "readraw offset (%.0f) !\n",
2727 (double)startpos ));
2728 reply_readbraw_error(xconn);
2729 END_PROFILE(SMBreadbraw);
2730 return;
2734 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
2735 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
2737 /* ensure we don't overrun the packet size */
2738 maxcount = MIN(65535,maxcount);
2740 init_strict_lock_struct(fsp,
2741 (uint64_t)req->smbpid,
2742 (uint64_t)startpos,
2743 (uint64_t)maxcount,
2744 READ_LOCK,
2745 lp_posix_cifsu_locktype(fsp),
2746 &lock);
2748 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
2749 reply_readbraw_error(xconn);
2750 END_PROFILE(SMBreadbraw);
2751 return;
2754 status = vfs_stat_fsp(fsp);
2755 if (NT_STATUS_IS_OK(status)) {
2756 size = fsp->fsp_name->st.st_ex_size;
2759 if (startpos >= size) {
2760 nread = 0;
2761 } else {
2762 nread = MIN(maxcount,(size - startpos));
2765 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2766 if (nread < mincount)
2767 nread = 0;
2768 #endif
2770 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
2771 "min=%lu nread=%lu\n",
2772 fsp_fnum_dbg(fsp), (double)startpos,
2773 (unsigned long)maxcount,
2774 (unsigned long)mincount,
2775 (unsigned long)nread ) );
2777 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
2779 DEBUG(5,("reply_readbraw finished\n"));
2781 END_PROFILE(SMBreadbraw);
2782 return;
2785 #undef DBGC_CLASS
2786 #define DBGC_CLASS DBGC_LOCKING
2788 /****************************************************************************
2789 Reply to a lockread (core+ protocol).
2790 ****************************************************************************/
2792 static void reply_lockread_locked(struct tevent_req *subreq);
2794 void reply_lockread(struct smb_request *req)
2796 struct tevent_req *subreq = NULL;
2797 connection_struct *conn = req->conn;
2798 files_struct *fsp;
2799 struct smbd_lock_element *lck = NULL;
2801 START_PROFILE(SMBlockread);
2803 if (req->wct < 5) {
2804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2805 END_PROFILE(SMBlockread);
2806 return;
2809 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2811 if (!check_fsp(conn, req, fsp)) {
2812 END_PROFILE(SMBlockread);
2813 return;
2816 if (!CHECK_READ(fsp,req)) {
2817 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2818 END_PROFILE(SMBlockread);
2819 return;
2822 lck = talloc(req, struct smbd_lock_element);
2823 if (lck == NULL) {
2824 reply_nterror(req, NT_STATUS_NO_MEMORY);
2825 END_PROFILE(SMBlockread);
2826 return;
2830 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2831 * protocol request that predates the read/write lock concept.
2832 * Thus instead of asking for a read lock here we need to ask
2833 * for a write lock. JRA.
2834 * Note that the requested lock size is unaffected by max_send.
2837 *lck = (struct smbd_lock_element) {
2838 .req_guid = smbd_request_guid(req, 0),
2839 .smblctx = req->smbpid,
2840 .brltype = WRITE_LOCK,
2841 .lock_flav = WINDOWS_LOCK,
2842 .count = SVAL(req->vwv+1, 0),
2843 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
2846 subreq = smbd_smb1_do_locks_send(
2847 fsp,
2848 req->sconn->ev_ctx,
2849 &req,
2850 fsp,
2852 false, /* large_offset */
2854 lck);
2855 if (subreq == NULL) {
2856 reply_nterror(req, NT_STATUS_NO_MEMORY);
2857 END_PROFILE(SMBlockread);
2858 return;
2860 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
2861 END_PROFILE(SMBlockread);
2864 static void reply_lockread_locked(struct tevent_req *subreq)
2866 struct smb_request *req = NULL;
2867 ssize_t nread = -1;
2868 char *data = NULL;
2869 NTSTATUS status;
2870 bool ok;
2871 off_t startpos;
2872 size_t numtoread, maxtoread;
2873 struct files_struct *fsp = NULL;
2874 char *p = NULL;
2876 START_PROFILE(SMBlockread);
2878 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
2879 SMB_ASSERT(ok);
2881 status = smbd_smb1_do_locks_recv(subreq);
2882 TALLOC_FREE(subreq);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 reply_nterror(req, status);
2886 goto send;
2889 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2890 if (fsp == NULL) {
2891 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
2892 goto send;
2895 numtoread = SVAL(req->vwv+1, 0);
2896 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2899 * However the requested READ size IS affected by max_send. Insanity.... JRA.
2901 maxtoread = req->xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
2903 if (numtoread > maxtoread) {
2904 DBG_WARNING("requested read size (%zu) is greater than "
2905 "maximum allowed (%zu/%d). "
2906 "Returning short read of maximum allowed for "
2907 "compatibility with Windows 2000.\n",
2908 numtoread,
2909 maxtoread,
2910 req->xconn->smb1.sessions.max_send);
2911 numtoread = maxtoread;
2914 reply_smb1_outbuf(req, 5, numtoread + 3);
2916 data = smb_buf(req->outbuf) + 3;
2918 nread = read_file(fsp,data,startpos,numtoread);
2920 if (nread < 0) {
2921 reply_nterror(req, map_nt_error_from_unix(errno));
2922 goto send;
2925 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
2927 SSVAL(req->outbuf,smb_vwv0,nread);
2928 SSVAL(req->outbuf,smb_vwv5,nread+3);
2929 p = smb_buf(req->outbuf);
2930 SCVAL(p,0,0); /* pad byte. */
2931 SSVAL(p,1,nread);
2933 DEBUG(3,("lockread %s num=%d nread=%d\n",
2934 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
2936 send:
2937 ok = smb1_srv_send(req->xconn,
2938 (char *)req->outbuf,
2939 true,
2940 req->seqnum+1,
2941 IS_CONN_ENCRYPTED(req->conn),
2942 NULL);
2943 if (!ok) {
2944 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
2946 TALLOC_FREE(req);
2947 END_PROFILE(SMBlockread);
2948 return;
2951 #undef DBGC_CLASS
2952 #define DBGC_CLASS DBGC_ALL
2954 /****************************************************************************
2955 Reply to a read.
2956 ****************************************************************************/
2958 void reply_read(struct smb_request *req)
2960 connection_struct *conn = req->conn;
2961 size_t numtoread;
2962 size_t maxtoread;
2963 ssize_t nread = 0;
2964 char *data;
2965 off_t startpos;
2966 files_struct *fsp;
2967 struct lock_struct lock;
2968 struct smbXsrv_connection *xconn = req->xconn;
2970 START_PROFILE(SMBread);
2972 if (req->wct < 3) {
2973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2974 END_PROFILE(SMBread);
2975 return;
2978 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2980 if (!check_fsp(conn, req, fsp)) {
2981 END_PROFILE(SMBread);
2982 return;
2985 if (!CHECK_READ(fsp,req)) {
2986 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2987 END_PROFILE(SMBread);
2988 return;
2991 numtoread = SVAL(req->vwv+1, 0);
2992 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
2995 * The requested read size cannot be greater than max_send. JRA.
2997 maxtoread = xconn->smb1.sessions.max_send - (MIN_SMB_SIZE + 5*2 + 3);
2999 if (numtoread > maxtoread) {
3000 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3001 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3002 (unsigned int)numtoread, (unsigned int)maxtoread,
3003 (unsigned int)xconn->smb1.sessions.max_send));
3004 numtoread = maxtoread;
3007 reply_smb1_outbuf(req, 5, numtoread+3);
3009 data = smb_buf(req->outbuf) + 3;
3011 init_strict_lock_struct(fsp,
3012 (uint64_t)req->smbpid,
3013 (uint64_t)startpos,
3014 (uint64_t)numtoread,
3015 READ_LOCK,
3016 lp_posix_cifsu_locktype(fsp),
3017 &lock);
3019 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3020 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3021 END_PROFILE(SMBread);
3022 return;
3025 if (numtoread > 0)
3026 nread = read_file(fsp,data,startpos,numtoread);
3028 if (nread < 0) {
3029 reply_nterror(req, map_nt_error_from_unix(errno));
3030 goto out;
3033 srv_smb1_set_message((char *)req->outbuf, 5, nread+3, False);
3035 SSVAL(req->outbuf,smb_vwv0,nread);
3036 SSVAL(req->outbuf,smb_vwv5,nread+3);
3037 SCVAL(smb_buf(req->outbuf),0,1);
3038 SSVAL(smb_buf(req->outbuf),1,nread);
3040 DEBUG(3, ("read %s num=%d nread=%d\n",
3041 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3043 out:
3044 END_PROFILE(SMBread);
3045 return;
3048 /****************************************************************************
3049 Setup readX header.
3050 ****************************************************************************/
3052 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3054 size_t outsize;
3056 outsize = srv_smb1_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3057 False);
3059 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3061 SCVAL(outbuf,smb_vwv0,0xFF);
3062 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3063 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3064 SSVAL(outbuf,smb_vwv6,
3065 (smb_wct - 4) /* offset from smb header to wct */
3066 + 1 /* the wct field */
3067 + 12 * sizeof(uint16_t) /* vwv */
3068 + 2 /* the buflen field */
3069 + 1); /* padding byte */
3070 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3071 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3072 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3073 _smb_setlen_large(outbuf,
3074 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3075 return outsize;
3078 /****************************************************************************
3079 Reply to a read and X - possibly using sendfile.
3080 ****************************************************************************/
3082 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3083 files_struct *fsp, off_t startpos,
3084 size_t smb_maxcnt)
3086 struct smbXsrv_connection *xconn = req->xconn;
3087 ssize_t nread = -1;
3088 struct lock_struct lock;
3089 int saved_errno = 0;
3090 NTSTATUS status;
3092 init_strict_lock_struct(fsp,
3093 (uint64_t)req->smbpid,
3094 (uint64_t)startpos,
3095 (uint64_t)smb_maxcnt,
3096 READ_LOCK,
3097 lp_posix_cifsu_locktype(fsp),
3098 &lock);
3100 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3101 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3102 return;
3106 * We can only use sendfile on a non-chained packet
3107 * but we can use on a non-oplocked file. tridge proved this
3108 * on a train in Germany :-). JRA.
3111 if (!req_is_in_chain(req) &&
3112 !req->encrypted &&
3113 !fsp_is_alternate_stream(fsp) &&
3114 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3115 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3116 DATA_BLOB header;
3118 status = vfs_stat_fsp(fsp);
3119 if (!NT_STATUS_IS_OK(status)) {
3120 reply_nterror(req, status);
3121 goto out;
3124 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3125 (startpos > fsp->fsp_name->st.st_ex_size) ||
3126 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3128 * We already know that we would do a short read, so don't
3129 * try the sendfile() path.
3131 goto nosendfile_read;
3135 * Set up the packet header before send. We
3136 * assume here the sendfile will work (get the
3137 * correct amount of data).
3140 header = data_blob_const(headerbuf, sizeof(headerbuf));
3142 construct_smb1_reply_common_req(req, (char *)headerbuf);
3143 setup_readX_header((char *)headerbuf, smb_maxcnt);
3145 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3146 startpos, smb_maxcnt);
3147 if (nread == -1) {
3148 saved_errno = errno;
3150 /* Returning ENOSYS means no data at all was sent.
3151 Do this as a normal read. */
3152 if (errno == ENOSYS) {
3153 goto normal_read;
3157 * Special hack for broken Linux with no working sendfile. If we
3158 * return EINTR we sent the header but not the rest of the data.
3159 * Fake this up by doing read/write calls.
3162 if (errno == EINTR) {
3163 /* Ensure we don't do this again. */
3164 set_use_sendfile(SNUM(conn), False);
3165 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3166 nread = fake_sendfile(xconn, fsp, startpos,
3167 smb_maxcnt);
3168 if (nread == -1) {
3169 saved_errno = errno;
3170 DEBUG(0,("send_file_readX: "
3171 "fake_sendfile failed for "
3172 "file %s (%s) for client %s. "
3173 "Terminating\n",
3174 fsp_str_dbg(fsp),
3175 smbXsrv_connection_dbg(xconn),
3176 strerror(saved_errno)));
3177 errno = saved_errno;
3178 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3180 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3181 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3182 /* No outbuf here means successful sendfile. */
3183 goto out;
3186 DEBUG(0,("send_file_readX: sendfile failed for file "
3187 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3188 strerror(errno)));
3189 exit_server_cleanly("send_file_readX sendfile failed");
3190 } else if (nread == 0) {
3192 * Some sendfile implementations return 0 to indicate
3193 * that there was a short read, but nothing was
3194 * actually written to the socket. In this case,
3195 * fallback to the normal read path so the header gets
3196 * the correct byte count.
3198 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3199 "falling back to the normal read: %s\n",
3200 fsp_str_dbg(fsp)));
3201 goto normal_read;
3204 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3205 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3207 /* Deal with possible short send. */
3208 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3209 ssize_t ret;
3211 ret = sendfile_short_send(xconn, fsp, nread,
3212 sizeof(headerbuf), smb_maxcnt);
3213 if (ret == -1) {
3214 const char *r;
3215 r = "send_file_readX: sendfile_short_send failed";
3216 DEBUG(0,("%s for file %s (%s).\n",
3217 r, fsp_str_dbg(fsp), strerror(errno)));
3218 exit_server_cleanly(r);
3221 /* No outbuf here means successful sendfile. */
3222 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3223 SMB_PERFCOUNT_END(&req->pcd);
3224 goto out;
3227 normal_read:
3229 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3230 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3231 ssize_t ret;
3233 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3234 (startpos > fsp->fsp_name->st.st_ex_size) ||
3235 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3237 * We already know that we would do a short
3238 * read, so don't try the sendfile() path.
3240 goto nosendfile_read;
3243 construct_smb1_reply_common_req(req, (char *)headerbuf);
3244 setup_readX_header((char *)headerbuf, smb_maxcnt);
3246 /* Send out the header. */
3247 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3248 sizeof(headerbuf));
3249 if (ret != sizeof(headerbuf)) {
3250 saved_errno = errno;
3252 * Try and give an error message saying what
3253 * client failed.
3255 DEBUG(0,("send_file_readX: write_data failed for file "
3256 "%s (%s) for client %s. Terminating\n",
3257 fsp_str_dbg(fsp),
3258 smbXsrv_connection_dbg(xconn),
3259 strerror(saved_errno)));
3260 errno = saved_errno;
3261 exit_server_cleanly("send_file_readX sendfile failed");
3263 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3264 if (nread == -1) {
3265 saved_errno = errno;
3266 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3267 "%s (%s) for client %s. Terminating\n",
3268 fsp_str_dbg(fsp),
3269 smbXsrv_connection_dbg(xconn),
3270 strerror(saved_errno)));
3271 errno = saved_errno;
3272 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3274 goto out;
3277 nosendfile_read:
3279 reply_smb1_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3280 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3281 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3283 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3284 startpos, smb_maxcnt);
3285 saved_errno = errno;
3287 if (nread < 0) {
3288 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3289 return;
3292 setup_readX_header((char *)req->outbuf, nread);
3294 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3295 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3296 return;
3298 out:
3299 TALLOC_FREE(req->outbuf);
3300 return;
3303 /****************************************************************************
3304 Work out how much space we have for a read return.
3305 ****************************************************************************/
3307 static size_t calc_max_read_pdu(const struct smb_request *req)
3309 struct smbXsrv_connection *xconn = req->xconn;
3311 if (xconn->protocol < PROTOCOL_NT1) {
3312 return xconn->smb1.sessions.max_send;
3315 if (!lp_large_readwrite()) {
3316 return xconn->smb1.sessions.max_send;
3319 if (req_is_in_chain(req)) {
3320 return xconn->smb1.sessions.max_send;
3323 if (req->encrypted) {
3325 * Don't take encrypted traffic up to the
3326 * limit. There are padding considerations
3327 * that make that tricky.
3329 return xconn->smb1.sessions.max_send;
3332 if (smb1_srv_is_signing_active(xconn)) {
3333 return 0x1FFFF;
3336 if (!lp_smb1_unix_extensions()) {
3337 return 0x1FFFF;
3341 * We can do ultra-large POSIX reads.
3343 return 0xFFFFFF;
3346 /****************************************************************************
3347 Calculate how big a read can be. Copes with all clients. It's always
3348 safe to return a short read - Windows does this.
3349 ****************************************************************************/
3351 static size_t calc_read_size(const struct smb_request *req,
3352 size_t upper_size,
3353 size_t lower_size)
3355 struct smbXsrv_connection *xconn = req->xconn;
3356 size_t max_pdu = calc_max_read_pdu(req);
3357 size_t total_size = 0;
3358 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3359 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3362 * Windows explicitly ignores upper size of 0xFFFF.
3363 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3364 * We must do the same as these will never fit even in
3365 * an extended size NetBIOS packet.
3367 if (upper_size == 0xFFFF) {
3368 upper_size = 0;
3371 if (xconn->protocol < PROTOCOL_NT1) {
3372 upper_size = 0;
3375 total_size = ((upper_size<<16) | lower_size);
3378 * LARGE_READX test shows it's always safe to return
3379 * a short read. Windows does so.
3381 return MIN(total_size, max_len);
3384 /****************************************************************************
3385 Reply to a read and X.
3386 ****************************************************************************/
3388 void reply_read_and_X(struct smb_request *req)
3390 connection_struct *conn = req->conn;
3391 files_struct *fsp;
3392 off_t startpos;
3393 size_t smb_maxcnt;
3394 size_t upper_size;
3395 bool big_readX = False;
3396 #if 0
3397 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3398 #endif
3400 START_PROFILE(SMBreadX);
3402 if ((req->wct != 10) && (req->wct != 12)) {
3403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3404 return;
3407 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3408 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3409 smb_maxcnt = SVAL(req->vwv+5, 0);
3411 /* If it's an IPC, pass off the pipe handler. */
3412 if (IS_IPC(conn)) {
3413 reply_pipe_read_and_X(req);
3414 END_PROFILE(SMBreadX);
3415 return;
3418 if (!check_fsp(conn, req, fsp)) {
3419 END_PROFILE(SMBreadX);
3420 return;
3423 if (!CHECK_READ(fsp,req)) {
3424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3425 END_PROFILE(SMBreadX);
3426 return;
3429 upper_size = SVAL(req->vwv+7, 0);
3430 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3431 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3433 * This is a heuristic to avoid keeping large
3434 * outgoing buffers around over long-lived aio
3435 * requests.
3437 big_readX = True;
3440 if (req->wct == 12) {
3442 * This is a large offset (64 bit) read.
3444 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3448 if (!big_readX) {
3449 NTSTATUS status = schedule_aio_read_and_X(conn,
3450 req,
3451 fsp,
3452 startpos,
3453 smb_maxcnt);
3454 if (NT_STATUS_IS_OK(status)) {
3455 /* Read scheduled - we're done. */
3456 goto out;
3458 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3459 /* Real error - report to client. */
3460 END_PROFILE(SMBreadX);
3461 reply_nterror(req, status);
3462 return;
3464 /* NT_STATUS_RETRY - fall back to sync read. */
3467 smbd_lock_socket(req->xconn);
3468 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3469 smbd_unlock_socket(req->xconn);
3471 out:
3472 END_PROFILE(SMBreadX);
3473 return;
3476 /****************************************************************************
3477 Error replies to writebraw must have smb_wct == 1. Fix this up.
3478 ****************************************************************************/
3480 void error_to_writebrawerr(struct smb_request *req)
3482 uint8_t *old_outbuf = req->outbuf;
3484 reply_smb1_outbuf(req, 1, 0);
3486 memcpy(req->outbuf, old_outbuf, smb_size);
3487 TALLOC_FREE(old_outbuf);
3490 /****************************************************************************
3491 Read 4 bytes of a smb packet and return the smb length of the packet.
3492 Store the result in the buffer. This version of the function will
3493 never return a session keepalive (length of zero).
3494 Timeout is in milliseconds.
3495 ****************************************************************************/
3497 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3498 size_t *len)
3500 uint8_t msgtype = NBSSkeepalive;
3502 while (msgtype == NBSSkeepalive) {
3503 NTSTATUS status;
3505 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3506 len);
3507 if (!NT_STATUS_IS_OK(status)) {
3508 char addr[INET6_ADDRSTRLEN];
3509 /* Try and give an error message
3510 * saying what client failed. */
3511 DEBUG(0, ("read_smb_length_return_keepalive failed for "
3512 "client %s read error = %s.\n",
3513 get_peer_addr(fd,addr,sizeof(addr)),
3514 nt_errstr(status)));
3515 return status;
3518 msgtype = CVAL(inbuf, 0);
3521 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3522 (unsigned long)len));
3524 return NT_STATUS_OK;
3527 /****************************************************************************
3528 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3529 ****************************************************************************/
3531 void reply_writebraw(struct smb_request *req)
3533 connection_struct *conn = req->conn;
3534 struct smbXsrv_connection *xconn = req->xconn;
3535 char *buf = NULL;
3536 ssize_t nwritten=0;
3537 ssize_t total_written=0;
3538 size_t numtowrite=0;
3539 size_t tcount;
3540 off_t startpos;
3541 const char *data=NULL;
3542 bool write_through;
3543 files_struct *fsp;
3544 struct lock_struct lock;
3545 NTSTATUS status;
3547 START_PROFILE(SMBwritebraw);
3550 * If we ever reply with an error, it must have the SMB command
3551 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3552 * we're finished.
3554 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3556 if (smb1_srv_is_signing_active(xconn)) {
3557 END_PROFILE(SMBwritebraw);
3558 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3559 "raw reads/writes are disallowed.");
3562 if (req->wct < 12) {
3563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3564 error_to_writebrawerr(req);
3565 END_PROFILE(SMBwritebraw);
3566 return;
3569 if (xconn->smb1.echo_handler.trusted_fde) {
3570 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3571 "'async smb echo handler = yes'\n"));
3572 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3573 error_to_writebrawerr(req);
3574 END_PROFILE(SMBwritebraw);
3575 return;
3578 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3579 if (!check_fsp(conn, req, fsp)) {
3580 error_to_writebrawerr(req);
3581 END_PROFILE(SMBwritebraw);
3582 return;
3585 if (!CHECK_WRITE(fsp)) {
3586 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3587 error_to_writebrawerr(req);
3588 END_PROFILE(SMBwritebraw);
3589 return;
3592 tcount = IVAL(req->vwv+1, 0);
3593 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3594 write_through = BITSETW(req->vwv+7,0);
3596 /* We have to deal with slightly different formats depending
3597 on whether we are using the core+ or lanman1.0 protocol */
3599 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3600 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3601 data = smb_buf_const(req->inbuf);
3602 } else {
3603 numtowrite = SVAL(req->vwv+10, 0);
3604 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3607 /* Ensure we don't write bytes past the end of this packet. */
3609 * This already protects us against CVE-2017-12163.
3611 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3613 error_to_writebrawerr(req);
3614 END_PROFILE(SMBwritebraw);
3615 return;
3618 if (!fsp->print_file) {
3619 init_strict_lock_struct(fsp,
3620 (uint64_t)req->smbpid,
3621 (uint64_t)startpos,
3622 (uint64_t)tcount,
3623 WRITE_LOCK,
3624 lp_posix_cifsu_locktype(fsp),
3625 &lock);
3627 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3628 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3629 error_to_writebrawerr(req);
3630 END_PROFILE(SMBwritebraw);
3631 return;
3635 if (numtowrite>0) {
3636 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3639 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3640 "wrote=%d sync=%d\n",
3641 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3642 (int)nwritten, (int)write_through));
3644 if (nwritten < (ssize_t)numtowrite) {
3645 reply_nterror(req, NT_STATUS_DISK_FULL);
3646 error_to_writebrawerr(req);
3647 goto out;
3650 total_written = nwritten;
3652 /* Allocate a buffer of 64k + length. */
3653 buf = talloc_array(NULL, char, 65540);
3654 if (!buf) {
3655 reply_nterror(req, NT_STATUS_NO_MEMORY);
3656 error_to_writebrawerr(req);
3657 goto out;
3660 /* Return a SMBwritebraw message to the redirector to tell
3661 * it to send more bytes */
3663 memcpy(buf, req->inbuf, smb_size);
3664 srv_smb1_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3665 SCVAL(buf,smb_com,SMBwritebraw);
3666 SSVALS(buf,smb_vwv0,0xFFFF);
3667 show_msg(buf);
3668 if (!smb1_srv_send(req->xconn,
3669 buf,
3670 false, 0, /* no signing */
3671 IS_CONN_ENCRYPTED(conn),
3672 &req->pcd)) {
3673 exit_server_cleanly("reply_writebraw: smb1_srv_send "
3674 "failed.");
3677 /* Now read the raw data into the buffer and write it */
3678 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
3679 &numtowrite);
3680 if (!NT_STATUS_IS_OK(status)) {
3681 exit_server_cleanly("secondary writebraw failed");
3684 /* Set up outbuf to return the correct size */
3685 reply_smb1_outbuf(req, 1, 0);
3687 if (numtowrite != 0) {
3689 if (numtowrite > 0xFFFF) {
3690 DEBUG(0,("reply_writebraw: Oversize secondary write "
3691 "raw requested (%u). Terminating\n",
3692 (unsigned int)numtowrite ));
3693 exit_server_cleanly("secondary writebraw failed");
3696 if (tcount > nwritten+numtowrite) {
3697 DEBUG(3,("reply_writebraw: Client overestimated the "
3698 "write %d %d %d\n",
3699 (int)tcount,(int)nwritten,(int)numtowrite));
3702 status = read_data_ntstatus(xconn->transport.sock, buf+4,
3703 numtowrite);
3705 if (!NT_STATUS_IS_OK(status)) {
3706 /* Try and give an error message
3707 * saying what client failed. */
3708 DEBUG(0, ("reply_writebraw: Oversize secondary write "
3709 "raw read failed (%s) for client %s. "
3710 "Terminating\n", nt_errstr(status),
3711 smbXsrv_connection_dbg(xconn)));
3712 exit_server_cleanly("secondary writebraw failed");
3716 * We are not vulnerable to CVE-2017-12163
3717 * here as we are guaranteed to have numtowrite
3718 * bytes available - we just read from the client.
3720 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3721 if (nwritten == -1) {
3722 TALLOC_FREE(buf);
3723 reply_nterror(req, map_nt_error_from_unix(errno));
3724 error_to_writebrawerr(req);
3725 goto out;
3728 if (nwritten < (ssize_t)numtowrite) {
3729 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3730 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3733 if (nwritten > 0) {
3734 total_written += nwritten;
3738 TALLOC_FREE(buf);
3739 SSVAL(req->outbuf,smb_vwv0,total_written);
3741 status = sync_file(conn, fsp, write_through);
3742 if (!NT_STATUS_IS_OK(status)) {
3743 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3744 fsp_str_dbg(fsp), nt_errstr(status)));
3745 reply_nterror(req, status);
3746 error_to_writebrawerr(req);
3747 goto out;
3750 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
3751 "wrote=%d\n",
3752 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3753 (int)total_written));
3755 /* We won't return a status if write through is not selected - this
3756 * follows what WfWg does */
3757 END_PROFILE(SMBwritebraw);
3759 if (!write_through && total_written==tcount) {
3761 #if RABBIT_PELLET_FIX
3763 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3764 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
3765 * JRA.
3767 if (!send_keepalive(xconn->transport.sock)) {
3768 exit_server_cleanly("reply_writebraw: send of "
3769 "keepalive failed");
3771 #endif
3772 TALLOC_FREE(req->outbuf);
3774 return;
3776 out:
3777 END_PROFILE(SMBwritebraw);
3778 return;
3781 #undef DBGC_CLASS
3782 #define DBGC_CLASS DBGC_LOCKING
3784 /****************************************************************************
3785 Reply to a writeunlock (core+).
3786 ****************************************************************************/
3788 void reply_writeunlock(struct smb_request *req)
3790 connection_struct *conn = req->conn;
3791 ssize_t nwritten = -1;
3792 size_t numtowrite;
3793 size_t remaining;
3794 off_t startpos;
3795 const char *data;
3796 NTSTATUS status = NT_STATUS_OK;
3797 files_struct *fsp;
3798 struct lock_struct lock;
3799 int saved_errno = 0;
3801 START_PROFILE(SMBwriteunlock);
3803 if (req->wct < 5) {
3804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3805 END_PROFILE(SMBwriteunlock);
3806 return;
3809 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3811 if (!check_fsp(conn, req, fsp)) {
3812 END_PROFILE(SMBwriteunlock);
3813 return;
3816 if (!CHECK_WRITE(fsp)) {
3817 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3818 END_PROFILE(SMBwriteunlock);
3819 return;
3822 numtowrite = SVAL(req->vwv+1, 0);
3823 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3824 data = (const char *)req->buf + 3;
3827 * Ensure client isn't asking us to write more than
3828 * they sent. CVE-2017-12163.
3830 remaining = smbreq_bufrem(req, data);
3831 if (numtowrite > remaining) {
3832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3833 END_PROFILE(SMBwriteunlock);
3834 return;
3837 if (!fsp->print_file && numtowrite > 0) {
3838 init_strict_lock_struct(fsp,
3839 (uint64_t)req->smbpid,
3840 (uint64_t)startpos,
3841 (uint64_t)numtowrite,
3842 WRITE_LOCK,
3843 lp_posix_cifsu_locktype(fsp),
3844 &lock);
3846 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3847 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3848 END_PROFILE(SMBwriteunlock);
3849 return;
3853 /* The special X/Open SMB protocol handling of
3854 zero length writes is *NOT* done for
3855 this call */
3856 if(numtowrite == 0) {
3857 nwritten = 0;
3858 } else {
3859 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3860 saved_errno = errno;
3863 status = sync_file(conn, fsp, False /* write through */);
3864 if (!NT_STATUS_IS_OK(status)) {
3865 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3866 fsp_str_dbg(fsp), nt_errstr(status)));
3867 reply_nterror(req, status);
3868 goto out;
3871 if(nwritten < 0) {
3872 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3873 goto out;
3876 if((nwritten < numtowrite) && (numtowrite != 0)) {
3877 reply_nterror(req, NT_STATUS_DISK_FULL);
3878 goto out;
3881 if (numtowrite && !fsp->print_file) {
3882 struct smbd_lock_element l = {
3883 .req_guid = smbd_request_guid(req, 0),
3884 .smblctx = req->smbpid,
3885 .brltype = UNLOCK_LOCK,
3886 .lock_flav = WINDOWS_LOCK,
3887 .offset = startpos,
3888 .count = numtowrite,
3890 status = smbd_do_unlocking(req, fsp, 1, &l);
3891 if (NT_STATUS_V(status)) {
3892 reply_nterror(req, status);
3893 goto out;
3897 reply_smb1_outbuf(req, 1, 0);
3899 SSVAL(req->outbuf,smb_vwv0,nwritten);
3901 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
3902 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
3904 out:
3905 END_PROFILE(SMBwriteunlock);
3906 return;
3909 #undef DBGC_CLASS
3910 #define DBGC_CLASS DBGC_ALL
3912 /****************************************************************************
3913 Reply to a write.
3914 ****************************************************************************/
3916 void reply_write(struct smb_request *req)
3918 connection_struct *conn = req->conn;
3919 size_t numtowrite;
3920 size_t remaining;
3921 ssize_t nwritten = -1;
3922 off_t startpos;
3923 const char *data;
3924 files_struct *fsp;
3925 struct lock_struct lock;
3926 NTSTATUS status;
3927 int saved_errno = 0;
3929 START_PROFILE(SMBwrite);
3931 if (req->wct < 5) {
3932 END_PROFILE(SMBwrite);
3933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3934 return;
3937 /* If it's an IPC, pass off the pipe handler. */
3938 if (IS_IPC(conn)) {
3939 reply_pipe_write(req);
3940 END_PROFILE(SMBwrite);
3941 return;
3944 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3946 if (!check_fsp(conn, req, fsp)) {
3947 END_PROFILE(SMBwrite);
3948 return;
3951 if (!CHECK_WRITE(fsp)) {
3952 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3953 END_PROFILE(SMBwrite);
3954 return;
3957 numtowrite = SVAL(req->vwv+1, 0);
3958 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3959 data = (const char *)req->buf + 3;
3962 * Ensure client isn't asking us to write more than
3963 * they sent. CVE-2017-12163.
3965 remaining = smbreq_bufrem(req, data);
3966 if (numtowrite > remaining) {
3967 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3968 END_PROFILE(SMBwrite);
3969 return;
3972 if (!fsp->print_file) {
3973 init_strict_lock_struct(fsp,
3974 (uint64_t)req->smbpid,
3975 (uint64_t)startpos,
3976 (uint64_t)numtowrite,
3977 WRITE_LOCK,
3978 lp_posix_cifsu_locktype(fsp),
3979 &lock);
3981 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3982 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3983 END_PROFILE(SMBwrite);
3984 return;
3989 * X/Open SMB protocol says that if smb_vwv1 is
3990 * zero then the file size should be extended or
3991 * truncated to the size given in smb_vwv[2-3].
3994 if(numtowrite == 0) {
3996 * This is actually an allocate call, and set EOF. JRA.
3998 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
3999 if (nwritten < 0) {
4000 reply_nterror(req, NT_STATUS_DISK_FULL);
4001 goto out;
4003 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4004 if (nwritten < 0) {
4005 reply_nterror(req, NT_STATUS_DISK_FULL);
4006 goto out;
4008 trigger_write_time_update_immediate(fsp);
4009 } else {
4010 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4013 status = sync_file(conn, fsp, False);
4014 if (!NT_STATUS_IS_OK(status)) {
4015 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4016 fsp_str_dbg(fsp), nt_errstr(status)));
4017 reply_nterror(req, status);
4018 goto out;
4021 if(nwritten < 0) {
4022 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4023 goto out;
4026 if((nwritten == 0) && (numtowrite != 0)) {
4027 reply_nterror(req, NT_STATUS_DISK_FULL);
4028 goto out;
4031 reply_smb1_outbuf(req, 1, 0);
4033 SSVAL(req->outbuf,smb_vwv0,nwritten);
4035 if (nwritten < (ssize_t)numtowrite) {
4036 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4037 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4040 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4042 out:
4043 END_PROFILE(SMBwrite);
4044 return;
4047 /****************************************************************************
4048 Ensure a buffer is a valid writeX for recvfile purposes.
4049 ****************************************************************************/
4051 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4052 (2*14) + /* word count (including bcc) */ \
4053 1 /* pad byte */)
4055 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4056 const uint8_t *inbuf)
4058 size_t numtowrite;
4059 unsigned int doff = 0;
4060 size_t len = smb_len_large(inbuf);
4061 uint16_t fnum;
4062 struct smbXsrv_open *op = NULL;
4063 struct files_struct *fsp = NULL;
4064 NTSTATUS status;
4066 if (is_encrypted_packet(inbuf)) {
4067 /* Can't do this on encrypted
4068 * connections. */
4069 return false;
4072 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4073 return false;
4076 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4077 CVAL(inbuf,smb_wct) != 14) {
4078 DEBUG(10,("is_valid_writeX_buffer: chained or "
4079 "invalid word length.\n"));
4080 return false;
4083 fnum = SVAL(inbuf, smb_vwv2);
4084 status = smb1srv_open_lookup(xconn,
4085 fnum,
4086 0, /* now */
4087 &op);
4088 if (!NT_STATUS_IS_OK(status)) {
4089 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4090 return false;
4092 fsp = op->compat;
4093 if (fsp == NULL) {
4094 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4095 return false;
4097 if (fsp->conn == NULL) {
4098 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4099 return false;
4102 if (IS_IPC(fsp->conn)) {
4103 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4104 return false;
4106 if (IS_PRINT(fsp->conn)) {
4107 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4108 return false;
4110 if (fsp_is_alternate_stream(fsp)) {
4111 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4112 return false;
4114 doff = SVAL(inbuf,smb_vwv11);
4116 numtowrite = SVAL(inbuf,smb_vwv10);
4118 if (len > doff && len - doff > 0xFFFF) {
4119 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4122 if (numtowrite == 0) {
4123 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4124 return false;
4127 /* Ensure the sizes match up. */
4128 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4129 /* no pad byte...old smbclient :-( */
4130 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4131 (unsigned int)doff,
4132 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4133 return false;
4136 if (len - doff != numtowrite) {
4137 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4138 "len = %u, doff = %u, numtowrite = %u\n",
4139 (unsigned int)len,
4140 (unsigned int)doff,
4141 (unsigned int)numtowrite ));
4142 return false;
4145 DEBUG(10,("is_valid_writeX_buffer: true "
4146 "len = %u, doff = %u, numtowrite = %u\n",
4147 (unsigned int)len,
4148 (unsigned int)doff,
4149 (unsigned int)numtowrite ));
4151 return true;
4154 /****************************************************************************
4155 Reply to a write and X.
4156 ****************************************************************************/
4158 void reply_write_and_X(struct smb_request *req)
4160 connection_struct *conn = req->conn;
4161 struct smbXsrv_connection *xconn = req->xconn;
4162 files_struct *fsp;
4163 struct lock_struct lock;
4164 off_t startpos;
4165 size_t numtowrite;
4166 bool write_through;
4167 ssize_t nwritten;
4168 unsigned int smb_doff;
4169 unsigned int smblen;
4170 const char *data;
4171 NTSTATUS status;
4172 int saved_errno = 0;
4174 START_PROFILE(SMBwriteX);
4176 if ((req->wct != 12) && (req->wct != 14)) {
4177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4178 goto out;
4181 numtowrite = SVAL(req->vwv+10, 0);
4182 smb_doff = SVAL(req->vwv+11, 0);
4183 smblen = smb_len(req->inbuf);
4185 if (req->unread_bytes > 0xFFFF ||
4186 (smblen > smb_doff &&
4187 smblen - smb_doff > 0xFFFF)) {
4188 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4191 if (req->unread_bytes) {
4192 /* Can't do a recvfile write on IPC$ */
4193 if (IS_IPC(conn)) {
4194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4195 goto out;
4197 if (numtowrite != req->unread_bytes) {
4198 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4199 goto out;
4201 } else {
4203 * This already protects us against CVE-2017-12163.
4205 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4206 smb_doff + numtowrite > smblen) {
4207 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4208 goto out;
4212 /* If it's an IPC, pass off the pipe handler. */
4213 if (IS_IPC(conn)) {
4214 if (req->unread_bytes) {
4215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4216 goto out;
4218 reply_pipe_write_and_X(req);
4219 goto out;
4222 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4223 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4224 write_through = BITSETW(req->vwv+7,0);
4226 if (!check_fsp(conn, req, fsp)) {
4227 goto out;
4230 if (!CHECK_WRITE(fsp)) {
4231 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4232 goto out;
4235 data = smb_base(req->inbuf) + smb_doff;
4237 if(req->wct == 14) {
4239 * This is a large offset (64 bit) write.
4241 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4245 /* X/Open SMB protocol says that, unlike SMBwrite
4246 if the length is zero then NO truncation is
4247 done, just a write of zero. To truncate a file,
4248 use SMBwrite. */
4250 if(numtowrite == 0) {
4251 nwritten = 0;
4252 } else {
4253 if (req->unread_bytes == 0) {
4254 status = schedule_aio_write_and_X(conn,
4255 req,
4256 fsp,
4257 data,
4258 startpos,
4259 numtowrite);
4261 if (NT_STATUS_IS_OK(status)) {
4262 /* write scheduled - we're done. */
4263 goto out;
4265 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4266 /* Real error - report to client. */
4267 reply_nterror(req, status);
4268 goto out;
4270 /* NT_STATUS_RETRY - fall through to sync write. */
4273 init_strict_lock_struct(fsp,
4274 (uint64_t)req->smbpid,
4275 (uint64_t)startpos,
4276 (uint64_t)numtowrite,
4277 WRITE_LOCK,
4278 lp_posix_cifsu_locktype(fsp),
4279 &lock);
4281 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4282 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4283 goto out;
4286 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4287 saved_errno = errno;
4290 if(nwritten < 0) {
4291 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4292 goto out;
4295 if((nwritten == 0) && (numtowrite != 0)) {
4296 reply_nterror(req, NT_STATUS_DISK_FULL);
4297 goto out;
4300 reply_smb1_outbuf(req, 6, 0);
4301 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4302 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4303 SSVAL(req->outbuf,smb_vwv2,nwritten);
4304 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4306 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4307 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4309 status = sync_file(conn, fsp, write_through);
4310 if (!NT_STATUS_IS_OK(status)) {
4311 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4312 fsp_str_dbg(fsp), nt_errstr(status)));
4313 reply_nterror(req, status);
4314 goto out;
4317 END_PROFILE(SMBwriteX);
4318 return;
4320 out:
4321 if (req->unread_bytes) {
4322 /* writeX failed. drain socket. */
4323 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4324 req->unread_bytes) {
4325 smb_panic("failed to drain pending bytes");
4327 req->unread_bytes = 0;
4330 END_PROFILE(SMBwriteX);
4331 return;
4334 /****************************************************************************
4335 Reply to a lseek.
4336 ****************************************************************************/
4338 void reply_lseek(struct smb_request *req)
4340 connection_struct *conn = req->conn;
4341 off_t startpos;
4342 off_t res= -1;
4343 int mode,umode;
4344 files_struct *fsp;
4345 NTSTATUS status;
4347 START_PROFILE(SMBlseek);
4349 if (req->wct < 4) {
4350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4351 END_PROFILE(SMBlseek);
4352 return;
4355 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4357 if (!check_fsp(conn, req, fsp)) {
4358 return;
4361 mode = SVAL(req->vwv+1, 0) & 3;
4362 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4363 startpos = (off_t)IVALS(req->vwv+2, 0);
4365 switch (mode) {
4366 case 0:
4367 umode = SEEK_SET;
4368 res = startpos;
4369 break;
4370 case 1:
4371 umode = SEEK_CUR;
4372 res = fh_get_pos(fsp->fh) + startpos;
4373 break;
4374 case 2:
4375 umode = SEEK_END;
4376 break;
4377 default:
4378 umode = SEEK_SET;
4379 res = startpos;
4380 break;
4383 if (umode == SEEK_END) {
4384 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4385 if(errno == EINVAL) {
4386 off_t current_pos = startpos;
4388 status = vfs_stat_fsp(fsp);
4389 if (!NT_STATUS_IS_OK(status)) {
4390 reply_nterror(req, status);
4391 END_PROFILE(SMBlseek);
4392 return;
4395 current_pos += fsp->fsp_name->st.st_ex_size;
4396 if(current_pos < 0)
4397 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4401 if(res == -1) {
4402 reply_nterror(req, map_nt_error_from_unix(errno));
4403 END_PROFILE(SMBlseek);
4404 return;
4408 fh_set_pos(fsp->fh, res);
4410 reply_smb1_outbuf(req, 2, 0);
4411 SIVAL(req->outbuf,smb_vwv0,res);
4413 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4414 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4416 END_PROFILE(SMBlseek);
4417 return;
4420 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4421 void *private_data)
4423 connection_struct *conn = talloc_get_type_abort(
4424 private_data, connection_struct);
4426 if (conn != fsp->conn) {
4427 return NULL;
4429 if (fsp_get_io_fd(fsp) == -1) {
4430 return NULL;
4432 sync_file(conn, fsp, True /* write through */);
4434 if (fsp->fsp_flags.modified) {
4435 trigger_write_time_update_immediate(fsp);
4438 return NULL;
4441 /****************************************************************************
4442 Reply to a flush.
4443 ****************************************************************************/
4445 void reply_flush(struct smb_request *req)
4447 connection_struct *conn = req->conn;
4448 uint16_t fnum;
4449 files_struct *fsp;
4451 START_PROFILE(SMBflush);
4453 if (req->wct < 1) {
4454 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4455 return;
4458 fnum = SVAL(req->vwv+0, 0);
4459 fsp = file_fsp(req, fnum);
4461 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4462 return;
4465 if (!fsp) {
4466 files_forall(req->sconn, file_sync_one_fn, conn);
4467 } else {
4468 NTSTATUS status = sync_file(conn, fsp, True);
4469 if (!NT_STATUS_IS_OK(status)) {
4470 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4471 fsp_str_dbg(fsp), nt_errstr(status)));
4472 reply_nterror(req, status);
4473 END_PROFILE(SMBflush);
4474 return;
4476 if (fsp->fsp_flags.modified) {
4477 trigger_write_time_update_immediate(fsp);
4481 reply_smb1_outbuf(req, 0, 0);
4483 DEBUG(3,("flush\n"));
4484 END_PROFILE(SMBflush);
4485 return;
4488 /****************************************************************************
4489 Reply to a exit.
4490 conn POINTER CAN BE NULL HERE !
4491 ****************************************************************************/
4493 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4494 static void reply_exit_done(struct tevent_req *req);
4496 void reply_exit(struct smb_request *smb1req)
4498 struct tevent_req *req;
4501 * Don't setup the profile charge here, take
4502 * it in reply_exit_done(). Not strictly correct
4503 * but better than the other SMB1 async
4504 * code that double-charges at the moment.
4506 req = reply_exit_send(smb1req);
4507 if (req == NULL) {
4508 /* Not going async, profile here. */
4509 START_PROFILE(SMBexit);
4510 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4511 END_PROFILE(SMBexit);
4512 return;
4515 /* We're async. This will complete later. */
4516 tevent_req_set_callback(req, reply_exit_done, smb1req);
4517 return;
4520 struct reply_exit_state {
4521 struct tevent_queue *wait_queue;
4524 static void reply_exit_wait_done(struct tevent_req *subreq);
4526 /****************************************************************************
4527 Async SMB1 exit.
4528 Note, on failure here we deallocate and return NULL to allow the caller to
4529 SMB1 return an error of ERRnomem immediately.
4530 ****************************************************************************/
4532 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4534 struct tevent_req *req;
4535 struct reply_exit_state *state;
4536 struct tevent_req *subreq;
4537 files_struct *fsp;
4538 struct smbd_server_connection *sconn = smb1req->sconn;
4540 req = tevent_req_create(smb1req, &state,
4541 struct reply_exit_state);
4542 if (req == NULL) {
4543 return NULL;
4545 state->wait_queue = tevent_queue_create(state,
4546 "reply_exit_wait_queue");
4547 if (tevent_req_nomem(state->wait_queue, req)) {
4548 TALLOC_FREE(req);
4549 return NULL;
4552 for (fsp = sconn->files; fsp; fsp = fsp->next) {
4553 if (fsp->file_pid != smb1req->smbpid) {
4554 continue;
4556 if (fsp->vuid != smb1req->vuid) {
4557 continue;
4560 * Flag the file as close in progress.
4561 * This will prevent any more IO being
4562 * done on it.
4564 fsp->fsp_flags.closing = true;
4566 if (fsp->num_aio_requests > 0) {
4568 * Now wait until all aio requests on this fsp are
4569 * finished.
4571 * We don't set a callback, as we just want to block the
4572 * wait queue and the talloc_free() of fsp->aio_request
4573 * will remove the item from the wait queue.
4575 subreq = tevent_queue_wait_send(fsp->aio_requests,
4576 sconn->ev_ctx,
4577 state->wait_queue);
4578 if (tevent_req_nomem(subreq, req)) {
4579 TALLOC_FREE(req);
4580 return NULL;
4586 * Now we add our own waiter to the end of the queue,
4587 * this way we get notified when all pending requests are finished
4588 * and reply to the outstanding SMB1 request.
4590 subreq = tevent_queue_wait_send(state,
4591 sconn->ev_ctx,
4592 state->wait_queue);
4593 if (tevent_req_nomem(subreq, req)) {
4594 TALLOC_FREE(req);
4595 return NULL;
4599 * We're really going async - move the SMB1 request from
4600 * a talloc stackframe above us to the conn talloc-context.
4601 * We need this to stick around until the wait_done
4602 * callback is invoked.
4604 smb1req = talloc_move(sconn, &smb1req);
4606 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4608 return req;
4611 static void reply_exit_wait_done(struct tevent_req *subreq)
4613 struct tevent_req *req = tevent_req_callback_data(
4614 subreq, struct tevent_req);
4616 tevent_queue_wait_recv(subreq);
4617 TALLOC_FREE(subreq);
4618 tevent_req_done(req);
4621 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4623 return tevent_req_simple_recv_ntstatus(req);
4626 static void reply_exit_done(struct tevent_req *req)
4628 struct smb_request *smb1req = tevent_req_callback_data(
4629 req, struct smb_request);
4630 struct smbd_server_connection *sconn = smb1req->sconn;
4631 struct smbXsrv_connection *xconn = smb1req->xconn;
4632 NTTIME now = timeval_to_nttime(&smb1req->request_time);
4633 struct smbXsrv_session *session = NULL;
4634 files_struct *fsp, *next;
4635 NTSTATUS status;
4638 * Take the profile charge here. Not strictly
4639 * correct but better than the other SMB1 async
4640 * code that double-charges at the moment.
4642 START_PROFILE(SMBexit);
4644 status = reply_exit_recv(req);
4645 TALLOC_FREE(req);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 TALLOC_FREE(smb1req);
4648 END_PROFILE(SMBexit);
4649 exit_server(__location__ ": reply_exit_recv failed");
4650 return;
4654 * Ensure the session is still valid.
4656 status = smb1srv_session_lookup(xconn,
4657 smb1req->vuid,
4658 now,
4659 &session);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4662 smb_request_done(smb1req);
4663 END_PROFILE(SMBexit);
4667 * Ensure the vuid is still valid - no one
4668 * called reply_ulogoffX() in the meantime.
4669 * reply_exit() doesn't have AS_USER set, so
4670 * use set_current_user_info() directly.
4671 * This is the same logic as in switch_message().
4673 if (session->global->auth_session_info != NULL) {
4674 set_current_user_info(
4675 session->global->auth_session_info->unix_info->sanitized_username,
4676 session->global->auth_session_info->unix_info->unix_name,
4677 session->global->auth_session_info->info->domain_name);
4680 /* No more aio - do the actual closes. */
4681 for (fsp = sconn->files; fsp; fsp = next) {
4682 bool ok;
4683 next = fsp->next;
4685 if (fsp->file_pid != smb1req->smbpid) {
4686 continue;
4688 if (fsp->vuid != smb1req->vuid) {
4689 continue;
4691 if (!fsp->fsp_flags.closing) {
4692 continue;
4696 * reply_exit() has the DO_CHDIR flag set.
4698 ok = chdir_current_service(fsp->conn);
4699 if (!ok) {
4700 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4701 smb_request_done(smb1req);
4702 END_PROFILE(SMBexit);
4704 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
4707 reply_smb1_outbuf(smb1req, 0, 0);
4709 * The following call is needed to push the
4710 * reply data back out the socket after async
4711 * return. Plus it frees smb1req.
4713 smb_request_done(smb1req);
4714 DBG_INFO("reply_exit complete\n");
4715 END_PROFILE(SMBexit);
4716 return;
4719 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
4720 files_struct *fsp);
4721 static void reply_close_done(struct tevent_req *req);
4723 void reply_close(struct smb_request *smb1req)
4725 connection_struct *conn = smb1req->conn;
4726 NTSTATUS status = NT_STATUS_OK;
4727 files_struct *fsp = NULL;
4728 START_PROFILE(SMBclose);
4730 if (smb1req->wct < 3) {
4731 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
4732 END_PROFILE(SMBclose);
4733 return;
4736 fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
4739 * We can only use check_fsp if we know it's not a directory.
4742 if (!check_fsp_open(conn, smb1req, fsp)) {
4743 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
4744 END_PROFILE(SMBclose);
4745 return;
4748 DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
4749 fsp->fsp_flags.is_directory ?
4750 "directory" : "file",
4751 fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
4752 conn->num_files_open);
4754 if (!fsp->fsp_flags.is_directory) {
4755 time_t t;
4758 * Take care of any time sent in the close.
4761 t = srv_make_unix_date3(smb1req->vwv+1);
4762 set_close_write_time(fsp, time_t_to_full_timespec(t));
4765 if (fsp->num_aio_requests != 0) {
4766 struct tevent_req *req;
4768 req = reply_close_send(smb1req, fsp);
4769 if (req == NULL) {
4770 status = NT_STATUS_NO_MEMORY;
4771 goto done;
4773 /* We're async. This will complete later. */
4774 tevent_req_set_callback(req, reply_close_done, smb1req);
4775 END_PROFILE(SMBclose);
4776 return;
4780 * close_file_free() returns the unix errno if an error was detected on
4781 * close - normally this is due to a disk full error. If not then it
4782 * was probably an I/O error.
4785 status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
4786 done:
4787 if (!NT_STATUS_IS_OK(status)) {
4788 reply_nterror(smb1req, status);
4789 END_PROFILE(SMBclose);
4790 return;
4793 reply_smb1_outbuf(smb1req, 0, 0);
4794 END_PROFILE(SMBclose);
4795 return;
4798 struct reply_close_state {
4799 files_struct *fsp;
4800 struct tevent_queue *wait_queue;
4803 static void reply_close_wait_done(struct tevent_req *subreq);
4805 /****************************************************************************
4806 Async SMB1 close.
4807 Note, on failure here we deallocate and return NULL to allow the caller to
4808 SMB1 return an error of ERRnomem immediately.
4809 ****************************************************************************/
4811 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
4812 files_struct *fsp)
4814 struct tevent_req *req;
4815 struct reply_close_state *state;
4816 struct tevent_req *subreq;
4817 struct smbd_server_connection *sconn = smb1req->sconn;
4819 req = tevent_req_create(smb1req, &state,
4820 struct reply_close_state);
4821 if (req == NULL) {
4822 return NULL;
4824 state->wait_queue = tevent_queue_create(state,
4825 "reply_close_wait_queue");
4826 if (tevent_req_nomem(state->wait_queue, req)) {
4827 TALLOC_FREE(req);
4828 return NULL;
4832 * Flag the file as close in progress.
4833 * This will prevent any more IO being
4834 * done on it.
4836 fsp->fsp_flags.closing = true;
4839 * Now wait until all aio requests on this fsp are
4840 * finished.
4842 * We don't set a callback, as we just want to block the
4843 * wait queue and the talloc_free() of fsp->aio_request
4844 * will remove the item from the wait queue.
4846 subreq = tevent_queue_wait_send(fsp->aio_requests,
4847 sconn->ev_ctx,
4848 state->wait_queue);
4849 if (tevent_req_nomem(subreq, req)) {
4850 TALLOC_FREE(req);
4851 return NULL;
4855 * Now we add our own waiter to the end of the queue,
4856 * this way we get notified when all pending requests are finished
4857 * and reply to the outstanding SMB1 request.
4859 subreq = tevent_queue_wait_send(state,
4860 sconn->ev_ctx,
4861 state->wait_queue);
4862 if (tevent_req_nomem(subreq, req)) {
4863 TALLOC_FREE(req);
4864 return NULL;
4868 * We're really going async - move the SMB1 request from
4869 * a talloc stackframe above us to the conn talloc-context.
4870 * We need this to stick around until the wait_done
4871 * callback is invoked.
4873 smb1req = talloc_move(sconn, &smb1req);
4875 tevent_req_set_callback(subreq, reply_close_wait_done, req);
4877 return req;
4880 static void reply_close_wait_done(struct tevent_req *subreq)
4882 struct tevent_req *req = tevent_req_callback_data(
4883 subreq, struct tevent_req);
4885 tevent_queue_wait_recv(subreq);
4886 TALLOC_FREE(subreq);
4887 tevent_req_done(req);
4890 static NTSTATUS reply_close_recv(struct tevent_req *req)
4892 return tevent_req_simple_recv_ntstatus(req);
4895 static void reply_close_done(struct tevent_req *req)
4897 struct smb_request *smb1req = tevent_req_callback_data(
4898 req, struct smb_request);
4899 struct reply_close_state *state = tevent_req_data(req,
4900 struct reply_close_state);
4901 NTSTATUS status;
4903 status = reply_close_recv(req);
4904 TALLOC_FREE(req);
4905 if (!NT_STATUS_IS_OK(status)) {
4906 TALLOC_FREE(smb1req);
4907 exit_server(__location__ ": reply_close_recv failed");
4908 return;
4911 status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
4912 if (NT_STATUS_IS_OK(status)) {
4913 reply_smb1_outbuf(smb1req, 0, 0);
4914 } else {
4915 reply_nterror(smb1req, status);
4918 * The following call is needed to push the
4919 * reply data back out the socket after async
4920 * return. Plus it frees smb1req.
4922 smb_request_done(smb1req);
4925 /****************************************************************************
4926 Reply to a writeclose (Core+ protocol).
4927 ****************************************************************************/
4929 void reply_writeclose(struct smb_request *req)
4931 connection_struct *conn = req->conn;
4932 size_t numtowrite;
4933 size_t remaining;
4934 ssize_t nwritten = -1;
4935 NTSTATUS close_status = NT_STATUS_OK;
4936 off_t startpos;
4937 const char *data;
4938 struct timespec mtime;
4939 files_struct *fsp;
4940 struct lock_struct lock;
4942 START_PROFILE(SMBwriteclose);
4944 if (req->wct < 6) {
4945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4946 END_PROFILE(SMBwriteclose);
4947 return;
4950 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4952 if (!check_fsp(conn, req, fsp)) {
4953 END_PROFILE(SMBwriteclose);
4954 return;
4956 if (!CHECK_WRITE(fsp)) {
4957 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4958 END_PROFILE(SMBwriteclose);
4959 return;
4962 numtowrite = SVAL(req->vwv+1, 0);
4963 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4964 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
4965 data = (const char *)req->buf + 1;
4968 * Ensure client isn't asking us to write more than
4969 * they sent. CVE-2017-12163.
4971 remaining = smbreq_bufrem(req, data);
4972 if (numtowrite > remaining) {
4973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4974 END_PROFILE(SMBwriteclose);
4975 return;
4978 if (fsp->print_file == NULL) {
4979 init_strict_lock_struct(fsp,
4980 (uint64_t)req->smbpid,
4981 (uint64_t)startpos,
4982 (uint64_t)numtowrite,
4983 WRITE_LOCK,
4984 lp_posix_cifsu_locktype(fsp),
4985 &lock);
4987 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4988 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4989 END_PROFILE(SMBwriteclose);
4990 return;
4994 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4996 set_close_write_time(fsp, mtime);
4999 * More insanity. W2K only closes the file if writelen > 0.
5000 * JRA.
5003 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5004 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5005 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5007 if (numtowrite) {
5008 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5009 "file %s\n", fsp_str_dbg(fsp)));
5010 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5013 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5014 reply_nterror(req, NT_STATUS_DISK_FULL);
5015 goto out;
5018 if(!NT_STATUS_IS_OK(close_status)) {
5019 reply_nterror(req, close_status);
5020 goto out;
5023 reply_smb1_outbuf(req, 1, 0);
5025 SSVAL(req->outbuf,smb_vwv0,nwritten);
5027 out:
5029 END_PROFILE(SMBwriteclose);
5030 return;
5033 #undef DBGC_CLASS
5034 #define DBGC_CLASS DBGC_LOCKING
5036 /****************************************************************************
5037 Reply to a lock.
5038 ****************************************************************************/
5040 static void reply_lock_done(struct tevent_req *subreq);
5042 void reply_lock(struct smb_request *req)
5044 struct tevent_req *subreq = NULL;
5045 connection_struct *conn = req->conn;
5046 files_struct *fsp;
5047 struct smbd_lock_element *lck = NULL;
5049 START_PROFILE(SMBlock);
5051 if (req->wct < 5) {
5052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5053 END_PROFILE(SMBlock);
5054 return;
5057 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5059 if (!check_fsp(conn, req, fsp)) {
5060 END_PROFILE(SMBlock);
5061 return;
5064 lck = talloc(req, struct smbd_lock_element);
5065 if (lck == NULL) {
5066 reply_nterror(req, NT_STATUS_NO_MEMORY);
5067 END_PROFILE(SMBlock);
5068 return;
5071 *lck = (struct smbd_lock_element) {
5072 .req_guid = smbd_request_guid(req, 0),
5073 .smblctx = req->smbpid,
5074 .brltype = WRITE_LOCK,
5075 .lock_flav = WINDOWS_LOCK,
5076 .count = IVAL(req->vwv+1, 0),
5077 .offset = IVAL(req->vwv+3, 0),
5080 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5081 fsp_get_io_fd(fsp),
5082 fsp_fnum_dbg(fsp),
5083 lck->offset,
5084 lck->count);
5086 subreq = smbd_smb1_do_locks_send(
5087 fsp,
5088 req->sconn->ev_ctx,
5089 &req,
5090 fsp,
5092 false, /* large_offset */
5094 lck);
5095 if (subreq == NULL) {
5096 reply_nterror(req, NT_STATUS_NO_MEMORY);
5097 END_PROFILE(SMBlock);
5098 return;
5100 tevent_req_set_callback(subreq, reply_lock_done, NULL);
5101 END_PROFILE(SMBlock);
5104 static void reply_lock_done(struct tevent_req *subreq)
5106 struct smb_request *req = NULL;
5107 NTSTATUS status;
5108 bool ok;
5110 START_PROFILE(SMBlock);
5112 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5113 SMB_ASSERT(ok);
5115 status = smbd_smb1_do_locks_recv(subreq);
5116 TALLOC_FREE(subreq);
5118 if (NT_STATUS_IS_OK(status)) {
5119 reply_smb1_outbuf(req, 0, 0);
5120 } else {
5121 reply_nterror(req, status);
5124 ok = smb1_srv_send(req->xconn,
5125 (char *)req->outbuf,
5126 true,
5127 req->seqnum+1,
5128 IS_CONN_ENCRYPTED(req->conn),
5129 NULL);
5130 if (!ok) {
5131 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
5133 TALLOC_FREE(req);
5134 END_PROFILE(SMBlock);
5137 /****************************************************************************
5138 Reply to a unlock.
5139 ****************************************************************************/
5141 void reply_unlock(struct smb_request *req)
5143 connection_struct *conn = req->conn;
5144 NTSTATUS status;
5145 files_struct *fsp;
5146 struct smbd_lock_element lck;
5148 START_PROFILE(SMBunlock);
5150 if (req->wct < 5) {
5151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5152 END_PROFILE(SMBunlock);
5153 return;
5156 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5158 if (!check_fsp(conn, req, fsp)) {
5159 END_PROFILE(SMBunlock);
5160 return;
5163 lck = (struct smbd_lock_element) {
5164 .req_guid = smbd_request_guid(req, 0),
5165 .smblctx = req->smbpid,
5166 .brltype = UNLOCK_LOCK,
5167 .lock_flav = WINDOWS_LOCK,
5168 .offset = IVAL(req->vwv+3, 0),
5169 .count = IVAL(req->vwv+1, 0),
5172 status = smbd_do_unlocking(req, fsp, 1, &lck);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 reply_nterror(req, status);
5176 END_PROFILE(SMBunlock);
5177 return;
5180 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5181 fsp_get_io_fd(fsp),
5182 fsp_fnum_dbg(fsp),
5183 lck.offset,
5184 lck.count);
5186 reply_smb1_outbuf(req, 0, 0);
5188 END_PROFILE(SMBunlock);
5189 return;
5192 #undef DBGC_CLASS
5193 #define DBGC_CLASS DBGC_ALL
5195 /****************************************************************************
5196 Reply to a tdis.
5197 conn POINTER CAN BE NULL HERE !
5198 ****************************************************************************/
5200 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5201 static void reply_tdis_done(struct tevent_req *req);
5203 void reply_tdis(struct smb_request *smb1req)
5205 connection_struct *conn = smb1req->conn;
5206 struct tevent_req *req;
5209 * Don't setup the profile charge here, take
5210 * it in reply_tdis_done(). Not strictly correct
5211 * but better than the other SMB1 async
5212 * code that double-charges at the moment.
5215 if (conn == NULL) {
5216 /* Not going async, profile here. */
5217 START_PROFILE(SMBtdis);
5218 DBG_INFO("Invalid connection in tdis\n");
5219 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5220 END_PROFILE(SMBtdis);
5221 return;
5224 req = reply_tdis_send(smb1req);
5225 if (req == NULL) {
5226 /* Not going async, profile here. */
5227 START_PROFILE(SMBtdis);
5228 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5229 END_PROFILE(SMBtdis);
5230 return;
5232 /* We're async. This will complete later. */
5233 tevent_req_set_callback(req, reply_tdis_done, smb1req);
5234 return;
5237 struct reply_tdis_state {
5238 struct tevent_queue *wait_queue;
5241 static void reply_tdis_wait_done(struct tevent_req *subreq);
5243 /****************************************************************************
5244 Async SMB1 tdis.
5245 Note, on failure here we deallocate and return NULL to allow the caller to
5246 SMB1 return an error of ERRnomem immediately.
5247 ****************************************************************************/
5249 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5251 struct tevent_req *req;
5252 struct reply_tdis_state *state;
5253 struct tevent_req *subreq;
5254 connection_struct *conn = smb1req->conn;
5255 files_struct *fsp;
5257 req = tevent_req_create(smb1req, &state,
5258 struct reply_tdis_state);
5259 if (req == NULL) {
5260 return NULL;
5262 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5263 if (tevent_req_nomem(state->wait_queue, req)) {
5264 TALLOC_FREE(req);
5265 return NULL;
5269 * Make sure that no new request will be able to use this tcon.
5270 * This ensures that once all outstanding fsp->aio_requests
5271 * on this tcon are done, we are safe to close it.
5273 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5275 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5276 if (fsp->conn != conn) {
5277 continue;
5280 * Flag the file as close in progress.
5281 * This will prevent any more IO being
5282 * done on it. Not strictly needed, but
5283 * doesn't hurt to flag it as closing.
5285 fsp->fsp_flags.closing = true;
5287 if (fsp->num_aio_requests > 0) {
5289 * Now wait until all aio requests on this fsp are
5290 * finished.
5292 * We don't set a callback, as we just want to block the
5293 * wait queue and the talloc_free() of fsp->aio_request
5294 * will remove the item from the wait queue.
5296 subreq = tevent_queue_wait_send(fsp->aio_requests,
5297 conn->sconn->ev_ctx,
5298 state->wait_queue);
5299 if (tevent_req_nomem(subreq, req)) {
5300 TALLOC_FREE(req);
5301 return NULL;
5307 * Now we add our own waiter to the end of the queue,
5308 * this way we get notified when all pending requests are finished
5309 * and reply to the outstanding SMB1 request.
5311 subreq = tevent_queue_wait_send(state,
5312 conn->sconn->ev_ctx,
5313 state->wait_queue);
5314 if (tevent_req_nomem(subreq, req)) {
5315 TALLOC_FREE(req);
5316 return NULL;
5320 * We're really going async - move the SMB1 request from
5321 * a talloc stackframe above us to the sconn talloc-context.
5322 * We need this to stick around until the wait_done
5323 * callback is invoked.
5325 smb1req = talloc_move(smb1req->sconn, &smb1req);
5327 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5329 return req;
5332 static void reply_tdis_wait_done(struct tevent_req *subreq)
5334 struct tevent_req *req = tevent_req_callback_data(
5335 subreq, struct tevent_req);
5337 tevent_queue_wait_recv(subreq);
5338 TALLOC_FREE(subreq);
5339 tevent_req_done(req);
5342 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5344 return tevent_req_simple_recv_ntstatus(req);
5347 static void reply_tdis_done(struct tevent_req *req)
5349 struct smb_request *smb1req = tevent_req_callback_data(
5350 req, struct smb_request);
5351 NTSTATUS status;
5352 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5353 bool ok;
5356 * Take the profile charge here. Not strictly
5357 * correct but better than the other SMB1 async
5358 * code that double-charges at the moment.
5360 START_PROFILE(SMBtdis);
5362 status = reply_tdis_recv(req);
5363 TALLOC_FREE(req);
5364 if (!NT_STATUS_IS_OK(status)) {
5365 TALLOC_FREE(smb1req);
5366 END_PROFILE(SMBtdis);
5367 exit_server(__location__ ": reply_tdis_recv failed");
5368 return;
5372 * As we've been awoken, we may have changed
5373 * directory in the meantime.
5374 * reply_tdis() has the DO_CHDIR flag set.
5376 ok = chdir_current_service(smb1req->conn);
5377 if (!ok) {
5378 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5379 smb_request_done(smb1req);
5380 END_PROFILE(SMBtdis);
5383 status = smbXsrv_tcon_disconnect(tcon,
5384 smb1req->vuid);
5385 if (!NT_STATUS_IS_OK(status)) {
5386 TALLOC_FREE(smb1req);
5387 END_PROFILE(SMBtdis);
5388 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5389 return;
5392 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5393 smb1req->conn = NULL;
5395 TALLOC_FREE(tcon);
5397 reply_smb1_outbuf(smb1req, 0, 0);
5399 * The following call is needed to push the
5400 * reply data back out the socket after async
5401 * return. Plus it frees smb1req.
5403 smb_request_done(smb1req);
5404 END_PROFILE(SMBtdis);
5407 /****************************************************************************
5408 Reply to a echo.
5409 conn POINTER CAN BE NULL HERE !
5410 ****************************************************************************/
5412 void reply_echo(struct smb_request *req)
5414 connection_struct *conn = req->conn;
5415 struct smb_perfcount_data local_pcd;
5416 struct smb_perfcount_data *cur_pcd;
5417 int smb_reverb;
5418 int seq_num;
5420 START_PROFILE(SMBecho);
5422 smb_init_perfcount_data(&local_pcd);
5424 if (req->wct < 1) {
5425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5426 END_PROFILE(SMBecho);
5427 return;
5430 smb_reverb = SVAL(req->vwv+0, 0);
5432 reply_smb1_outbuf(req, 1, req->buflen);
5434 /* copy any incoming data back out */
5435 if (req->buflen > 0) {
5436 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5439 if (smb_reverb > 100) {
5440 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5441 smb_reverb = 100;
5444 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5446 /* this makes sure we catch the request pcd */
5447 if (seq_num == smb_reverb) {
5448 cur_pcd = &req->pcd;
5449 } else {
5450 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5451 cur_pcd = &local_pcd;
5454 SSVAL(req->outbuf,smb_vwv0,seq_num);
5456 show_msg((char *)req->outbuf);
5457 if (!smb1_srv_send(req->xconn,
5458 (char *)req->outbuf,
5459 true, req->seqnum+1,
5460 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5461 cur_pcd))
5462 exit_server_cleanly("reply_echo: smb1_srv_send failed.");
5465 DEBUG(3,("echo %d times\n", smb_reverb));
5467 TALLOC_FREE(req->outbuf);
5469 END_PROFILE(SMBecho);
5470 return;
5473 /****************************************************************************
5474 Reply to a printopen.
5475 ****************************************************************************/
5477 void reply_printopen(struct smb_request *req)
5479 connection_struct *conn = req->conn;
5480 files_struct *fsp;
5481 NTSTATUS status;
5483 START_PROFILE(SMBsplopen);
5485 if (req->wct < 2) {
5486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5487 END_PROFILE(SMBsplopen);
5488 return;
5491 if (!CAN_PRINT(conn)) {
5492 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5493 END_PROFILE(SMBsplopen);
5494 return;
5497 status = file_new(req, conn, &fsp);
5498 if(!NT_STATUS_IS_OK(status)) {
5499 reply_nterror(req, status);
5500 END_PROFILE(SMBsplopen);
5501 return;
5504 /* Open for exclusive use, write only. */
5505 status = print_spool_open(fsp, NULL, req->vuid);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 file_free(req, fsp);
5509 reply_nterror(req, status);
5510 END_PROFILE(SMBsplopen);
5511 return;
5514 reply_smb1_outbuf(req, 1, 0);
5515 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5517 DEBUG(3,("openprint fd=%d %s\n",
5518 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5520 END_PROFILE(SMBsplopen);
5521 return;
5524 /****************************************************************************
5525 Reply to a printclose.
5526 ****************************************************************************/
5528 void reply_printclose(struct smb_request *req)
5530 connection_struct *conn = req->conn;
5531 files_struct *fsp;
5532 NTSTATUS status;
5534 START_PROFILE(SMBsplclose);
5536 if (req->wct < 1) {
5537 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5538 END_PROFILE(SMBsplclose);
5539 return;
5542 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5544 if (!check_fsp(conn, req, fsp)) {
5545 END_PROFILE(SMBsplclose);
5546 return;
5549 if (!CAN_PRINT(conn)) {
5550 reply_force_doserror(req, ERRSRV, ERRerror);
5551 END_PROFILE(SMBsplclose);
5552 return;
5555 DEBUG(3,("printclose fd=%d %s\n",
5556 fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5558 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5560 if(!NT_STATUS_IS_OK(status)) {
5561 reply_nterror(req, status);
5562 END_PROFILE(SMBsplclose);
5563 return;
5566 reply_smb1_outbuf(req, 0, 0);
5568 END_PROFILE(SMBsplclose);
5569 return;
5572 /****************************************************************************
5573 Reply to a printqueue.
5574 ****************************************************************************/
5576 void reply_printqueue(struct smb_request *req)
5578 const struct loadparm_substitution *lp_sub =
5579 loadparm_s3_global_substitution();
5580 connection_struct *conn = req->conn;
5581 int max_count;
5582 int start_index;
5584 START_PROFILE(SMBsplretq);
5586 if (req->wct < 2) {
5587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5588 END_PROFILE(SMBsplretq);
5589 return;
5592 max_count = SVAL(req->vwv+0, 0);
5593 start_index = SVAL(req->vwv+1, 0);
5595 /* we used to allow the client to get the cnum wrong, but that
5596 is really quite gross and only worked when there was only
5597 one printer - I think we should now only accept it if they
5598 get it right (tridge) */
5599 if (!CAN_PRINT(conn)) {
5600 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5601 END_PROFILE(SMBsplretq);
5602 return;
5605 reply_smb1_outbuf(req, 2, 3);
5606 SSVAL(req->outbuf,smb_vwv0,0);
5607 SSVAL(req->outbuf,smb_vwv1,0);
5608 SCVAL(smb_buf(req->outbuf),0,1);
5609 SSVAL(smb_buf(req->outbuf),1,0);
5611 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5612 start_index, max_count));
5615 TALLOC_CTX *mem_ctx = talloc_tos();
5616 NTSTATUS status;
5617 WERROR werr;
5618 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5619 struct rpc_pipe_client *cli = NULL;
5620 struct dcerpc_binding_handle *b = NULL;
5621 struct policy_handle handle;
5622 struct spoolss_DevmodeContainer devmode_ctr;
5623 union spoolss_JobInfo *info;
5624 uint32_t count;
5625 uint32_t num_to_get;
5626 uint32_t first;
5627 uint32_t i;
5629 ZERO_STRUCT(handle);
5631 status = rpc_pipe_open_interface(mem_ctx,
5632 &ndr_table_spoolss,
5633 conn->session_info,
5634 conn->sconn->remote_address,
5635 conn->sconn->local_address,
5636 conn->sconn->msg_ctx,
5637 &cli);
5638 if (!NT_STATUS_IS_OK(status)) {
5639 DEBUG(0, ("reply_printqueue: "
5640 "could not connect to spoolss: %s\n",
5641 nt_errstr(status)));
5642 reply_nterror(req, status);
5643 goto out;
5645 b = cli->binding_handle;
5647 ZERO_STRUCT(devmode_ctr);
5649 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5650 sharename,
5651 NULL, devmode_ctr,
5652 SEC_FLAG_MAXIMUM_ALLOWED,
5653 &handle,
5654 &werr);
5655 if (!NT_STATUS_IS_OK(status)) {
5656 reply_nterror(req, status);
5657 goto out;
5659 if (!W_ERROR_IS_OK(werr)) {
5660 reply_nterror(req, werror_to_ntstatus(werr));
5661 goto out;
5664 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5665 &handle,
5666 0, /* firstjob */
5667 0xff, /* numjobs */
5668 2, /* level */
5669 0, /* offered */
5670 &count,
5671 &info);
5672 if (!W_ERROR_IS_OK(werr)) {
5673 reply_nterror(req, werror_to_ntstatus(werr));
5674 goto out;
5677 if (max_count > 0) {
5678 first = start_index;
5679 } else {
5680 first = start_index + max_count + 1;
5683 if (first >= count) {
5684 num_to_get = first;
5685 } else {
5686 num_to_get = first + MIN(ABS(max_count), count - first);
5689 for (i = first; i < num_to_get; i++) {
5690 char blob[28];
5691 char *p = blob;
5692 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5693 int qstatus;
5694 size_t len = 0;
5695 uint16_t qrapjobid = pjobid_to_rap(sharename,
5696 info[i].info2.job_id);
5698 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5699 qstatus = 2;
5700 } else {
5701 qstatus = 3;
5704 srv_put_dos_date2(p, 0, qtime);
5705 SCVAL(p, 4, qstatus);
5706 SSVAL(p, 5, qrapjobid);
5707 SIVAL(p, 7, info[i].info2.size);
5708 SCVAL(p, 11, 0);
5709 status = srvstr_push(blob, req->flags2, p+12,
5710 info[i].info2.notify_name, 16, STR_ASCII, &len);
5711 if (!NT_STATUS_IS_OK(status)) {
5712 reply_nterror(req, status);
5713 goto out;
5715 if (message_push_blob(
5716 &req->outbuf,
5717 data_blob_const(
5718 blob, sizeof(blob))) == -1) {
5719 reply_nterror(req, NT_STATUS_NO_MEMORY);
5720 goto out;
5724 if (count > 0) {
5725 SSVAL(req->outbuf,smb_vwv0,count);
5726 SSVAL(req->outbuf,smb_vwv1,
5727 (max_count>0?first+count:first-1));
5728 SCVAL(smb_buf(req->outbuf),0,1);
5729 SSVAL(smb_buf(req->outbuf),1,28*count);
5733 DEBUG(3, ("%u entries returned in queue\n",
5734 (unsigned)count));
5736 out:
5737 if (b && is_valid_policy_hnd(&handle)) {
5738 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5743 END_PROFILE(SMBsplretq);
5744 return;
5747 /****************************************************************************
5748 Reply to a printwrite.
5749 ****************************************************************************/
5751 void reply_printwrite(struct smb_request *req)
5753 connection_struct *conn = req->conn;
5754 int numtowrite;
5755 const char *data;
5756 files_struct *fsp;
5758 START_PROFILE(SMBsplwr);
5760 if (req->wct < 1) {
5761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5762 END_PROFILE(SMBsplwr);
5763 return;
5766 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5768 if (!check_fsp(conn, req, fsp)) {
5769 END_PROFILE(SMBsplwr);
5770 return;
5773 if (!fsp->print_file) {
5774 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5775 END_PROFILE(SMBsplwr);
5776 return;
5779 if (!CHECK_WRITE(fsp)) {
5780 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5781 END_PROFILE(SMBsplwr);
5782 return;
5785 numtowrite = SVAL(req->buf, 1);
5788 * This already protects us against CVE-2017-12163.
5790 if (req->buflen < numtowrite + 3) {
5791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5792 END_PROFILE(SMBsplwr);
5793 return;
5796 data = (const char *)req->buf + 3;
5798 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5799 reply_nterror(req, map_nt_error_from_unix(errno));
5800 END_PROFILE(SMBsplwr);
5801 return;
5804 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5806 reply_smb1_outbuf(req, 0, 0);
5808 END_PROFILE(SMBsplwr);
5809 return;
5812 /****************************************************************************
5813 Reply to a mkdir.
5814 ****************************************************************************/
5816 void reply_mkdir(struct smb_request *req)
5818 connection_struct *conn = req->conn;
5819 struct files_struct *dirfsp = NULL;
5820 struct smb_filename *smb_dname = NULL;
5821 char *directory = NULL;
5822 NTSTATUS status;
5823 uint32_t ucf_flags;
5824 NTTIME twrp = 0;
5825 TALLOC_CTX *ctx = talloc_tos();
5827 START_PROFILE(SMBmkdir);
5829 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5830 STR_TERMINATE, &status);
5831 if (!NT_STATUS_IS_OK(status)) {
5832 reply_nterror(req, status);
5833 goto out;
5836 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
5837 if (ucf_flags & UCF_GMT_PATHNAME) {
5838 extract_snapshot_token(directory, &twrp);
5840 status = filename_convert_dirfsp(ctx,
5841 conn,
5842 directory,
5843 ucf_flags,
5844 twrp,
5845 &dirfsp,
5846 &smb_dname);
5847 if (!NT_STATUS_IS_OK(status)) {
5848 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5849 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5850 ERRSRV, ERRbadpath);
5851 goto out;
5853 reply_nterror(req, status);
5854 goto out;
5857 status = create_directory(conn, req, dirfsp, smb_dname);
5859 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5861 if (!NT_STATUS_IS_OK(status)) {
5863 if (!use_nt_status()
5864 && NT_STATUS_EQUAL(status,
5865 NT_STATUS_OBJECT_NAME_COLLISION)) {
5867 * Yes, in the DOS error code case we get a
5868 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5869 * samba4 torture test.
5871 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5874 reply_nterror(req, status);
5875 goto out;
5878 reply_smb1_outbuf(req, 0, 0);
5880 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5881 out:
5882 TALLOC_FREE(smb_dname);
5883 END_PROFILE(SMBmkdir);
5884 return;
5887 /****************************************************************************
5888 Reply to a rmdir.
5889 ****************************************************************************/
5891 void reply_rmdir(struct smb_request *req)
5893 connection_struct *conn = req->conn;
5894 struct smb_filename *smb_dname = NULL;
5895 char *directory = NULL;
5896 NTSTATUS status;
5897 TALLOC_CTX *ctx = talloc_tos();
5898 struct files_struct *dirfsp = NULL;
5899 files_struct *fsp = NULL;
5900 int info = 0;
5901 NTTIME twrp = 0;
5902 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5904 START_PROFILE(SMBrmdir);
5906 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5907 STR_TERMINATE, &status);
5908 if (!NT_STATUS_IS_OK(status)) {
5909 reply_nterror(req, status);
5910 goto out;
5913 if (ucf_flags & UCF_GMT_PATHNAME) {
5914 extract_snapshot_token(directory, &twrp);
5916 status = filename_convert_dirfsp(ctx,
5917 conn,
5918 directory,
5919 ucf_flags,
5920 twrp,
5921 &dirfsp,
5922 &smb_dname);
5923 if (!NT_STATUS_IS_OK(status)) {
5924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5925 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5926 ERRSRV, ERRbadpath);
5927 goto out;
5929 reply_nterror(req, status);
5930 goto out;
5933 status = SMB_VFS_CREATE_FILE(
5934 conn, /* conn */
5935 req, /* req */
5936 dirfsp, /* dirfsp */
5937 smb_dname, /* fname */
5938 DELETE_ACCESS, /* access_mask */
5939 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5940 FILE_SHARE_DELETE),
5941 FILE_OPEN, /* create_disposition*/
5942 FILE_DIRECTORY_FILE, /* create_options */
5943 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5944 0, /* oplock_request */
5945 NULL, /* lease */
5946 0, /* allocation_size */
5947 0, /* private_flags */
5948 NULL, /* sd */
5949 NULL, /* ea_list */
5950 &fsp, /* result */
5951 &info, /* pinfo */
5952 NULL, NULL); /* create context */
5954 if (!NT_STATUS_IS_OK(status)) {
5955 if (open_was_deferred(req->xconn, req->mid)) {
5956 /* We have re-scheduled this call. */
5957 goto out;
5959 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
5960 bool ok = defer_smb1_sharing_violation(req);
5961 if (ok) {
5962 goto out;
5965 reply_nterror(req, status);
5966 goto out;
5969 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5970 if (!NT_STATUS_IS_OK(status)) {
5971 close_file_free(req, &fsp, ERROR_CLOSE);
5972 reply_nterror(req, status);
5973 goto out;
5976 if (!set_delete_on_close(fsp, true,
5977 conn->session_info->security_token,
5978 conn->session_info->unix_token)) {
5979 close_file_free(req, &fsp, ERROR_CLOSE);
5980 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5981 goto out;
5984 status = close_file_free(req, &fsp, NORMAL_CLOSE);
5985 if (!NT_STATUS_IS_OK(status)) {
5986 reply_nterror(req, status);
5987 } else {
5988 reply_smb1_outbuf(req, 0, 0);
5991 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5992 out:
5993 TALLOC_FREE(smb_dname);
5994 END_PROFILE(SMBrmdir);
5995 return;
5998 /****************************************************************************
5999 Reply to a mv.
6000 ****************************************************************************/
6002 void reply_mv(struct smb_request *req)
6004 connection_struct *conn = req->conn;
6005 char *name = NULL;
6006 char *newname = NULL;
6007 const char *p;
6008 uint32_t attrs;
6009 NTSTATUS status;
6010 TALLOC_CTX *ctx = talloc_tos();
6011 struct files_struct *src_dirfsp = NULL;
6012 struct smb_filename *smb_fname_src = NULL;
6013 struct files_struct *dst_dirfsp = NULL;
6014 struct smb_filename *smb_fname_dst = NULL;
6015 const char *dst_original_lcomp = NULL;
6016 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
6017 NTTIME src_twrp = 0;
6018 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
6019 NTTIME dst_twrp = 0;
6020 bool stream_rename = false;
6022 START_PROFILE(SMBmv);
6024 if (req->wct < 1) {
6025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6026 goto out;
6029 attrs = SVAL(req->vwv+0, 0);
6031 p = (const char *)req->buf + 1;
6032 p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
6033 &status);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 reply_nterror(req, status);
6036 goto out;
6038 p++;
6039 p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
6040 &status);
6041 if (!NT_STATUS_IS_OK(status)) {
6042 reply_nterror(req, status);
6043 goto out;
6046 if (!req->posix_pathnames) {
6047 /* The newname must begin with a ':' if the
6048 name contains a ':'. */
6049 if (strchr_m(name, ':')) {
6050 if (newname[0] != ':') {
6051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6052 goto out;
6054 stream_rename = true;
6058 if (src_ucf_flags & UCF_GMT_PATHNAME) {
6059 extract_snapshot_token(name, &src_twrp);
6061 status = filename_convert_dirfsp(ctx,
6062 conn,
6063 name,
6064 src_ucf_flags,
6065 src_twrp,
6066 &src_dirfsp,
6067 &smb_fname_src);
6069 if (!NT_STATUS_IS_OK(status)) {
6070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6071 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6072 ERRSRV, ERRbadpath);
6073 goto out;
6075 reply_nterror(req, status);
6076 goto out;
6079 if (dst_ucf_flags & UCF_GMT_PATHNAME) {
6080 extract_snapshot_token(newname, &dst_twrp);
6082 status = filename_convert_dirfsp(ctx,
6083 conn,
6084 newname,
6085 dst_ucf_flags,
6086 dst_twrp,
6087 &dst_dirfsp,
6088 &smb_fname_dst);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6092 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6093 ERRSRV, ERRbadpath);
6094 goto out;
6096 reply_nterror(req, status);
6097 goto out;
6100 /* Get the last component of the destination for rename_internals(). */
6101 dst_original_lcomp = get_original_lcomp(ctx,
6102 conn,
6103 newname,
6104 dst_ucf_flags);
6105 if (dst_original_lcomp == NULL) {
6106 reply_nterror(req, NT_STATUS_NO_MEMORY);
6107 goto out;
6110 if (stream_rename) {
6111 /* smb_fname_dst->base_name must be the same as
6112 smb_fname_src->base_name. */
6113 TALLOC_FREE(smb_fname_dst->base_name);
6114 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6115 smb_fname_src->base_name);
6116 if (!smb_fname_dst->base_name) {
6117 reply_nterror(req, NT_STATUS_NO_MEMORY);
6118 goto out;
6122 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6123 smb_fname_str_dbg(smb_fname_dst)));
6125 status = rename_internals(ctx,
6126 conn,
6127 req,
6128 src_dirfsp, /* src_dirfsp */
6129 smb_fname_src,
6130 dst_dirfsp, /* dst_dirfsp */
6131 smb_fname_dst,
6132 dst_original_lcomp,
6133 attrs,
6134 false,
6135 DELETE_ACCESS);
6136 if (!NT_STATUS_IS_OK(status)) {
6137 if (open_was_deferred(req->xconn, req->mid)) {
6138 /* We have re-scheduled this call. */
6139 goto out;
6141 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6142 bool ok = defer_smb1_sharing_violation(req);
6143 if (ok) {
6144 goto out;
6147 reply_nterror(req, status);
6148 goto out;
6151 reply_smb1_outbuf(req, 0, 0);
6152 out:
6153 TALLOC_FREE(smb_fname_src);
6154 TALLOC_FREE(smb_fname_dst);
6155 END_PROFILE(SMBmv);
6156 return;
6159 /****************************************************************************
6160 Reply to a file copy.
6162 From MS-CIFS.
6164 This command was introduced in the LAN Manager 1.0 dialect
6165 It was rendered obsolete in the NT LAN Manager dialect.
6166 This command was used to perform server-side file copies, but
6167 is no longer used. Clients SHOULD
6168 NOT send requests using this command code.
6169 Servers receiving requests with this command code
6170 SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
6171 ****************************************************************************/
6173 void reply_copy(struct smb_request *req)
6175 START_PROFILE(SMBcopy);
6176 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
6177 END_PROFILE(SMBcopy);
6178 return;
6181 #undef DBGC_CLASS
6182 #define DBGC_CLASS DBGC_LOCKING
6184 /****************************************************************************
6185 Get a lock pid, dealing with large count requests.
6186 ****************************************************************************/
6188 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6189 bool large_file_format)
6191 if(!large_file_format)
6192 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6193 else
6194 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6197 /****************************************************************************
6198 Get a lock count, dealing with large count requests.
6199 ****************************************************************************/
6201 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6202 bool large_file_format)
6204 uint64_t count = 0;
6206 if(!large_file_format) {
6207 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6208 } else {
6210 * No BVAL, this is reversed!
6212 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6213 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6216 return count;
6219 /****************************************************************************
6220 Reply to a lockingX request.
6221 ****************************************************************************/
6223 static void reply_lockingx_done(struct tevent_req *subreq);
6225 void reply_lockingX(struct smb_request *req)
6227 connection_struct *conn = req->conn;
6228 files_struct *fsp;
6229 unsigned char locktype;
6230 enum brl_type brltype;
6231 unsigned char oplocklevel;
6232 uint16_t num_ulocks;
6233 uint16_t num_locks;
6234 int32_t lock_timeout;
6235 uint16_t i;
6236 const uint8_t *data;
6237 bool large_file_format;
6238 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6239 struct smbd_lock_element *locks = NULL;
6240 struct tevent_req *subreq = NULL;
6242 START_PROFILE(SMBlockingX);
6244 if (req->wct < 8) {
6245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6246 END_PROFILE(SMBlockingX);
6247 return;
6250 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
6251 locktype = CVAL(req->vwv+3, 0);
6252 oplocklevel = CVAL(req->vwv+3, 1);
6253 num_ulocks = SVAL(req->vwv+6, 0);
6254 num_locks = SVAL(req->vwv+7, 0);
6255 lock_timeout = IVAL(req->vwv+4, 0);
6256 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
6258 if (!check_fsp(conn, req, fsp)) {
6259 END_PROFILE(SMBlockingX);
6260 return;
6263 data = req->buf;
6265 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6266 /* we don't support these - and CANCEL_LOCK makes w2k
6267 and XP reboot so I don't really want to be
6268 compatible! (tridge) */
6269 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
6270 END_PROFILE(SMBlockingX);
6271 return;
6274 /* Check if this is an oplock break on a file
6275 we have granted an oplock on.
6277 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
6278 /* Client can insist on breaking to none. */
6279 bool break_to_none = (oplocklevel == 0);
6280 bool result;
6282 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6283 "for %s\n", (unsigned int)oplocklevel,
6284 fsp_fnum_dbg(fsp)));
6287 * Make sure we have granted an exclusive or batch oplock on
6288 * this file.
6291 if (fsp->oplock_type == 0) {
6293 /* The Samba4 nbench simulator doesn't understand
6294 the difference between break to level2 and break
6295 to none from level2 - it sends oplock break
6296 replies in both cases. Don't keep logging an error
6297 message here - just ignore it. JRA. */
6299 DEBUG(5,("reply_lockingX: Error : oplock break from "
6300 "client for %s (oplock=%d) and no "
6301 "oplock granted on this file (%s).\n",
6302 fsp_fnum_dbg(fsp), fsp->oplock_type,
6303 fsp_str_dbg(fsp)));
6305 /* if this is a pure oplock break request then don't
6306 * send a reply */
6307 if (num_locks == 0 && num_ulocks == 0) {
6308 END_PROFILE(SMBlockingX);
6309 return;
6312 END_PROFILE(SMBlockingX);
6313 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6314 return;
6317 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6318 (break_to_none)) {
6319 result = remove_oplock(fsp);
6320 } else {
6321 result = downgrade_oplock(fsp);
6324 if (!result) {
6325 DEBUG(0, ("reply_lockingX: error in removing "
6326 "oplock on file %s\n", fsp_str_dbg(fsp)));
6327 /* Hmmm. Is this panic justified? */
6328 smb_panic("internal tdb error");
6331 /* if this is a pure oplock break request then don't send a
6332 * reply */
6333 if (num_locks == 0 && num_ulocks == 0) {
6334 /* Sanity check - ensure a pure oplock break is not a
6335 chained request. */
6336 if (CVAL(req->vwv+0, 0) != 0xff) {
6337 DEBUG(0,("reply_lockingX: Error : pure oplock "
6338 "break is a chained %d request !\n",
6339 (unsigned int)CVAL(req->vwv+0, 0)));
6341 END_PROFILE(SMBlockingX);
6342 return;
6346 if (req->buflen <
6347 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6349 END_PROFILE(SMBlockingX);
6350 return;
6353 if (num_ulocks != 0) {
6354 struct smbd_lock_element *ulocks = NULL;
6355 bool ok;
6357 ulocks = talloc_array(
6358 req, struct smbd_lock_element, num_ulocks);
6359 if (ulocks == NULL) {
6360 reply_nterror(req, NT_STATUS_NO_MEMORY);
6361 END_PROFILE(SMBlockingX);
6362 return;
6366 * Data now points at the beginning of the list of
6367 * smb_unlkrng structs
6369 for (i = 0; i < num_ulocks; i++) {
6370 ulocks[i].req_guid = smbd_request_guid(req,
6371 UINT16_MAX - i),
6372 ulocks[i].smblctx = get_lock_pid(
6373 data, i, large_file_format);
6374 ulocks[i].count = get_lock_count(
6375 data, i, large_file_format);
6376 ulocks[i].offset = get_lock_offset(
6377 data, i, large_file_format);
6378 ulocks[i].brltype = UNLOCK_LOCK;
6379 ulocks[i].lock_flav = WINDOWS_LOCK;
6383 * Unlock cancels pending locks
6386 ok = smbd_smb1_brl_finish_by_lock(
6387 fsp,
6388 large_file_format,
6389 ulocks[0],
6390 NT_STATUS_OK);
6391 if (ok) {
6392 reply_smb1_outbuf(req, 2, 0);
6393 SSVAL(req->outbuf, smb_vwv0, 0xff);
6394 SSVAL(req->outbuf, smb_vwv1, 0);
6395 END_PROFILE(SMBlockingX);
6396 return;
6399 status = smbd_do_unlocking(
6400 req, fsp, num_ulocks, ulocks);
6401 TALLOC_FREE(ulocks);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 END_PROFILE(SMBlockingX);
6404 reply_nterror(req, status);
6405 return;
6409 /* Now do any requested locks */
6410 data += ((large_file_format ? 20 : 10)*num_ulocks);
6412 /* Data now points at the beginning of the list
6413 of smb_lkrng structs */
6415 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
6416 brltype = READ_LOCK;
6417 } else {
6418 brltype = WRITE_LOCK;
6421 locks = talloc_array(req, struct smbd_lock_element, num_locks);
6422 if (locks == NULL) {
6423 reply_nterror(req, NT_STATUS_NO_MEMORY);
6424 END_PROFILE(SMBlockingX);
6425 return;
6428 for (i = 0; i < num_locks; i++) {
6429 locks[i].req_guid = smbd_request_guid(req, i),
6430 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
6431 locks[i].count = get_lock_count(data, i, large_file_format);
6432 locks[i].offset = get_lock_offset(data, i, large_file_format);
6433 locks[i].brltype = brltype;
6434 locks[i].lock_flav = WINDOWS_LOCK;
6437 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6439 bool ok;
6441 if (num_locks == 0) {
6442 /* See smbtorture3 lock11 test */
6443 reply_smb1_outbuf(req, 2, 0);
6444 /* andx chain ends */
6445 SSVAL(req->outbuf, smb_vwv0, 0xff);
6446 SSVAL(req->outbuf, smb_vwv1, 0);
6447 END_PROFILE(SMBlockingX);
6448 return;
6451 ok = smbd_smb1_brl_finish_by_lock(
6452 fsp,
6453 large_file_format,
6454 locks[0], /* Windows only cancels the first lock */
6455 NT_STATUS_FILE_LOCK_CONFLICT);
6457 if (!ok) {
6458 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
6459 END_PROFILE(SMBlockingX);
6460 return;
6463 reply_smb1_outbuf(req, 2, 0);
6464 SSVAL(req->outbuf, smb_vwv0, 0xff);
6465 SSVAL(req->outbuf, smb_vwv1, 0);
6466 END_PROFILE(SMBlockingX);
6467 return;
6470 subreq = smbd_smb1_do_locks_send(
6471 fsp,
6472 req->sconn->ev_ctx,
6473 &req,
6474 fsp,
6475 lock_timeout,
6476 large_file_format,
6477 num_locks,
6478 locks);
6479 if (subreq == NULL) {
6480 reply_nterror(req, NT_STATUS_NO_MEMORY);
6481 END_PROFILE(SMBlockingX);
6482 return;
6484 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
6485 END_PROFILE(SMBlockingX);
6488 static void reply_lockingx_done(struct tevent_req *subreq)
6490 struct smb_request *req = NULL;
6491 NTSTATUS status;
6492 bool ok;
6494 START_PROFILE(SMBlockingX);
6496 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6497 SMB_ASSERT(ok);
6499 status = smbd_smb1_do_locks_recv(subreq);
6500 TALLOC_FREE(subreq);
6502 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
6504 if (NT_STATUS_IS_OK(status)) {
6505 reply_smb1_outbuf(req, 2, 0);
6506 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
6507 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
6508 } else {
6509 reply_nterror(req, status);
6512 ok = smb1_srv_send(req->xconn,
6513 (char *)req->outbuf,
6514 true,
6515 req->seqnum+1,
6516 IS_CONN_ENCRYPTED(req->conn),
6517 NULL);
6518 if (!ok) {
6519 exit_server_cleanly("reply_lock_done: smb1_srv_send failed.");
6521 TALLOC_FREE(req);
6522 END_PROFILE(SMBlockingX);
6525 #undef DBGC_CLASS
6526 #define DBGC_CLASS DBGC_ALL
6528 /****************************************************************************
6529 Reply to a SMBreadbmpx (read block multiplex) request.
6530 Always reply with an error, if someone has a platform really needs this,
6531 please contact vl@samba.org
6532 ****************************************************************************/
6534 void reply_readbmpx(struct smb_request *req)
6536 START_PROFILE(SMBreadBmpx);
6537 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6538 END_PROFILE(SMBreadBmpx);
6539 return;
6542 /****************************************************************************
6543 Reply to a SMBreadbs (read block multiplex secondary) request.
6544 Always reply with an error, if someone has a platform really needs this,
6545 please contact vl@samba.org
6546 ****************************************************************************/
6548 void reply_readbs(struct smb_request *req)
6550 START_PROFILE(SMBreadBs);
6551 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6552 END_PROFILE(SMBreadBs);
6553 return;
6556 /****************************************************************************
6557 Reply to a SMBsetattrE.
6558 ****************************************************************************/
6560 void reply_setattrE(struct smb_request *req)
6562 connection_struct *conn = req->conn;
6563 struct smb_file_time ft;
6564 files_struct *fsp;
6565 NTSTATUS status;
6567 START_PROFILE(SMBsetattrE);
6568 init_smb_file_time(&ft);
6570 if (req->wct < 7) {
6571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6572 goto out;
6575 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6577 if(!fsp || (fsp->conn != conn)) {
6578 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6579 goto out;
6583 * Convert the DOS times into unix times.
6586 ft.atime = time_t_to_full_timespec(
6587 srv_make_unix_date2(req->vwv+3));
6588 ft.mtime = time_t_to_full_timespec(
6589 srv_make_unix_date2(req->vwv+5));
6590 ft.create_time = time_t_to_full_timespec(
6591 srv_make_unix_date2(req->vwv+1));
6593 reply_smb1_outbuf(req, 0, 0);
6596 * Patch from Ray Frush <frush@engr.colostate.edu>
6597 * Sometimes times are sent as zero - ignore them.
6600 /* Ensure we have a valid stat struct for the source. */
6601 status = vfs_stat_fsp(fsp);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 reply_nterror(req, status);
6604 goto out;
6607 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6608 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6609 goto out;
6612 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
6613 if (!NT_STATUS_IS_OK(status)) {
6614 reply_nterror(req, status);
6615 goto out;
6618 if (fsp->fsp_flags.modified) {
6619 trigger_write_time_update_immediate(fsp);
6622 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
6623 " createtime=%u\n",
6624 fsp_fnum_dbg(fsp),
6625 (unsigned int)ft.atime.tv_sec,
6626 (unsigned int)ft.mtime.tv_sec,
6627 (unsigned int)ft.create_time.tv_sec
6629 out:
6630 END_PROFILE(SMBsetattrE);
6631 return;
6635 /* Back from the dead for OS/2..... JRA. */
6637 /****************************************************************************
6638 Reply to a SMBwritebmpx (write block multiplex primary) request.
6639 Always reply with an error, if someone has a platform really needs this,
6640 please contact vl@samba.org
6641 ****************************************************************************/
6643 void reply_writebmpx(struct smb_request *req)
6645 START_PROFILE(SMBwriteBmpx);
6646 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6647 END_PROFILE(SMBwriteBmpx);
6648 return;
6651 /****************************************************************************
6652 Reply to a SMBwritebs (write block multiplex secondary) request.
6653 Always reply with an error, if someone has a platform really needs this,
6654 please contact vl@samba.org
6655 ****************************************************************************/
6657 void reply_writebs(struct smb_request *req)
6659 START_PROFILE(SMBwriteBs);
6660 reply_force_doserror(req, ERRSRV, ERRuseSTD);
6661 END_PROFILE(SMBwriteBs);
6662 return;
6665 /****************************************************************************
6666 Reply to a SMBgetattrE.
6667 ****************************************************************************/
6669 void reply_getattrE(struct smb_request *req)
6671 connection_struct *conn = req->conn;
6672 int mode;
6673 files_struct *fsp;
6674 struct timespec create_ts;
6675 NTSTATUS status;
6677 START_PROFILE(SMBgetattrE);
6679 if (req->wct < 1) {
6680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6681 END_PROFILE(SMBgetattrE);
6682 return;
6685 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6687 if(!fsp || (fsp->conn != conn)) {
6688 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6689 END_PROFILE(SMBgetattrE);
6690 return;
6693 /* Do an fstat on this file */
6694 status = vfs_stat_fsp(fsp);
6695 if (!NT_STATUS_IS_OK(status)) {
6696 reply_nterror(req, status);
6697 END_PROFILE(SMBgetattrE);
6698 return;
6701 mode = fdos_mode(fsp);
6704 * Convert the times into dos times. Set create
6705 * date to be last modify date as UNIX doesn't save
6706 * this.
6709 reply_smb1_outbuf(req, 11, 0);
6711 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
6712 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
6713 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
6714 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
6715 /* Should we check pending modtime here ? JRA */
6716 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
6717 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
6719 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
6720 SIVAL(req->outbuf, smb_vwv6, 0);
6721 SIVAL(req->outbuf, smb_vwv8, 0);
6722 } else {
6723 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
6724 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
6725 SIVAL(req->outbuf, smb_vwv8, allocation_size);
6727 SSVAL(req->outbuf,smb_vwv10, mode);
6729 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
6731 END_PROFILE(SMBgetattrE);
6732 return;
6735 /****************************************************************************
6736 Reply to a SMBfindclose (stop trans2 directory search).
6737 ****************************************************************************/
6739 void reply_findclose(struct smb_request *req)
6741 int dptr_num;
6742 struct smbd_server_connection *sconn = req->sconn;
6743 files_struct *fsp = NULL;
6745 START_PROFILE(SMBfindclose);
6747 if (req->wct < 1) {
6748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6749 END_PROFILE(SMBfindclose);
6750 return;
6753 dptr_num = SVALS(req->vwv+0, 0);
6755 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6758 * OS/2 seems to use -1 to indicate "close all directories"
6759 * This has to mean on this specific connection struct.
6761 if (dptr_num == -1) {
6762 dptr_closecnum(req->conn);
6763 } else {
6764 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
6765 dptr_num = -1;
6766 if (fsp != NULL) {
6767 close_file_free(NULL, &fsp, NORMAL_CLOSE);
6771 reply_smb1_outbuf(req, 0, 0);
6773 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6775 END_PROFILE(SMBfindclose);
6776 return;
6779 /****************************************************************************
6780 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6781 ****************************************************************************/
6783 void reply_findnclose(struct smb_request *req)
6785 int dptr_num;
6787 START_PROFILE(SMBfindnclose);
6789 if (req->wct < 1) {
6790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6791 END_PROFILE(SMBfindnclose);
6792 return;
6795 dptr_num = SVAL(req->vwv+0, 0);
6797 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6799 /* We never give out valid handles for a
6800 findnotifyfirst - so any dptr_num is ok here.
6801 Just ignore it. */
6803 reply_smb1_outbuf(req, 0, 0);
6805 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6807 END_PROFILE(SMBfindnclose);
6808 return;