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