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