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