smbd: Move reply_special to smb2_reply.c
[samba.git] / source3 / smbd / reply.c
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
8
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.
13
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.
18
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/>.
21 */
22 /*
23    This file handles most of the reply_ calls that the server
24    makes to handle specific protocols
25 */
26
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 "smb1_utils.h"
51 #include "libcli/smb/smb2_posix.h"
52 #include "lib/util/string_wrappers.h"
53 #include "source3/printing/rap_jobid.h"
54 #include "source3/lib/substitute.h"
55
56 /****************************************************************************
57  Reply to a tcon.
58  conn POINTER CAN BE NULL HERE !
59 ****************************************************************************/
60
61 void reply_tcon(struct smb_request *req)
62 {
63         connection_struct *conn = req->conn;
64         const char *service;
65         char *service_buf = NULL;
66         char *password = NULL;
67         char *dev = NULL;
68         int pwlen=0;
69         NTSTATUS nt_status;
70         const uint8_t *p;
71         const char *p2;
72         TALLOC_CTX *ctx = talloc_tos();
73         struct smbXsrv_connection *xconn = req->xconn;
74         NTTIME now = timeval_to_nttime(&req->request_time);
75
76         START_PROFILE(SMBtcon);
77
78         if (req->buflen < 4) {
79                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
80                 END_PROFILE(SMBtcon);
81                 return;
82         }
83
84         p = req->buf + 1;
85         p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
86         p += 1;
87         pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
88         p += pwlen+1;
89         p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
90         p += 1;
91
92         if (service_buf == NULL || password == NULL || dev == NULL) {
93                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
94                 END_PROFILE(SMBtcon);
95                 return;
96         }
97         p2 = strrchr_m(service_buf,'\\');
98         if (p2) {
99                 service = p2+1;
100         } else {
101                 service = service_buf;
102         }
103
104         conn = make_connection(req, now, service, dev,
105                                req->vuid,&nt_status);
106         req->conn = conn;
107
108         if (!conn) {
109                 reply_nterror(req, nt_status);
110                 END_PROFILE(SMBtcon);
111                 return;
112         }
113
114         reply_outbuf(req, 2, 0);
115         SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
116         SSVAL(req->outbuf,smb_vwv1,conn->cnum);
117         SSVAL(req->outbuf,smb_tid,conn->cnum);
118
119         DEBUG(3,("tcon service=%s cnum=%d\n",
120                  service, conn->cnum));
121
122         END_PROFILE(SMBtcon);
123         return;
124 }
125
126 /****************************************************************************
127  Reply to a tcon and X.
128  conn POINTER CAN BE NULL HERE !
129 ****************************************************************************/
130
131 void reply_tcon_and_X(struct smb_request *req)
132 {
133         const struct loadparm_substitution *lp_sub =
134                 loadparm_s3_global_substitution();
135         connection_struct *conn = req->conn;
136         const char *service = NULL;
137         TALLOC_CTX *ctx = talloc_tos();
138         /* what the client thinks the device is */
139         char *client_devicetype = NULL;
140         /* what the server tells the client the share represents */
141         const char *server_devicetype;
142         NTSTATUS nt_status;
143         int passlen;
144         char *path = NULL;
145         const uint8_t *p;
146         const char *q;
147         uint16_t tcon_flags;
148         struct smbXsrv_session *session = NULL;
149         NTTIME now = timeval_to_nttime(&req->request_time);
150         bool session_key_updated = false;
151         uint16_t optional_support = 0;
152         struct smbXsrv_connection *xconn = req->xconn;
153
154         START_PROFILE(SMBtconX);
155
156         if (req->wct < 4) {
157                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
158                 END_PROFILE(SMBtconX);
159                 return;
160         }
161
162         passlen = SVAL(req->vwv+3, 0);
163         tcon_flags = SVAL(req->vwv+2, 0);
164
165         /* we might have to close an old one */
166         if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
167                 struct smbXsrv_tcon *tcon;
168                 NTSTATUS status;
169
170                 tcon = conn->tcon;
171                 req->conn = NULL;
172                 conn = NULL;
173
174                 /*
175                  * TODO: cancel all outstanding requests on the tcon
176                  */
177                 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
178                 if (!NT_STATUS_IS_OK(status)) {
179                         DEBUG(0, ("reply_tcon_and_X: "
180                                   "smbXsrv_tcon_disconnect() failed: %s\n",
181                                   nt_errstr(status)));
182                         /*
183                          * If we hit this case, there is something completely
184                          * wrong, so we better disconnect the transport connection.
185                          */
186                         END_PROFILE(SMBtconX);
187                         exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
188                         return;
189                 }
190
191                 TALLOC_FREE(tcon);
192                 /*
193                  * This tree id is gone. Make sure we can't re-use it
194                  * by accident.
195                  */
196                 req->tid = 0;
197         }
198
199         if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
200                 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
201                 END_PROFILE(SMBtconX);
202                 return;
203         }
204
205         if (xconn->smb1.negprot.encrypted_passwords) {
206                 p = req->buf + passlen;
207         } else {
208                 p = req->buf + passlen + 1;
209         }
210
211         p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
212
213         if (path == NULL) {
214                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
215                 END_PROFILE(SMBtconX);
216                 return;
217         }
218
219         /*
220          * the service name can be either: \\server\share
221          * or share directly like on the DELL PowerVault 705
222          */
223         if (*path=='\\') {
224                 q = strchr_m(path+2,'\\');
225                 if (!q) {
226                         reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
227                         END_PROFILE(SMBtconX);
228                         return;
229                 }
230                 service = q+1;
231         } else {
232                 service = path;
233         }
234
235         p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
236                                 &client_devicetype, p,
237                                 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
238
239         if (client_devicetype == NULL) {
240                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
241                 END_PROFILE(SMBtconX);
242                 return;
243         }
244
245         DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
246
247         nt_status = smb1srv_session_lookup(xconn,
248                                            req->vuid, now, &session);
249         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
250                 reply_force_doserror(req, ERRSRV, ERRbaduid);
251                 END_PROFILE(SMBtconX);
252                 return;
253         }
254         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
255                 reply_nterror(req, nt_status);
256                 END_PROFILE(SMBtconX);
257                 return;
258         }
259         if (!NT_STATUS_IS_OK(nt_status)) {
260                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
261                 END_PROFILE(SMBtconX);
262                 return;
263         }
264
265         if (session->global->auth_session_info == NULL) {
266                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
267                 END_PROFILE(SMBtconX);
268                 return;
269         }
270
271         /*
272          * If there is no application key defined yet
273          * we create one.
274          *
275          * This means we setup the application key on the
276          * first tcon that happens via the given session.
277          *
278          * Once the application key is defined, it does not
279          * change any more.
280          */
281         if (session->global->application_key_blob.length == 0 &&
282             smb2_signing_key_valid(session->global->signing_key))
283         {
284                 struct smbXsrv_session *x = session;
285                 struct auth_session_info *session_info =
286                         session->global->auth_session_info;
287                 uint8_t session_key[16];
288
289                 ZERO_STRUCT(session_key);
290                 memcpy(session_key, x->global->signing_key->blob.data,
291                        MIN(x->global->signing_key->blob.length, sizeof(session_key)));
292
293                 /*
294                  * The application key is truncated/padded to 16 bytes
295                  */
296                 x->global->application_key_blob = data_blob_talloc(x->global,
297                                                              session_key,
298                                                              sizeof(session_key));
299                 ZERO_STRUCT(session_key);
300                 if (x->global->application_key_blob.data == NULL) {
301                         reply_nterror(req, NT_STATUS_NO_MEMORY);
302                         END_PROFILE(SMBtconX);
303                         return;
304                 }
305                 talloc_keep_secret(x->global->application_key_blob.data);
306
307                 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
308                         NTSTATUS status;
309
310                         status = smb1_key_derivation(x->global->application_key_blob.data,
311                                                     x->global->application_key_blob.length,
312                                                     x->global->application_key_blob.data);
313                         if (!NT_STATUS_IS_OK(status)) {
314                                 DBG_ERR("smb1_key_derivation failed: %s\n",
315                                         nt_errstr(status));
316                                 END_PROFILE(SMBtconX);
317                                 return;
318                         }
319                         optional_support |= SMB_EXTENDED_SIGNATURES;
320                 }
321
322                 /*
323                  * Place the application key into the session_info
324                  */
325                 data_blob_clear_free(&session_info->session_key);
326                 session_info->session_key = data_blob_dup_talloc(session_info,
327                                                 x->global->application_key_blob);
328                 if (session_info->session_key.data == NULL) {
329                         data_blob_clear_free(&x->global->application_key_blob);
330                         reply_nterror(req, NT_STATUS_NO_MEMORY);
331                         END_PROFILE(SMBtconX);
332                         return;
333                 }
334                 talloc_keep_secret(session_info->session_key.data);
335                 session_key_updated = true;
336         }
337
338         conn = make_connection(req, now, service, client_devicetype,
339                                req->vuid, &nt_status);
340         req->conn =conn;
341
342         if (!conn) {
343                 if (session_key_updated) {
344                         struct smbXsrv_session *x = session;
345                         struct auth_session_info *session_info =
346                                 session->global->auth_session_info;
347                         data_blob_clear_free(&x->global->application_key_blob);
348                         data_blob_clear_free(&session_info->session_key);
349                 }
350                 reply_nterror(req, nt_status);
351                 END_PROFILE(SMBtconX);
352                 return;
353         }
354
355         if ( IS_IPC(conn) )
356                 server_devicetype = "IPC";
357         else if ( IS_PRINT(conn) )
358                 server_devicetype = "LPT1:";
359         else
360                 server_devicetype = "A:";
361
362         if (get_Protocol() < PROTOCOL_NT1) {
363                 reply_outbuf(req, 2, 0);
364                 if (message_push_string(&req->outbuf, server_devicetype,
365                                         STR_TERMINATE|STR_ASCII) == -1) {
366                         reply_nterror(req, NT_STATUS_NO_MEMORY);
367                         END_PROFILE(SMBtconX);
368                         return;
369                 }
370         } else {
371                 /* NT sets the fstype of IPC$ to the null string */
372                 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
373
374                 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
375                         /* Return permissions. */
376                         uint32_t perm1 = 0;
377                         uint32_t perm2 = 0;
378
379                         reply_outbuf(req, 7, 0);
380
381                         if (IS_IPC(conn)) {
382                                 perm1 = FILE_ALL_ACCESS;
383                                 perm2 = FILE_ALL_ACCESS;
384                         } else {
385                                 perm1 = conn->share_access;
386                         }
387
388                         SIVAL(req->outbuf, smb_vwv3, perm1);
389                         SIVAL(req->outbuf, smb_vwv5, perm2);
390                 } else {
391                         reply_outbuf(req, 3, 0);
392                 }
393
394                 if ((message_push_string(&req->outbuf, server_devicetype,
395                                          STR_TERMINATE|STR_ASCII) == -1)
396                     || (message_push_string(&req->outbuf, fstype,
397                                             STR_TERMINATE) == -1)) {
398                         reply_nterror(req, NT_STATUS_NO_MEMORY);
399                         END_PROFILE(SMBtconX);
400                         return;
401                 }
402
403                 /* what does setting this bit do? It is set by NT4 and
404                    may affect the ability to autorun mounted cdroms */
405                 optional_support |= SMB_SUPPORT_SEARCH_BITS;
406                 optional_support |=
407                         (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
408
409                 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
410                         DEBUG(2,("Serving %s as a Dfs root\n",
411                                  lp_servicename(ctx, lp_sub, SNUM(conn)) ));
412                         optional_support |= SMB_SHARE_IN_DFS;
413                 }
414
415                 SSVAL(req->outbuf, smb_vwv2, optional_support);
416         }
417
418         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
419         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
420
421         DEBUG(3,("tconX service=%s \n",
422                  service));
423
424         /* set the incoming and outgoing tid to the just created one */
425         SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
426         SSVAL(req->outbuf,smb_tid,conn->cnum);
427
428         END_PROFILE(SMBtconX);
429
430         req->tid = conn->cnum;
431 }
432
433 /****************************************************************************
434  Reply to an unknown type.
435 ****************************************************************************/
436
437 void reply_unknown_new(struct smb_request *req, uint8_t type)
438 {
439         DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
440                   smb_fn_name(type), type, type));
441         reply_force_doserror(req, ERRSRV, ERRunknownsmb);
442         return;
443 }
444
445 /****************************************************************************
446  Reply to an ioctl.
447  conn POINTER CAN BE NULL HERE !
448 ****************************************************************************/
449
450 void reply_ioctl(struct smb_request *req)
451 {
452         const struct loadparm_substitution *lp_sub =
453                 loadparm_s3_global_substitution();
454         connection_struct *conn = req->conn;
455         uint16_t device;
456         uint16_t function;
457         uint32_t ioctl_code;
458         int replysize;
459         char *p;
460
461         START_PROFILE(SMBioctl);
462
463         if (req->wct < 3) {
464                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
465                 END_PROFILE(SMBioctl);
466                 return;
467         }
468
469         device     = SVAL(req->vwv+1, 0);
470         function   = SVAL(req->vwv+2, 0);
471         ioctl_code = (device << 16) + function;
472
473         DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
474
475         switch (ioctl_code) {
476             case IOCTL_QUERY_JOB_INFO:
477                     replysize = 32;
478                     break;
479             default:
480                     reply_force_doserror(req, ERRSRV, ERRnosupport);
481                     END_PROFILE(SMBioctl);
482                     return;
483         }
484
485         reply_outbuf(req, 8, replysize+1);
486         SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
487         SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
488         SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
489         p = smb_buf(req->outbuf);
490         memset(p, '\0', replysize+1); /* valgrind-safe. */
491         p += 1;          /* Allow for alignment */
492
493         switch (ioctl_code) {
494                 case IOCTL_QUERY_JOB_INFO:                  
495                 {
496                         NTSTATUS status;
497                         size_t len = 0;
498                         files_struct *fsp = file_fsp(
499                                 req, SVAL(req->vwv+0, 0));
500                         if (!fsp) {
501                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
502                                 END_PROFILE(SMBioctl);
503                                 return;
504                         }
505                         /* Job number */
506                         SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
507
508                         status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
509                                     lp_netbios_name(), 15,
510                                     STR_TERMINATE|STR_ASCII, &len);
511                         if (!NT_STATUS_IS_OK(status)) {
512                                 reply_nterror(req, status);
513                                 END_PROFILE(SMBioctl);
514                                 return;
515                         }
516                         if (conn) {
517                                 status = srvstr_push((char *)req->outbuf, req->flags2,
518                                             p+18,
519                                             lp_servicename(talloc_tos(),
520                                                            lp_sub,
521                                                            SNUM(conn)),
522                                             13, STR_TERMINATE|STR_ASCII, &len);
523                                 if (!NT_STATUS_IS_OK(status)) {
524                                         reply_nterror(req, status);
525                                         END_PROFILE(SMBioctl);
526                                         return;
527                                 }
528                         } else {
529                                 memset(p+18, 0, 13);
530                         }
531                         break;
532                 }
533         }
534
535         END_PROFILE(SMBioctl);
536         return;
537 }
538
539 /****************************************************************************
540  Strange checkpath NTSTATUS mapping.
541 ****************************************************************************/
542
543 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
544 {
545         /* Strange DOS error code semantics only for checkpath... */
546         if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
547                 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
548                         /* We need to map to ERRbadpath */
549                         return NT_STATUS_OBJECT_PATH_NOT_FOUND;
550                 }
551         }
552         return status;
553 }
554
555 /****************************************************************************
556  Reply to a checkpath.
557 ****************************************************************************/
558
559 void reply_checkpath(struct smb_request *req)
560 {
561         connection_struct *conn = req->conn;
562         struct smb_filename *smb_fname = NULL;
563         char *name = NULL;
564         NTSTATUS status;
565         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
566         TALLOC_CTX *ctx = talloc_tos();
567
568         START_PROFILE(SMBcheckpath);
569
570         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
571                             STR_TERMINATE, &status);
572
573         if (!NT_STATUS_IS_OK(status)) {
574                 status = map_checkpath_error(req->flags2, status);
575                 reply_nterror(req, status);
576                 END_PROFILE(SMBcheckpath);
577                 return;
578         }
579
580         DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
581
582         status = filename_convert(ctx,
583                                 conn,
584                                 name,
585                                 ucf_flags,
586                                 0,
587                                 &smb_fname);
588
589         if (!NT_STATUS_IS_OK(status)) {
590                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
591                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
592                                         ERRSRV, ERRbadpath);
593                         END_PROFILE(SMBcheckpath);
594                         return;
595                 }
596                 goto path_err;
597         }
598
599         if (!VALID_STAT(smb_fname->st) &&
600             (SMB_VFS_STAT(conn, smb_fname) != 0)) {
601                 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
602                         smb_fname_str_dbg(smb_fname), strerror(errno)));
603                 status = map_nt_error_from_unix(errno);
604                 goto path_err;
605         }
606
607         if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
608                 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
609                                 ERRDOS, ERRbadpath);
610                 goto out;
611         }
612
613         reply_outbuf(req, 0, 0);
614
615  path_err:
616         /* We special case this - as when a Windows machine
617                 is parsing a path is steps through the components
618                 one at a time - if a component fails it expects
619                 ERRbadpath, not ERRbadfile.
620         */
621         status = map_checkpath_error(req->flags2, status);
622         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
623                 /*
624                  * Windows returns different error codes if
625                  * the parent directory is valid but not the
626                  * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
627                  * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
628                  * if the path is invalid.
629                  */
630                 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
631                                 ERRDOS, ERRbadpath);
632                 goto out;
633         }
634
635         reply_nterror(req, status);
636
637  out:
638         TALLOC_FREE(smb_fname);
639         END_PROFILE(SMBcheckpath);
640         return;
641 }
642
643 /****************************************************************************
644  Reply to a getatr.
645 ****************************************************************************/
646
647 void reply_getatr(struct smb_request *req)
648 {
649         connection_struct *conn = req->conn;
650         struct smb_filename *smb_fname = NULL;
651         char *fname = NULL;
652         int mode=0;
653         off_t size=0;
654         time_t mtime=0;
655         const char *p;
656         NTSTATUS status;
657         TALLOC_CTX *ctx = talloc_tos();
658         bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
659
660         START_PROFILE(SMBgetatr);
661
662         p = (const char *)req->buf + 1;
663         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
664         if (!NT_STATUS_IS_OK(status)) {
665                 reply_nterror(req, status);
666                 goto out;
667         }
668
669         /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
670                 under WfWg - weird! */
671         if (*fname == '\0') {
672                 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
673                 if (!CAN_WRITE(conn)) {
674                         mode |= FILE_ATTRIBUTE_READONLY;
675                 }
676                 size = 0;
677                 mtime = 0;
678         } else {
679                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
680                 status = filename_convert(ctx,
681                                 conn,
682                                 fname,
683                                 ucf_flags,
684                                 0,
685                                 &smb_fname);
686                 if (!NT_STATUS_IS_OK(status)) {
687                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
688                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
689                                                 ERRSRV, ERRbadpath);
690                                 goto out;
691                         }
692                         reply_nterror(req, status);
693                         goto out;
694                 }
695                 if (!VALID_STAT(smb_fname->st) &&
696                     (SMB_VFS_STAT(conn, smb_fname) != 0)) {
697                         DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
698                                  smb_fname_str_dbg(smb_fname),
699                                  strerror(errno)));
700                         reply_nterror(req,  map_nt_error_from_unix(errno));
701                         goto out;
702                 }
703
704                 mode = fdos_mode(smb_fname->fsp);
705                 size = smb_fname->st.st_ex_size;
706
707                 if (ask_sharemode) {
708                         struct timespec write_time_ts;
709                         struct file_id fileid;
710
711                         ZERO_STRUCT(write_time_ts);
712                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
713                         get_file_infos(fileid, 0, NULL, &write_time_ts);
714                         if (!is_omit_timespec(&write_time_ts)) {
715                                 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
716                         }
717                 }
718
719                 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
720                 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
721                         size = 0;
722                 }
723         }
724
725         reply_outbuf(req, 10, 0);
726
727         SSVAL(req->outbuf,smb_vwv0,mode);
728         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
729                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
730         } else {
731                 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
732         }
733         SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
734
735         if (get_Protocol() >= PROTOCOL_NT1) {
736                 SSVAL(req->outbuf, smb_flg2,
737                       SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
738         }
739
740         DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
741                  smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
742
743  out:
744         TALLOC_FREE(smb_fname);
745         TALLOC_FREE(fname);
746         END_PROFILE(SMBgetatr);
747         return;
748 }
749
750 /****************************************************************************
751  Reply to a setatr.
752 ****************************************************************************/
753
754 void reply_setatr(struct smb_request *req)
755 {
756         struct smb_file_time ft;
757         connection_struct *conn = req->conn;
758         struct smb_filename *smb_fname = NULL;
759         char *fname = NULL;
760         int mode;
761         time_t mtime;
762         const char *p;
763         NTSTATUS status;
764         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
765         TALLOC_CTX *ctx = talloc_tos();
766
767         START_PROFILE(SMBsetatr);
768         init_smb_file_time(&ft);
769
770         if (req->wct < 2) {
771                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
772                 goto out;
773         }
774
775         p = (const char *)req->buf + 1;
776         p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
777         if (!NT_STATUS_IS_OK(status)) {
778                 reply_nterror(req, status);
779                 goto out;
780         }
781
782         status = filename_convert(ctx,
783                                 conn,
784                                 fname,
785                                 ucf_flags,
786                                 0,
787                                 &smb_fname);
788         if (!NT_STATUS_IS_OK(status)) {
789                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
790                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
791                                         ERRSRV, ERRbadpath);
792                         goto out;
793                 }
794                 reply_nterror(req, status);
795                 goto out;
796         }
797
798         if (ISDOT(smb_fname->base_name)) {
799                 /*
800                  * Not sure here is the right place to catch this
801                  * condition. Might be moved to somewhere else later -- vl
802                  */
803                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
804                 goto out;
805         }
806
807         if (smb_fname->fsp == NULL) {
808                 /* Can't set access rights on a symlink. */
809                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
810                 goto out;
811         }
812
813         mode = SVAL(req->vwv+0, 0);
814         mtime = srv_make_unix_date3(req->vwv+1);
815
816         if (mode != FILE_ATTRIBUTE_NORMAL) {
817                 if (VALID_STAT_OF_DIR(smb_fname->st))
818                         mode |= FILE_ATTRIBUTE_DIRECTORY;
819                 else
820                         mode &= ~FILE_ATTRIBUTE_DIRECTORY;
821
822                 status = smbd_check_access_rights_fsp(conn->cwd_fsp,
823                                         smb_fname->fsp,
824                                         false,
825                                         FILE_WRITE_ATTRIBUTES);
826                 if (!NT_STATUS_IS_OK(status)) {
827                         reply_nterror(req, status);
828                         goto out;
829                 }
830
831                 if (file_set_dosmode(conn, smb_fname, mode, NULL,
832                                      false) != 0) {
833                         reply_nterror(req, map_nt_error_from_unix(errno));
834                         goto out;
835                 }
836         }
837
838         ft.mtime = time_t_to_full_timespec(mtime);
839
840         status = smb_set_file_time(conn, smb_fname->fsp, smb_fname, &ft, true);
841         if (!NT_STATUS_IS_OK(status)) {
842                 reply_nterror(req, status);
843                 goto out;
844         }
845
846         reply_outbuf(req, 0, 0);
847
848         DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
849                  mode));
850  out:
851         TALLOC_FREE(smb_fname);
852         END_PROFILE(SMBsetatr);
853         return;
854 }
855
856 /****************************************************************************
857  Reply to a dskattr.
858 ****************************************************************************/
859
860 void reply_dskattr(struct smb_request *req)
861 {
862         connection_struct *conn = req->conn;
863         uint64_t ret;
864         uint64_t dfree,dsize,bsize;
865         struct smb_filename smb_fname;
866         START_PROFILE(SMBdskattr);
867
868         ZERO_STRUCT(smb_fname);
869         smb_fname.base_name = discard_const_p(char, ".");
870
871         if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
872                 reply_nterror(req, map_nt_error_from_unix(errno));
873                 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
874                 END_PROFILE(SMBdskattr);
875                 return;
876         }
877
878         ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
879         if (ret == (uint64_t)-1) {
880                 reply_nterror(req, map_nt_error_from_unix(errno));
881                 END_PROFILE(SMBdskattr);
882                 return;
883         }
884
885         /*
886          * Force max to fit in 16 bit fields.
887          */
888         while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
889                 dfree /= 2;
890                 dsize /= 2;
891                 bsize *= 2;
892                 if (bsize > (WORDMAX*512)) {
893                         bsize = (WORDMAX*512);
894                         if (dsize > WORDMAX)
895                                 dsize = WORDMAX;
896                         if (dfree >  WORDMAX)
897                                 dfree = WORDMAX;
898                         break;
899                 }
900         }
901
902         reply_outbuf(req, 5, 0);
903
904         if (get_Protocol() <= PROTOCOL_LANMAN2) {
905                 double total_space, free_space;
906                 /* we need to scale this to a number that DOS6 can handle. We
907                    use floating point so we can handle large drives on systems
908                    that don't have 64 bit integers 
909
910                    we end up displaying a maximum of 2G to DOS systems
911                 */
912                 total_space = dsize * (double)bsize;
913                 free_space = dfree * (double)bsize;
914
915                 dsize = (uint64_t)((total_space+63*512) / (64*512));
916                 dfree = (uint64_t)((free_space+63*512) / (64*512));
917
918                 if (dsize > 0xFFFF) dsize = 0xFFFF;
919                 if (dfree > 0xFFFF) dfree = 0xFFFF;
920
921                 SSVAL(req->outbuf,smb_vwv0,dsize);
922                 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
923                 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
924                 SSVAL(req->outbuf,smb_vwv3,dfree);
925         } else {
926                 SSVAL(req->outbuf,smb_vwv0,dsize);
927                 SSVAL(req->outbuf,smb_vwv1,bsize/512);
928                 SSVAL(req->outbuf,smb_vwv2,512);
929                 SSVAL(req->outbuf,smb_vwv3,dfree);
930         }
931
932         DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
933
934         END_PROFILE(SMBdskattr);
935         return;
936 }
937
938 /****************************************************************************
939  Make a dir struct.
940 ****************************************************************************/
941
942 static bool make_dir_struct(TALLOC_CTX *ctx,
943                             char *buf,
944                             const char *mask,
945                             const char *fname,
946                             off_t size,
947                             uint32_t mode,
948                             time_t date,
949                             bool uc)
950 {
951         char *p;
952         char *mask2 = talloc_strdup(ctx, mask);
953
954         if (!mask2) {
955                 return False;
956         }
957
958         if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
959                 size = 0;
960         }
961
962         memset(buf+1,' ',11);
963         if ((p = strchr_m(mask2,'.')) != NULL) {
964                 *p = 0;
965                 push_ascii(buf+1,mask2,8, 0);
966                 push_ascii(buf+9,p+1,3, 0);
967                 *p = '.';
968         } else {
969                 push_ascii(buf+1,mask2,11, 0);
970         }
971
972         memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
973         SCVAL(buf,21,mode);
974         srv_put_dos_date(buf,22,date);
975         SSVAL(buf,26,size & 0xFFFF);
976         SSVAL(buf,28,(size >> 16)&0xFFFF);
977         /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
978            Strange, but verified on W2K3. Needed for OS/2. JRA. */
979         push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
980         DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
981         return True;
982 }
983
984 /****************************************************************************
985  Reply to a search.
986  Can be called from SMBsearch, SMBffirst or SMBfunique.
987 ****************************************************************************/
988
989 void reply_search(struct smb_request *req)
990 {
991         connection_struct *conn = req->conn;
992         char *path = NULL;
993         char *mask = NULL;
994         char *directory = NULL;
995         struct smb_filename *smb_fname = NULL;
996         char *fname = NULL;
997         off_t size;
998         uint32_t mode;
999         struct timespec date;
1000         uint32_t dirtype;
1001         unsigned int numentries = 0;
1002         unsigned int maxentries = 0;
1003         bool finished = False;
1004         const char *p;
1005         int status_len;
1006         char status[21];
1007         int dptr_num= -1;
1008         bool check_descend = False;
1009         bool expect_close = False;
1010         NTSTATUS nt_status;
1011         bool mask_contains_wcard = False;
1012         bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1013         TALLOC_CTX *ctx = talloc_tos();
1014         bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1015         struct smbXsrv_connection *xconn = req->xconn;
1016         struct smbd_server_connection *sconn = req->sconn;
1017         files_struct *fsp = NULL;
1018         const struct loadparm_substitution *lp_sub =
1019                 loadparm_s3_global_substitution();
1020
1021         START_PROFILE(SMBsearch);
1022
1023         if (req->wct < 2) {
1024                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1025                 goto out;
1026         }
1027
1028         if (req->posix_pathnames) {
1029                 reply_unknown_new(req, req->cmd);
1030                 goto out;
1031         }
1032
1033         /* If we were called as SMBffirst then we must expect close. */
1034         if(req->cmd == SMBffirst) {
1035                 expect_close = True;
1036         }
1037
1038         reply_outbuf(req, 1, 3);
1039         maxentries = SVAL(req->vwv+0, 0);
1040         dirtype = SVAL(req->vwv+1, 0);
1041         p = (const char *)req->buf + 1;
1042         p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1043                                        &nt_status);
1044         if (!NT_STATUS_IS_OK(nt_status)) {
1045                 reply_nterror(req, nt_status);
1046                 goto out;
1047         }
1048
1049         if (smbreq_bufrem(req, p) < 3) {
1050                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1051                 goto out;
1052         }
1053
1054         p++;
1055         status_len = SVAL(p, 0);
1056         p += 2;
1057
1058         /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1059
1060         if (status_len == 0) {
1061                 const char *dirpath;
1062                 struct smb_filename *smb_dname = NULL;
1063                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1064
1065                 nt_status = filename_convert_smb1_search_path(ctx,
1066                                         conn,
1067                                         path,
1068                                         ucf_flags,
1069                                         &smb_dname,
1070                                         &mask);
1071
1072                 if (!NT_STATUS_IS_OK(nt_status)) {
1073                         if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1074                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1075                                                 ERRSRV, ERRbadpath);
1076                                 goto out;
1077                         }
1078                         reply_nterror(req, nt_status);
1079                         goto out;
1080                 }
1081
1082                 memset((char *)status,'\0',21);
1083                 SCVAL(status,0,(dirtype & 0x1F));
1084
1085                 /*
1086                  * Open an fsp on this directory for the dptr.
1087                  */
1088                 nt_status = SMB_VFS_CREATE_FILE(
1089                                 conn, /* conn */
1090                                 req, /* req */
1091                                 smb_dname, /* dname */
1092                                 FILE_LIST_DIRECTORY, /* access_mask */
1093                                 FILE_SHARE_READ|
1094                                 FILE_SHARE_WRITE, /* share_access */
1095                                 FILE_OPEN, /* create_disposition*/
1096                                 FILE_DIRECTORY_FILE, /* create_options */
1097                                 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1098                                 NO_OPLOCK, /* oplock_request */
1099                                 NULL, /* lease */
1100                                 0, /* allocation_size */
1101                                 0, /* private_flags */
1102                                 NULL, /* sd */
1103                                 NULL, /* ea_list */
1104                                 &fsp, /* result */
1105                                 NULL, /* pinfo */
1106                                 NULL, /* in_context */
1107                                 NULL);/* out_context */
1108
1109                 if (!NT_STATUS_IS_OK(nt_status)) {
1110                         DBG_ERR("failed to open directory %s\n",
1111                                 smb_fname_str_dbg(smb_dname));
1112                         reply_nterror(req, nt_status);
1113                         goto out;
1114                 }
1115
1116                 nt_status = dptr_create(conn,
1117                                         NULL, /* req */
1118                                         fsp, /* fsp */
1119                                         True,
1120                                         expect_close,
1121                                         req->smbpid,
1122                                         mask,
1123                                         dirtype,
1124                                         &fsp->dptr);
1125
1126                 TALLOC_FREE(smb_dname);
1127
1128                 if (!NT_STATUS_IS_OK(nt_status)) {
1129                         /*
1130                          * Use NULL here for the first parameter (req)
1131                          * as this is not a client visible handle so
1132                          * can'tbe part of an SMB1 chain.
1133                          */
1134                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
1135                         reply_nterror(req, nt_status);
1136                         goto out;
1137                 }
1138
1139                 dptr_num = dptr_dnum(fsp->dptr);
1140                 dirpath = dptr_path(sconn, dptr_num);
1141                 directory = talloc_strdup(ctx, dirpath);
1142                 if (!directory) {
1143                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1144                         goto out;
1145                 }
1146
1147         } else {
1148                 int status_dirtype;
1149                 const char *dirpath;
1150
1151                 if (smbreq_bufrem(req, p) < 21) {
1152                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1153                         goto out;
1154                 }
1155
1156                 memcpy(status,p,21);
1157                 status_dirtype = CVAL(status,0) & 0x1F;
1158                 if (status_dirtype != (dirtype & 0x1F)) {
1159                         dirtype = status_dirtype;
1160                 }
1161
1162                 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1163                 if (fsp == NULL) {
1164                         goto SearchEmpty;
1165                 }
1166                 dirpath = dptr_path(sconn, dptr_num);
1167                 directory = talloc_strdup(ctx, dirpath);
1168                 if (!directory) {
1169                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1170                         goto out;
1171                 }
1172
1173                 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1174                 if (!mask) {
1175                         goto SearchEmpty;
1176                 }
1177                 dirtype = dptr_attr(sconn, dptr_num);
1178         }
1179
1180         mask_contains_wcard = dptr_has_wild(fsp->dptr);
1181
1182         DEBUG(4,("dptr_num is %d\n",dptr_num));
1183
1184         if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1185                 char buf[DIR_STRUCT_SIZE];
1186                 memcpy(buf,status,21);
1187                 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1188                                 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1189                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1190                         goto out;
1191                 }
1192                 dptr_fill(sconn, buf+12,dptr_num);
1193                 if (dptr_zero(buf+12) && (status_len==0)) {
1194                         numentries = 1;
1195                 } else {
1196                         numentries = 0;
1197                 }
1198                 if (message_push_blob(&req->outbuf,
1199                                       data_blob_const(buf, sizeof(buf)))
1200                     == -1) {
1201                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1202                         goto out;
1203                 }
1204         } else {
1205                 unsigned int i;
1206                 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1207                 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1208
1209                 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1210
1211                 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1212                          directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
1213                 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
1214                         check_descend = True;
1215                 }
1216
1217                 for (i=numentries;(i<maxentries) && !finished;i++) {
1218                         finished = !get_dir_entry(ctx,
1219                                                   fsp->dptr,
1220                                                   mask,
1221                                                   dirtype,
1222                                                   &fname,
1223                                                   &size,
1224                                                   &mode,
1225                                                   &date,
1226                                                   check_descend,
1227                                                   ask_sharemode);
1228                         if (!finished) {
1229                                 char buf[DIR_STRUCT_SIZE];
1230                                 memcpy(buf,status,21);
1231                                 if (!make_dir_struct(ctx,
1232                                                 buf,
1233                                                 mask,
1234                                                 fname,
1235                                                 size,
1236                                                 mode,
1237                                                 convert_timespec_to_time_t(date),
1238                                                 !allow_long_path_components)) {
1239                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1240                                         goto out;
1241                                 }
1242                                 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1243                                         break;
1244                                 }
1245                                 if (message_push_blob(&req->outbuf,
1246                                                       data_blob_const(buf, sizeof(buf)))
1247                                     == -1) {
1248                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1249                                         goto out;
1250                                 }
1251                                 numentries++;
1252                         }
1253                 }
1254         }
1255
1256   SearchEmpty:
1257
1258         /* If we were called as SMBffirst with smb_search_id == NULL
1259                 and no entries were found then return error and close fsp->dptr
1260                 (X/Open spec) */
1261
1262         if (numentries == 0) {
1263                 dptr_num = -1;
1264                 if (fsp != NULL) {
1265                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
1266                 }
1267         } else if(expect_close && status_len == 0) {
1268                 /* Close the dptr - we know it's gone */
1269                 dptr_num = -1;
1270                 if (fsp != NULL) {
1271                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
1272                 }
1273         }
1274
1275         /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
1276         if(dptr_num >= 0 && req->cmd == SMBfunique) {
1277                 dptr_num = -1;
1278                 /* fsp may have been closed above. */
1279                 if (fsp != NULL) {
1280                         close_file_free(NULL, &fsp, NORMAL_CLOSE);
1281                 }
1282         }
1283
1284         if ((numentries == 0) && !mask_contains_wcard) {
1285                 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1286                 goto out;
1287         }
1288
1289         SSVAL(req->outbuf,smb_vwv0,numentries);
1290         SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1291         SCVAL(smb_buf(req->outbuf),0,5);
1292         SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1293
1294         /* The replies here are never long name. */
1295         SSVAL(req->outbuf, smb_flg2,
1296               SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1297         if (!allow_long_path_components) {
1298                 SSVAL(req->outbuf, smb_flg2,
1299                       SVAL(req->outbuf, smb_flg2)
1300                       & (~FLAGS2_LONG_PATH_COMPONENTS));
1301         }
1302
1303         /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1304         SSVAL(req->outbuf, smb_flg2,
1305               (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1306
1307         DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1308                 smb_fn_name(req->cmd),
1309                 mask,
1310                 directory,
1311                 dirtype,
1312                 numentries,
1313                 maxentries ));
1314  out:
1315         TALLOC_FREE(directory);
1316         TALLOC_FREE(mask);
1317         TALLOC_FREE(smb_fname);
1318         END_PROFILE(SMBsearch);
1319         return;
1320 }
1321
1322 /****************************************************************************
1323  Reply to a fclose (stop directory search).
1324 ****************************************************************************/
1325
1326 void reply_fclose(struct smb_request *req)
1327 {
1328         int status_len;
1329         char status[21];
1330         int dptr_num= -2;
1331         const char *p;
1332         char *path = NULL;
1333         NTSTATUS err;
1334         TALLOC_CTX *ctx = talloc_tos();
1335         struct smbd_server_connection *sconn = req->sconn;
1336         files_struct *fsp = NULL;
1337
1338         START_PROFILE(SMBfclose);
1339
1340         if (req->posix_pathnames) {
1341                 reply_unknown_new(req, req->cmd);
1342                 END_PROFILE(SMBfclose);
1343                 return;
1344         }
1345
1346         p = (const char *)req->buf + 1;
1347         p += srvstr_get_path_req(ctx, req, &path, p, STR_TERMINATE,
1348                                        &err);
1349         if (!NT_STATUS_IS_OK(err)) {
1350                 reply_nterror(req, err);
1351                 END_PROFILE(SMBfclose);
1352                 return;
1353         }
1354
1355         if (smbreq_bufrem(req, p) < 3) {
1356                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1357                 END_PROFILE(SMBfclose);
1358                 return;
1359         }
1360
1361         p++;
1362         status_len = SVAL(p,0);
1363         p += 2;
1364
1365         if (status_len == 0) {
1366                 reply_force_doserror(req, ERRSRV, ERRsrverror);
1367                 END_PROFILE(SMBfclose);
1368                 return;
1369         }
1370
1371         if (smbreq_bufrem(req, p) < 21) {
1372                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1373                 END_PROFILE(SMBfclose);
1374                 return;
1375         }
1376
1377         memcpy(status,p,21);
1378
1379         fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1380         if(fsp != NULL) {
1381                 /*  Close the file - we know it's gone */
1382                 close_file_free(NULL, &fsp, NORMAL_CLOSE);
1383                 dptr_num = -1;
1384         }
1385
1386         reply_outbuf(req, 1, 0);
1387         SSVAL(req->outbuf,smb_vwv0,0);
1388
1389         DEBUG(3,("search close\n"));
1390
1391         END_PROFILE(SMBfclose);
1392         return;
1393 }
1394
1395 /****************************************************************************
1396  Reply to an open.
1397 ****************************************************************************/
1398
1399 void reply_open(struct smb_request *req)
1400 {
1401         connection_struct *conn = req->conn;
1402         struct smb_filename *smb_fname = NULL;
1403         char *fname = NULL;
1404         uint32_t fattr=0;
1405         off_t size = 0;
1406         time_t mtime=0;
1407         int info;
1408         files_struct *fsp;
1409         int oplock_request;
1410         int deny_mode;
1411         uint32_t dos_attr;
1412         uint32_t access_mask;
1413         uint32_t share_mode;
1414         uint32_t create_disposition;
1415         uint32_t create_options = 0;
1416         uint32_t private_flags = 0;
1417         NTSTATUS status;
1418         uint32_t ucf_flags;
1419         TALLOC_CTX *ctx = talloc_tos();
1420
1421         START_PROFILE(SMBopen);
1422
1423         if (req->wct < 2) {
1424                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1425                 goto out;
1426         }
1427
1428         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1429         deny_mode = SVAL(req->vwv+0, 0);
1430         dos_attr = SVAL(req->vwv+1, 0);
1431
1432         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1433                             STR_TERMINATE, &status);
1434         if (!NT_STATUS_IS_OK(status)) {
1435                 reply_nterror(req, status);
1436                 goto out;
1437         }
1438
1439         if (!map_open_params_to_ntcreate(fname, deny_mode,
1440                                          OPENX_FILE_EXISTS_OPEN, &access_mask,
1441                                          &share_mode, &create_disposition,
1442                                          &create_options, &private_flags)) {
1443                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1444                 goto out;
1445         }
1446
1447         ucf_flags = filename_create_ucf_flags(req, create_disposition);
1448
1449         status = filename_convert(ctx,
1450                                 conn,
1451                                 fname,
1452                                 ucf_flags,
1453                                 0,
1454                                 &smb_fname);
1455         if (!NT_STATUS_IS_OK(status)) {
1456                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1457                         reply_botherror(req,
1458                                         NT_STATUS_PATH_NOT_COVERED,
1459                                         ERRSRV, ERRbadpath);
1460                         goto out;
1461                 }
1462                 reply_nterror(req, status);
1463                 goto out;
1464         }
1465
1466         status = SMB_VFS_CREATE_FILE(
1467                 conn,                                   /* conn */
1468                 req,                                    /* req */
1469                 smb_fname,                              /* fname */
1470                 access_mask,                            /* access_mask */
1471                 share_mode,                             /* share_access */
1472                 create_disposition,                     /* create_disposition*/
1473                 create_options,                         /* create_options */
1474                 dos_attr,                               /* file_attributes */
1475                 oplock_request,                         /* oplock_request */
1476                 NULL,                                   /* lease */
1477                 0,                                      /* allocation_size */
1478                 private_flags,
1479                 NULL,                                   /* sd */
1480                 NULL,                                   /* ea_list */
1481                 &fsp,                                   /* result */
1482                 &info,                                  /* pinfo */
1483                 NULL, NULL);                            /* create context */
1484
1485         if (!NT_STATUS_IS_OK(status)) {
1486                 if (open_was_deferred(req->xconn, req->mid)) {
1487                         /* We have re-scheduled this call. */
1488                         goto out;
1489                 }
1490
1491                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1492                         reply_openerror(req, status);
1493                         goto out;
1494                 }
1495
1496                 fsp = fcb_or_dos_open(
1497                         req,
1498                         smb_fname,
1499                         access_mask,
1500                         create_options,
1501                         private_flags);
1502                 if (fsp == NULL) {
1503                         bool ok = defer_smb1_sharing_violation(req);
1504                         if (ok) {
1505                                 goto out;
1506                         }
1507                         reply_openerror(req, status);
1508                         goto out;
1509                 }
1510         }
1511
1512         /* Ensure we're pointing at the correct stat struct. */
1513         TALLOC_FREE(smb_fname);
1514         smb_fname = fsp->fsp_name;
1515
1516         size = smb_fname->st.st_ex_size;
1517         fattr = fdos_mode(fsp);
1518
1519         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1520
1521         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1522                 DEBUG(3,("attempt to open a directory %s\n",
1523                          fsp_str_dbg(fsp)));
1524                 close_file_free(req, &fsp, ERROR_CLOSE);
1525                 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1526                         ERRDOS, ERRnoaccess);
1527                 goto out;
1528         }
1529
1530         reply_outbuf(req, 7, 0);
1531         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1532         SSVAL(req->outbuf,smb_vwv1,fattr);
1533         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1534                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1535         } else {
1536                 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1537         }
1538         SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
1539         SSVAL(req->outbuf,smb_vwv6,deny_mode);
1540
1541         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1542                 SCVAL(req->outbuf,smb_flg,
1543                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1544         }
1545
1546         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1547                 SCVAL(req->outbuf,smb_flg,
1548                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1549         }
1550  out:
1551         END_PROFILE(SMBopen);
1552         return;
1553 }
1554
1555 /****************************************************************************
1556  Reply to an open and X.
1557 ****************************************************************************/
1558
1559 void reply_open_and_X(struct smb_request *req)
1560 {
1561         connection_struct *conn = req->conn;
1562         struct smb_filename *smb_fname = NULL;
1563         char *fname = NULL;
1564         uint16_t open_flags;
1565         int deny_mode;
1566         uint32_t smb_attr;
1567         /* Breakout the oplock request bits so we can set the
1568                 reply bits separately. */
1569         int ex_oplock_request;
1570         int core_oplock_request;
1571         int oplock_request;
1572 #if 0
1573         int smb_sattr = SVAL(req->vwv+4, 0);
1574         uint32_t smb_time = make_unix_date3(req->vwv+6);
1575 #endif
1576         int smb_ofun;
1577         uint32_t fattr=0;
1578         int mtime=0;
1579         int smb_action = 0;
1580         files_struct *fsp;
1581         NTSTATUS status;
1582         uint64_t allocation_size;
1583         ssize_t retval = -1;
1584         uint32_t access_mask;
1585         uint32_t share_mode;
1586         uint32_t create_disposition;
1587         uint32_t create_options = 0;
1588         uint32_t private_flags = 0;
1589         uint32_t ucf_flags;
1590         TALLOC_CTX *ctx = talloc_tos();
1591
1592         START_PROFILE(SMBopenX);
1593
1594         if (req->wct < 15) {
1595                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1596                 goto out;
1597         }
1598
1599         open_flags = SVAL(req->vwv+2, 0);
1600         deny_mode = SVAL(req->vwv+3, 0);
1601         smb_attr = SVAL(req->vwv+5, 0);
1602         ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1603         core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1604         oplock_request = ex_oplock_request | core_oplock_request;
1605         smb_ofun = SVAL(req->vwv+8, 0);
1606         allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1607
1608         /* If it's an IPC, pass off the pipe handler. */
1609         if (IS_IPC(conn)) {
1610                 if (lp_nt_pipe_support()) {
1611                         reply_open_pipe_and_X(conn, req);
1612                 } else {
1613                         reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1614                 }
1615                 goto out;
1616         }
1617
1618         /* XXXX we need to handle passed times, sattr and flags */
1619         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1620                         STR_TERMINATE, &status);
1621         if (!NT_STATUS_IS_OK(status)) {
1622                 reply_nterror(req, status);
1623                 goto out;
1624         }
1625
1626         if (!map_open_params_to_ntcreate(fname, deny_mode,
1627                                          smb_ofun,
1628                                          &access_mask, &share_mode,
1629                                          &create_disposition,
1630                                          &create_options,
1631                                          &private_flags)) {
1632                 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1633                 goto out;
1634         }
1635
1636         ucf_flags = filename_create_ucf_flags(req, create_disposition);
1637
1638         status = filename_convert(ctx,
1639                                 conn,
1640                                 fname,
1641                                 ucf_flags,
1642                                 0,
1643                                 &smb_fname);
1644         if (!NT_STATUS_IS_OK(status)) {
1645                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1646                         reply_botherror(req,
1647                                         NT_STATUS_PATH_NOT_COVERED,
1648                                         ERRSRV, ERRbadpath);
1649                         goto out;
1650                 }
1651                 reply_nterror(req, status);
1652                 goto out;
1653         }
1654
1655         status = SMB_VFS_CREATE_FILE(
1656                 conn,                                   /* conn */
1657                 req,                                    /* req */
1658                 smb_fname,                              /* fname */
1659                 access_mask,                            /* access_mask */
1660                 share_mode,                             /* share_access */
1661                 create_disposition,                     /* create_disposition*/
1662                 create_options,                         /* create_options */
1663                 smb_attr,                               /* file_attributes */
1664                 oplock_request,                         /* oplock_request */
1665                 NULL,                                   /* lease */
1666                 0,                                      /* allocation_size */
1667                 private_flags,
1668                 NULL,                                   /* sd */
1669                 NULL,                                   /* ea_list */
1670                 &fsp,                                   /* result */
1671                 &smb_action,                            /* pinfo */
1672                 NULL, NULL);                            /* create context */
1673
1674         if (!NT_STATUS_IS_OK(status)) {
1675                 if (open_was_deferred(req->xconn, req->mid)) {
1676                         /* We have re-scheduled this call. */
1677                         goto out;
1678                 }
1679
1680                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1681                         reply_openerror(req, status);
1682                         goto out;
1683                 }
1684
1685                 fsp = fcb_or_dos_open(
1686                         req,
1687                         smb_fname,
1688                         access_mask,
1689                         create_options,
1690                         private_flags);
1691                 if (fsp == NULL) {
1692                         bool ok = defer_smb1_sharing_violation(req);
1693                         if (ok) {
1694                                 goto out;
1695                         }
1696                         reply_openerror(req, status);
1697                         goto out;
1698                 }
1699
1700
1701                 smb_action = FILE_WAS_OPENED;
1702         }
1703
1704         /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1705            if the file is truncated or created. */
1706         if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1707                 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1708                 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1709                         close_file_free(req, &fsp, ERROR_CLOSE);
1710                         reply_nterror(req, NT_STATUS_DISK_FULL);
1711                         goto out;
1712                 }
1713                 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
1714                 if (retval < 0) {
1715                         close_file_free(req, &fsp, ERROR_CLOSE);
1716                         reply_nterror(req, NT_STATUS_DISK_FULL);
1717                         goto out;
1718                 }
1719                 status = vfs_stat_fsp(fsp);
1720                 if (!NT_STATUS_IS_OK(status)) {
1721                         close_file_free(req, &fsp, ERROR_CLOSE);
1722                         reply_nterror(req, status);
1723                         goto out;
1724                 }
1725         }
1726
1727         fattr = fdos_mode(fsp);
1728         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1729                 close_file_free(req, &fsp, ERROR_CLOSE);
1730                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1731                 goto out;
1732         }
1733         mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
1734
1735         /* If the caller set the extended oplock request bit
1736                 and we granted one (by whatever means) - set the
1737                 correct bit for extended oplock reply.
1738         */
1739
1740         if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1741                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1742         }
1743
1744         if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1745                 smb_action |= EXTENDED_OPLOCK_GRANTED;
1746         }
1747
1748         /* If the caller set the core oplock request bit
1749                 and we granted one (by whatever means) - set the
1750                 correct bit for core oplock reply.
1751         */
1752
1753         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1754                 reply_outbuf(req, 19, 0);
1755         } else {
1756                 reply_outbuf(req, 15, 0);
1757         }
1758
1759         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1760         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
1761
1762         if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1763                 SCVAL(req->outbuf, smb_flg,
1764                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1765         }
1766
1767         if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1768                 SCVAL(req->outbuf, smb_flg,
1769                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1770         }
1771
1772         SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1773         SSVAL(req->outbuf,smb_vwv3,fattr);
1774         if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1775                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
1776         } else {
1777                 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
1778         }
1779         SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
1780         SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1781         SSVAL(req->outbuf,smb_vwv11,smb_action);
1782
1783         if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1784                 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
1785         }
1786
1787  out:
1788         TALLOC_FREE(smb_fname);
1789         END_PROFILE(SMBopenX);
1790         return;
1791 }
1792
1793 /****************************************************************************
1794  Reply to a SMBulogoffX.
1795 ****************************************************************************/
1796
1797 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1798                                 struct smbXsrv_session *session);
1799 static void reply_ulogoffX_done(struct tevent_req *req);
1800
1801 void reply_ulogoffX(struct smb_request *smb1req)
1802 {
1803         struct timeval now = timeval_current();
1804         struct smbXsrv_session *session = NULL;
1805         struct tevent_req *req;
1806         NTSTATUS status;
1807
1808         /*
1809          * Don't setup the profile charge here, take
1810          * it in reply_ulogoffX_done(). Not strictly correct
1811          * but better than the other SMB1 async
1812          * code that double-charges at the moment.
1813          */
1814
1815         status = smb1srv_session_lookup(smb1req->xconn,
1816                                         smb1req->vuid,
1817                                         timeval_to_nttime(&now),
1818                                         &session);
1819         if (!NT_STATUS_IS_OK(status)) {
1820                 /* Not going async, profile here. */
1821                 START_PROFILE(SMBulogoffX);
1822                 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
1823                          (unsigned long long)smb1req->vuid);
1824
1825                 smb1req->vuid = UID_FIELD_INVALID;
1826                 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
1827                 END_PROFILE(SMBulogoffX);
1828                 return;
1829         }
1830
1831         req = reply_ulogoffX_send(smb1req, session);
1832         if (req == NULL) {
1833                 /* Not going async, profile here. */
1834                 START_PROFILE(SMBulogoffX);
1835                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
1836                 END_PROFILE(SMBulogoffX);
1837                 return;
1838         }
1839
1840         /* We're async. This will complete later. */
1841         tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
1842         return;
1843 }
1844
1845 struct reply_ulogoffX_state {
1846         struct tevent_queue *wait_queue;
1847         struct smbXsrv_session *session;
1848 };
1849
1850 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
1851
1852 /****************************************************************************
1853  Async SMB1 ulogoffX.
1854  Note, on failure here we deallocate and return NULL to allow the caller to
1855  SMB1 return an error of ERRnomem immediately.
1856 ****************************************************************************/
1857
1858 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
1859                                         struct smbXsrv_session *session)
1860 {
1861         struct tevent_req *req;
1862         struct reply_ulogoffX_state *state;
1863         struct tevent_req *subreq;
1864         files_struct *fsp;
1865         struct smbd_server_connection *sconn = session->client->sconn;
1866         uint64_t vuid = session->global->session_wire_id;
1867
1868         req = tevent_req_create(smb1req, &state,
1869                         struct reply_ulogoffX_state);
1870         if (req == NULL) {
1871                 return NULL;
1872         }
1873         state->wait_queue = tevent_queue_create(state,
1874                                 "reply_ulogoffX_wait_queue");
1875         if (tevent_req_nomem(state->wait_queue, req)) {
1876                 TALLOC_FREE(req);
1877                 return NULL;
1878         }
1879         state->session = session;
1880
1881         /*
1882          * Make sure that no new request will be able to use this session.
1883          * This ensures that once all outstanding fsp->aio_requests
1884          * on this session are done, we are safe to close it.
1885          */
1886         session->status = NT_STATUS_USER_SESSION_DELETED;
1887
1888         for (fsp = sconn->files; fsp; fsp = fsp->next) {
1889                 if (fsp->vuid != vuid) {
1890                         continue;
1891                 }
1892                 /*
1893                  * Flag the file as close in progress.
1894                  * This will prevent any more IO being
1895                  * done on it.
1896                  */
1897                 fsp->fsp_flags.closing = true;
1898
1899                 if (fsp->num_aio_requests > 0) {
1900                         /*
1901                          * Now wait until all aio requests on this fsp are
1902                          * finished.
1903                          *
1904                          * We don't set a callback, as we just want to block the
1905                          * wait queue and the talloc_free() of fsp->aio_request
1906                          * will remove the item from the wait queue.
1907                          */
1908                         subreq = tevent_queue_wait_send(fsp->aio_requests,
1909                                                 sconn->ev_ctx,
1910                                                 state->wait_queue);
1911                         if (tevent_req_nomem(subreq, req)) {
1912                                 TALLOC_FREE(req);
1913                                 return NULL;
1914                         }
1915                 }
1916         }
1917
1918         /*
1919          * Now we add our own waiter to the end of the queue,
1920          * this way we get notified when all pending requests are finished
1921          * and reply to the outstanding SMB1 request.
1922          */
1923         subreq = tevent_queue_wait_send(state,
1924                                 sconn->ev_ctx,
1925                                 state->wait_queue);
1926         if (tevent_req_nomem(subreq, req)) {
1927                 TALLOC_FREE(req);
1928                 return NULL;
1929         }
1930
1931         /*
1932          * We're really going async - move the SMB1 request from
1933          * a talloc stackframe above us to the sconn talloc-context.
1934          * We need this to stick around until the wait_done
1935          * callback is invoked.
1936          */
1937         smb1req = talloc_move(sconn, &smb1req);
1938
1939         tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
1940
1941         return req;
1942 }
1943
1944 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
1945 {
1946         struct tevent_req *req = tevent_req_callback_data(
1947                 subreq, struct tevent_req);
1948
1949         tevent_queue_wait_recv(subreq);
1950         TALLOC_FREE(subreq);
1951         tevent_req_done(req);
1952 }
1953
1954 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
1955 {
1956         return tevent_req_simple_recv_ntstatus(req);
1957 }
1958
1959 static void reply_ulogoffX_done(struct tevent_req *req)
1960 {
1961         struct smb_request *smb1req = tevent_req_callback_data(
1962                 req, struct smb_request);
1963         struct reply_ulogoffX_state *state = tevent_req_data(req,
1964                                                 struct reply_ulogoffX_state);
1965         struct smbXsrv_session *session = state->session;
1966         NTSTATUS status;
1967
1968         /*
1969          * Take the profile charge here. Not strictly
1970          * correct but better than the other SMB1 async
1971          * code that double-charges at the moment.
1972          */
1973         START_PROFILE(SMBulogoffX);
1974
1975         status = reply_ulogoffX_recv(req);
1976         TALLOC_FREE(req);
1977         if (!NT_STATUS_IS_OK(status)) {
1978                 TALLOC_FREE(smb1req);
1979                 END_PROFILE(SMBulogoffX);
1980                 exit_server(__location__ ": reply_ulogoffX_recv failed");
1981                 return;
1982         }
1983
1984         status = smbXsrv_session_logoff(session);
1985         if (!NT_STATUS_IS_OK(status)) {
1986                 TALLOC_FREE(smb1req);
1987                 END_PROFILE(SMBulogoffX);
1988                 exit_server(__location__ ": smbXsrv_session_logoff failed");
1989                 return;
1990         }
1991
1992         TALLOC_FREE(session);
1993
1994         reply_outbuf(smb1req, 2, 0);
1995         SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1996         SSVAL(smb1req->outbuf, smb_vwv1, 0);    /* no andx offset */
1997
1998         DBG_NOTICE("ulogoffX vuid=%llu\n",
1999                   (unsigned long long)smb1req->vuid);
2000
2001         smb1req->vuid = UID_FIELD_INVALID;
2002         /*
2003          * The following call is needed to push the
2004          * reply data back out the socket after async
2005          * return. Plus it frees smb1req.
2006          */
2007         smb_request_done(smb1req);
2008         END_PROFILE(SMBulogoffX);
2009 }
2010
2011 /****************************************************************************
2012  Reply to a mknew or a create.
2013 ****************************************************************************/
2014
2015 void reply_mknew(struct smb_request *req)
2016 {
2017         connection_struct *conn = req->conn;
2018         struct smb_filename *smb_fname = NULL;
2019         char *fname = NULL;
2020         uint32_t fattr = 0;
2021         struct smb_file_time ft;
2022         files_struct *fsp;
2023         int oplock_request = 0;
2024         NTSTATUS status;
2025         uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2026         uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2027         uint32_t create_disposition;
2028         uint32_t create_options = 0;
2029         uint32_t ucf_flags;
2030         TALLOC_CTX *ctx = talloc_tos();
2031
2032         START_PROFILE(SMBcreate);
2033         init_smb_file_time(&ft);
2034
2035         if (req->wct < 3) {
2036                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2037                 goto out;
2038         }
2039
2040         fattr = SVAL(req->vwv+0, 0);
2041         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2042
2043         if (req->cmd == SMBmknew) {
2044                 /* We should fail if file exists. */
2045                 create_disposition = FILE_CREATE;
2046         } else {
2047                 /* Create if file doesn't exist, truncate if it does. */
2048                 create_disposition = FILE_OVERWRITE_IF;
2049         }
2050
2051         /* mtime. */
2052         ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2053
2054         srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2055                             STR_TERMINATE, &status);
2056         if (!NT_STATUS_IS_OK(status)) {
2057                 reply_nterror(req, status);
2058                 goto out;
2059         }
2060
2061         ucf_flags = filename_create_ucf_flags(req, create_disposition);
2062         status = filename_convert(ctx,
2063                                 conn,
2064                                 fname,
2065                                 ucf_flags,
2066                                 0,
2067                                 &smb_fname);
2068         if (!NT_STATUS_IS_OK(status)) {
2069                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2070                         reply_botherror(req,
2071                                         NT_STATUS_PATH_NOT_COVERED,
2072                                         ERRSRV, ERRbadpath);
2073                         goto out;
2074                 }
2075                 reply_nterror(req, status);
2076                 goto out;
2077         }
2078
2079         if (fattr & FILE_ATTRIBUTE_VOLUME) {
2080                 DEBUG(0,("Attempt to create file (%s) with volid set - "
2081                          "please report this\n",
2082                          smb_fname_str_dbg(smb_fname)));
2083         }
2084
2085         status = SMB_VFS_CREATE_FILE(
2086                 conn,                                   /* conn */
2087                 req,                                    /* req */
2088                 smb_fname,                              /* fname */
2089                 access_mask,                            /* access_mask */
2090                 share_mode,                             /* share_access */
2091                 create_disposition,                     /* create_disposition*/
2092                 create_options,                         /* create_options */
2093                 fattr,                                  /* file_attributes */
2094                 oplock_request,                         /* oplock_request */
2095                 NULL,                                   /* lease */
2096                 0,                                      /* allocation_size */
2097                 0,                                      /* private_flags */
2098                 NULL,                                   /* sd */
2099                 NULL,                                   /* ea_list */
2100                 &fsp,                                   /* result */
2101                 NULL,                                   /* pinfo */
2102                 NULL, NULL);                            /* create context */
2103
2104         if (!NT_STATUS_IS_OK(status)) {
2105                 if (open_was_deferred(req->xconn, req->mid)) {
2106                         /* We have re-scheduled this call. */
2107                         goto out;
2108                 }
2109                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2110                         bool ok = defer_smb1_sharing_violation(req);
2111                         if (ok) {
2112                                 goto out;
2113                         }
2114                 }
2115                 reply_openerror(req, status);
2116                 goto out;
2117         }
2118
2119         ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2120         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2121         if (!NT_STATUS_IS_OK(status)) {
2122                 END_PROFILE(SMBcreate);
2123                 goto out;
2124         }
2125
2126         reply_outbuf(req, 1, 0);
2127         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2128
2129         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2130                 SCVAL(req->outbuf,smb_flg,
2131                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2132         }
2133
2134         if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2135                 SCVAL(req->outbuf,smb_flg,
2136                                 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2137         }
2138
2139         DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2140         DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2141                   smb_fname_str_dbg(smb_fname), fsp_get_io_fd(fsp),
2142                   (unsigned int)fattr));
2143
2144  out:
2145         TALLOC_FREE(smb_fname);
2146         END_PROFILE(SMBcreate);
2147         return;
2148 }
2149
2150 /****************************************************************************
2151  Reply to a create temporary file.
2152 ****************************************************************************/
2153
2154 void reply_ctemp(struct smb_request *req)
2155 {
2156         connection_struct *conn = req->conn;
2157         struct smb_filename *smb_fname = NULL;
2158         char *wire_name = NULL;
2159         char *fname = NULL;
2160         uint32_t fattr;
2161         files_struct *fsp;
2162         int oplock_request;
2163         char *s;
2164         NTSTATUS status;
2165         int i;
2166         uint32_t ucf_flags;
2167         TALLOC_CTX *ctx = talloc_tos();
2168
2169         START_PROFILE(SMBctemp);
2170
2171         if (req->wct < 3) {
2172                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2173                 goto out;
2174         }
2175
2176         fattr = SVAL(req->vwv+0, 0);
2177         oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2178
2179         srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2180                             STR_TERMINATE, &status);
2181         if (!NT_STATUS_IS_OK(status)) {
2182                 reply_nterror(req, status);
2183                 goto out;
2184         }
2185
2186         for (i = 0; i < 10; i++) {
2187                 if (*wire_name) {
2188                         fname = talloc_asprintf(ctx,
2189                                         "%s/TMP%s",
2190                                         wire_name,
2191                                         generate_random_str_list(ctx, 5, "0123456789"));
2192                 } else {
2193                         fname = talloc_asprintf(ctx,
2194                                         "TMP%s",
2195                                         generate_random_str_list(ctx, 5, "0123456789"));
2196                 }
2197
2198                 if (!fname) {
2199                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2200                         goto out;
2201                 }
2202
2203                 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
2204                 status = filename_convert(ctx, conn,
2205                                 fname,
2206                                 ucf_flags,
2207                                 0,
2208                                 &smb_fname);
2209                 if (!NT_STATUS_IS_OK(status)) {
2210                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2211                                 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2212                                         ERRSRV, ERRbadpath);
2213                                 goto out;
2214                         }
2215                         reply_nterror(req, status);
2216                         goto out;
2217                 }
2218
2219                 /* Create the file. */
2220                 status = SMB_VFS_CREATE_FILE(
2221                         conn,                                   /* conn */
2222                         req,                                    /* req */
2223                         smb_fname,                              /* fname */
2224                         FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2225                         FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
2226                         FILE_CREATE,                            /* create_disposition*/
2227                         0,                                      /* create_options */
2228                         fattr,                                  /* file_attributes */
2229                         oplock_request,                         /* oplock_request */
2230                         NULL,                                   /* lease */
2231                         0,                                      /* allocation_size */
2232                         0,                                      /* private_flags */
2233                         NULL,                                   /* sd */
2234                         NULL,                                   /* ea_list */
2235                         &fsp,                                   /* result */
2236                         NULL,                                   /* pinfo */
2237                         NULL, NULL);                            /* create context */
2238
2239                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2240                         TALLOC_FREE(fname);
2241                         TALLOC_FREE(smb_fname);
2242                         continue;
2243                 }
2244
2245                 if (!NT_STATUS_IS_OK(status)) {
2246                         if (open_was_deferred(req->xconn, req->mid)) {
2247                                 /* We have re-scheduled this call. */
2248                                 goto out;
2249                         }
2250                         if (NT_STATUS_EQUAL(
2251                                     status, NT_STATUS_SHARING_VIOLATION)) {
2252                                 bool ok = defer_smb1_sharing_violation(req);
2253                                 if (ok) {
2254                                         goto out;
2255                                 }
2256                         }
2257                         reply_openerror(req, status);
2258                         goto out;
2259                 }
2260
2261                 break;
2262         }
2263
2264         if (i == 10) {
2265                 /* Collision after 10 times... */
2266                 reply_nterror(req, status);
2267                 goto out;
2268         }
2269
2270         reply_outbuf(req, 1, 0);
2271         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2272
2273         /* the returned filename is relative to the directory */
2274         s = strrchr_m(fsp->fsp_name->base_name, '/');
2275         if (!s) {
2276                 s = fsp->fsp_name->base_name;
2277         } else {
2278                 s++;
2279         }
2280
2281 #if 0
2282         /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2283            thing in the byte section. JRA */
2284         SSVALS(p, 0, -1); /* what is this? not in spec */
2285 #endif
2286         if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2287             == -1) {
2288                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2289                 goto out;
2290         }
2291
2292         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2293                 SCVAL(req->outbuf, smb_flg,
2294                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2295         }
2296
2297         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2298                 SCVAL(req->outbuf, smb_flg,
2299                       CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2300         }
2301
2302         DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2303         DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2304                     fsp_get_io_fd(fsp), (unsigned int)smb_fname->st.st_ex_mode));
2305  out:
2306         TALLOC_FREE(smb_fname);
2307         TALLOC_FREE(wire_name);
2308         END_PROFILE(SMBctemp);
2309         return;
2310 }
2311
2312 /*******************************************************************
2313  Check if a user is allowed to rename a file.
2314 ********************************************************************/
2315
2316 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2317                         uint16_t dirtype)
2318 {
2319         if (!CAN_WRITE(conn)) {
2320                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2321         }
2322
2323         if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2324                         (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2325                 /* Only bother to read the DOS attribute if we might deny the
2326                    rename on the grounds of attribute mismatch. */
2327                 uint32_t fmode = fdos_mode(fsp);
2328                 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2329                         return NT_STATUS_NO_SUCH_FILE;
2330                 }
2331         }
2332
2333         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2334                 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
2335                         return NT_STATUS_OK;
2336                 }
2337
2338                 /* If no pathnames are open below this
2339                    directory, allow the rename. */
2340
2341                 if (lp_strict_rename(SNUM(conn))) {
2342                         /*
2343                          * Strict rename, check open file db.
2344                          */
2345                         if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
2346                                 return NT_STATUS_ACCESS_DENIED;
2347                         }
2348                 } else if (file_find_subpath(fsp)) {
2349                         /*
2350                          * No strict rename, just look in local process.
2351                          */
2352                         return NT_STATUS_ACCESS_DENIED;
2353                 }
2354                 return NT_STATUS_OK;
2355         }
2356
2357         if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2358                 return NT_STATUS_OK;
2359         }
2360
2361         return NT_STATUS_ACCESS_DENIED;
2362 }
2363
2364 /*******************************************************************
2365  * unlink a file with all relevant access checks
2366  *******************************************************************/
2367
2368 NTSTATUS unlink_internals(connection_struct *conn,
2369                         struct smb_request *req,
2370                         uint32_t dirtype,
2371                         struct smb_filename *smb_fname)
2372 {
2373         uint32_t fattr;
2374         files_struct *fsp;
2375         uint32_t dirtype_orig = dirtype;
2376         NTSTATUS status;
2377         int ret;
2378         struct smb2_create_blobs *posx = NULL;
2379
2380         if (dirtype == 0) {
2381                 dirtype = FILE_ATTRIBUTE_NORMAL;
2382         }
2383
2384         DBG_DEBUG("%s, dirtype = %d\n",
2385                   smb_fname_str_dbg(smb_fname),
2386                   dirtype);
2387
2388         if (!CAN_WRITE(conn)) {
2389                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2390         }
2391
2392         ret = vfs_stat(conn, smb_fname);
2393         if (ret != 0) {
2394                 return map_nt_error_from_unix(errno);
2395         }
2396
2397         fattr = fdos_mode(smb_fname->fsp);
2398
2399         if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2400                 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2401         }
2402
2403         dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2404         if (!dirtype) {
2405                 return NT_STATUS_NO_SUCH_FILE;
2406         }
2407
2408         if (!dir_check_ftype(fattr, dirtype)) {
2409                 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2410                         return NT_STATUS_FILE_IS_A_DIRECTORY;
2411                 }
2412                 return NT_STATUS_NO_SUCH_FILE;
2413         }
2414
2415         if (dirtype_orig & 0x8000) {
2416                 /* These will never be set for POSIX. */
2417                 return NT_STATUS_NO_SUCH_FILE;
2418         }
2419
2420 #if 0
2421         if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2422                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2423         }
2424
2425         if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2426                 return NT_STATUS_NO_SUCH_FILE;
2427         }
2428
2429         if (dirtype & 0xFF00) {
2430                 /* These will never be set for POSIX. */
2431                 return NT_STATUS_NO_SUCH_FILE;
2432         }
2433
2434         dirtype &= 0xFF;
2435         if (!dirtype) {
2436                 return NT_STATUS_NO_SUCH_FILE;
2437         }
2438
2439         /* Can't delete a directory. */
2440         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2441                 return NT_STATUS_FILE_IS_A_DIRECTORY;
2442         }
2443 #endif
2444
2445 #if 0 /* JRATEST */
2446         else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2447                 return NT_STATUS_OBJECT_NAME_INVALID;
2448 #endif /* JRATEST */
2449
2450         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
2451                 status = make_smb2_posix_create_ctx(
2452                         talloc_tos(), &posx, 0777);
2453                 if (!NT_STATUS_IS_OK(status)) {
2454                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
2455                                     nt_errstr(status));
2456                         return status;
2457                 }
2458         }
2459
2460         /* On open checks the open itself will check the share mode, so
2461            don't do it here as we'll get it wrong. */
2462
2463         status = SMB_VFS_CREATE_FILE
2464                 (conn,                  /* conn */
2465                  req,                   /* req */
2466                  smb_fname,             /* fname */
2467                  DELETE_ACCESS,         /* access_mask */
2468                  FILE_SHARE_NONE,       /* share_access */
2469                  FILE_OPEN,             /* create_disposition*/
2470                  FILE_NON_DIRECTORY_FILE, /* create_options */
2471                  FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2472                  0,                     /* oplock_request */
2473                  NULL,                  /* lease */
2474                  0,                     /* allocation_size */
2475                  0,                     /* private_flags */
2476                  NULL,                  /* sd */
2477                  NULL,                  /* ea_list */
2478                  &fsp,                  /* result */
2479                  NULL,                  /* pinfo */
2480                  posx,                  /* in_context_blobs */
2481                  NULL);                 /* out_context_blobs */
2482
2483         TALLOC_FREE(posx);
2484
2485         if (!NT_STATUS_IS_OK(status)) {
2486                 DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n",
2487                            nt_errstr(status));
2488                 return status;
2489         }
2490
2491         status = can_set_delete_on_close(fsp, fattr);
2492         if (!NT_STATUS_IS_OK(status)) {
2493                 DBG_DEBUG("can_set_delete_on_close for file %s - "
2494                         "(%s)\n",
2495                         smb_fname_str_dbg(smb_fname),
2496                         nt_errstr(status));
2497                 close_file_free(req, &fsp, NORMAL_CLOSE);
2498                 return status;
2499         }
2500
2501         /* The set is across all open files on this dev/inode pair. */
2502         if (!set_delete_on_close(fsp, True,
2503                                 conn->session_info->security_token,
2504                                 conn->session_info->unix_token)) {
2505                 close_file_free(req, &fsp, NORMAL_CLOSE);
2506                 return NT_STATUS_ACCESS_DENIED;
2507         }
2508
2509         return close_file_free(req, &fsp, NORMAL_CLOSE);
2510 }
2511
2512 /****************************************************************************
2513  Reply to a unlink
2514 ****************************************************************************/
2515
2516 void reply_unlink(struct smb_request *req)
2517 {
2518         connection_struct *conn = req->conn;
2519         char *name = NULL;
2520         struct smb_filename *smb_fname = NULL;
2521         uint32_t dirtype;
2522         NTSTATUS status;
2523         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
2524         TALLOC_CTX *ctx = talloc_tos();
2525
2526         START_PROFILE(SMBunlink);
2527
2528         if (req->wct < 1) {
2529                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2530                 goto out;
2531         }
2532
2533         dirtype = SVAL(req->vwv+0, 0);
2534
2535         srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
2536                                   STR_TERMINATE, &status);
2537         if (!NT_STATUS_IS_OK(status)) {
2538                 reply_nterror(req, status);
2539                 goto out;
2540         }
2541
2542         status = filename_convert(ctx, conn,
2543                                   name,
2544                                   ucf_flags,
2545                                   0,
2546                                   &smb_fname);
2547         if (!NT_STATUS_IS_OK(status)) {
2548                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2549                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2550                                         ERRSRV, ERRbadpath);
2551                         goto out;
2552                 }
2553                 reply_nterror(req, status);
2554                 goto out;
2555         }
2556
2557         DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2558
2559         status = unlink_internals(conn, req, dirtype, smb_fname);
2560         if (!NT_STATUS_IS_OK(status)) {
2561                 if (open_was_deferred(req->xconn, req->mid)) {
2562                         /* We have re-scheduled this call. */
2563                         goto out;
2564                 }
2565                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2566                         bool ok = defer_smb1_sharing_violation(req);
2567                         if (ok) {
2568                                 goto out;
2569                         }
2570                 }
2571                 reply_nterror(req, status);
2572                 goto out;
2573         }
2574
2575         reply_outbuf(req, 0, 0);
2576  out:
2577         TALLOC_FREE(smb_fname);
2578         END_PROFILE(SMBunlink);
2579         return;
2580 }
2581
2582 /****************************************************************************
2583  Fail for readbraw.
2584 ****************************************************************************/
2585
2586 static void fail_readraw(void)
2587 {
2588         const char *errstr = talloc_asprintf(talloc_tos(),
2589                         "FAIL ! reply_readbraw: socket write fail (%s)",
2590                         strerror(errno));
2591         if (!errstr) {
2592                 errstr = "";
2593         }
2594         exit_server_cleanly(errstr);
2595 }
2596
2597 /****************************************************************************
2598  Fake (read/write) sendfile. Returns -1 on read or write fail.
2599 ****************************************************************************/
2600
2601 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
2602                       off_t startpos, size_t nread)
2603 {
2604         size_t bufsize;
2605         size_t tosend = nread;
2606         char *buf;
2607
2608         if (nread == 0) {
2609                 return 0;
2610         }
2611
2612         bufsize = MIN(nread, 65536);
2613
2614         if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2615                 return -1;
2616         }
2617
2618         while (tosend > 0) {
2619                 ssize_t ret;
2620                 size_t cur_read;
2621
2622                 cur_read = MIN(tosend, bufsize);
2623                 ret = read_file(fsp,buf,startpos,cur_read);
2624                 if (ret == -1) {
2625                         SAFE_FREE(buf);
2626                         return -1;
2627                 }
2628
2629                 /* If we had a short read, fill with zeros. */
2630                 if (ret < cur_read) {
2631                         memset(buf + ret, '\0', cur_read - ret);
2632                 }
2633
2634                 ret = write_data(xconn->transport.sock, buf, cur_read);
2635                 if (ret != cur_read) {
2636                         int saved_errno = errno;
2637                         /*
2638                          * Try and give an error message saying what
2639                          * client failed.
2640                          */
2641                         DEBUG(0, ("write_data failed for client %s. "
2642                                   "Error %s\n",
2643                                   smbXsrv_connection_dbg(xconn),
2644                                   strerror(saved_errno)));
2645                         SAFE_FREE(buf);
2646                         errno = saved_errno;
2647                         return -1;
2648                 }
2649                 tosend -= cur_read;
2650                 startpos += cur_read;
2651         }
2652
2653         SAFE_FREE(buf);
2654         return (ssize_t)nread;
2655 }
2656
2657 /****************************************************************************
2658  Deal with the case of sendfile reading less bytes from the file than
2659  requested. Fill with zeros (all we can do). Returns 0 on success
2660 ****************************************************************************/
2661
2662 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
2663                             files_struct *fsp,
2664                             ssize_t nread,
2665                             size_t headersize,
2666                             size_t smb_maxcnt)
2667 {
2668 #define SHORT_SEND_BUFSIZE 1024
2669         if (nread < headersize) {
2670                 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2671                         "header for file %s (%s). Terminating\n",
2672                         fsp_str_dbg(fsp), strerror(errno)));
2673                 return -1;
2674         }
2675
2676         nread -= headersize;
2677
2678         if (nread < smb_maxcnt) {
2679                 char buf[SHORT_SEND_BUFSIZE] = { 0 };
2680
2681                 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2682                         "with zeros !\n", fsp_str_dbg(fsp)));
2683
2684                 while (nread < smb_maxcnt) {
2685                         /*
2686                          * We asked for the real file size and told sendfile
2687                          * to not go beyond the end of the file. But it can
2688                          * happen that in between our fstat call and the
2689                          * sendfile call the file was truncated. This is very
2690                          * bad because we have already announced the larger
2691                          * number of bytes to the client.
2692                          *
2693                          * The best we can do now is to send 0-bytes, just as
2694                          * a read from a hole in a sparse file would do.
2695                          *
2696                          * This should happen rarely enough that I don't care
2697                          * about efficiency here :-)
2698                          */
2699                         size_t to_write;
2700                         ssize_t ret;
2701
2702                         to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2703                         ret = write_data(xconn->transport.sock, buf, to_write);
2704                         if (ret != to_write) {
2705                                 int saved_errno = errno;
2706                                 /*
2707                                  * Try and give an error message saying what
2708                                  * client failed.
2709                                  */
2710                                 DEBUG(0, ("write_data failed for client %s. "
2711                                           "Error %s\n",
2712                                           smbXsrv_connection_dbg(xconn),
2713                                           strerror(saved_errno)));
2714                                 errno = saved_errno;
2715                                 return -1;
2716                         }
2717                         nread += to_write;
2718                 }
2719         }
2720
2721         return 0;
2722 }
2723
2724 /****************************************************************************
2725  Return a readbraw error (4 bytes of zero).
2726 ****************************************************************************/
2727
2728 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
2729 {
2730         char header[4];
2731
2732         SIVAL(header,0,0);
2733
2734         smbd_lock_socket(xconn);
2735         if (write_data(xconn->transport.sock,header,4) != 4) {
2736                 int saved_errno = errno;
2737                 /*
2738                  * Try and give an error message saying what
2739                  * client failed.
2740                  */
2741                 DEBUG(0, ("write_data failed for client %s. "
2742                           "Error %s\n",
2743                           smbXsrv_connection_dbg(xconn),
2744                           strerror(saved_errno)));
2745                 errno = saved_errno;
2746
2747                 fail_readraw();
2748         }
2749         smbd_unlock_socket(xconn);
2750 }
2751
2752 /*******************************************************************
2753  Ensure we don't use sendfile if server smb signing is active.
2754 ********************************************************************/
2755
2756 static bool lp_use_sendfile(int snum, struct smb1_signing_state *signing_state)
2757 {
2758         bool sign_active = false;
2759
2760         /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
2761         if (get_Protocol() < PROTOCOL_NT1) {
2762                 return false;
2763         }
2764         if (signing_state) {
2765                 sign_active = smb1_signing_is_active(signing_state);
2766         }
2767         return (lp__use_sendfile(snum) &&
2768                         (get_remote_arch() != RA_WIN95) &&
2769                         !sign_active);
2770 }
2771 /****************************************************************************
2772  Use sendfile in readbraw.
2773 ****************************************************************************/
2774
2775 static void send_file_readbraw(connection_struct *conn,
2776                                struct smb_request *req,
2777                                files_struct *fsp,
2778                                off_t startpos,
2779                                size_t nread,
2780                                ssize_t mincount)
2781 {
2782         struct smbXsrv_connection *xconn = req->xconn;
2783         char *outbuf = NULL;
2784         ssize_t ret=0;
2785
2786         /*
2787          * We can only use sendfile on a non-chained packet 
2788          * but we can use on a non-oplocked file. tridge proved this
2789          * on a train in Germany :-). JRA.
2790          * reply_readbraw has already checked the length.
2791          */
2792
2793         if ( !req_is_in_chain(req) &&
2794              (nread > 0) &&
2795              !fsp_is_alternate_stream(fsp) &&
2796              lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
2797                 ssize_t sendfile_read = -1;
2798                 char header[4];
2799                 DATA_BLOB header_blob;
2800
2801                 _smb_setlen(header,nread);
2802                 header_blob = data_blob_const(header, 4);
2803
2804                 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
2805                                                  &header_blob, startpos,
2806                                                  nread);
2807                 if (sendfile_read == -1) {
2808                         /* Returning ENOSYS means no data at all was sent.
2809                          * Do this as a normal read. */
2810                         if (errno == ENOSYS) {
2811                                 goto normal_readbraw;
2812                         }
2813
2814                         /*
2815                          * Special hack for broken Linux with no working sendfile. If we
2816                          * return EINTR we sent the header but not the rest of the data.
2817                          * Fake this up by doing read/write calls.
2818                          */
2819                         if (errno == EINTR) {
2820                                 /* Ensure we don't do this again. */
2821                                 set_use_sendfile(SNUM(conn), False);
2822                                 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2823
2824                                 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
2825                                         DEBUG(0,("send_file_readbraw: "
2826                                                  "fake_sendfile failed for "
2827                                                  "file %s (%s).\n",
2828                                                  fsp_str_dbg(fsp),
2829                                                  strerror(errno)));
2830                                         exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2831                                 }
2832                                 return;
2833                         }
2834
2835                         DEBUG(0,("send_file_readbraw: sendfile failed for "
2836                                  "file %s (%s). Terminating\n",
2837                                  fsp_str_dbg(fsp), strerror(errno)));
2838                         exit_server_cleanly("send_file_readbraw sendfile failed");
2839                 } else if (sendfile_read == 0) {
2840                         /*
2841                          * Some sendfile implementations return 0 to indicate
2842                          * that there was a short read, but nothing was
2843                          * actually written to the socket.  In this case,
2844                          * fallback to the normal read path so the header gets
2845                          * the correct byte count.
2846                          */
2847                         DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2848                                   "bytes falling back to the normal read: "
2849                                   "%s\n", fsp_str_dbg(fsp)));
2850                         goto normal_readbraw;
2851                 }
2852
2853                 /* Deal with possible short send. */
2854                 if (sendfile_read != 4+nread) {
2855                         ret = sendfile_short_send(xconn, fsp,
2856                                                   sendfile_read, 4, nread);
2857                         if (ret == -1) {
2858                                 fail_readraw();
2859                         }
2860                 }
2861                 return;
2862         }
2863
2864 normal_readbraw:
2865
2866         outbuf = talloc_array(NULL, char, nread+4);
2867         if (!outbuf) {
2868                 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
2869                         (unsigned)(nread+4)));
2870                 reply_readbraw_error(xconn);
2871                 return;
2872         }
2873
2874         if (nread > 0) {
2875                 ret = read_file(fsp,outbuf+4,startpos,nread);
2876 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2877                 if (ret < mincount)
2878                         ret = 0;
2879 #else
2880                 if (ret < nread)
2881                         ret = 0;
2882 #endif
2883         }
2884
2885         _smb_setlen(outbuf,ret);
2886         if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
2887                 int saved_errno = errno;
2888                 /*
2889                  * Try and give an error message saying what
2890                  * client failed.
2891                  */
2892                 DEBUG(0, ("write_data failed for client %s. Error %s\n",
2893                           smbXsrv_connection_dbg(xconn),
2894                           strerror(saved_errno)));
2895                 errno = saved_errno;
2896
2897                 fail_readraw();
2898         }
2899
2900         TALLOC_FREE(outbuf);
2901 }
2902
2903 /****************************************************************************
2904  Reply to a readbraw (core+ protocol).
2905 ****************************************************************************/
2906
2907 void reply_readbraw(struct smb_request *req)
2908 {
2909         connection_struct *conn = req->conn;
2910         struct smbXsrv_connection *xconn = req->xconn;
2911         ssize_t maxcount,mincount;
2912         size_t nread = 0;
2913         off_t startpos;
2914         files_struct *fsp;
2915         struct lock_struct lock;
2916         off_t size = 0;
2917         NTSTATUS status;
2918
2919         START_PROFILE(SMBreadbraw);
2920
2921         if (smb1_srv_is_signing_active(xconn) || req->encrypted) {
2922                 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
2923                         "raw reads/writes are disallowed.");
2924         }
2925
2926         if (req->wct < 8) {
2927                 reply_readbraw_error(xconn);
2928                 END_PROFILE(SMBreadbraw);
2929                 return;
2930         }
2931
2932         if (xconn->smb1.echo_handler.trusted_fde) {
2933                 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
2934                          "'async smb echo handler = yes'\n"));
2935                 reply_readbraw_error(xconn);
2936                 END_PROFILE(SMBreadbraw);
2937                 return;
2938         }
2939
2940         /*
2941          * Special check if an oplock break has been issued
2942          * and the readraw request croses on the wire, we must
2943          * return a zero length response here.
2944          */
2945
2946         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
2947
2948         /*
2949          * We have to do a check_fsp by hand here, as
2950          * we must always return 4 zero bytes on error,
2951          * not a NTSTATUS.
2952          */
2953
2954         if (fsp == NULL ||
2955             conn == NULL ||
2956             conn != fsp->conn ||
2957             req->vuid != fsp->vuid ||
2958             fsp->fsp_flags.is_directory ||
2959             fsp_get_io_fd(fsp) == -1)
2960         {
2961                 /*
2962                  * fsp could be NULL here so use the value from the packet. JRA.
2963                  */
2964                 DEBUG(3,("reply_readbraw: fnum %d not valid "
2965                         "- cache prime?\n",
2966                         (int)SVAL(req->vwv+0, 0)));
2967                 reply_readbraw_error(xconn);
2968                 END_PROFILE(SMBreadbraw);
2969                 return;
2970         }
2971
2972         /* Do a "by hand" version of CHECK_READ. */
2973         if (!(fsp->fsp_flags.can_read ||
2974                         ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
2975                                 (fsp->access_mask & FILE_EXECUTE)))) {
2976                 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
2977                                 (int)SVAL(req->vwv+0, 0)));
2978                 reply_readbraw_error(xconn);
2979                 END_PROFILE(SMBreadbraw);
2980                 return;
2981         }
2982
2983         startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
2984         if(req->wct == 10) {
2985                 /*
2986                  * This is a large offset (64 bit) read.
2987                  */
2988
2989                 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
2990
2991                 if(startpos < 0) {
2992                         DEBUG(0,("reply_readbraw: negative 64 bit "
2993                                 "readraw offset (%.0f) !\n",
2994                                 (double)startpos ));
2995                         reply_readbraw_error(xconn);
2996                         END_PROFILE(SMBreadbraw);
2997                         return;
2998                 }
2999         }
3000
3001         maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3002         mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3003
3004         /* ensure we don't overrun the packet size */
3005         maxcount = MIN(65535,maxcount);
3006
3007         init_strict_lock_struct(fsp,
3008                         (uint64_t)req->smbpid,
3009                         (uint64_t)startpos,
3010                         (uint64_t)maxcount,
3011                         READ_LOCK,
3012                         lp_posix_cifsu_locktype(fsp),
3013                         &lock);
3014
3015         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3016                 reply_readbraw_error(xconn);
3017                 END_PROFILE(SMBreadbraw);
3018                 return;
3019         }
3020
3021         status = vfs_stat_fsp(fsp);
3022         if (NT_STATUS_IS_OK(status)) {
3023                 size = fsp->fsp_name->st.st_ex_size;
3024         }
3025
3026         if (startpos >= size) {
3027                 nread = 0;
3028         } else {
3029                 nread = MIN(maxcount,(size - startpos));
3030         }
3031
3032 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3033         if (nread < mincount)
3034                 nread = 0;
3035 #endif
3036
3037         DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3038                 "min=%lu nread=%lu\n",
3039                 fsp_fnum_dbg(fsp), (double)startpos,
3040                 (unsigned long)maxcount,
3041                 (unsigned long)mincount,
3042                 (unsigned long)nread ) );
3043
3044         send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3045
3046         DEBUG(5,("reply_readbraw finished\n"));
3047
3048         END_PROFILE(SMBreadbraw);
3049         return;
3050 }
3051
3052 #undef DBGC_CLASS
3053 #define DBGC_CLASS DBGC_LOCKING
3054
3055 /****************************************************************************
3056  Reply to a lockread (core+ protocol).
3057 ****************************************************************************/
3058
3059 static void reply_lockread_locked(struct tevent_req *subreq);
3060
3061 void reply_lockread(struct smb_request *req)
3062 {
3063         struct tevent_req *subreq = NULL;
3064         connection_struct *conn = req->conn;
3065         files_struct *fsp;
3066         struct smbd_lock_element *lck = NULL;
3067
3068         START_PROFILE(SMBlockread);
3069
3070         if (req->wct < 5) {
3071                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3072                 END_PROFILE(SMBlockread);
3073                 return;
3074         }
3075
3076         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3077
3078         if (!check_fsp(conn, req, fsp)) {
3079                 END_PROFILE(SMBlockread);
3080                 return;
3081         }
3082
3083         if (!CHECK_READ(fsp,req)) {
3084                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3085                 END_PROFILE(SMBlockread);
3086                 return;
3087         }
3088
3089         lck = talloc(req, struct smbd_lock_element);
3090         if (lck == NULL) {
3091                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3092                 END_PROFILE(SMBlockread);
3093                 return;
3094         }
3095
3096         /*
3097          * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3098          * protocol request that predates the read/write lock concept. 
3099          * Thus instead of asking for a read lock here we need to ask
3100          * for a write lock. JRA.
3101          * Note that the requested lock size is unaffected by max_send.
3102          */
3103
3104         *lck = (struct smbd_lock_element) {
3105                 .req_guid = smbd_request_guid(req, 0),
3106                 .smblctx = req->smbpid,
3107                 .brltype = WRITE_LOCK,
3108                 .lock_flav = WINDOWS_LOCK,
3109                 .count = SVAL(req->vwv+1, 0),
3110                 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
3111         };
3112
3113         subreq = smbd_smb1_do_locks_send(
3114                 fsp,
3115                 req->sconn->ev_ctx,
3116                 &req,
3117                 fsp,
3118                 0,
3119                 false,          /* large_offset */
3120                 1,
3121                 lck);
3122         if (subreq == NULL) {
3123                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3124                 END_PROFILE(SMBlockread);
3125                 return;
3126         }
3127         tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
3128         END_PROFILE(SMBlockread);
3129 }
3130
3131 static void reply_lockread_locked(struct tevent_req *subreq)
3132 {
3133         struct smb_request *req = NULL;
3134         ssize_t nread = -1;
3135         char *data = NULL;
3136         NTSTATUS status;
3137         bool ok;
3138         off_t startpos;
3139         size_t numtoread, maxtoread;
3140         struct files_struct *fsp = NULL;
3141         char *p = NULL;
3142
3143         START_PROFILE(SMBlockread);
3144
3145         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
3146         SMB_ASSERT(ok);
3147
3148         status = smbd_smb1_do_locks_recv(subreq);
3149         TALLOC_FREE(subreq);
3150
3151         if (!NT_STATUS_IS_OK(status)) {
3152                 reply_nterror(req, status);
3153                 goto send;
3154         }
3155
3156         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3157         if (fsp == NULL) {
3158                 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
3159                 goto send;
3160         }
3161
3162         numtoread = SVAL(req->vwv+1, 0);
3163         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3164
3165         /*
3166          * However the requested READ size IS affected by max_send. Insanity.... JRA.
3167          */
3168         maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3169
3170         if (numtoread > maxtoread) {
3171                 DBG_WARNING("requested read size (%zu) is greater than "
3172                             "maximum allowed (%zu/%d). "
3173                             "Returning short read of maximum allowed for "
3174                             "compatibility with Windows 2000.\n",
3175                             numtoread,
3176                             maxtoread,
3177                             req->xconn->smb1.sessions.max_send);
3178                 numtoread = maxtoread;
3179         }
3180
3181         reply_outbuf(req, 5, numtoread + 3);
3182
3183         data = smb_buf(req->outbuf) + 3;
3184
3185         nread = read_file(fsp,data,startpos,numtoread);
3186
3187         if (nread < 0) {
3188                 reply_nterror(req, map_nt_error_from_unix(errno));
3189                 goto send;
3190         }
3191
3192         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3193
3194         SSVAL(req->outbuf,smb_vwv0,nread);
3195         SSVAL(req->outbuf,smb_vwv5,nread+3);
3196         p = smb_buf(req->outbuf);
3197         SCVAL(p,0,0); /* pad byte. */
3198         SSVAL(p,1,nread);
3199
3200         DEBUG(3,("lockread %s num=%d nread=%d\n",
3201                  fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3202
3203 send:
3204         ok = srv_send_smb(req->xconn,
3205                           (char *)req->outbuf,
3206                           true,
3207                           req->seqnum+1,
3208                           IS_CONN_ENCRYPTED(req->conn),
3209                           NULL);
3210         if (!ok) {
3211                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
3212         }
3213         TALLOC_FREE(req);
3214         END_PROFILE(SMBlockread);
3215         return;
3216 }
3217
3218 #undef DBGC_CLASS
3219 #define DBGC_CLASS DBGC_ALL
3220
3221 /****************************************************************************
3222  Reply to a read.
3223 ****************************************************************************/
3224
3225 void reply_read(struct smb_request *req)
3226 {
3227         connection_struct *conn = req->conn;
3228         size_t numtoread;
3229         size_t maxtoread;
3230         ssize_t nread = 0;
3231         char *data;
3232         off_t startpos;
3233         files_struct *fsp;
3234         struct lock_struct lock;
3235         struct smbXsrv_connection *xconn = req->xconn;
3236
3237         START_PROFILE(SMBread);
3238
3239         if (req->wct < 3) {
3240                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3241                 END_PROFILE(SMBread);
3242                 return;
3243         }
3244
3245         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3246
3247         if (!check_fsp(conn, req, fsp)) {
3248                 END_PROFILE(SMBread);
3249                 return;
3250         }
3251
3252         if (!CHECK_READ(fsp,req)) {
3253                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3254                 END_PROFILE(SMBread);
3255                 return;
3256         }
3257
3258         numtoread = SVAL(req->vwv+1, 0);
3259         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3260
3261         /*
3262          * The requested read size cannot be greater than max_send. JRA.
3263          */
3264         maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3265
3266         if (numtoread > maxtoread) {
3267                 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3268 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3269                         (unsigned int)numtoread, (unsigned int)maxtoread,
3270                         (unsigned int)xconn->smb1.sessions.max_send));
3271                 numtoread = maxtoread;
3272         }
3273
3274         reply_outbuf(req, 5, numtoread+3);
3275
3276         data = smb_buf(req->outbuf) + 3;
3277
3278         init_strict_lock_struct(fsp,
3279                         (uint64_t)req->smbpid,
3280                         (uint64_t)startpos,
3281                         (uint64_t)numtoread,
3282                         READ_LOCK,
3283                         lp_posix_cifsu_locktype(fsp),
3284                         &lock);
3285
3286         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3287                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3288                 END_PROFILE(SMBread);
3289                 return;
3290         }
3291
3292         if (numtoread > 0)
3293                 nread = read_file(fsp,data,startpos,numtoread);
3294
3295         if (nread < 0) {
3296                 reply_nterror(req, map_nt_error_from_unix(errno));
3297                 goto out;
3298         }
3299
3300         srv_set_message((char *)req->outbuf, 5, nread+3, False);
3301
3302         SSVAL(req->outbuf,smb_vwv0,nread);
3303         SSVAL(req->outbuf,smb_vwv5,nread+3);
3304         SCVAL(smb_buf(req->outbuf),0,1);
3305         SSVAL(smb_buf(req->outbuf),1,nread);
3306
3307         DEBUG(3, ("read %s num=%d nread=%d\n",
3308                   fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3309
3310 out:
3311         END_PROFILE(SMBread);
3312         return;
3313 }
3314
3315 /****************************************************************************
3316  Setup readX header.
3317 ****************************************************************************/
3318
3319 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
3320 {
3321         size_t outsize;
3322
3323         outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3324                                   False);
3325
3326         memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3327
3328         SCVAL(outbuf,smb_vwv0,0xFF);
3329         SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3330         SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3331         SSVAL(outbuf,smb_vwv6,
3332               (smb_wct - 4)     /* offset from smb header to wct */
3333               + 1               /* the wct field */
3334               + 12 * sizeof(uint16_t) /* vwv */
3335               + 2               /* the buflen field */
3336               + 1);             /* padding byte */
3337         SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3338         SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3339         /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3340         _smb_setlen_large(outbuf,
3341                           smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3342         return outsize;
3343 }
3344
3345 /****************************************************************************
3346  Reply to a read and X - possibly using sendfile.
3347 ****************************************************************************/
3348
3349 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3350                             files_struct *fsp, off_t startpos,
3351                             size_t smb_maxcnt)
3352 {
3353         struct smbXsrv_connection *xconn = req->xconn;
3354         ssize_t nread = -1;
3355         struct lock_struct lock;
3356         int saved_errno = 0;
3357         NTSTATUS status;
3358
3359         init_strict_lock_struct(fsp,
3360                         (uint64_t)req->smbpid,
3361                         (uint64_t)startpos,
3362                         (uint64_t)smb_maxcnt,
3363                         READ_LOCK,
3364                         lp_posix_cifsu_locktype(fsp),
3365                         &lock);
3366
3367         if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3368                 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3369                 return;
3370         }
3371
3372         /*
3373          * We can only use sendfile on a non-chained packet
3374          * but we can use on a non-oplocked file. tridge proved this
3375          * on a train in Germany :-). JRA.
3376          */
3377
3378         if (!req_is_in_chain(req) &&
3379             !req->encrypted &&
3380             !fsp_is_alternate_stream(fsp) &&
3381             lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3382                 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3383                 DATA_BLOB header;
3384
3385                 status = vfs_stat_fsp(fsp);
3386                 if (!NT_STATUS_IS_OK(status)) {
3387                         reply_nterror(req, status);
3388                         goto out;
3389                 }
3390
3391                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3392                     (startpos > fsp->fsp_name->st.st_ex_size) ||
3393                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3394                         /*
3395                          * We already know that we would do a short read, so don't
3396                          * try the sendfile() path.
3397                          */
3398                         goto nosendfile_read;
3399                 }
3400
3401                 /*
3402                  * Set up the packet header before send. We
3403                  * assume here the sendfile will work (get the
3404                  * correct amount of data).
3405                  */
3406
3407                 header = data_blob_const(headerbuf, sizeof(headerbuf));
3408
3409                 construct_reply_common_req(req, (char *)headerbuf);
3410                 setup_readX_header((char *)headerbuf, smb_maxcnt);
3411
3412                 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3413                                          startpos, smb_maxcnt);
3414                 if (nread == -1) {
3415                         saved_errno = errno;
3416
3417                         /* Returning ENOSYS means no data at all was sent.
3418                            Do this as a normal read. */
3419                         if (errno == ENOSYS) {
3420                                 goto normal_read;
3421                         }
3422
3423                         /*
3424                          * Special hack for broken Linux with no working sendfile. If we
3425                          * return EINTR we sent the header but not the rest of the data.
3426                          * Fake this up by doing read/write calls.
3427                          */
3428
3429                         if (errno == EINTR) {
3430                                 /* Ensure we don't do this again. */
3431                                 set_use_sendfile(SNUM(conn), False);
3432                                 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3433                                 nread = fake_sendfile(xconn, fsp, startpos,
3434                                                       smb_maxcnt);
3435                                 if (nread == -1) {
3436                                         saved_errno = errno;
3437                                         DEBUG(0,("send_file_readX: "
3438                                                  "fake_sendfile failed for "
3439                                                  "file %s (%s) for client %s. "
3440                                                  "Terminating\n",
3441                                                  fsp_str_dbg(fsp),
3442                                                  smbXsrv_connection_dbg(xconn),
3443                                                  strerror(saved_errno)));
3444                                         errno = saved_errno;
3445                                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3446                                 }
3447                                 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3448                                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3449                                 /* No outbuf here means successful sendfile. */
3450                                 goto out;
3451                         }
3452
3453                         DEBUG(0,("send_file_readX: sendfile failed for file "
3454                                  "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3455                                  strerror(errno)));
3456                         exit_server_cleanly("send_file_readX sendfile failed");
3457                 } else if (nread == 0) {
3458                         /*
3459                          * Some sendfile implementations return 0 to indicate
3460                          * that there was a short read, but nothing was
3461                          * actually written to the socket.  In this case,
3462                          * fallback to the normal read path so the header gets
3463                          * the correct byte count.
3464                          */
3465                         DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3466                                   "falling back to the normal read: %s\n",
3467                                   fsp_str_dbg(fsp)));
3468                         goto normal_read;
3469                 }
3470
3471                 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3472                           fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3473
3474                 /* Deal with possible short send. */
3475                 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3476                         ssize_t ret;
3477
3478                         ret = sendfile_short_send(xconn, fsp, nread,
3479                                                   sizeof(headerbuf), smb_maxcnt);
3480                         if (ret == -1) {
3481                                 const char *r;
3482                                 r = "send_file_readX: sendfile_short_send failed";
3483                                 DEBUG(0,("%s for file %s (%s).\n",
3484                                          r, fsp_str_dbg(fsp), strerror(errno)));
3485                                 exit_server_cleanly(r);
3486                         }
3487                 }
3488                 /* No outbuf here means successful sendfile. */
3489                 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3490                 SMB_PERFCOUNT_END(&req->pcd);
3491                 goto out;
3492         }
3493
3494 normal_read:
3495
3496         if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3497                 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3498                 ssize_t ret;
3499
3500                 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3501                     (startpos > fsp->fsp_name->st.st_ex_size) ||
3502                     (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3503                         /*
3504                          * We already know that we would do a short
3505                          * read, so don't try the sendfile() path.
3506                          */
3507                         goto nosendfile_read;
3508                 }
3509
3510                 construct_reply_common_req(req, (char *)headerbuf);
3511                 setup_readX_header((char *)headerbuf, smb_maxcnt);
3512
3513                 /* Send out the header. */
3514                 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3515                                  sizeof(headerbuf));
3516                 if (ret != sizeof(headerbuf)) {
3517                         saved_errno = errno;
3518                         /*
3519                          * Try and give an error message saying what
3520                          * client failed.
3521                          */
3522                         DEBUG(0,("send_file_readX: write_data failed for file "
3523                                  "%s (%s) for client %s. Terminating\n",
3524                                  fsp_str_dbg(fsp),
3525                                  smbXsrv_connection_dbg(xconn),
3526                                  strerror(saved_errno)));
3527                         errno = saved_errno;
3528                         exit_server_cleanly("send_file_readX sendfile failed");
3529                 }
3530                 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3531                 if (nread == -1) {
3532                         saved_errno = errno;
3533                         DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3534                                  "%s (%s) for client %s. Terminating\n",
3535                                  fsp_str_dbg(fsp),
3536                                  smbXsrv_connection_dbg(xconn),
3537                                  strerror(saved_errno)));
3538                         errno = saved_errno;
3539                         exit_server_cleanly("send_file_readX: fake_sendfile failed");
3540                 }
3541                 goto out;
3542         }
3543
3544 nosendfile_read:
3545
3546         reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3547         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3548         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
3549
3550         nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3551                           startpos, smb_maxcnt);
3552         saved_errno = errno;
3553
3554         if (nread < 0) {
3555                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3556                 return;
3557         }
3558
3559         setup_readX_header((char *)req->outbuf, nread);
3560
3561         DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3562                   fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3563         return;
3564
3565 out:
3566         TALLOC_FREE(req->outbuf);
3567         return;
3568 }
3569
3570 /****************************************************************************
3571  Work out how much space we have for a read return.
3572 ****************************************************************************/
3573
3574 static size_t calc_max_read_pdu(const struct smb_request *req)
3575 {
3576         struct smbXsrv_connection *xconn = req->xconn;
3577
3578         if (xconn->protocol < PROTOCOL_NT1) {
3579                 return xconn->smb1.sessions.max_send;
3580         }
3581
3582         if (!lp_large_readwrite()) {
3583                 return xconn->smb1.sessions.max_send;
3584         }
3585
3586         if (req_is_in_chain(req)) {
3587                 return xconn->smb1.sessions.max_send;
3588         }
3589
3590         if (req->encrypted) {
3591                 /*
3592                  * Don't take encrypted traffic up to the
3593                  * limit. There are padding considerations
3594                  * that make that tricky.
3595                  */
3596                 return xconn->smb1.sessions.max_send;
3597         }
3598
3599         if (smb1_srv_is_signing_active(xconn)) {
3600                 return 0x1FFFF;
3601         }
3602
3603         if (!lp_smb1_unix_extensions()) {
3604                 return 0x1FFFF;
3605         }
3606
3607         /*
3608          * We can do ultra-large POSIX reads.
3609          */
3610         return 0xFFFFFF;
3611 }
3612
3613 /****************************************************************************
3614  Calculate how big a read can be. Copes with all clients. It's always
3615  safe to return a short read - Windows does this.
3616 ****************************************************************************/
3617
3618 static size_t calc_read_size(const struct smb_request *req,
3619                              size_t upper_size,
3620                              size_t lower_size)
3621 {
3622         struct smbXsrv_connection *xconn = req->xconn;
3623         size_t max_pdu = calc_max_read_pdu(req);
3624         size_t total_size = 0;
3625         size_t hdr_len = MIN_SMB_SIZE + VWV(12);
3626         size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
3627
3628         /*
3629          * Windows explicitly ignores upper size of 0xFFFF.
3630          * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
3631          * We must do the same as these will never fit even in
3632          * an extended size NetBIOS packet.
3633          */
3634         if (upper_size == 0xFFFF) {
3635                 upper_size = 0;
3636         }
3637
3638         if (xconn->protocol < PROTOCOL_NT1) {
3639                 upper_size = 0;
3640         }
3641
3642         total_size = ((upper_size<<16) | lower_size);
3643
3644         /*
3645          * LARGE_READX test shows it's always safe to return
3646          * a short read. Windows does so.
3647          */
3648         return MIN(total_size, max_len);
3649 }
3650
3651 /****************************************************************************
3652  Reply to a read and X.
3653 ****************************************************************************/
3654
3655 void reply_read_and_X(struct smb_request *req)
3656 {
3657         connection_struct *conn = req->conn;
3658         files_struct *fsp;
3659         off_t startpos;
3660         size_t smb_maxcnt;
3661         size_t upper_size;
3662         bool big_readX = False;
3663 #if 0
3664         size_t smb_mincnt = SVAL(req->vwv+6, 0);
3665 #endif
3666
3667         START_PROFILE(SMBreadX);
3668
3669         if ((req->wct != 10) && (req->wct != 12)) {
3670                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3671                 return;
3672         }
3673
3674         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3675         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3676         smb_maxcnt = SVAL(req->vwv+5, 0);
3677
3678         /* If it's an IPC, pass off the pipe handler. */
3679         if (IS_IPC(conn)) {
3680                 reply_pipe_read_and_X(req);
3681                 END_PROFILE(SMBreadX);
3682                 return;
3683         }
3684
3685         if (!check_fsp(conn, req, fsp)) {
3686                 END_PROFILE(SMBreadX);
3687                 return;
3688         }
3689
3690         if (!CHECK_READ(fsp,req)) {
3691                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3692                 END_PROFILE(SMBreadX);
3693                 return;
3694         }
3695
3696         upper_size = SVAL(req->vwv+7, 0);
3697         smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
3698         if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
3699                 /*
3700                  * This is a heuristic to avoid keeping large
3701                  * outgoing buffers around over long-lived aio
3702                  * requests.
3703                  */
3704                 big_readX = True;
3705         }
3706
3707         if (req->wct == 12) {
3708                 /*
3709                  * This is a large offset (64 bit) read.
3710                  */
3711                 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3712
3713         }
3714
3715         if (!big_readX) {
3716                 NTSTATUS status = schedule_aio_read_and_X(conn,
3717                                         req,
3718                                         fsp,
3719                                         startpos,
3720                                         smb_maxcnt);
3721                 if (NT_STATUS_IS_OK(status)) {
3722                         /* Read scheduled - we're done. */
3723                         goto out;
3724                 }
3725                 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3726                         /* Real error - report to client. */
3727                         END_PROFILE(SMBreadX);
3728                         reply_nterror(req, status);
3729                         return;
3730                 }
3731                 /* NT_STATUS_RETRY - fall back to sync read. */
3732         }
3733
3734         smbd_lock_socket(req->xconn);
3735         send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3736         smbd_unlock_socket(req->xconn);
3737
3738  out:
3739         END_PROFILE(SMBreadX);
3740         return;
3741 }
3742
3743 /****************************************************************************
3744  Error replies to writebraw must have smb_wct == 1. Fix this up.
3745 ****************************************************************************/
3746
3747 void error_to_writebrawerr(struct smb_request *req)
3748 {
3749         uint8_t *old_outbuf = req->outbuf;
3750
3751         reply_outbuf(req, 1, 0);
3752
3753         memcpy(req->outbuf, old_outbuf, smb_size);
3754         TALLOC_FREE(old_outbuf);
3755 }
3756
3757 /****************************************************************************
3758  Read 4 bytes of a smb packet and return the smb length of the packet.
3759  Store the result in the buffer. This version of the function will
3760  never return a session keepalive (length of zero).
3761  Timeout is in milliseconds.
3762 ****************************************************************************/
3763
3764 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3765                                 size_t *len)
3766 {
3767         uint8_t msgtype = NBSSkeepalive;
3768
3769         while (msgtype == NBSSkeepalive) {
3770                 NTSTATUS status;
3771
3772                 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3773                                                           len);
3774                 if (!NT_STATUS_IS_OK(status)) {
3775                         char addr[INET6_ADDRSTRLEN];
3776                         /* Try and give an error message
3777                          * saying what client failed. */
3778                         DEBUG(0, ("read_smb_length_return_keepalive failed for "
3779                                   "client %s read error = %s.\n",
3780                                   get_peer_addr(fd,addr,sizeof(addr)),
3781                                   nt_errstr(status)));
3782                         return status;
3783                 }
3784
3785                 msgtype = CVAL(inbuf, 0);
3786         }
3787
3788         DEBUG(10,("read_smb_length: got smb length of %lu\n",
3789                   (unsigned long)len));
3790
3791         return NT_STATUS_OK;
3792 }
3793
3794 /****************************************************************************
3795  Reply to a writebraw (core+ or LANMAN1.0 protocol).
3796 ****************************************************************************/
3797
3798 void reply_writebraw(struct smb_request *req)
3799 {
3800         connection_struct *conn = req->conn;
3801         struct smbXsrv_connection *xconn = req->xconn;
3802         char *buf = NULL;
3803         ssize_t nwritten=0;
3804         ssize_t total_written=0;
3805         size_t numtowrite=0;
3806         size_t tcount;
3807         off_t startpos;
3808         const char *data=NULL;
3809         bool write_through;
3810         files_struct *fsp;
3811         struct lock_struct lock;
3812         NTSTATUS status;
3813
3814         START_PROFILE(SMBwritebraw);
3815
3816         /*
3817          * If we ever reply with an error, it must have the SMB command
3818          * type of SMBwritec, not SMBwriteBraw, as this tells the client
3819          * we're finished.
3820          */
3821         SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3822
3823         if (smb1_srv_is_signing_active(xconn)) {
3824                 END_PROFILE(SMBwritebraw);
3825                 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3826                                 "raw reads/writes are disallowed.");
3827         }
3828
3829         if (req->wct < 12) {
3830                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3831                 error_to_writebrawerr(req);
3832                 END_PROFILE(SMBwritebraw);
3833                 return;
3834         }
3835
3836         if (xconn->smb1.echo_handler.trusted_fde) {
3837                 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3838                          "'async smb echo handler = yes'\n"));
3839                 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3840                 error_to_writebrawerr(req);
3841                 END_PROFILE(SMBwritebraw);
3842                 return;
3843         }
3844
3845         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3846         if (!check_fsp(conn, req, fsp)) {
3847                 error_to_writebrawerr(req);
3848                 END_PROFILE(SMBwritebraw);
3849                 return;
3850         }
3851
3852         if (!CHECK_WRITE(fsp)) {
3853                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3854                 error_to_writebrawerr(req);
3855                 END_PROFILE(SMBwritebraw);
3856                 return;
3857         }
3858
3859         tcount = IVAL(req->vwv+1, 0);
3860         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3861         write_through = BITSETW(req->vwv+7,0);
3862
3863         /* We have to deal with slightly different formats depending
3864                 on whether we are using the core+ or lanman1.0 protocol */
3865
3866         if(get_Protocol() <= PROTOCOL_COREPLUS) {
3867                 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3868                 data = smb_buf_const(req->inbuf);
3869         } else {
3870                 numtowrite = SVAL(req->vwv+10, 0);
3871                 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3872         }
3873
3874         /* Ensure we don't write bytes past the end of this packet. */
3875         /*
3876          * This already protects us against CVE-2017-12163.
3877          */
3878         if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3879                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3880                 error_to_writebrawerr(req);
3881                 END_PROFILE(SMBwritebraw);
3882                 return;
3883         }
3884
3885         if (!fsp->print_file) {
3886                 init_strict_lock_struct(fsp,
3887                                 (uint64_t)req->smbpid,
3888                                 (uint64_t)startpos,
3889                                 (uint64_t)tcount,
3890                                 WRITE_LOCK,
3891                                 lp_posix_cifsu_locktype(fsp),
3892                                 &lock);
3893
3894                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
3895                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3896                         error_to_writebrawerr(req);
3897                         END_PROFILE(SMBwritebraw);
3898                         return;
3899                 }
3900         }
3901
3902         if (numtowrite>0) {
3903                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3904         }
3905
3906         DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
3907                         "wrote=%d sync=%d\n",
3908                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
3909                 (int)nwritten, (int)write_through));
3910
3911         if (nwritten < (ssize_t)numtowrite)  {
3912                 reply_nterror(req, NT_STATUS_DISK_FULL);
3913                 error_to_writebrawerr(req);
3914                 goto out;
3915         }
3916
3917         total_written = nwritten;
3918
3919         /* Allocate a buffer of 64k + length. */
3920         buf = talloc_array(NULL, char, 65540);
3921         if (!buf) {
3922                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3923                 error_to_writebrawerr(req);
3924                 goto out;
3925         }
3926
3927         /* Return a SMBwritebraw message to the redirector to tell
3928          * it to send more bytes */
3929
3930         memcpy(buf, req->inbuf, smb_size);
3931         srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3932         SCVAL(buf,smb_com,SMBwritebraw);
3933         SSVALS(buf,smb_vwv0,0xFFFF);
3934         show_msg(buf);
3935         if (!srv_send_smb(req->xconn,
3936                           buf,
3937                           false, 0, /* no signing */
3938                           IS_CONN_ENCRYPTED(conn),
3939                           &req->pcd)) {
3940                 exit_server_cleanly("reply_writebraw: srv_send_smb "
3941                         "failed.");
3942         }
3943
3944         /* Now read the raw data into the buffer and write it */
3945         status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
3946                                  &numtowrite);
3947         if (!NT_STATUS_IS_OK(status)) {
3948                 exit_server_cleanly("secondary writebraw failed");
3949         }
3950
3951         /* Set up outbuf to return the correct size */
3952         reply_outbuf(req, 1, 0);
3953
3954         if (numtowrite != 0) {
3955
3956                 if (numtowrite > 0xFFFF) {
3957                         DEBUG(0,("reply_writebraw: Oversize secondary write "
3958                                 "raw requested (%u). Terminating\n",
3959                                 (unsigned int)numtowrite ));
3960                         exit_server_cleanly("secondary writebraw failed");
3961                 }
3962
3963                 if (tcount > nwritten+numtowrite) {
3964                         DEBUG(3,("reply_writebraw: Client overestimated the "
3965                                 "write %d %d %d\n",
3966                                 (int)tcount,(int)nwritten,(int)numtowrite));
3967                 }
3968
3969                 status = read_data_ntstatus(xconn->transport.sock, buf+4,
3970                                             numtowrite);
3971
3972                 if (!NT_STATUS_IS_OK(status)) {
3973                         /* Try and give an error message
3974                          * saying what client failed. */
3975                         DEBUG(0, ("reply_writebraw: Oversize secondary write "
3976                                   "raw read failed (%s) for client %s. "
3977                                   "Terminating\n", nt_errstr(status),
3978                                   smbXsrv_connection_dbg(xconn)));
3979                         exit_server_cleanly("secondary writebraw failed");
3980                 }
3981
3982                 /*
3983                  * We are not vulnerable to CVE-2017-12163
3984                  * here as we are guaranteed to have numtowrite
3985                  * bytes available - we just read from the client.
3986                  */
3987                 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3988                 if (nwritten == -1) {
3989                         TALLOC_FREE(buf);
3990                         reply_nterror(req, map_nt_error_from_unix(errno));
3991                         error_to_writebrawerr(req);
3992                         goto out;
3993                 }
3994
3995                 if (nwritten < (ssize_t)numtowrite) {
3996                         SCVAL(req->outbuf,smb_rcls,ERRHRD);
3997                         SSVAL(req->outbuf,smb_err,ERRdiskfull);
3998                 }
3999
4000                 if (nwritten > 0) {
4001                         total_written += nwritten;
4002                 }
4003         }
4004
4005         TALLOC_FREE(buf);
4006         SSVAL(req->outbuf,smb_vwv0,total_written);
4007
4008         status = sync_file(conn, fsp, write_through);
4009         if (!NT_STATUS_IS_OK(status)) {
4010                 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4011                          fsp_str_dbg(fsp), nt_errstr(status)));
4012                 reply_nterror(req, status);
4013                 error_to_writebrawerr(req);
4014                 goto out;
4015         }
4016
4017         DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4018                 "wrote=%d\n",
4019                 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4020                 (int)total_written));
4021
4022         /* We won't return a status if write through is not selected - this
4023          * follows what WfWg does */
4024         END_PROFILE(SMBwritebraw);
4025
4026         if (!write_through && total_written==tcount) {
4027
4028 #if RABBIT_PELLET_FIX
4029                 /*
4030                  * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4031                  * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4032                  * JRA.
4033                  */
4034                 if (!send_keepalive(xconn->transport.sock)) {
4035                         exit_server_cleanly("reply_writebraw: send of "
4036                                 "keepalive failed");
4037                 }
4038 #endif
4039                 TALLOC_FREE(req->outbuf);
4040         }
4041         return;
4042
4043 out:
4044         END_PROFILE(SMBwritebraw);
4045         return;
4046 }
4047
4048 #undef DBGC_CLASS
4049 #define DBGC_CLASS DBGC_LOCKING
4050
4051 /****************************************************************************
4052  Reply to a writeunlock (core+).
4053 ****************************************************************************/
4054
4055 void reply_writeunlock(struct smb_request *req)
4056 {
4057         connection_struct *conn = req->conn;
4058         ssize_t nwritten = -1;
4059         size_t numtowrite;
4060         size_t remaining;
4061         off_t startpos;
4062         const char *data;
4063         NTSTATUS status = NT_STATUS_OK;
4064         files_struct *fsp;
4065         struct lock_struct lock;
4066         int saved_errno = 0;
4067
4068         START_PROFILE(SMBwriteunlock);
4069
4070         if (req->wct < 5) {
4071                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4072                 END_PROFILE(SMBwriteunlock);
4073                 return;
4074         }
4075
4076         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4077
4078         if (!check_fsp(conn, req, fsp)) {
4079                 END_PROFILE(SMBwriteunlock);
4080                 return;
4081         }
4082
4083         if (!CHECK_WRITE(fsp)) {
4084                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4085                 END_PROFILE(SMBwriteunlock);
4086                 return;
4087         }
4088
4089         numtowrite = SVAL(req->vwv+1, 0);
4090         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4091         data = (const char *)req->buf + 3;
4092
4093         /*
4094          * Ensure client isn't asking us to write more than
4095          * they sent. CVE-2017-12163.
4096          */
4097         remaining = smbreq_bufrem(req, data);
4098         if (numtowrite > remaining) {
4099                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4100                 END_PROFILE(SMBwriteunlock);
4101                 return;
4102         }
4103
4104         if (!fsp->print_file && numtowrite > 0) {
4105                 init_strict_lock_struct(fsp,
4106                                 (uint64_t)req->smbpid,
4107                                 (uint64_t)startpos,
4108                                 (uint64_t)numtowrite,
4109                                 WRITE_LOCK,
4110                                 lp_posix_cifsu_locktype(fsp),
4111                                 &lock);
4112
4113                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4114                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4115                         END_PROFILE(SMBwriteunlock);
4116                         return;
4117                 }
4118         }
4119
4120         /* The special X/Open SMB protocol handling of
4121            zero length writes is *NOT* done for
4122            this call */
4123         if(numtowrite == 0) {
4124                 nwritten = 0;
4125         } else {
4126                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4127                 saved_errno = errno;
4128         }
4129
4130         status = sync_file(conn, fsp, False /* write through */);
4131         if (!NT_STATUS_IS_OK(status)) {
4132                 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4133                          fsp_str_dbg(fsp), nt_errstr(status)));
4134                 reply_nterror(req, status);
4135                 goto out;
4136         }
4137
4138         if(nwritten < 0) {
4139                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4140                 goto out;
4141         }
4142
4143         if((nwritten < numtowrite) && (numtowrite != 0)) {
4144                 reply_nterror(req, NT_STATUS_DISK_FULL);
4145                 goto out;
4146         }
4147
4148         if (numtowrite && !fsp->print_file) {
4149                 struct smbd_lock_element l = {
4150                         .req_guid = smbd_request_guid(req, 0),
4151                         .smblctx = req->smbpid,
4152                         .brltype = UNLOCK_LOCK,
4153                         .lock_flav = WINDOWS_LOCK,
4154                         .offset = startpos,
4155                         .count = numtowrite,
4156                 };
4157                 status = smbd_do_unlocking(req, fsp, 1, &l);
4158                 if (NT_STATUS_V(status)) {
4159                         reply_nterror(req, status);
4160                         goto out;
4161                 }
4162         }
4163
4164         reply_outbuf(req, 1, 0);
4165
4166         SSVAL(req->outbuf,smb_vwv0,nwritten);
4167
4168         DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4169                   fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4170
4171 out:
4172         END_PROFILE(SMBwriteunlock);
4173         return;
4174 }
4175
4176 #undef DBGC_CLASS
4177 #define DBGC_CLASS DBGC_ALL
4178
4179 /****************************************************************************
4180  Reply to a write.
4181 ****************************************************************************/
4182
4183 void reply_write(struct smb_request *req)
4184 {
4185         connection_struct *conn = req->conn;
4186         size_t numtowrite;
4187         size_t remaining;
4188         ssize_t nwritten = -1;
4189         off_t startpos;
4190         const char *data;
4191         files_struct *fsp;
4192         struct lock_struct lock;
4193         NTSTATUS status;
4194         int saved_errno = 0;
4195
4196         START_PROFILE(SMBwrite);
4197
4198         if (req->wct < 5) {
4199                 END_PROFILE(SMBwrite);
4200                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4201                 return;
4202         }
4203
4204         /* If it's an IPC, pass off the pipe handler. */
4205         if (IS_IPC(conn)) {
4206                 reply_pipe_write(req);
4207                 END_PROFILE(SMBwrite);
4208                 return;
4209         }
4210
4211         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4212
4213         if (!check_fsp(conn, req, fsp)) {
4214                 END_PROFILE(SMBwrite);
4215                 return;
4216         }
4217
4218         if (!CHECK_WRITE(fsp)) {
4219                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4220                 END_PROFILE(SMBwrite);
4221                 return;
4222         }
4223
4224         numtowrite = SVAL(req->vwv+1, 0);
4225         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4226         data = (const char *)req->buf + 3;
4227
4228         /*
4229          * Ensure client isn't asking us to write more than
4230          * they sent. CVE-2017-12163.
4231          */
4232         remaining = smbreq_bufrem(req, data);
4233         if (numtowrite > remaining) {
4234                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4235                 END_PROFILE(SMBwrite);
4236                 return;
4237         }
4238
4239         if (!fsp->print_file) {
4240                 init_strict_lock_struct(fsp,
4241                                 (uint64_t)req->smbpid,
4242                                 (uint64_t)startpos,
4243                                 (uint64_t)numtowrite,
4244                                 WRITE_LOCK,
4245                                 lp_posix_cifsu_locktype(fsp),
4246                                 &lock);
4247
4248                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4249                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4250                         END_PROFILE(SMBwrite);
4251                         return;
4252                 }
4253         }
4254
4255         /*
4256          * X/Open SMB protocol says that if smb_vwv1 is
4257          * zero then the file size should be extended or
4258          * truncated to the size given in smb_vwv[2-3].
4259          */
4260
4261         if(numtowrite == 0) {
4262                 /*
4263                  * This is actually an allocate call, and set EOF. JRA.
4264                  */
4265                 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4266                 if (nwritten < 0) {
4267                         reply_nterror(req, NT_STATUS_DISK_FULL);
4268                         goto out;
4269                 }
4270                 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4271                 if (nwritten < 0) {
4272                         reply_nterror(req, NT_STATUS_DISK_FULL);
4273                         goto out;
4274                 }
4275                 trigger_write_time_update_immediate(fsp);
4276         } else {
4277                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4278         }
4279
4280         status = sync_file(conn, fsp, False);
4281         if (!NT_STATUS_IS_OK(status)) {
4282                 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4283                          fsp_str_dbg(fsp), nt_errstr(status)));
4284                 reply_nterror(req, status);
4285                 goto out;
4286         }
4287
4288         if(nwritten < 0) {
4289                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4290                 goto out;
4291         }
4292
4293         if((nwritten == 0) && (numtowrite != 0)) {
4294                 reply_nterror(req, NT_STATUS_DISK_FULL);
4295                 goto out;
4296         }
4297
4298         reply_outbuf(req, 1, 0);
4299
4300         SSVAL(req->outbuf,smb_vwv0,nwritten);
4301
4302         if (nwritten < (ssize_t)numtowrite) {
4303                 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4304                 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4305         }
4306
4307         DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4308
4309 out:
4310         END_PROFILE(SMBwrite);
4311         return;
4312 }
4313
4314 /****************************************************************************
4315  Ensure a buffer is a valid writeX for recvfile purposes.
4316 ****************************************************************************/
4317
4318 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4319                                                 (2*14) + /* word count (including bcc) */ \
4320                                                 1 /* pad byte */)
4321
4322 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4323                             const uint8_t *inbuf)
4324 {
4325         size_t numtowrite;
4326         unsigned int doff = 0;
4327         size_t len = smb_len_large(inbuf);
4328         uint16_t fnum;
4329         struct smbXsrv_open *op = NULL;
4330         struct files_struct *fsp = NULL;
4331         NTSTATUS status;
4332
4333         if (is_encrypted_packet(inbuf)) {
4334                 /* Can't do this on encrypted
4335                  * connections. */
4336                 return false;
4337         }
4338
4339         if (CVAL(inbuf,smb_com) != SMBwriteX) {
4340                 return false;
4341         }
4342
4343         if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4344                         CVAL(inbuf,smb_wct) != 14) {
4345                 DEBUG(10,("is_valid_writeX_buffer: chained or "
4346                         "invalid word length.\n"));
4347                 return false;
4348         }
4349
4350         fnum = SVAL(inbuf, smb_vwv2);
4351         status = smb1srv_open_lookup(xconn,
4352                                      fnum,
4353                                      0, /* now */
4354                                      &op);
4355         if (!NT_STATUS_IS_OK(status)) {
4356                 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4357                 return false;
4358         }
4359         fsp = op->compat;
4360         if (fsp == NULL) {
4361                 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4362                 return false;
4363         }
4364         if (fsp->conn == NULL) {
4365                 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4366                 return false;
4367         }
4368
4369         if (IS_IPC(fsp->conn)) {
4370                 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4371                 return false;
4372         }
4373         if (IS_PRINT(fsp->conn)) {
4374                 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4375                 return false;
4376         }
4377         if (fsp_is_alternate_stream(fsp)) {
4378                 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
4379                 return false;
4380         }
4381         doff = SVAL(inbuf,smb_vwv11);
4382
4383         numtowrite = SVAL(inbuf,smb_vwv10);
4384
4385         if (len > doff && len - doff > 0xFFFF) {
4386                 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4387         }
4388
4389         if (numtowrite == 0) {
4390                 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4391                 return false;
4392         }
4393
4394         /* Ensure the sizes match up. */
4395         if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4396                 /* no pad byte...old smbclient :-( */
4397                 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4398                         (unsigned int)doff,
4399                         (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4400                 return false;
4401         }
4402
4403         if (len - doff != numtowrite) {
4404                 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4405                         "len = %u, doff = %u, numtowrite = %u\n",
4406                         (unsigned int)len,
4407                         (unsigned int)doff,
4408                         (unsigned int)numtowrite ));
4409                 return false;
4410         }
4411
4412         DEBUG(10,("is_valid_writeX_buffer: true "
4413                 "len = %u, doff = %u, numtowrite = %u\n",
4414                 (unsigned int)len,
4415                 (unsigned int)doff,
4416                 (unsigned int)numtowrite ));
4417
4418         return true;
4419 }
4420
4421 /****************************************************************************
4422  Reply to a write and X.
4423 ****************************************************************************/
4424
4425 void reply_write_and_X(struct smb_request *req)
4426 {
4427         connection_struct *conn = req->conn;
4428         struct smbXsrv_connection *xconn = req->xconn;
4429         files_struct *fsp;
4430         struct lock_struct lock;
4431         off_t startpos;
4432         size_t numtowrite;
4433         bool write_through;
4434         ssize_t nwritten;
4435         unsigned int smb_doff;
4436         unsigned int smblen;
4437         const char *data;
4438         NTSTATUS status;
4439         int saved_errno = 0;
4440
4441         START_PROFILE(SMBwriteX);
4442
4443         if ((req->wct != 12) && (req->wct != 14)) {
4444                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4445                 goto out;
4446         }
4447
4448         numtowrite = SVAL(req->vwv+10, 0);
4449         smb_doff = SVAL(req->vwv+11, 0);
4450         smblen = smb_len(req->inbuf);
4451
4452         if (req->unread_bytes > 0xFFFF ||
4453                         (smblen > smb_doff &&
4454                                 smblen - smb_doff > 0xFFFF)) {
4455                 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4456         }
4457
4458         if (req->unread_bytes) {
4459                 /* Can't do a recvfile write on IPC$ */
4460                 if (IS_IPC(conn)) {
4461                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4462                         goto out;
4463                 }
4464                 if (numtowrite != req->unread_bytes) {
4465                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4466                         goto out;
4467                 }
4468         } else {
4469                 /*
4470                  * This already protects us against CVE-2017-12163.
4471                  */
4472                 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4473                                 smb_doff + numtowrite > smblen) {
4474                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4475                         goto out;
4476                 }
4477         }
4478
4479         /* If it's an IPC, pass off the pipe handler. */
4480         if (IS_IPC(conn)) {
4481                 if (req->unread_bytes) {
4482                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4483                         goto out;
4484                 }
4485                 reply_pipe_write_and_X(req);
4486                 goto out;
4487         }
4488
4489         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4490         startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4491         write_through = BITSETW(req->vwv+7,0);
4492
4493         if (!check_fsp(conn, req, fsp)) {
4494                 goto out;
4495         }
4496
4497         if (!CHECK_WRITE(fsp)) {
4498                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4499                 goto out;
4500         }
4501
4502         data = smb_base(req->inbuf) + smb_doff;
4503
4504         if(req->wct == 14) {
4505                 /*
4506                  * This is a large offset (64 bit) write.
4507                  */
4508                 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4509
4510         }
4511
4512         /* X/Open SMB protocol says that, unlike SMBwrite
4513         if the length is zero then NO truncation is
4514         done, just a write of zero. To truncate a file,
4515         use SMBwrite. */
4516
4517         if(numtowrite == 0) {
4518                 nwritten = 0;
4519         } else {
4520                 if (req->unread_bytes == 0) {
4521                         status = schedule_aio_write_and_X(conn,
4522                                                 req,
4523                                                 fsp,
4524                                                 data,
4525                                                 startpos,
4526                                                 numtowrite);
4527
4528                         if (NT_STATUS_IS_OK(status)) {
4529                                 /* write scheduled - we're done. */
4530                                 goto out;
4531                         }
4532                         if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4533                                 /* Real error - report to client. */
4534                                 reply_nterror(req, status);
4535                                 goto out;
4536                         }
4537                         /* NT_STATUS_RETRY - fall through to sync write. */
4538                 }
4539
4540                 init_strict_lock_struct(fsp,
4541                                 (uint64_t)req->smbpid,
4542                                 (uint64_t)startpos,
4543                                 (uint64_t)numtowrite,
4544                                 WRITE_LOCK,
4545                                 lp_posix_cifsu_locktype(fsp),
4546                                 &lock);
4547
4548                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4549                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4550                         goto out;
4551                 }
4552
4553                 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4554                 saved_errno = errno;
4555         }
4556
4557         if(nwritten < 0) {
4558                 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4559                 goto out;
4560         }
4561
4562         if((nwritten == 0) && (numtowrite != 0)) {
4563                 reply_nterror(req, NT_STATUS_DISK_FULL);
4564                 goto out;
4565         }
4566
4567         reply_outbuf(req, 6, 0);
4568         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4569         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
4570         SSVAL(req->outbuf,smb_vwv2,nwritten);
4571         SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4572
4573         DEBUG(3,("writeX %s num=%d wrote=%d\n",
4574                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4575
4576         status = sync_file(conn, fsp, write_through);
4577         if (!NT_STATUS_IS_OK(status)) {
4578                 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4579                          fsp_str_dbg(fsp), nt_errstr(status)));
4580                 reply_nterror(req, status);
4581                 goto out;
4582         }
4583
4584         END_PROFILE(SMBwriteX);
4585         return;
4586
4587 out:
4588         if (req->unread_bytes) {
4589                 /* writeX failed. drain socket. */
4590                 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4591                                 req->unread_bytes) {
4592                         smb_panic("failed to drain pending bytes");
4593                 }
4594                 req->unread_bytes = 0;
4595         }
4596
4597         END_PROFILE(SMBwriteX);
4598         return;
4599 }
4600
4601 /****************************************************************************
4602  Reply to a lseek.
4603 ****************************************************************************/
4604
4605 void reply_lseek(struct smb_request *req)
4606 {
4607         connection_struct *conn = req->conn;
4608         off_t startpos;
4609         off_t res= -1;
4610         int mode,umode;
4611         files_struct *fsp;
4612         NTSTATUS status;
4613
4614         START_PROFILE(SMBlseek);
4615
4616         if (req->wct < 4) {
4617                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4618                 END_PROFILE(SMBlseek);
4619                 return;
4620         }
4621
4622         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4623
4624         if (!check_fsp(conn, req, fsp)) {
4625                 return;
4626         }
4627
4628         mode = SVAL(req->vwv+1, 0) & 3;
4629         /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4630         startpos = (off_t)IVALS(req->vwv+2, 0);
4631
4632         switch (mode) {
4633                 case 0:
4634                         umode = SEEK_SET;
4635                         res = startpos;
4636                         break;
4637                 case 1:
4638                         umode = SEEK_CUR;
4639                         res = fh_get_pos(fsp->fh) + startpos;
4640                         break;
4641                 case 2:
4642                         umode = SEEK_END;
4643                         break;
4644                 default:
4645                         umode = SEEK_SET;
4646                         res = startpos;
4647                         break;
4648         }
4649
4650         if (umode == SEEK_END) {
4651                 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4652                         if(errno == EINVAL) {
4653                                 off_t current_pos = startpos;
4654
4655                                 status = vfs_stat_fsp(fsp);
4656                                 if (!NT_STATUS_IS_OK(status)) {
4657                                         reply_nterror(req, status);
4658                                         END_PROFILE(SMBlseek);
4659                                         return;
4660                                 }
4661
4662                                 current_pos += fsp->fsp_name->st.st_ex_size;
4663                                 if(current_pos < 0)
4664                                         res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4665                         }
4666                 }
4667
4668                 if(res == -1) {
4669                         reply_nterror(req, map_nt_error_from_unix(errno));
4670                         END_PROFILE(SMBlseek);
4671                         return;
4672                 }
4673         }
4674
4675         fh_set_pos(fsp->fh, res);
4676
4677         reply_outbuf(req, 2, 0);
4678         SIVAL(req->outbuf,smb_vwv0,res);
4679
4680         DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4681                 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4682
4683         END_PROFILE(SMBlseek);
4684         return;
4685 }
4686
4687 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
4688                                              void *private_data)
4689 {
4690         connection_struct *conn = talloc_get_type_abort(
4691                 private_data, connection_struct);
4692
4693         if (conn != fsp->conn) {
4694                 return NULL;
4695         }
4696         if (fsp_get_io_fd(fsp) == -1) {
4697                 return NULL;
4698         }
4699         sync_file(conn, fsp, True /* write through */);
4700
4701         if (fsp->fsp_flags.modified) {
4702                 trigger_write_time_update_immediate(fsp);
4703         }
4704
4705         return NULL;
4706 }
4707
4708 /****************************************************************************
4709  Reply to a flush.
4710 ****************************************************************************/
4711
4712 void reply_flush(struct smb_request *req)
4713 {
4714         connection_struct *conn = req->conn;
4715         uint16_t fnum;
4716         files_struct *fsp;
4717
4718         START_PROFILE(SMBflush);
4719
4720         if (req->wct < 1) {
4721                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4722                 return;
4723         }
4724
4725         fnum = SVAL(req->vwv+0, 0);
4726         fsp = file_fsp(req, fnum);
4727
4728         if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4729                 return;
4730         }
4731
4732         if (!fsp) {
4733                 files_forall(req->sconn, file_sync_one_fn, conn);
4734         } else {
4735                 NTSTATUS status = sync_file(conn, fsp, True);
4736                 if (!NT_STATUS_IS_OK(status)) {
4737                         DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4738                                 fsp_str_dbg(fsp), nt_errstr(status)));
4739                         reply_nterror(req, status);
4740                         END_PROFILE(SMBflush);
4741                         return;
4742                 }
4743                 if (fsp->fsp_flags.modified) {
4744                         trigger_write_time_update_immediate(fsp);
4745                 }
4746         }
4747
4748         reply_outbuf(req, 0, 0);
4749
4750         DEBUG(3,("flush\n"));
4751         END_PROFILE(SMBflush);
4752         return;
4753 }
4754
4755 /****************************************************************************
4756  Reply to a exit.
4757  conn POINTER CAN BE NULL HERE !
4758 ****************************************************************************/
4759
4760 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
4761 static void reply_exit_done(struct tevent_req *req);
4762
4763 void reply_exit(struct smb_request *smb1req)
4764 {
4765         struct tevent_req *req;
4766
4767         /*
4768          * Don't setup the profile charge here, take
4769          * it in reply_exit_done(). Not strictly correct
4770          * but better than the other SMB1 async
4771          * code that double-charges at the moment.
4772          */
4773         req = reply_exit_send(smb1req);
4774         if (req == NULL) {
4775                 /* Not going async, profile here. */
4776                 START_PROFILE(SMBexit);
4777                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
4778                 END_PROFILE(SMBexit);
4779                 return;
4780         }
4781
4782         /* We're async. This will complete later. */
4783         tevent_req_set_callback(req, reply_exit_done, smb1req);
4784         return;
4785 }
4786
4787 struct reply_exit_state {
4788         struct tevent_queue *wait_queue;
4789 };
4790
4791 static void reply_exit_wait_done(struct tevent_req *subreq);
4792
4793 /****************************************************************************
4794  Async SMB1 exit.
4795  Note, on failure here we deallocate and return NULL to allow the caller to
4796  SMB1 return an error of ERRnomem immediately.
4797 ****************************************************************************/
4798
4799 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
4800 {
4801         struct tevent_req *req;
4802         struct reply_exit_state *state;
4803         struct tevent_req *subreq;
4804         files_struct *fsp;
4805         struct smbd_server_connection *sconn = smb1req->sconn;
4806
4807         req = tevent_req_create(smb1req, &state,
4808                         struct reply_exit_state);
4809         if (req == NULL) {
4810                 return NULL;
4811         }
4812         state->wait_queue = tevent_queue_create(state,
4813                                 "reply_exit_wait_queue");
4814         if (tevent_req_nomem(state->wait_queue, req)) {
4815                 TALLOC_FREE(req);
4816                 return NULL;
4817         }
4818
4819         for (fsp = sconn->files; fsp; fsp = fsp->next) {
4820                 if (fsp->file_pid != smb1req->smbpid) {
4821                         continue;
4822                 }
4823                 if (fsp->vuid != smb1req->vuid) {
4824                         continue;
4825                 }
4826                 /*
4827                  * Flag the file as close in progress.
4828                  * This will prevent any more IO being
4829                  * done on it.
4830                  */
4831                 fsp->fsp_flags.closing = true;
4832
4833                 if (fsp->num_aio_requests > 0) {
4834                         /*
4835                          * Now wait until all aio requests on this fsp are
4836                          * finished.
4837                          *
4838                          * We don't set a callback, as we just want to block the
4839                          * wait queue and the talloc_free() of fsp->aio_request
4840                          * will remove the item from the wait queue.
4841                          */
4842                         subreq = tevent_queue_wait_send(fsp->aio_requests,
4843                                                 sconn->ev_ctx,
4844                                                 state->wait_queue);
4845                         if (tevent_req_nomem(subreq, req)) {
4846                                 TALLOC_FREE(req);
4847                                 return NULL;
4848                         }
4849                 }
4850         }
4851
4852         /*
4853          * Now we add our own waiter to the end of the queue,
4854          * this way we get notified when all pending requests are finished
4855          * and reply to the outstanding SMB1 request.
4856          */
4857         subreq = tevent_queue_wait_send(state,
4858                                 sconn->ev_ctx,
4859                                 state->wait_queue);
4860         if (tevent_req_nomem(subreq, req)) {
4861                 TALLOC_FREE(req);
4862                 return NULL;
4863         }
4864
4865         /*
4866          * We're really going async - move the SMB1 request from
4867          * a talloc stackframe above us to the conn talloc-context.
4868          * We need this to stick around until the wait_done
4869          * callback is invoked.
4870          */
4871         smb1req = talloc_move(sconn, &smb1req);
4872
4873         tevent_req_set_callback(subreq, reply_exit_wait_done, req);
4874
4875         return req;
4876 }
4877
4878 static void reply_exit_wait_done(struct tevent_req *subreq)
4879 {
4880         struct tevent_req *req = tevent_req_callback_data(
4881                 subreq, struct tevent_req);
4882
4883         tevent_queue_wait_recv(subreq);
4884         TALLOC_FREE(subreq);
4885         tevent_req_done(req);
4886 }
4887
4888 static NTSTATUS reply_exit_recv(struct tevent_req *req)
4889 {
4890         return tevent_req_simple_recv_ntstatus(req);
4891 }
4892
4893 static void reply_exit_done(struct tevent_req *req)
4894 {
4895         struct smb_request *smb1req = tevent_req_callback_data(
4896                 req, struct smb_request);
4897         struct smbd_server_connection *sconn = smb1req->sconn;
4898         struct smbXsrv_connection *xconn = smb1req->xconn;
4899         NTTIME now = timeval_to_nttime(&smb1req->request_time);
4900         struct smbXsrv_session *session = NULL;
4901         files_struct *fsp, *next;
4902         NTSTATUS status;
4903
4904         /*
4905          * Take the profile charge here. Not strictly
4906          * correct but better than the other SMB1 async
4907          * code that double-charges at the moment.
4908          */
4909         START_PROFILE(SMBexit);
4910
4911         status = reply_exit_recv(req);
4912         TALLOC_FREE(req);
4913         if (!NT_STATUS_IS_OK(status)) {
4914                 TALLOC_FREE(smb1req);
4915                 END_PROFILE(SMBexit);
4916                 exit_server(__location__ ": reply_exit_recv failed");
4917                 return;
4918         }
4919
4920         /*
4921          * Ensure the session is still valid.
4922          */
4923         status = smb1srv_session_lookup(xconn,
4924                                         smb1req->vuid,
4925                                         now,
4926                                         &session);
4927         if (!NT_STATUS_IS_OK(status)) {
4928                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4929                 smb_request_done(smb1req);
4930                 END_PROFILE(SMBexit);
4931         }
4932
4933         /*
4934          * Ensure the vuid is still valid - no one
4935          * called reply_ulogoffX() in the meantime.
4936          * reply_exit() doesn't have AS_USER set, so
4937          * use set_current_user_info() directly.
4938          * This is the same logic as in switch_message().
4939          */
4940         if (session->global->auth_session_info != NULL) {
4941                 set_current_user_info(
4942                         session->global->auth_session_info->unix_info->sanitized_username,
4943                         session->global->auth_session_info->unix_info->unix_name,
4944                         session->global->auth_session_info->info->domain_name);
4945         }
4946
4947         /* No more aio - do the actual closes. */
4948         for (fsp = sconn->files; fsp; fsp = next) {
4949                 bool ok;
4950                 next = fsp->next;
4951
4952                 if (fsp->file_pid != smb1req->smbpid) {
4953                         continue;
4954                 }
4955                 if (fsp->vuid != smb1req->vuid) {
4956                         continue;
4957                 }
4958                 if (!fsp->fsp_flags.closing) {
4959                         continue;
4960                 }
4961
4962                 /*
4963                  * reply_exit() has the DO_CHDIR flag set.
4964                  */
4965                 ok = chdir_current_service(fsp->conn);
4966                 if (!ok) {
4967                         reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
4968                         smb_request_done(smb1req);
4969                         END_PROFILE(SMBexit);
4970                 }
4971                 close_file_free(NULL, &fsp, SHUTDOWN_CLOSE);
4972         }
4973
4974         reply_outbuf(smb1req, 0, 0);
4975         /*
4976          * The following call is needed to push the
4977          * reply data back out the socket after async
4978          * return. Plus it frees smb1req.
4979          */
4980         smb_request_done(smb1req);
4981         DBG_INFO("reply_exit complete\n");
4982         END_PROFILE(SMBexit);
4983         return;
4984 }
4985
4986 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
4987                                 files_struct *fsp);
4988 static void reply_close_done(struct tevent_req *req);
4989
4990 void reply_close(struct smb_request *smb1req)
4991 {
4992         connection_struct *conn = smb1req->conn;
4993         NTSTATUS status = NT_STATUS_OK;
4994         files_struct *fsp = NULL;
4995         START_PROFILE(SMBclose);
4996
4997         if (smb1req->wct < 3) {
4998                 reply_nterror(smb1req, NT_STATUS_INVALID_PARAMETER);
4999                 END_PROFILE(SMBclose);
5000                 return;
5001         }
5002
5003         fsp = file_fsp(smb1req, SVAL(smb1req->vwv+0, 0));
5004
5005         /*
5006          * We can only use check_fsp if we know it's not a directory.
5007          */
5008
5009         if (!check_fsp_open(conn, smb1req, fsp)) {
5010                 reply_nterror(smb1req, NT_STATUS_INVALID_HANDLE);
5011                 END_PROFILE(SMBclose);
5012                 return;
5013         }
5014
5015         DBG_NOTICE("Close %s fd=%d %s (numopen=%d)\n",
5016                   fsp->fsp_flags.is_directory ?
5017                   "directory" : "file",
5018                   fsp_get_pathref_fd(fsp), fsp_fnum_dbg(fsp),
5019                   conn->num_files_open);
5020
5021         if (!fsp->fsp_flags.is_directory) {
5022                 time_t t;
5023
5024                 /*
5025                  * Take care of any time sent in the close.
5026                  */
5027
5028                 t = srv_make_unix_date3(smb1req->vwv+1);
5029                 set_close_write_time(fsp, time_t_to_full_timespec(t));
5030         }
5031
5032         if (fsp->num_aio_requests != 0) {
5033                 struct tevent_req *req;
5034
5035                 req = reply_close_send(smb1req, fsp);
5036                 if (req == NULL) {
5037                         status = NT_STATUS_NO_MEMORY;
5038                         goto done;
5039                 }
5040                 /* We're async. This will complete later. */
5041                 tevent_req_set_callback(req, reply_close_done, smb1req);
5042                 END_PROFILE(SMBclose);
5043                 return;
5044         }
5045
5046         /*
5047          * close_file_free() returns the unix errno if an error was detected on
5048          * close - normally this is due to a disk full error. If not then it
5049          * was probably an I/O error.
5050          */
5051
5052         status = close_file_free(smb1req, &fsp, NORMAL_CLOSE);
5053 done:
5054         if (!NT_STATUS_IS_OK(status)) {
5055                 reply_nterror(smb1req, status);
5056                 END_PROFILE(SMBclose);
5057                 return;
5058         }
5059
5060         reply_outbuf(smb1req, 0, 0);
5061         END_PROFILE(SMBclose);
5062         return;
5063 }
5064
5065 struct reply_close_state {
5066         files_struct *fsp;
5067         struct tevent_queue *wait_queue;
5068 };
5069
5070 static void reply_close_wait_done(struct tevent_req *subreq);
5071
5072 /****************************************************************************
5073  Async SMB1 close.
5074  Note, on failure here we deallocate and return NULL to allow the caller to
5075  SMB1 return an error of ERRnomem immediately.
5076 ****************************************************************************/
5077
5078 static struct tevent_req *reply_close_send(struct smb_request *smb1req,
5079                                 files_struct *fsp)
5080 {
5081         struct tevent_req *req;
5082         struct reply_close_state *state;
5083         struct tevent_req *subreq;
5084         struct smbd_server_connection *sconn = smb1req->sconn;
5085
5086         req = tevent_req_create(smb1req, &state,
5087                         struct reply_close_state);
5088         if (req == NULL) {
5089                 return NULL;
5090         }
5091         state->wait_queue = tevent_queue_create(state,
5092                                 "reply_close_wait_queue");
5093         if (tevent_req_nomem(state->wait_queue, req)) {
5094                 TALLOC_FREE(req);
5095                 return NULL;
5096         }
5097
5098         /*
5099          * Flag the file as close in progress.
5100          * This will prevent any more IO being
5101          * done on it.
5102          */
5103         fsp->fsp_flags.closing = true;
5104
5105         /*
5106          * Now wait until all aio requests on this fsp are
5107          * finished.
5108          *
5109          * We don't set a callback, as we just want to block the
5110          * wait queue and the talloc_free() of fsp->aio_request
5111          * will remove the item from the wait queue.
5112          */
5113         subreq = tevent_queue_wait_send(fsp->aio_requests,
5114                                         sconn->ev_ctx,
5115                                         state->wait_queue);
5116         if (tevent_req_nomem(subreq, req)) {
5117                 TALLOC_FREE(req);
5118                 return NULL;
5119         }
5120
5121         /*
5122          * Now we add our own waiter to the end of the queue,
5123          * this way we get notified when all pending requests are finished
5124          * and reply to the outstanding SMB1 request.
5125          */
5126         subreq = tevent_queue_wait_send(state,
5127                                 sconn->ev_ctx,
5128                                 state->wait_queue);
5129         if (tevent_req_nomem(subreq, req)) {
5130                 TALLOC_FREE(req);
5131                 return NULL;
5132         }
5133
5134         /*
5135          * We're really going async - move the SMB1 request from
5136          * a talloc stackframe above us to the conn talloc-context.
5137          * We need this to stick around until the wait_done
5138          * callback is invoked.
5139          */
5140         smb1req = talloc_move(sconn, &smb1req);
5141
5142         tevent_req_set_callback(subreq, reply_close_wait_done, req);
5143
5144         return req;
5145 }
5146
5147 static void reply_close_wait_done(struct tevent_req *subreq)
5148 {
5149         struct tevent_req *req = tevent_req_callback_data(
5150                 subreq, struct tevent_req);
5151
5152         tevent_queue_wait_recv(subreq);
5153         TALLOC_FREE(subreq);
5154         tevent_req_done(req);
5155 }
5156
5157 static NTSTATUS reply_close_recv(struct tevent_req *req)
5158 {
5159         return tevent_req_simple_recv_ntstatus(req);
5160 }
5161
5162 static void reply_close_done(struct tevent_req *req)
5163 {
5164         struct smb_request *smb1req = tevent_req_callback_data(
5165                         req, struct smb_request);
5166         struct reply_close_state *state = tevent_req_data(req,
5167                                                 struct reply_close_state);
5168         NTSTATUS status;
5169
5170         status = reply_close_recv(req);
5171         TALLOC_FREE(req);
5172         if (!NT_STATUS_IS_OK(status)) {
5173                 TALLOC_FREE(smb1req);
5174                 exit_server(__location__ ": reply_close_recv failed");
5175                 return;
5176         }
5177
5178         status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE);
5179         if (NT_STATUS_IS_OK(status)) {
5180                 reply_outbuf(smb1req, 0, 0);
5181         } else {
5182                 reply_nterror(smb1req, status);
5183         }
5184         /*
5185          * The following call is needed to push the
5186          * reply data back out the socket after async
5187          * return. Plus it frees smb1req.
5188          */
5189         smb_request_done(smb1req);
5190 }
5191
5192 /****************************************************************************
5193  Reply to a writeclose (Core+ protocol).
5194 ****************************************************************************/
5195
5196 void reply_writeclose(struct smb_request *req)
5197 {
5198         connection_struct *conn = req->conn;
5199         size_t numtowrite;
5200         size_t remaining;
5201         ssize_t nwritten = -1;
5202         NTSTATUS close_status = NT_STATUS_OK;
5203         off_t startpos;
5204         const char *data;
5205         struct timespec mtime;
5206         files_struct *fsp;
5207         struct lock_struct lock;
5208
5209         START_PROFILE(SMBwriteclose);
5210
5211         if (req->wct < 6) {
5212                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5213                 END_PROFILE(SMBwriteclose);
5214                 return;
5215         }
5216
5217         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5218
5219         if (!check_fsp(conn, req, fsp)) {
5220                 END_PROFILE(SMBwriteclose);
5221                 return;
5222         }
5223         if (!CHECK_WRITE(fsp)) {
5224                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5225                 END_PROFILE(SMBwriteclose);
5226                 return;
5227         }
5228
5229         numtowrite = SVAL(req->vwv+1, 0);
5230         startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5231         mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
5232         data = (const char *)req->buf + 1;
5233
5234         /*
5235          * Ensure client isn't asking us to write more than
5236          * they sent. CVE-2017-12163.
5237          */
5238         remaining = smbreq_bufrem(req, data);
5239         if (numtowrite > remaining) {
5240                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5241                 END_PROFILE(SMBwriteclose);
5242                 return;
5243         }
5244
5245         if (fsp->print_file == NULL) {
5246                 init_strict_lock_struct(fsp,
5247                                 (uint64_t)req->smbpid,
5248                                 (uint64_t)startpos,
5249                                 (uint64_t)numtowrite,
5250                                 WRITE_LOCK,
5251                                 lp_posix_cifsu_locktype(fsp),
5252                                 &lock);
5253
5254                 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5255                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5256                         END_PROFILE(SMBwriteclose);
5257                         return;
5258                 }
5259         }
5260
5261         nwritten = write_file(req,fsp,data,startpos,numtowrite);
5262
5263         set_close_write_time(fsp, mtime);
5264
5265         /*
5266          * More insanity. W2K only closes the file if writelen > 0.
5267          * JRA.
5268          */
5269
5270         DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5271                 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5272                 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5273
5274         if (numtowrite) {
5275                 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5276                          "file %s\n", fsp_str_dbg(fsp)));
5277                 close_status = close_file_free(req, &fsp, NORMAL_CLOSE);
5278         }
5279
5280         if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5281                 reply_nterror(req, NT_STATUS_DISK_FULL);
5282                 goto out;
5283         }
5284
5285         if(!NT_STATUS_IS_OK(close_status)) {
5286                 reply_nterror(req, close_status);
5287                 goto out;
5288         }
5289
5290         reply_outbuf(req, 1, 0);
5291
5292         SSVAL(req->outbuf,smb_vwv0,nwritten);
5293
5294 out:
5295
5296         END_PROFILE(SMBwriteclose);
5297         return;
5298 }
5299
5300 #undef DBGC_CLASS
5301 #define DBGC_CLASS DBGC_LOCKING
5302
5303 /****************************************************************************
5304  Reply to a lock.
5305 ****************************************************************************/
5306
5307 static void reply_lock_done(struct tevent_req *subreq);
5308
5309 void reply_lock(struct smb_request *req)
5310 {
5311         struct tevent_req *subreq = NULL;
5312         connection_struct *conn = req->conn;
5313         files_struct *fsp;
5314         struct smbd_lock_element *lck = NULL;
5315
5316         START_PROFILE(SMBlock);
5317
5318         if (req->wct < 5) {
5319                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5320                 END_PROFILE(SMBlock);
5321                 return;
5322         }
5323
5324         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5325
5326         if (!check_fsp(conn, req, fsp)) {
5327                 END_PROFILE(SMBlock);
5328                 return;
5329         }
5330
5331         lck = talloc(req, struct smbd_lock_element);
5332         if (lck == NULL) {
5333                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5334                 END_PROFILE(SMBlock);
5335                 return;
5336         }
5337
5338         *lck = (struct smbd_lock_element) {
5339                 .req_guid = smbd_request_guid(req, 0),
5340                 .smblctx = req->smbpid,
5341                 .brltype = WRITE_LOCK,
5342                 .lock_flav = WINDOWS_LOCK,
5343                 .count = IVAL(req->vwv+1, 0),
5344                 .offset = IVAL(req->vwv+3, 0),
5345         };
5346
5347         DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5348                    fsp_get_io_fd(fsp),
5349                    fsp_fnum_dbg(fsp),
5350                    lck->offset,
5351                    lck->count);
5352
5353         subreq = smbd_smb1_do_locks_send(
5354                 fsp,
5355                 req->sconn->ev_ctx,
5356                 &req,
5357                 fsp,
5358                 0,
5359                 false,          /* large_offset */
5360                 1,
5361                 lck);
5362         if (subreq == NULL) {
5363                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5364                 END_PROFILE(SMBlock);
5365                 return;
5366         }
5367         tevent_req_set_callback(subreq, reply_lock_done, NULL);
5368         END_PROFILE(SMBlock);
5369 }
5370
5371 static void reply_lock_done(struct tevent_req *subreq)
5372 {
5373         struct smb_request *req = NULL;
5374         NTSTATUS status;
5375         bool ok;
5376
5377         START_PROFILE(SMBlock);
5378
5379         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
5380         SMB_ASSERT(ok);
5381
5382         status = smbd_smb1_do_locks_recv(subreq);
5383         TALLOC_FREE(subreq);
5384
5385         if (NT_STATUS_IS_OK(status)) {
5386                 reply_outbuf(req, 0, 0);
5387         } else {
5388                 reply_nterror(req, status);
5389         }
5390
5391         ok = srv_send_smb(req->xconn,
5392                           (char *)req->outbuf,
5393                           true,
5394                           req->seqnum+1,
5395                           IS_CONN_ENCRYPTED(req->conn),
5396                           NULL);
5397         if (!ok) {
5398                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
5399         }
5400         TALLOC_FREE(req);
5401         END_PROFILE(SMBlock);
5402 }
5403
5404 /****************************************************************************
5405  Reply to a unlock.
5406 ****************************************************************************/
5407
5408 void reply_unlock(struct smb_request *req)
5409 {
5410         connection_struct *conn = req->conn;
5411         NTSTATUS status;
5412         files_struct *fsp;
5413         struct smbd_lock_element lck;
5414
5415         START_PROFILE(SMBunlock);
5416
5417         if (req->wct < 5) {
5418                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5419                 END_PROFILE(SMBunlock);
5420                 return;
5421         }
5422
5423         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5424
5425         if (!check_fsp(conn, req, fsp)) {
5426                 END_PROFILE(SMBunlock);
5427                 return;
5428         }
5429
5430         lck = (struct smbd_lock_element) {
5431                 .req_guid = smbd_request_guid(req, 0),
5432                 .smblctx = req->smbpid,
5433                 .brltype = UNLOCK_LOCK,
5434                 .lock_flav = WINDOWS_LOCK,
5435                 .offset = IVAL(req->vwv+3, 0),
5436                 .count = IVAL(req->vwv+1, 0),
5437         };
5438
5439         status = smbd_do_unlocking(req, fsp, 1, &lck);
5440
5441         if (!NT_STATUS_IS_OK(status)) {
5442                 reply_nterror(req, status);
5443                 END_PROFILE(SMBunlock);
5444                 return;
5445         }
5446
5447         DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
5448                    fsp_get_io_fd(fsp),
5449                    fsp_fnum_dbg(fsp),
5450                    lck.offset,
5451                    lck.count);
5452
5453         reply_outbuf(req, 0, 0);
5454
5455         END_PROFILE(SMBunlock);
5456         return;
5457 }
5458
5459 #undef DBGC_CLASS
5460 #define DBGC_CLASS DBGC_ALL
5461
5462 /****************************************************************************
5463  Reply to a tdis.
5464  conn POINTER CAN BE NULL HERE !
5465 ****************************************************************************/
5466
5467 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
5468 static void reply_tdis_done(struct tevent_req *req);
5469
5470 void reply_tdis(struct smb_request *smb1req)
5471 {
5472         connection_struct *conn = smb1req->conn;
5473         struct tevent_req *req;
5474
5475         /*
5476          * Don't setup the profile charge here, take
5477          * it in reply_tdis_done(). Not strictly correct
5478          * but better than the other SMB1 async
5479          * code that double-charges at the moment.
5480          */
5481
5482         if (conn == NULL) {
5483                 /* Not going async, profile here. */
5484                 START_PROFILE(SMBtdis);
5485                 DBG_INFO("Invalid connection in tdis\n");
5486                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5487                 END_PROFILE(SMBtdis);
5488                 return;
5489         }
5490
5491         req = reply_tdis_send(smb1req);
5492         if (req == NULL) {
5493                 /* Not going async, profile here. */
5494                 START_PROFILE(SMBtdis);
5495                 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5496                 END_PROFILE(SMBtdis);
5497                 return;
5498         }
5499         /* We're async. This will complete later. */
5500         tevent_req_set_callback(req, reply_tdis_done, smb1req);
5501         return;
5502 }
5503
5504 struct reply_tdis_state {
5505         struct tevent_queue *wait_queue;
5506 };
5507
5508 static void reply_tdis_wait_done(struct tevent_req *subreq);
5509
5510 /****************************************************************************
5511  Async SMB1 tdis.
5512  Note, on failure here we deallocate and return NULL to allow the caller to
5513  SMB1 return an error of ERRnomem immediately.
5514 ****************************************************************************/
5515
5516 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
5517 {
5518         struct tevent_req *req;
5519         struct reply_tdis_state *state;
5520         struct tevent_req *subreq;
5521         connection_struct *conn = smb1req->conn;
5522         files_struct *fsp;
5523
5524         req = tevent_req_create(smb1req, &state,
5525                         struct reply_tdis_state);
5526         if (req == NULL) {
5527                 return NULL;
5528         }
5529         state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
5530         if (tevent_req_nomem(state->wait_queue, req)) {
5531                 TALLOC_FREE(req);
5532                 return NULL;
5533         }
5534
5535         /*
5536          * Make sure that no new request will be able to use this tcon.
5537          * This ensures that once all outstanding fsp->aio_requests
5538          * on this tcon are done, we are safe to close it.
5539          */
5540         conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
5541
5542         for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
5543                 if (fsp->conn != conn) {
5544                         continue;
5545                 }
5546                 /*
5547                  * Flag the file as close in progress.
5548                  * This will prevent any more IO being
5549                  * done on it. Not strictly needed, but
5550                  * doesn't hurt to flag it as closing.
5551                  */
5552                 fsp->fsp_flags.closing = true;
5553
5554                 if (fsp->num_aio_requests > 0) {
5555                         /*
5556                          * Now wait until all aio requests on this fsp are
5557                          * finished.
5558                          *
5559                          * We don't set a callback, as we just want to block the
5560                          * wait queue and the talloc_free() of fsp->aio_request
5561                          * will remove the item from the wait queue.
5562                          */
5563                         subreq = tevent_queue_wait_send(fsp->aio_requests,
5564                                                 conn->sconn->ev_ctx,
5565                                                 state->wait_queue);
5566                         if (tevent_req_nomem(subreq, req)) {
5567                                 TALLOC_FREE(req);
5568                                 return NULL;
5569                         }
5570                 }
5571         }
5572
5573         /*
5574          * Now we add our own waiter to the end of the queue,
5575          * this way we get notified when all pending requests are finished
5576          * and reply to the outstanding SMB1 request.
5577          */
5578         subreq = tevent_queue_wait_send(state,
5579                                 conn->sconn->ev_ctx,
5580                                 state->wait_queue);
5581         if (tevent_req_nomem(subreq, req)) {
5582                 TALLOC_FREE(req);
5583                 return NULL;
5584         }
5585
5586         /*
5587          * We're really going async - move the SMB1 request from
5588          * a talloc stackframe above us to the sconn talloc-context.
5589          * We need this to stick around until the wait_done
5590          * callback is invoked.
5591          */
5592         smb1req = talloc_move(smb1req->sconn, &smb1req);
5593
5594         tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
5595
5596         return req;
5597 }
5598
5599 static void reply_tdis_wait_done(struct tevent_req *subreq)
5600 {
5601         struct tevent_req *req = tevent_req_callback_data(
5602                 subreq, struct tevent_req);
5603
5604         tevent_queue_wait_recv(subreq);
5605         TALLOC_FREE(subreq);
5606         tevent_req_done(req);
5607 }
5608
5609 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
5610 {
5611         return tevent_req_simple_recv_ntstatus(req);
5612 }
5613
5614 static void reply_tdis_done(struct tevent_req *req)
5615 {
5616         struct smb_request *smb1req = tevent_req_callback_data(
5617                 req, struct smb_request);
5618         NTSTATUS status;
5619         struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
5620         bool ok;
5621
5622         /*
5623          * Take the profile charge here. Not strictly
5624          * correct but better than the other SMB1 async
5625          * code that double-charges at the moment.
5626          */
5627         START_PROFILE(SMBtdis);
5628
5629         status = reply_tdis_recv(req);
5630         TALLOC_FREE(req);
5631         if (!NT_STATUS_IS_OK(status)) {
5632                 TALLOC_FREE(smb1req);
5633                 END_PROFILE(SMBtdis);
5634                 exit_server(__location__ ": reply_tdis_recv failed");
5635                 return;
5636         }
5637
5638         /*
5639          * As we've been awoken, we may have changed
5640          * directory in the meantime.
5641          * reply_tdis() has the DO_CHDIR flag set.
5642          */
5643         ok = chdir_current_service(smb1req->conn);
5644         if (!ok) {
5645                 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5646                 smb_request_done(smb1req);
5647                 END_PROFILE(SMBtdis);
5648         }
5649
5650         status = smbXsrv_tcon_disconnect(tcon,
5651                                          smb1req->vuid);
5652         if (!NT_STATUS_IS_OK(status)) {
5653                 TALLOC_FREE(smb1req);
5654                 END_PROFILE(SMBtdis);
5655                 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5656                 return;
5657         }
5658
5659         /* smbXsrv_tcon_disconnect frees smb1req->conn. */
5660         smb1req->conn = NULL;
5661
5662         TALLOC_FREE(tcon);
5663
5664         reply_outbuf(smb1req, 0, 0);
5665         /*
5666          * The following call is needed to push the
5667          * reply data back out the socket after async
5668          * return. Plus it frees smb1req.
5669          */
5670         smb_request_done(smb1req);
5671         END_PROFILE(SMBtdis);
5672 }
5673
5674 /****************************************************************************
5675  Reply to a echo.
5676  conn POINTER CAN BE NULL HERE !
5677 ****************************************************************************/
5678
5679 void reply_echo(struct smb_request *req)
5680 {
5681         connection_struct *conn = req->conn;
5682         struct smb_perfcount_data local_pcd;
5683         struct smb_perfcount_data *cur_pcd;
5684         int smb_reverb;
5685         int seq_num;
5686
5687         START_PROFILE(SMBecho);
5688
5689         smb_init_perfcount_data(&local_pcd);
5690
5691         if (req->wct < 1) {
5692                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5693                 END_PROFILE(SMBecho);
5694                 return;
5695         }
5696
5697         smb_reverb = SVAL(req->vwv+0, 0);
5698
5699         reply_outbuf(req, 1, req->buflen);
5700
5701         /* copy any incoming data back out */
5702         if (req->buflen > 0) {
5703                 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5704         }
5705
5706         if (smb_reverb > 100) {
5707                 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5708                 smb_reverb = 100;
5709         }
5710
5711         for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5712
5713                 /* this makes sure we catch the request pcd */
5714                 if (seq_num == smb_reverb) {
5715                         cur_pcd = &req->pcd;
5716                 } else {
5717                         SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5718                         cur_pcd = &local_pcd;
5719                 }
5720
5721                 SSVAL(req->outbuf,smb_vwv0,seq_num);
5722
5723                 show_msg((char *)req->outbuf);
5724                 if (!srv_send_smb(req->xconn,
5725                                 (char *)req->outbuf,
5726                                 true, req->seqnum+1,
5727                                 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5728                                 cur_pcd))
5729                         exit_server_cleanly("reply_echo: srv_send_smb failed.");
5730         }
5731
5732         DEBUG(3,("echo %d times\n", smb_reverb));
5733
5734         TALLOC_FREE(req->outbuf);
5735
5736         END_PROFILE(SMBecho);
5737         return;
5738 }
5739
5740 /****************************************************************************
5741  Reply to a printopen.
5742 ****************************************************************************/
5743
5744 void reply_printopen(struct smb_request *req)
5745 {
5746         connection_struct *conn = req->conn;
5747         files_struct *fsp;
5748         NTSTATUS status;
5749
5750         START_PROFILE(SMBsplopen);
5751
5752         if (req->wct < 2) {
5753                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5754                 END_PROFILE(SMBsplopen);
5755                 return;
5756         }
5757
5758         if (!CAN_PRINT(conn)) {
5759                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5760                 END_PROFILE(SMBsplopen);
5761                 return;
5762         }
5763
5764         status = file_new(req, conn, &fsp);
5765         if(!NT_STATUS_IS_OK(status)) {
5766                 reply_nterror(req, status);
5767                 END_PROFILE(SMBsplopen);
5768                 return;
5769         }
5770
5771         /* Open for exclusive use, write only. */
5772         status = print_spool_open(fsp, NULL, req->vuid);
5773
5774         if (!NT_STATUS_IS_OK(status)) {
5775                 file_free(req, fsp);
5776                 reply_nterror(req, status);
5777                 END_PROFILE(SMBsplopen);
5778                 return;
5779         }
5780
5781         reply_outbuf(req, 1, 0);
5782         SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5783
5784         DEBUG(3,("openprint fd=%d %s\n",
5785                  fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5786
5787         END_PROFILE(SMBsplopen);
5788         return;
5789 }
5790
5791 /****************************************************************************
5792  Reply to a printclose.
5793 ****************************************************************************/
5794
5795 void reply_printclose(struct smb_request *req)
5796 {
5797         connection_struct *conn = req->conn;
5798         files_struct *fsp;
5799         NTSTATUS status;
5800
5801         START_PROFILE(SMBsplclose);
5802
5803         if (req->wct < 1) {
5804                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5805                 END_PROFILE(SMBsplclose);
5806                 return;
5807         }
5808
5809         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5810
5811         if (!check_fsp(conn, req, fsp)) {
5812                 END_PROFILE(SMBsplclose);
5813                 return;
5814         }
5815
5816         if (!CAN_PRINT(conn)) {
5817                 reply_force_doserror(req, ERRSRV, ERRerror);
5818                 END_PROFILE(SMBsplclose);
5819                 return;
5820         }
5821
5822         DEBUG(3,("printclose fd=%d %s\n",
5823                  fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp)));
5824
5825         status = close_file_free(req, &fsp, NORMAL_CLOSE);
5826
5827         if(!NT_STATUS_IS_OK(status)) {
5828                 reply_nterror(req, status);
5829                 END_PROFILE(SMBsplclose);
5830                 return;
5831         }
5832
5833         reply_outbuf(req, 0, 0);
5834
5835         END_PROFILE(SMBsplclose);
5836         return;
5837 }
5838
5839 /****************************************************************************
5840  Reply to a printqueue.
5841 ****************************************************************************/
5842
5843 void reply_printqueue(struct smb_request *req)
5844 {
5845         const struct loadparm_substitution *lp_sub =
5846                 loadparm_s3_global_substitution();
5847         connection_struct *conn = req->conn;
5848         int max_count;
5849         int start_index;
5850
5851         START_PROFILE(SMBsplretq);
5852
5853         if (req->wct < 2) {
5854                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5855                 END_PROFILE(SMBsplretq);
5856                 return;
5857         }
5858
5859         max_count = SVAL(req->vwv+0, 0);
5860         start_index = SVAL(req->vwv+1, 0);
5861
5862         /* we used to allow the client to get the cnum wrong, but that
5863            is really quite gross and only worked when there was only
5864            one printer - I think we should now only accept it if they
5865            get it right (tridge) */
5866         if (!CAN_PRINT(conn)) {
5867                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5868                 END_PROFILE(SMBsplretq);
5869                 return;
5870         }
5871
5872         reply_outbuf(req, 2, 3);
5873         SSVAL(req->outbuf,smb_vwv0,0);
5874         SSVAL(req->outbuf,smb_vwv1,0);
5875         SCVAL(smb_buf(req->outbuf),0,1);
5876         SSVAL(smb_buf(req->outbuf),1,0);
5877
5878         DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5879                  start_index, max_count));
5880
5881         {
5882                 TALLOC_CTX *mem_ctx = talloc_tos();
5883                 NTSTATUS status;
5884                 WERROR werr;
5885                 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
5886                 struct rpc_pipe_client *cli = NULL;
5887                 struct dcerpc_binding_handle *b = NULL;
5888                 struct policy_handle handle;
5889                 struct spoolss_DevmodeContainer devmode_ctr;
5890                 union spoolss_JobInfo *info;
5891                 uint32_t count;
5892                 uint32_t num_to_get;
5893                 uint32_t first;
5894                 uint32_t i;
5895
5896                 ZERO_STRUCT(handle);
5897
5898                 status = rpc_pipe_open_interface(mem_ctx,
5899                                                  &ndr_table_spoolss,
5900                                                  conn->session_info,
5901                                                  conn->sconn->remote_address,
5902                                                  conn->sconn->local_address,
5903                                                  conn->sconn->msg_ctx,
5904                                                  &cli);
5905                 if (!NT_STATUS_IS_OK(status)) {
5906                         DEBUG(0, ("reply_printqueue: "
5907                                   "could not connect to spoolss: %s\n",
5908                                   nt_errstr(status)));
5909                         reply_nterror(req, status);
5910                         goto out;
5911                 }
5912                 b = cli->binding_handle;
5913
5914                 ZERO_STRUCT(devmode_ctr);
5915
5916                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5917                                                 sharename,
5918                                                 NULL, devmode_ctr,
5919                                                 SEC_FLAG_MAXIMUM_ALLOWED,
5920                                                 &handle,
5921                                                 &werr);
5922                 if (!NT_STATUS_IS_OK(status)) {
5923                         reply_nterror(req, status);
5924                         goto out;
5925                 }
5926                 if (!W_ERROR_IS_OK(werr)) {
5927                         reply_nterror(req, werror_to_ntstatus(werr));
5928                         goto out;
5929                 }
5930
5931                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5932                                                &handle,
5933                                                0, /* firstjob */
5934                                                0xff, /* numjobs */
5935                                                2, /* level */
5936                                                0, /* offered */
5937                                                &count,
5938                                                &info);
5939                 if (!W_ERROR_IS_OK(werr)) {
5940                         reply_nterror(req, werror_to_ntstatus(werr));
5941                         goto out;
5942                 }
5943
5944                 if (max_count > 0) {
5945                         first = start_index;
5946                 } else {
5947                         first = start_index + max_count + 1;
5948                 }
5949
5950                 if (first >= count) {
5951                         num_to_get = first;
5952                 } else {
5953                         num_to_get = first + MIN(ABS(max_count), count - first);
5954                 }
5955
5956                 for (i = first; i < num_to_get; i++) {
5957                         char blob[28];
5958                         char *p = blob;
5959                         time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5960                         int qstatus;
5961                         size_t len = 0;
5962                         uint16_t qrapjobid = pjobid_to_rap(sharename,
5963                                                         info[i].info2.job_id);
5964
5965                         if (info[i].info2.status == JOB_STATUS_PRINTING) {
5966                                 qstatus = 2;
5967                         } else {
5968                                 qstatus = 3;
5969                         }
5970
5971                         srv_put_dos_date2(p, 0, qtime);
5972                         SCVAL(p, 4, qstatus);
5973                         SSVAL(p, 5, qrapjobid);
5974                         SIVAL(p, 7, info[i].info2.size);
5975                         SCVAL(p, 11, 0);
5976                         status = srvstr_push(blob, req->flags2, p+12,
5977                                     info[i].info2.notify_name, 16, STR_ASCII, &len);
5978                         if (!NT_STATUS_IS_OK(status)) {
5979                                 reply_nterror(req, status);
5980                                 goto out;
5981                         }
5982                         if (message_push_blob(
5983                                     &req->outbuf,
5984                                     data_blob_const(
5985                                             blob, sizeof(blob))) == -1) {
5986                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
5987                                 goto out;
5988                         }
5989                 }
5990
5991                 if (count > 0) {
5992                         SSVAL(req->outbuf,smb_vwv0,count);
5993                         SSVAL(req->outbuf,smb_vwv1,
5994                               (max_count>0?first+count:first-1));
5995                         SCVAL(smb_buf(req->outbuf),0,1);
5996                         SSVAL(smb_buf(req->outbuf),1,28*count);
5997                 }
5998
5999
6000                 DEBUG(3, ("%u entries returned in queue\n",
6001                           (unsigned)count));
6002
6003 out:
6004                 if (b && is_valid_policy_hnd(&handle)) {
6005                         dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6006                 }
6007
6008         }
6009
6010         END_PROFILE(SMBsplretq);
6011         return;
6012 }
6013
6014 /****************************************************************************
6015  Reply to a printwrite.
6016 ****************************************************************************/
6017
6018 void reply_printwrite(struct smb_request *req)
6019 {
6020         connection_struct *conn = req->conn;
6021         int numtowrite;
6022         const char *data;
6023         files_struct *fsp;
6024
6025         START_PROFILE(SMBsplwr);
6026
6027         if (req->wct < 1) {
6028                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6029                 END_PROFILE(SMBsplwr);
6030                 return;
6031         }
6032
6033         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6034
6035         if (!check_fsp(conn, req, fsp)) {
6036                 END_PROFILE(SMBsplwr);
6037                 return;
6038         }
6039
6040         if (!fsp->print_file) {
6041                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6042                 END_PROFILE(SMBsplwr);
6043                 return;
6044         }
6045
6046         if (!CHECK_WRITE(fsp)) {
6047                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6048                 END_PROFILE(SMBsplwr);
6049                 return;
6050         }
6051
6052         numtowrite = SVAL(req->buf, 1);
6053
6054         /*
6055          * This already protects us against CVE-2017-12163.
6056          */
6057         if (req->buflen < numtowrite + 3) {
6058                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6059                 END_PROFILE(SMBsplwr);
6060                 return;
6061         }
6062
6063         data = (const char *)req->buf + 3;
6064
6065         if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
6066                 reply_nterror(req, map_nt_error_from_unix(errno));
6067                 END_PROFILE(SMBsplwr);
6068                 return;
6069         }
6070
6071         DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
6072
6073         reply_outbuf(req, 0, 0);
6074
6075         END_PROFILE(SMBsplwr);
6076         return;
6077 }
6078
6079 /****************************************************************************
6080  Reply to a mkdir.
6081 ****************************************************************************/
6082
6083 void reply_mkdir(struct smb_request *req)
6084 {
6085         connection_struct *conn = req->conn;
6086         struct smb_filename *smb_dname = NULL;
6087         char *directory = NULL;
6088         NTSTATUS status;
6089         uint32_t ucf_flags;
6090         TALLOC_CTX *ctx = talloc_tos();
6091
6092         START_PROFILE(SMBmkdir);
6093
6094         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6095                             STR_TERMINATE, &status);
6096         if (!NT_STATUS_IS_OK(status)) {
6097                 reply_nterror(req, status);
6098                 goto out;
6099         }
6100
6101         ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
6102         status = filename_convert(ctx, conn,
6103                                  directory,
6104                                  ucf_flags,
6105                                  0,
6106                                  &smb_dname);
6107         if (!NT_STATUS_IS_OK(status)) {
6108                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6109                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6110                                         ERRSRV, ERRbadpath);
6111                         goto out;
6112                 }
6113                 reply_nterror(req, status);
6114                 goto out;
6115         }
6116
6117         status = create_directory(conn, req, smb_dname);
6118
6119         DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
6120
6121         if (!NT_STATUS_IS_OK(status)) {
6122
6123                 if (!use_nt_status()
6124                     && NT_STATUS_EQUAL(status,
6125                                        NT_STATUS_OBJECT_NAME_COLLISION)) {
6126                         /*
6127                          * Yes, in the DOS error code case we get a
6128                          * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
6129                          * samba4 torture test.
6130                          */
6131                         status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
6132                 }
6133
6134                 reply_nterror(req, status);
6135                 goto out;
6136         }
6137
6138         reply_outbuf(req, 0, 0);
6139
6140         DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6141  out:
6142         TALLOC_FREE(smb_dname);
6143         END_PROFILE(SMBmkdir);
6144         return;
6145 }
6146
6147 /****************************************************************************
6148  Reply to a rmdir.
6149 ****************************************************************************/
6150
6151 void reply_rmdir(struct smb_request *req)
6152 {
6153         connection_struct *conn = req->conn;
6154         struct smb_filename *smb_dname = NULL;
6155         char *directory = NULL;
6156         NTSTATUS status;
6157         TALLOC_CTX *ctx = talloc_tos();
6158         files_struct *fsp = NULL;
6159         int info = 0;
6160         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6161
6162         START_PROFILE(SMBrmdir);
6163
6164         srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6165                             STR_TERMINATE, &status);
6166         if (!NT_STATUS_IS_OK(status)) {
6167                 reply_nterror(req, status);
6168                 goto out;
6169         }
6170
6171         status = filename_convert(ctx, conn,
6172                                  directory,
6173                                  ucf_flags,
6174                                  0,
6175                                  &smb_dname);
6176         if (!NT_STATUS_IS_OK(status)) {
6177                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6178                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6179                                         ERRSRV, ERRbadpath);
6180                         goto out;
6181                 }
6182                 reply_nterror(req, status);
6183                 goto out;
6184         }
6185
6186         status = SMB_VFS_CREATE_FILE(
6187                 conn,                                   /* conn */
6188                 req,                                    /* req */
6189                 smb_dname,                              /* fname */
6190                 DELETE_ACCESS,                          /* access_mask */
6191                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
6192                         FILE_SHARE_DELETE),
6193                 FILE_OPEN,                              /* create_disposition*/
6194                 FILE_DIRECTORY_FILE,                    /* create_options */
6195                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
6196                 0,                                      /* oplock_request */
6197                 NULL,                                   /* lease */
6198                 0,                                      /* allocation_size */
6199                 0,                                      /* private_flags */
6200                 NULL,                                   /* sd */
6201                 NULL,                                   /* ea_list */
6202                 &fsp,                                   /* result */
6203                 &info,                                  /* pinfo */
6204                 NULL, NULL);                            /* create context */
6205
6206         if (!NT_STATUS_IS_OK(status)) {
6207                 if (open_was_deferred(req->xconn, req->mid)) {
6208                         /* We have re-scheduled this call. */
6209                         goto out;
6210                 }
6211                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6212                         bool ok = defer_smb1_sharing_violation(req);
6213                         if (ok) {
6214                                 goto out;
6215                         }
6216                 }
6217                 reply_nterror(req, status);
6218                 goto out;
6219         }
6220
6221         status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6222         if (!NT_STATUS_IS_OK(status)) {
6223                 close_file_free(req, &fsp, ERROR_CLOSE);
6224                 reply_nterror(req, status);
6225                 goto out;
6226         }
6227
6228         if (!set_delete_on_close(fsp, true,
6229                         conn->session_info->security_token,
6230                         conn->session_info->unix_token)) {
6231                 close_file_free(req, &fsp, ERROR_CLOSE);
6232                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6233                 goto out;
6234         }
6235
6236         status = close_file_free(req, &fsp, NORMAL_CLOSE);
6237         if (!NT_STATUS_IS_OK(status)) {
6238                 reply_nterror(req, status);
6239         } else {
6240                 reply_outbuf(req, 0, 0);
6241         }
6242
6243         DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6244  out:
6245         TALLOC_FREE(smb_dname);
6246         END_PROFILE(SMBrmdir);
6247         return;
6248 }
6249
6250 /****************************************************************************
6251  Ensure open files have their names updated. Updated to notify other smbd's
6252  asynchronously.
6253 ****************************************************************************/
6254
6255 static void rename_open_files(connection_struct *conn,
6256                               struct share_mode_lock *lck,
6257                               struct file_id id,
6258                               uint32_t orig_name_hash,
6259                               const struct smb_filename *smb_fname_dst)
6260 {
6261         files_struct *fsp;
6262         bool did_rename = False;
6263         NTSTATUS status;
6264         uint32_t new_name_hash = 0;
6265
6266         for(fsp = file_find_di_first(conn->sconn, id, false); fsp;
6267             fsp = file_find_di_next(fsp, false)) {
6268                 SMB_STRUCT_STAT fsp_orig_sbuf;
6269                 struct file_id_buf idbuf;
6270                 /* fsp_name is a relative path under the fsp. To change this for other
6271                    sharepaths we need to manipulate relative paths. */
6272                 /* TODO - create the absolute path and manipulate the newname
6273                    relative to the sharepath. */
6274                 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6275                         continue;
6276                 }
6277                 if (fsp->name_hash != orig_name_hash) {
6278                         continue;
6279                 }
6280                 DBG_DEBUG("renaming file %s "
6281                           "(file_id %s) from %s -> %s\n",
6282                           fsp_fnum_dbg(fsp),
6283                           file_id_str_buf(fsp->file_id, &idbuf),
6284                           fsp_str_dbg(fsp),
6285                           smb_fname_str_dbg(smb_fname_dst));
6286
6287                 /*
6288                  * The incoming smb_fname_dst here has an
6289                  * invalid stat struct (it must not have
6290                  * existed for the rename to succeed).
6291                  * Preserve the existing stat from the
6292                  * open fsp after fsp_set_smb_fname()
6293                  * overwrites with the invalid stat.
6294                  *
6295                  * We will do an fstat before returning
6296                  * any of this metadata to the client anyway.
6297                  */
6298                 fsp_orig_sbuf = fsp->fsp_name->st;
6299                 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6300                 if (NT_STATUS_IS_OK(status)) {
6301                         did_rename = True;
6302                         new_name_hash = fsp->name_hash;
6303                         /* Restore existing stat. */
6304                         fsp->fsp_name->st = fsp_orig_sbuf;
6305                 }
6306         }
6307
6308         if (!did_rename) {
6309                 struct file_id_buf idbuf;
6310                 DBG_DEBUG("no open files on file_id %s "
6311                           "for %s\n",
6312                           file_id_str_buf(id, &idbuf),
6313                           smb_fname_str_dbg(smb_fname_dst));
6314         }
6315
6316         /* Send messages to all smbd's (not ourself) that the name has changed. */
6317         rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6318                               orig_name_hash, new_name_hash,
6319                               smb_fname_dst);
6320
6321 }
6322
6323 /****************************************************************************
6324  We need to check if the source path is a parent directory of the destination
6325  (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6326  refuse the rename with a sharing violation. Under UNIX the above call can
6327  *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6328  probably need to check that the client is a Windows one before disallowing
6329  this as a UNIX client (one with UNIX extensions) can know the source is a
6330  symlink and make this decision intelligently. Found by an excellent bug
6331  report from <AndyLiebman@aol.com>.
6332 ****************************************************************************/
6333
6334 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6335                                      const struct smb_filename *smb_fname_dst)
6336 {
6337         const char *psrc = smb_fname_src->base_name;
6338         const char *pdst = smb_fname_dst->base_name;
6339         size_t slen;
6340
6341         if (psrc[0] == '.' && psrc[1] == '/') {
6342                 psrc += 2;
6343         }
6344         if (pdst[0] == '.' && pdst[1] == '/') {
6345                 pdst += 2;
6346         }
6347         if ((slen = strlen(psrc)) > strlen(pdst)) {
6348                 return False;
6349         }
6350         return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6351 }
6352
6353 /*
6354  * Do the notify calls from a rename
6355  */
6356
6357 static void notify_rename(connection_struct *conn, bool is_dir,
6358                           const struct smb_filename *smb_fname_src,
6359                           const struct smb_filename *smb_fname_dst)
6360 {
6361         char *parent_dir_src = NULL;
6362         char *parent_dir_dst = NULL;
6363         uint32_t mask;
6364
6365         mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6366                 : FILE_NOTIFY_CHANGE_FILE_NAME;
6367
6368         if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6369                             &parent_dir_src, NULL) ||
6370             !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6371                             &parent_dir_dst, NULL)) {
6372                 goto out;
6373         }
6374
6375         if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6376                 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6377                              smb_fname_src->base_name);
6378                 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6379                              smb_fname_dst->base_name);
6380         }
6381         else {
6382                 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6383                              smb_fname_src->base_name);
6384                 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6385                              smb_fname_dst->base_name);
6386         }
6387
6388         /* this is a strange one. w2k3 gives an additional event for
6389            CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6390            files, but not directories */
6391         if (!is_dir) {
6392                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6393                              FILE_NOTIFY_CHANGE_ATTRIBUTES
6394                              |FILE_NOTIFY_CHANGE_CREATION,
6395                              smb_fname_dst->base_name);
6396         }
6397  out:
6398         TALLOC_FREE(parent_dir_src);
6399         TALLOC_FREE(parent_dir_dst);
6400 }
6401
6402 /****************************************************************************
6403  Returns an error if the parent directory for a filename is open in an
6404  incompatible way.
6405 ****************************************************************************/
6406
6407 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6408                                         const struct smb_filename *smb_fname_dst_in)
6409 {
6410         struct smb_filename *smb_fname_parent = NULL;
6411         struct file_id id;
6412         files_struct *fsp = NULL;
6413         int ret;
6414         NTSTATUS status;
6415
6416         status = SMB_VFS_PARENT_PATHNAME(conn,
6417                                          talloc_tos(),
6418                                          smb_fname_dst_in,
6419                                          &smb_fname_parent,
6420                                          NULL);
6421         if (!NT_STATUS_IS_OK(status)) {
6422                 return status;
6423         }
6424
6425         ret = vfs_stat(conn, smb_fname_parent);
6426         if (ret == -1) {
6427                 return map_nt_error_from_unix(errno);
6428         }
6429
6430         /*
6431          * We're only checking on this smbd here, mostly good
6432          * enough.. and will pass tests.
6433          */
6434
6435         id = vfs_file_id_from_sbuf(conn, &smb_fname_parent->st);
6436         for (fsp = file_find_di_first(conn->sconn, id, true); fsp;
6437                         fsp = file_find_di_next(fsp, true)) {
6438                 if (fsp->access_mask & DELETE_ACCESS) {
6439                         return NT_STATUS_SHARING_VIOLATION;
6440                 }
6441         }
6442         return NT_STATUS_OK;
6443 }
6444
6445 /****************************************************************************
6446  Rename an open file - given an fsp.
6447 ****************************************************************************/
6448
6449 NTSTATUS rename_internals_fsp(connection_struct *conn,
6450                         files_struct *fsp,
6451                         struct smb_filename *smb_fname_dst_in,
6452                         const char *dst_original_lcomp,
6453                         uint32_t attrs,
6454                         bool replace_if_exists)
6455 {
6456         TALLOC_CTX *ctx = talloc_tos();
6457         struct smb_filename *parent_dir_fname_dst = NULL;
6458         struct smb_filename *parent_dir_fname_dst_atname = NULL;
6459         struct smb_filename *parent_dir_fname_src = NULL;
6460         struct smb_filename *parent_dir_fname_src_atname = NULL;
6461         struct smb_filename *smb_fname_dst = NULL;
6462         NTSTATUS status = NT_STATUS_OK;
6463         struct share_mode_lock *lck = NULL;
6464         uint32_t access_mask = SEC_DIR_ADD_FILE;
6465         bool dst_exists, old_is_stream, new_is_stream;
6466         int ret;
6467         bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
6468                                 true : conn->case_sensitive;
6469         bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
6470                                 true : conn->case_preserve;
6471
6472         status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6473         if (!NT_STATUS_IS_OK(status)) {
6474                 return status;
6475         }
6476
6477         if (file_has_open_streams(fsp)) {
6478                 return NT_STATUS_ACCESS_DENIED;
6479         }
6480
6481         /* Make a copy of the dst smb_fname structs */
6482
6483         smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6484         if (smb_fname_dst == NULL) {
6485                 status = NT_STATUS_NO_MEMORY;
6486                 goto out;
6487         }
6488
6489         /*
6490          * Check for special case with case preserving and not
6491          * case sensitive. If the new last component differs from the original
6492          * last component only by case, then we should allow
6493          * the rename (user is trying to change the case of the
6494          * filename).
6495          */
6496         if (!case_sensitive && case_preserve &&
6497             strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6498             strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6499                 char *fname_dst_parent = NULL;
6500                 const char *fname_dst_lcomp = NULL;
6501                 char *orig_lcomp_path = NULL;
6502                 char *orig_lcomp_stream = NULL;
6503                 bool ok = true;
6504
6505                 /*
6506                  * Split off the last component of the processed
6507                  * destination name. We will compare this to
6508                  * the split components of dst_original_lcomp.
6509                  */
6510                 if (!parent_dirname(ctx,
6511                                 smb_fname_dst->base_name,
6512                                 &fname_dst_parent,
6513                                 &fname_dst_lcomp)) {
6514                         status = NT_STATUS_NO_MEMORY;
6515                         goto out;
6516                 }
6517
6518                 /*
6519                  * The dst_original_lcomp component contains
6520                  * the last_component of the path + stream
6521                  * name (if a stream exists).
6522                  *
6523                  * Split off the stream name so we
6524                  * can check them separately.
6525                  */
6526
6527                 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
6528                         /* POSIX - no stream component. */
6529                         orig_lcomp_path = talloc_strdup(ctx,
6530                                                 dst_original_lcomp);
6531                         if (orig_lcomp_path == NULL) {
6532                                 ok = false;
6533                         }
6534                 } else {
6535                         ok = split_stream_filename(ctx,
6536                                         dst_original_lcomp,
6537                                         &orig_lcomp_path,
6538                                         &orig_lcomp_stream);
6539                 }
6540
6541                 if (!ok) {
6542                         TALLOC_FREE(fname_dst_parent);
6543                         status = NT_STATUS_NO_MEMORY;
6544                         goto out;
6545                 }
6546
6547                 /* If the base names only differ by case, use original. */
6548                 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
6549                         char *tmp;
6550                         /*
6551                          * Replace the modified last component with the
6552                          * original.
6553                          */
6554                         if (!ISDOT(fname_dst_parent)) {
6555                                 tmp = talloc_asprintf(smb_fname_dst,
6556                                         "%s/%s",
6557                                         fname_dst_parent,
6558                                         orig_lcomp_path);
6559                         } else {
6560                                 tmp = talloc_strdup(smb_fname_dst,
6561                                         orig_lcomp_path);
6562                         }
6563                         if (tmp == NULL) {
6564                                 status = NT_STATUS_NO_MEMORY;
6565                                 TALLOC_FREE(fname_dst_parent);
6566                                 TALLOC_FREE(orig_lcomp_path);
6567                                 TALLOC_FREE(orig_lcomp_stream);
6568                                 goto out;
6569                         }
6570                         TALLOC_FREE(smb_fname_dst->base_name);
6571                         smb_fname_dst->base_name = tmp;
6572                 }
6573
6574                 /* If the stream_names only differ by case, use original. */
6575                 if(!strcsequal(smb_fname_dst->stream_name,
6576                                orig_lcomp_stream)) {
6577                         /* Use the original stream. */
6578                         char *tmp = talloc_strdup(smb_fname_dst,
6579                                             orig_lcomp_stream);
6580                         if (tmp == NULL) {
6581                                 status = NT_STATUS_NO_MEMORY;
6582                                 TALLOC_FREE(fname_dst_parent);
6583                                 TALLOC_FREE(orig_lcomp_path);
6584                                 TALLOC_FREE(orig_lcomp_stream);
6585                                 goto out;
6586                         }
6587                         TALLOC_FREE(smb_fname_dst->stream_name);
6588                         smb_fname_dst->stream_name = tmp;
6589                 }
6590                 TALLOC_FREE(fname_dst_parent);
6591                 TALLOC_FREE(orig_lcomp_path);
6592                 TALLOC_FREE(orig_lcomp_stream);
6593         }
6594
6595         /*
6596          * If the src and dest names are identical - including case,
6597          * don't do the rename, just return success.
6598          */
6599
6600         if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6601             strcsequal(fsp->fsp_name->stream_name,
6602                        smb_fname_dst->stream_name)) {
6603                 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6604                           "- returning success\n",
6605                           smb_fname_str_dbg(smb_fname_dst)));
6606                 status = NT_STATUS_OK;
6607                 goto out;
6608         }
6609
6610         old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6611         new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6612
6613         /* Return the correct error code if both names aren't streams. */
6614         if (!old_is_stream && new_is_stream) {
6615                 status = NT_STATUS_OBJECT_NAME_INVALID;
6616                 goto out;
6617         }
6618
6619         if (old_is_stream && !new_is_stream) {
6620                 status = NT_STATUS_INVALID_PARAMETER;
6621                 goto out;
6622         }
6623
6624         dst_exists = vfs_stat(conn, smb_fname_dst) == 0;
6625
6626         if(!replace_if_exists && dst_exists) {
6627                 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6628                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6629                           smb_fname_str_dbg(smb_fname_dst)));
6630                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6631                 goto out;
6632         }
6633
6634         /*
6635          * Drop the pathref fsp on the destination otherwise we trip upon in in
6636          * the below check for open files check.
6637          */
6638         if (smb_fname_dst_in->fsp != NULL) {
6639                 fd_close(smb_fname_dst_in->fsp);
6640                 file_free(NULL, smb_fname_dst_in->fsp);
6641                 SMB_ASSERT(smb_fname_dst_in->fsp == NULL);
6642         }
6643
6644         if (dst_exists) {
6645                 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6646                     &smb_fname_dst->st);
6647                 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6648                                                            fileid, true);
6649                 /* The file can be open when renaming a stream */
6650                 if (dst_fsp && !new_is_stream) {
6651                         DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6652                         status = NT_STATUS_ACCESS_DENIED;
6653                         goto out;
6654                 }
6655         }
6656
6657         /* Ensure we have a valid stat struct for the source. */
6658         status = vfs_stat_fsp(fsp);
6659         if (!NT_STATUS_IS_OK(status)) {
6660                 goto out;
6661         }
6662
6663         status = can_rename(conn, fsp, attrs);
6664
6665         if (!NT_STATUS_IS_OK(status)) {
6666                 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6667                           nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6668                           smb_fname_str_dbg(smb_fname_dst)));
6669                 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6670                         status = NT_STATUS_ACCESS_DENIED;
6671                 goto out;
6672         }
6673
6674         if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6675                 status = NT_STATUS_ACCESS_DENIED;
6676                 goto out;
6677         }
6678
6679         /* Do we have rights to move into the destination ? */
6680         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
6681                 /* We're moving a directory. */
6682                 access_mask = SEC_DIR_ADD_SUBDIR;
6683         }
6684
6685         /*
6686          * Get a pathref on the destination parent directory, so
6687          * we can call check_parent_access_fsp().
6688          */
6689         status = parent_pathref(ctx,
6690                                 conn->cwd_fsp,
6691                                 smb_fname_dst,
6692                                 &parent_dir_fname_dst,
6693                                 &parent_dir_fname_dst_atname);
6694         if (!NT_STATUS_IS_OK(status)) {
6695                 goto out;
6696         }
6697
6698         status = check_parent_access_fsp(parent_dir_fname_dst->fsp,
6699                                 access_mask);
6700         if (!NT_STATUS_IS_OK(status)) {
6701                 DBG_INFO("check_parent_access_fsp on "
6702                         "dst %s returned %s\n",
6703                         smb_fname_str_dbg(smb_fname_dst),
6704                         nt_errstr(status));
6705                 goto out;
6706         }
6707
6708         /*
6709          * If the target existed, make sure the destination
6710          * atname has the same stat struct.
6711          */
6712         parent_dir_fname_dst_atname->st = smb_fname_dst->st;
6713
6714         /*
6715          * It's very common that source and
6716          * destination directories are the same.
6717          * Optimize by not opening the
6718          * second parent_pathref if we know
6719          * this is the case.
6720          */
6721
6722         status = SMB_VFS_PARENT_PATHNAME(conn,
6723                                          ctx,
6724                                          fsp->fsp_name,
6725                                          &parent_dir_fname_src,
6726                                          &parent_dir_fname_src_atname);
6727         if (!NT_STATUS_IS_OK(status)) {
6728                 goto out;
6729         }
6730
6731         /*
6732          * We do a case-sensitive string comparison. We want to be *sure*
6733          * this is the same path. The worst that can happen if
6734          * the case doesn't match is we lose out on the optimization,
6735          * the code still works.
6736          *
6737          * We can ignore twrp fields here. Rename is not allowed on
6738          * shadow copy handles.
6739          */
6740
6741         if (strcmp(parent_dir_fname_src->base_name,
6742                    parent_dir_fname_dst->base_name) == 0) {
6743                 /*
6744                  * parent directory is the same for source
6745                  * and destination.
6746                  */
6747                 /* Reparent the src_atname to the parent_dir_dest fname. */
6748                 parent_dir_fname_src_atname = talloc_move(
6749                                                 parent_dir_fname_dst,
6750                                                 &parent_dir_fname_src_atname);
6751                 /* Free the unneeded duplicate parent name. */
6752                 TALLOC_FREE(parent_dir_fname_src);
6753                 /*
6754                  * And make the source parent name a copy of the
6755                  * destination parent name.
6756                  */
6757                 parent_dir_fname_src = parent_dir_fname_dst;
6758         } else {
6759                 /*
6760                  * source and destination parent directories are
6761                  * different.
6762                  *
6763                  * Get a pathref on the source parent directory, so
6764                  * we can do a relative rename.
6765                  */
6766                 TALLOC_FREE(parent_dir_fname_src);
6767                 status = parent_pathref(ctx,
6768                                 conn->cwd_fsp,
6769                                 fsp->fsp_name,
6770                                 &parent_dir_fname_src,
6771                                 &parent_dir_fname_src_atname);
6772                 if (!NT_STATUS_IS_OK(status)) {
6773                         goto out;
6774                 }
6775         }
6776
6777         /*
6778          * Some modules depend on the source smb_fname having a valid stat.
6779          * The parent_dir_fname_src_atname is the relative name of the
6780          * currently open file, so just copy the stat from the open fsp.
6781          */
6782         parent_dir_fname_src_atname->st = fsp->fsp_name->st;
6783
6784         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6785
6786         /*
6787          * We have the file open ourselves, so not being able to get the
6788          * corresponding share mode lock is a fatal error.
6789          */
6790
6791         SMB_ASSERT(lck != NULL);
6792
6793         ret = SMB_VFS_RENAMEAT(conn,
6794                         parent_dir_fname_src->fsp,
6795                         parent_dir_fname_src_atname,
6796                         parent_dir_fname_dst->fsp,
6797                         parent_dir_fname_dst_atname);
6798         if (ret == 0) {
6799                 uint32_t create_options = fh_get_private_options(fsp->fh);
6800
6801                 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6802                           "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6803                           smb_fname_str_dbg(smb_fname_dst)));
6804
6805                 notify_rename(conn,
6806                               fsp->fsp_flags.is_directory,
6807                               fsp->fsp_name,
6808                               smb_fname_dst);
6809
6810                 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6811                                   smb_fname_dst);
6812
6813                 if (!fsp->fsp_flags.is_directory &&
6814                     !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
6815                     (lp_map_archive(SNUM(conn)) ||
6816                      lp_store_dos_attributes(SNUM(conn))))
6817                 {
6818                         /*
6819                          * We must set the archive bit on the newly renamed
6820                          * file.
6821                          */
6822                         status = vfs_stat_fsp(fsp);
6823                         if (NT_STATUS_IS_OK(status)) {
6824                                 uint32_t old_dosmode;
6825                                 old_dosmode = fdos_mode(fsp);
6826                                 /*
6827                                  * We can use fsp->fsp_name here as it has
6828                                  * already been changed to the new name.
6829                                  */
6830                                 SMB_ASSERT(fsp->fsp_name->fsp == fsp);
6831                                 file_set_dosmode(conn,
6832                                                 fsp->fsp_name,
6833                                                 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6834                                                 NULL,
6835                                                 true);
6836                         }
6837                 }
6838
6839                 /*
6840                  * A rename acts as a new file create w.r.t. allowing an initial delete
6841                  * on close, probably because in Windows there is a new handle to the
6842                  * new file. If initial delete on close was requested but not
6843                  * originally set, we need to set it here. This is probably not 100% correct,
6844                  * but will work for the CIFSFS client which in non-posix mode
6845                  * depends on these semantics. JRA.
6846                  */
6847
6848                 if (create_options & FILE_DELETE_ON_CLOSE) {
6849                         status = can_set_delete_on_close(fsp, 0);
6850
6851                         if (NT_STATUS_IS_OK(status)) {
6852                                 /* Note that here we set the *initial* delete on close flag,
6853                                  * not the regular one. The magic gets handled in close. */
6854                                 fsp->fsp_flags.initial_delete_on_close = true;
6855                         }
6856                 }
6857                 TALLOC_FREE(lck);
6858                 status = NT_STATUS_OK;
6859                 goto out;
6860         }
6861
6862         TALLOC_FREE(lck);
6863
6864         if (errno == ENOTDIR || errno == EISDIR) {
6865                 status = NT_STATUS_OBJECT_NAME_COLLISION;
6866         } else {
6867                 status = map_nt_error_from_unix(errno);
6868         }
6869
6870         DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6871                   nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6872                   smb_fname_str_dbg(smb_fname_dst)));
6873
6874  out:
6875
6876         /*
6877          * parent_dir_fname_src may be a copy of parent_dir_fname_dst.
6878          * See the optimization for same source and destination directory
6879          * above. Only free one in that case.
6880          */
6881         if (parent_dir_fname_src != parent_dir_fname_dst) {
6882                 TALLOC_FREE(parent_dir_fname_src);
6883         }
6884         TALLOC_FREE(parent_dir_fname_dst);
6885         TALLOC_FREE(smb_fname_dst);
6886
6887         return status;
6888 }
6889
6890 /****************************************************************************
6891  The guts of the rename command, split out so it may be called by the NT SMB
6892  code.
6893 ****************************************************************************/
6894
6895 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6896                         connection_struct *conn,
6897                         struct smb_request *req,
6898                         struct smb_filename *smb_fname_src,
6899                         struct smb_filename *smb_fname_dst,
6900                         const char *dst_original_lcomp,
6901                         uint32_t attrs,
6902                         bool replace_if_exists,
6903                         uint32_t access_mask)
6904 {
6905         NTSTATUS status = NT_STATUS_OK;
6906         int create_options = 0;
6907         struct smb2_create_blobs *posx = NULL;
6908         struct files_struct *fsp = NULL;
6909         bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
6910         bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
6911         bool case_preserve = posix_pathname ? true : conn->case_preserve;
6912         bool short_case_preserve = posix_pathname ? true :
6913                                         conn->short_case_preserve;
6914
6915         if (posix_pathname) {
6916                 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
6917                 if (!NT_STATUS_IS_OK(status)) {
6918                         DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
6919                                     nt_errstr(status));
6920                         goto out;
6921                 }
6922         }
6923
6924         DBG_NOTICE("case_sensitive = %d, "
6925                   "case_preserve = %d, short case preserve = %d, "
6926                   "directory = %s, newname = %s, "
6927                   "last_component_dest = %s\n",
6928                   case_sensitive, case_preserve,
6929                   short_case_preserve,
6930                   smb_fname_str_dbg(smb_fname_src),
6931                   smb_fname_str_dbg(smb_fname_dst),
6932                   dst_original_lcomp);
6933
6934         ZERO_STRUCT(smb_fname_src->st);
6935
6936         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
6937         if (!NT_STATUS_IS_OK(status)) {
6938                 if (!NT_STATUS_EQUAL(status,
6939                                 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
6940                         goto out;
6941                 }
6942                 /*
6943                  * Possible symlink src.
6944                  */
6945                 if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
6946                         goto out;
6947                 }
6948                 if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
6949                         goto out;
6950                 }
6951         }
6952
6953         if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6954                 create_options |= FILE_DIRECTORY_FILE;
6955         }
6956
6957         status = SMB_VFS_CREATE_FILE(
6958                         conn,                           /* conn */
6959                         req,                            /* req */
6960                         smb_fname_src,                  /* fname */
6961                         access_mask,                    /* access_mask */
6962                         (FILE_SHARE_READ |              /* share_access */
6963                             FILE_SHARE_WRITE),
6964                         FILE_OPEN,                      /* create_disposition*/
6965                         create_options,                 /* create_options */
6966                         0,                              /* file_attributes */
6967                         0,                              /* oplock_request */
6968                         NULL,                           /* lease */
6969                         0,                              /* allocation_size */
6970                         0,                              /* private_flags */
6971                         NULL,                           /* sd */
6972                         NULL,                           /* ea_list */
6973                         &fsp,                           /* result */
6974                         NULL,                           /* pinfo */
6975                         posx,                           /* in_context_blobs */
6976                         NULL);                          /* out_context_blobs */
6977
6978         if (!NT_STATUS_IS_OK(status)) {
6979                 DBG_NOTICE("Could not open rename source %s: %s\n",
6980                           smb_fname_str_dbg(smb_fname_src),
6981                           nt_errstr(status));
6982                 goto out;
6983         }
6984
6985         status = rename_internals_fsp(conn,
6986                                         fsp,
6987                                         smb_fname_dst,
6988                                         dst_original_lcomp,
6989                                         attrs,
6990                                         replace_if_exists);
6991
6992         close_file_free(req, &fsp, NORMAL_CLOSE);
6993
6994         DBG_NOTICE("Error %s rename %s -> %s\n",
6995                   nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6996                   smb_fname_str_dbg(smb_fname_dst));
6997
6998  out:
6999         TALLOC_FREE(posx);
7000         return status;
7001 }
7002
7003 /****************************************************************************
7004  Reply to a mv.
7005 ****************************************************************************/
7006
7007 void reply_mv(struct smb_request *req)
7008 {
7009         connection_struct *conn = req->conn;
7010         char *name = NULL;
7011         char *newname = NULL;
7012         const char *p;
7013         uint32_t attrs;
7014         NTSTATUS status;
7015         TALLOC_CTX *ctx = talloc_tos();
7016         struct smb_filename *smb_fname_src = NULL;
7017         struct smb_filename *smb_fname_dst = NULL;
7018         const char *dst_original_lcomp = NULL;
7019         uint32_t src_ucf_flags = ucf_flags_from_smb_request(req);
7020         uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req);
7021         bool stream_rename = false;
7022
7023         START_PROFILE(SMBmv);
7024
7025         if (req->wct < 1) {
7026                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7027                 goto out;
7028         }
7029
7030         attrs = SVAL(req->vwv+0, 0);
7031
7032         p = (const char *)req->buf + 1;
7033         p += srvstr_get_path_req(ctx, req, &name, p, STR_TERMINATE,
7034                                        &status);
7035         if (!NT_STATUS_IS_OK(status)) {
7036                 reply_nterror(req, status);
7037                 goto out;
7038         }
7039         p++;
7040         p += srvstr_get_path_req(ctx, req, &newname, p, STR_TERMINATE,
7041                                        &status);
7042         if (!NT_STATUS_IS_OK(status)) {
7043                 reply_nterror(req, status);
7044                 goto out;
7045         }
7046
7047         if (!req->posix_pathnames) {
7048                 /* The newname must begin with a ':' if the
7049                    name contains a ':'. */
7050                 if (strchr_m(name, ':')) {
7051                         if (newname[0] != ':') {
7052                                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7053                                 goto out;
7054                         }
7055                         stream_rename = true;
7056                 }
7057         }
7058
7059         status = filename_convert(ctx,
7060                                   conn,
7061                                   name,
7062                                   src_ucf_flags,
7063                                   0,
7064                                   &smb_fname_src);
7065
7066         if (!NT_STATUS_IS_OK(status)) {
7067                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7068                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7069                                         ERRSRV, ERRbadpath);
7070                         goto out;
7071                 }
7072                 reply_nterror(req, status);
7073                 goto out;
7074         }
7075
7076         status = filename_convert(ctx,
7077                                   conn,
7078                                   newname,
7079                                   dst_ucf_flags,
7080                                   0,
7081                                   &smb_fname_dst);
7082
7083         if (!NT_STATUS_IS_OK(status)) {
7084                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7085                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7086                                         ERRSRV, ERRbadpath);
7087                         goto out;
7088                 }
7089                 reply_nterror(req, status);
7090                 goto out;
7091         }
7092
7093         /* Get the last component of the destination for rename_internals(). */
7094         dst_original_lcomp = get_original_lcomp(ctx,
7095                                         conn,
7096                                         newname,
7097                                         dst_ucf_flags);
7098         if (dst_original_lcomp == NULL) {
7099                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7100                 goto out;
7101         }
7102
7103         if (stream_rename) {
7104                 /* smb_fname_dst->base_name must be the same as
7105                    smb_fname_src->base_name. */
7106                 TALLOC_FREE(smb_fname_dst->base_name);
7107                 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7108                                                 smb_fname_src->base_name);
7109                 if (!smb_fname_dst->base_name) {
7110                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7111                         goto out;
7112                 }
7113         }
7114
7115         DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7116                  smb_fname_str_dbg(smb_fname_dst)));
7117
7118         status = rename_internals(ctx,
7119                                 conn,
7120                                 req,
7121                                 smb_fname_src,
7122                                 smb_fname_dst,
7123                                 dst_original_lcomp,
7124                                 attrs,
7125                                 false,
7126                                 DELETE_ACCESS);
7127         if (!NT_STATUS_IS_OK(status)) {
7128                 if (open_was_deferred(req->xconn, req->mid)) {
7129                         /* We have re-scheduled this call. */
7130                         goto out;
7131                 }
7132                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7133                         bool ok = defer_smb1_sharing_violation(req);
7134                         if (ok) {
7135                                 goto out;
7136                         }
7137                 }
7138                 reply_nterror(req, status);
7139                 goto out;
7140         }
7141
7142         reply_outbuf(req, 0, 0);
7143  out:
7144         TALLOC_FREE(smb_fname_src);
7145         TALLOC_FREE(smb_fname_dst);
7146         END_PROFILE(SMBmv);
7147         return;
7148 }
7149
7150 /*******************************************************************
7151  Copy a file as part of a reply_copy.
7152 ******************************************************************/
7153
7154 /*
7155  * TODO: check error codes on all callers
7156  */
7157
7158 NTSTATUS copy_file(TALLOC_CTX *ctx,
7159                         connection_struct *conn,
7160                         struct smb_filename *smb_fname_src,
7161                         struct smb_filename *smb_fname_dst,
7162                         int ofun,
7163                         int count,
7164                         bool target_is_directory)
7165 {
7166         struct smb_filename *smb_fname_dst_tmp = NULL;
7167         off_t ret=-1;
7168         files_struct *fsp1,*fsp2;
7169         uint32_t dosattrs;
7170         uint32_t new_create_disposition;
7171         NTSTATUS status;
7172
7173
7174         smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7175         if (smb_fname_dst_tmp == NULL) {
7176                 return NT_STATUS_NO_MEMORY;
7177         }
7178
7179         /*
7180          * If the target is a directory, extract the last component from the
7181          * src filename and append it to the dst filename
7182          */
7183         if (target_is_directory) {
7184                 const char *p;
7185
7186                 /* dest/target can't be a stream if it's a directory. */
7187                 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7188
7189                 p = strrchr_m(smb_fname_src->base_name,'/');
7190                 if (p) {
7191                         p++;
7192                 } else {
7193                         p = smb_fname_src->base_name;
7194                 }
7195                 smb_fname_dst_tmp->base_name =
7196                     talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7197                                            p);
7198                 if (!smb_fname_dst_tmp->base_name) {
7199                         status = NT_STATUS_NO_MEMORY;
7200                         goto out;
7201                 }
7202         }
7203
7204         status = vfs_file_exist(conn, smb_fname_src);
7205         if (!NT_STATUS_IS_OK(status)) {
7206                 goto out;
7207         }
7208
7209         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
7210         if (!NT_STATUS_IS_OK(status)) {
7211                 goto out;
7212         }
7213
7214         if (!target_is_directory && count) {
7215                 new_create_disposition = FILE_OPEN;
7216         } else {
7217                 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7218                                                  0, ofun,
7219                                                  NULL, NULL,
7220                                                  &new_create_disposition,
7221                                                  NULL,
7222                                                  NULL)) {
7223                         status = NT_STATUS_INVALID_PARAMETER;
7224                         goto out;
7225                 }
7226         }
7227
7228         /* Open the src file for reading. */
7229         status = SMB_VFS_CREATE_FILE(
7230                 conn,                                   /* conn */
7231                 NULL,                                   /* req */
7232                 smb_fname_src,                          /* fname */
7233                 FILE_GENERIC_READ,                      /* access_mask */
7234                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7235                 FILE_OPEN,                              /* create_disposition*/
7236                 0,                                      /* create_options */
7237                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
7238                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7239                 NULL,                                   /* lease */
7240                 0,                                      /* allocation_size */
7241                 0,                                      /* private_flags */
7242                 NULL,                                   /* sd */
7243                 NULL,                                   /* ea_list */
7244                 &fsp1,                                  /* result */
7245                 NULL,                                   /* psbuf */
7246                 NULL, NULL);                            /* create context */
7247
7248         if (!NT_STATUS_IS_OK(status)) {
7249                 goto out;
7250         }
7251
7252         dosattrs = fdos_mode(fsp1);
7253
7254         if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7255                 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7256         }
7257
7258         status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_dst);
7259         if (!NT_STATUS_IS_OK(status) &&
7260             !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))
7261         {
7262                 goto out;
7263         }
7264
7265         /* Open the dst file for writing. */
7266         status = SMB_VFS_CREATE_FILE(
7267                 conn,                                   /* conn */
7268                 NULL,                                   /* req */
7269                 smb_fname_dst,                          /* fname */
7270                 FILE_GENERIC_WRITE,                     /* access_mask */
7271                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share_access */
7272                 new_create_disposition,                 /* create_disposition*/
7273                 0,                                      /* create_options */
7274                 dosattrs,                               /* file_attributes */
7275                 INTERNAL_OPEN_ONLY,                     /* oplock_request */
7276                 NULL,                                   /* lease */
7277                 0,                                      /* allocation_size */
7278                 0,                                      /* private_flags */
7279                 NULL,                                   /* sd */
7280                 NULL,                                   /* ea_list */
7281                 &fsp2,                                  /* result */
7282                 NULL,                                   /* psbuf */
7283                 NULL, NULL);                            /* create context */
7284
7285         if (!NT_STATUS_IS_OK(status)) {
7286                 close_file_free(NULL, &fsp1, ERROR_CLOSE);
7287                 goto out;
7288         }
7289
7290         if (ofun & OPENX_FILE_EXISTS_OPEN) {
7291                 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7292                 if (ret == -1) {
7293                         DEBUG(0, ("error - vfs lseek returned error %s\n",
7294                                 strerror(errno)));
7295                         status = map_nt_error_from_unix(errno);
7296                         close_file_free(NULL, &fsp1, ERROR_CLOSE);
7297                         close_file_free(NULL, &fsp2, ERROR_CLOSE);
7298                         goto out;
7299                 }
7300         }
7301
7302         /* Do the actual copy. */
7303         if (smb_fname_src->st.st_ex_size) {
7304                 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7305         } else {
7306                 ret = 0;
7307         }
7308
7309         close_file_free(NULL, &fsp1, NORMAL_CLOSE);
7310
7311         /* Ensure the modtime is set correctly on the destination file. */
7312         set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7313
7314         /*
7315          * As we are opening fsp1 read-only we only expect
7316          * an error on close on fsp2 if we are out of space.
7317          * Thus we don't look at the error return from the
7318          * close of fsp1.
7319          */
7320         status = close_file_free(NULL, &fsp2, NORMAL_CLOSE);
7321
7322         if (!NT_STATUS_IS_OK(status)) {
7323                 goto out;
7324         }
7325
7326         if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7327                 status = NT_STATUS_DISK_FULL;
7328                 goto out;
7329         }
7330
7331         status = NT_STATUS_OK;
7332
7333  out:
7334         TALLOC_FREE(smb_fname_dst_tmp);
7335         return status;
7336 }
7337
7338 /****************************************************************************
7339  Reply to a file copy.
7340
7341  From MS-CIFS.
7342
7343  This command was introduced in the LAN Manager 1.0 dialect
7344  It was rendered obsolete in the NT LAN Manager dialect.
7345  This command was used to perform server-side file copies, but
7346  is no longer used. Clients SHOULD
7347  NOT send requests using this command code.
7348  Servers receiving requests with this command code
7349  SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc).
7350 ****************************************************************************/
7351
7352 void reply_copy(struct smb_request *req)
7353 {
7354         START_PROFILE(SMBcopy);
7355         reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
7356         END_PROFILE(SMBcopy);
7357         return;
7358 }
7359
7360 #undef DBGC_CLASS
7361 #define DBGC_CLASS DBGC_LOCKING
7362
7363 /****************************************************************************
7364  Get a lock pid, dealing with large count requests.
7365 ****************************************************************************/
7366
7367 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7368                     bool large_file_format)
7369 {
7370         if(!large_file_format)
7371                 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7372         else
7373                 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7374 }
7375
7376 /****************************************************************************
7377  Get a lock count, dealing with large count requests.
7378 ****************************************************************************/
7379
7380 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7381                         bool large_file_format)
7382 {
7383         uint64_t count = 0;
7384
7385         if(!large_file_format) {
7386                 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7387         } else {
7388                 /*
7389                  * No BVAL, this is reversed!
7390                  */
7391                 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7392                         ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7393         }
7394
7395         return count;
7396 }
7397
7398 /****************************************************************************
7399  Get a lock offset, dealing with large offset requests.
7400 ****************************************************************************/
7401
7402 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7403                          bool large_file_format)
7404 {
7405         uint64_t offset = 0;
7406
7407         if(!large_file_format) {
7408                 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7409         } else {
7410                 /*
7411                  * No BVAL, this is reversed!
7412                  */
7413                 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7414                                 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7415         }
7416
7417         return offset;
7418 }
7419
7420 struct smbd_do_unlocking_state {
7421         struct files_struct *fsp;
7422         uint16_t num_ulocks;
7423         struct smbd_lock_element *ulocks;
7424         NTSTATUS status;
7425 };
7426
7427 static void smbd_do_unlocking_fn(
7428         const uint8_t *buf,
7429         size_t buflen,
7430         bool *pmodified_dependent,
7431         void *private_data)
7432 {
7433         struct smbd_do_unlocking_state *state = private_data;
7434         struct files_struct *fsp = state->fsp;
7435         uint16_t i;
7436
7437         for (i = 0; i < state->num_ulocks; i++) {
7438                 struct smbd_lock_element *e = &state->ulocks[i];
7439
7440                 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
7441                           "pid %"PRIu64", file %s\n",
7442                           e->offset,
7443                           e->count,
7444                           e->smblctx,
7445                           fsp_str_dbg(fsp));
7446
7447                 if (e->brltype != UNLOCK_LOCK) {
7448                         /* this can only happen with SMB2 */
7449                         state->status = NT_STATUS_INVALID_PARAMETER;
7450                         return;
7451                 }
7452
7453                 state->status = do_unlock(
7454                         fsp, e->smblctx, e->count, e->offset, e->lock_flav);
7455
7456                 DBG_DEBUG("do_unlock returned %s\n",
7457                           nt_errstr(state->status));
7458
7459                 if (!NT_STATUS_IS_OK(state->status)) {
7460                         return;
7461                 }
7462         }
7463
7464         *pmodified_dependent = true;
7465 }
7466
7467 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7468                            files_struct *fsp,
7469                            uint16_t num_ulocks,
7470                            struct smbd_lock_element *ulocks)
7471 {
7472         struct smbd_do_unlocking_state state = {
7473                 .fsp = fsp,
7474                 .num_ulocks = num_ulocks,
7475                 .ulocks = ulocks,
7476         };
7477         NTSTATUS status;
7478
7479         DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
7480
7481         status = share_mode_do_locked(
7482                 fsp->file_id, smbd_do_unlocking_fn, &state);
7483
7484         if (!NT_STATUS_IS_OK(status)) {
7485                 DBG_DEBUG("share_mode_do_locked failed: %s\n",
7486                           nt_errstr(status));
7487                 return status;
7488         }
7489         if (!NT_STATUS_IS_OK(state.status)) {
7490                 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
7491                           nt_errstr(status));
7492                 return state.status;
7493         }
7494
7495         return NT_STATUS_OK;
7496 }
7497
7498 /****************************************************************************
7499  Reply to a lockingX request.
7500 ****************************************************************************/
7501
7502 static void reply_lockingx_done(struct tevent_req *subreq);
7503
7504 void reply_lockingX(struct smb_request *req)
7505 {
7506         connection_struct *conn = req->conn;
7507         files_struct *fsp;
7508         unsigned char locktype;
7509         enum brl_type brltype;
7510         unsigned char oplocklevel;
7511         uint16_t num_ulocks;
7512         uint16_t num_locks;
7513         int32_t lock_timeout;
7514         uint16_t i;
7515         const uint8_t *data;
7516         bool large_file_format;
7517         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7518         struct smbd_lock_element *locks = NULL;
7519         struct tevent_req *subreq = NULL;
7520
7521         START_PROFILE(SMBlockingX);
7522
7523         if (req->wct < 8) {
7524                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7525                 END_PROFILE(SMBlockingX);
7526                 return;
7527         }
7528
7529         fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7530         locktype = CVAL(req->vwv+3, 0);
7531         oplocklevel = CVAL(req->vwv+3, 1);
7532         num_ulocks = SVAL(req->vwv+6, 0);
7533         num_locks = SVAL(req->vwv+7, 0);
7534         lock_timeout = IVAL(req->vwv+4, 0);
7535         large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
7536
7537         if (!check_fsp(conn, req, fsp)) {
7538                 END_PROFILE(SMBlockingX);
7539                 return;
7540         }
7541
7542         data = req->buf;
7543
7544         if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7545                 /* we don't support these - and CANCEL_LOCK makes w2k
7546                    and XP reboot so I don't really want to be
7547                    compatible! (tridge) */
7548                 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7549                 END_PROFILE(SMBlockingX);
7550                 return;
7551         }
7552
7553         /* Check if this is an oplock break on a file
7554            we have granted an oplock on.
7555         */
7556         if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
7557                 /* Client can insist on breaking to none. */
7558                 bool break_to_none = (oplocklevel == 0);
7559                 bool result;
7560
7561                 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7562                          "for %s\n", (unsigned int)oplocklevel,
7563                          fsp_fnum_dbg(fsp)));
7564
7565                 /*
7566                  * Make sure we have granted an exclusive or batch oplock on
7567                  * this file.
7568                  */
7569
7570                 if (fsp->oplock_type == 0) {
7571
7572                         /* The Samba4 nbench simulator doesn't understand
7573                            the difference between break to level2 and break
7574                            to none from level2 - it sends oplock break
7575                            replies in both cases. Don't keep logging an error
7576                            message here - just ignore it. JRA. */
7577
7578                         DEBUG(5,("reply_lockingX: Error : oplock break from "
7579                                  "client for %s (oplock=%d) and no "
7580                                  "oplock granted on this file (%s).\n",
7581                                  fsp_fnum_dbg(fsp), fsp->oplock_type,
7582                                  fsp_str_dbg(fsp)));
7583
7584                         /* if this is a pure oplock break request then don't
7585                          * send a reply */
7586                         if (num_locks == 0 && num_ulocks == 0) {
7587                                 END_PROFILE(SMBlockingX);
7588                                 return;
7589                         }
7590
7591                         END_PROFILE(SMBlockingX);
7592                         reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7593                         return;
7594                 }
7595
7596                 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7597                     (break_to_none)) {
7598                         result = remove_oplock(fsp);
7599                 } else {
7600                         result = downgrade_oplock(fsp);
7601                 }
7602
7603                 if (!result) {
7604                         DEBUG(0, ("reply_lockingX: error in removing "
7605                                   "oplock on file %s\n", fsp_str_dbg(fsp)));
7606                         /* Hmmm. Is this panic justified? */
7607                         smb_panic("internal tdb error");
7608                 }
7609
7610                 /* if this is a pure oplock break request then don't send a
7611                  * reply */
7612                 if (num_locks == 0 && num_ulocks == 0) {
7613                         /* Sanity check - ensure a pure oplock break is not a
7614                            chained request. */
7615                         if (CVAL(req->vwv+0, 0) != 0xff) {
7616                                 DEBUG(0,("reply_lockingX: Error : pure oplock "
7617                                          "break is a chained %d request !\n",
7618                                          (unsigned int)CVAL(req->vwv+0, 0)));
7619                         }
7620                         END_PROFILE(SMBlockingX);
7621                         return;
7622                 }
7623         }
7624
7625         if (req->buflen <
7626             (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7627                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7628                 END_PROFILE(SMBlockingX);
7629                 return;
7630         }
7631
7632         if (num_ulocks != 0) {
7633                 struct smbd_lock_element *ulocks = NULL;
7634                 bool ok;
7635
7636                 ulocks = talloc_array(
7637                         req, struct smbd_lock_element, num_ulocks);
7638                 if (ulocks == NULL) {
7639                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7640                         END_PROFILE(SMBlockingX);
7641                         return;
7642                 }
7643
7644                 /*
7645                  * Data now points at the beginning of the list of
7646                  * smb_unlkrng structs
7647                  */
7648                 for (i = 0; i < num_ulocks; i++) {
7649                         ulocks[i].req_guid = smbd_request_guid(req,
7650                                 UINT16_MAX - i),
7651                         ulocks[i].smblctx = get_lock_pid(
7652                                 data, i, large_file_format);
7653                         ulocks[i].count = get_lock_count(
7654                                 data, i, large_file_format);
7655                         ulocks[i].offset = get_lock_offset(
7656                                 data, i, large_file_format);
7657                         ulocks[i].brltype = UNLOCK_LOCK;
7658                         ulocks[i].lock_flav = WINDOWS_LOCK;
7659                 }
7660
7661                 /*
7662                  * Unlock cancels pending locks
7663                  */
7664
7665                 ok = smbd_smb1_brl_finish_by_lock(
7666                         fsp,
7667                         large_file_format,
7668                         ulocks[0],
7669                         NT_STATUS_OK);
7670                 if (ok) {
7671                         reply_outbuf(req, 2, 0);
7672                         SSVAL(req->outbuf, smb_vwv0, 0xff);
7673                         SSVAL(req->outbuf, smb_vwv1, 0);
7674                         END_PROFILE(SMBlockingX);
7675                         return;
7676                 }
7677
7678                 status = smbd_do_unlocking(
7679                         req, fsp, num_ulocks, ulocks);
7680                 TALLOC_FREE(ulocks);
7681                 if (!NT_STATUS_IS_OK(status)) {
7682                         END_PROFILE(SMBlockingX);
7683                         reply_nterror(req, status);
7684                         return;
7685                 }
7686         }
7687
7688         /* Now do any requested locks */
7689         data += ((large_file_format ? 20 : 10)*num_ulocks);
7690
7691         /* Data now points at the beginning of the list
7692            of smb_lkrng structs */
7693
7694         if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7695                 brltype = READ_LOCK;
7696         } else {
7697                 brltype = WRITE_LOCK;
7698         }
7699
7700         locks = talloc_array(req, struct smbd_lock_element, num_locks);
7701         if (locks == NULL) {
7702                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7703                 END_PROFILE(SMBlockingX);
7704                 return;
7705         }
7706
7707         for (i = 0; i < num_locks; i++) {
7708                 locks[i].req_guid = smbd_request_guid(req, i),
7709                 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7710                 locks[i].count = get_lock_count(data, i, large_file_format);
7711                 locks[i].offset = get_lock_offset(data, i, large_file_format);
7712                 locks[i].brltype = brltype;
7713                 locks[i].lock_flav = WINDOWS_LOCK;
7714         }
7715
7716         if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7717
7718                 bool ok;
7719
7720                 if (num_locks == 0) {
7721                         /* See smbtorture3 lock11 test */
7722                         reply_outbuf(req, 2, 0);
7723                         /* andx chain ends */
7724                         SSVAL(req->outbuf, smb_vwv0, 0xff);
7725                         SSVAL(req->outbuf, smb_vwv1, 0);
7726                         END_PROFILE(SMBlockingX);
7727                         return;
7728                 }
7729
7730                 ok = smbd_smb1_brl_finish_by_lock(
7731                         fsp,
7732                         large_file_format,
7733                         locks[0], /* Windows only cancels the first lock */
7734                         NT_STATUS_FILE_LOCK_CONFLICT);
7735
7736                 if (!ok) {
7737                         reply_force_doserror(req, ERRDOS, ERRcancelviolation);
7738                         END_PROFILE(SMBlockingX);
7739                         return;
7740                 }
7741
7742                 reply_outbuf(req, 2, 0);
7743                 SSVAL(req->outbuf, smb_vwv0, 0xff);
7744                 SSVAL(req->outbuf, smb_vwv1, 0);
7745                 END_PROFILE(SMBlockingX);
7746                 return;
7747         }
7748
7749         subreq = smbd_smb1_do_locks_send(
7750                 fsp,
7751                 req->sconn->ev_ctx,
7752                 &req,
7753                 fsp,
7754                 lock_timeout,
7755                 large_file_format,
7756                 num_locks,
7757                 locks);
7758         if (subreq == NULL) {
7759                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760                 END_PROFILE(SMBlockingX);
7761                 return;
7762         }
7763         tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
7764         END_PROFILE(SMBlockingX);
7765 }
7766
7767 static void reply_lockingx_done(struct tevent_req *subreq)
7768 {
7769         struct smb_request *req = NULL;
7770         NTSTATUS status;
7771         bool ok;
7772
7773         START_PROFILE(SMBlockingX);
7774
7775         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7776         SMB_ASSERT(ok);
7777
7778         status = smbd_smb1_do_locks_recv(subreq);
7779         TALLOC_FREE(subreq);
7780
7781         DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
7782
7783         if (NT_STATUS_IS_OK(status)) {
7784                 reply_outbuf(req, 2, 0);
7785                 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7786                 SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
7787         } else {
7788                 reply_nterror(req, status);
7789         }
7790
7791         ok = srv_send_smb(req->xconn,
7792                           (char *)req->outbuf,
7793                           true,
7794                           req->seqnum+1,
7795                           IS_CONN_ENCRYPTED(req->conn),
7796                           NULL);
7797         if (!ok) {
7798                 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
7799         }
7800         TALLOC_FREE(req);
7801         END_PROFILE(SMBlockingX);
7802 }
7803
7804 #undef DBGC_CLASS
7805 #define DBGC_CLASS DBGC_ALL
7806
7807 /****************************************************************************
7808  Reply to a SMBreadbmpx (read block multiplex) request.
7809  Always reply with an error, if someone has a platform really needs this,
7810  please contact vl@samba.org
7811 ****************************************************************************/
7812
7813 void reply_readbmpx(struct smb_request *req)
7814 {
7815         START_PROFILE(SMBreadBmpx);
7816         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7817         END_PROFILE(SMBreadBmpx);
7818         return;
7819 }
7820
7821 /****************************************************************************
7822  Reply to a SMBreadbs (read block multiplex secondary) request.
7823  Always reply with an error, if someone has a platform really needs this,
7824  please contact vl@samba.org
7825 ****************************************************************************/
7826
7827 void reply_readbs(struct smb_request *req)
7828 {
7829         START_PROFILE(SMBreadBs);
7830         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7831         END_PROFILE(SMBreadBs);
7832         return;
7833 }
7834
7835 /****************************************************************************
7836  Reply to a SMBsetattrE.
7837 ****************************************************************************/
7838
7839 void reply_setattrE(struct smb_request *req)
7840 {
7841         connection_struct *conn = req->conn;
7842         struct smb_file_time ft;
7843         files_struct *fsp;
7844         NTSTATUS status;
7845
7846         START_PROFILE(SMBsetattrE);
7847         init_smb_file_time(&ft);
7848
7849         if (req->wct < 7) {
7850                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7851                 goto out;
7852         }
7853
7854         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7855
7856         if(!fsp || (fsp->conn != conn)) {
7857                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7858                 goto out;
7859         }
7860
7861         /*
7862          * Convert the DOS times into unix times.
7863          */
7864
7865         ft.atime = time_t_to_full_timespec(
7866             srv_make_unix_date2(req->vwv+3));
7867         ft.mtime = time_t_to_full_timespec(
7868             srv_make_unix_date2(req->vwv+5));
7869         ft.create_time = time_t_to_full_timespec(
7870             srv_make_unix_date2(req->vwv+1));
7871
7872         reply_outbuf(req, 0, 0);
7873
7874         /* 
7875          * Patch from Ray Frush <frush@engr.colostate.edu>
7876          * Sometimes times are sent as zero - ignore them.
7877          */
7878
7879         /* Ensure we have a valid stat struct for the source. */
7880         status = vfs_stat_fsp(fsp);
7881         if (!NT_STATUS_IS_OK(status)) {
7882                 reply_nterror(req, status);
7883                 goto out;
7884         }
7885
7886         if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7887                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7888                 goto out;
7889         }
7890
7891         status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7892         if (!NT_STATUS_IS_OK(status)) {
7893                 reply_nterror(req, status);
7894                 goto out;
7895         }
7896
7897         if (fsp->fsp_flags.modified) {
7898                 trigger_write_time_update_immediate(fsp);
7899         }
7900
7901         DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
7902                " createtime=%u\n",
7903                 fsp_fnum_dbg(fsp),
7904                 (unsigned int)ft.atime.tv_sec,
7905                 (unsigned int)ft.mtime.tv_sec,
7906                 (unsigned int)ft.create_time.tv_sec
7907                 ));
7908  out:
7909         END_PROFILE(SMBsetattrE);
7910         return;
7911 }
7912
7913
7914 /* Back from the dead for OS/2..... JRA. */
7915
7916 /****************************************************************************
7917  Reply to a SMBwritebmpx (write block multiplex primary) request.
7918  Always reply with an error, if someone has a platform really needs this,
7919  please contact vl@samba.org
7920 ****************************************************************************/
7921
7922 void reply_writebmpx(struct smb_request *req)
7923 {
7924         START_PROFILE(SMBwriteBmpx);
7925         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7926         END_PROFILE(SMBwriteBmpx);
7927         return;
7928 }
7929
7930 /****************************************************************************
7931  Reply to a SMBwritebs (write block multiplex secondary) request.
7932  Always reply with an error, if someone has a platform really needs this,
7933  please contact vl@samba.org
7934 ****************************************************************************/
7935
7936 void reply_writebs(struct smb_request *req)
7937 {
7938         START_PROFILE(SMBwriteBs);
7939         reply_force_doserror(req, ERRSRV, ERRuseSTD);
7940         END_PROFILE(SMBwriteBs);
7941         return;
7942 }
7943
7944 /****************************************************************************
7945  Reply to a SMBgetattrE.
7946 ****************************************************************************/
7947
7948 void reply_getattrE(struct smb_request *req)
7949 {
7950         connection_struct *conn = req->conn;
7951         int mode;
7952         files_struct *fsp;
7953         struct timespec create_ts;
7954         NTSTATUS status;
7955
7956         START_PROFILE(SMBgetattrE);
7957
7958         if (req->wct < 1) {
7959                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7960                 END_PROFILE(SMBgetattrE);
7961                 return;
7962         }
7963
7964         fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7965
7966         if(!fsp || (fsp->conn != conn)) {
7967                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7968                 END_PROFILE(SMBgetattrE);
7969                 return;
7970         }
7971
7972         /* Do an fstat on this file */
7973         status = vfs_stat_fsp(fsp);
7974         if (!NT_STATUS_IS_OK(status)) {
7975                 reply_nterror(req, status);
7976                 END_PROFILE(SMBgetattrE);
7977                 return;
7978         }
7979
7980         mode = fdos_mode(fsp);
7981
7982         /*
7983          * Convert the times into dos times. Set create
7984          * date to be last modify date as UNIX doesn't save
7985          * this.
7986          */
7987
7988         reply_outbuf(req, 11, 0);
7989
7990         create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7991         srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7992         srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7993                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7994         /* Should we check pending modtime here ? JRA */
7995         srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7996                           convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7997
7998         if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7999                 SIVAL(req->outbuf, smb_vwv6, 0);
8000                 SIVAL(req->outbuf, smb_vwv8, 0);
8001         } else {
8002                 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8003                 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8004                 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8005         }
8006         SSVAL(req->outbuf,smb_vwv10, mode);
8007
8008         DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8009
8010         END_PROFILE(SMBgetattrE);
8011         return;
8012 }