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