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