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