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 "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "fake_file.h"
34 #include "rpc_client/rpc_client.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "lib/util/tevent_ntstatus.h"
46 #include "libcli/smb/smb_signing.h"
47 #include "lib/util/sys_rw_data.h"
48 #include "librpc/gen_ndr/open_files.h"
49 #include "smb1_utils.h"
50
51 /****************************************************************************
52 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
53 path or anything including wildcards.
54 We're assuming here that '/' is not the second byte in any multibyte char
55 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
56 set.
57 ****************************************************************************/
58
59 /* Custom version for processing POSIX paths. */
60 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
61
check_path_syntax_internal(char * path,bool posix_path,bool * p_last_component_contains_wcard)62 static NTSTATUS check_path_syntax_internal(char *path,
63 bool posix_path,
64 bool *p_last_component_contains_wcard)
65 {
66 char *d = path;
67 const char *s = path;
68 NTSTATUS ret = NT_STATUS_OK;
69 bool start_of_name_component = True;
70 bool stream_started = false;
71
72 *p_last_component_contains_wcard = False;
73
74 while (*s) {
75 if (stream_started) {
76 switch (*s) {
77 case '/':
78 case '\\':
79 return NT_STATUS_OBJECT_NAME_INVALID;
80 case ':':
81 if (s[1] == '\0') {
82 return NT_STATUS_OBJECT_NAME_INVALID;
83 }
84 if (strchr_m(&s[1], ':')) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
86 }
87 break;
88 }
89 }
90
91 if ((*s == ':') && !posix_path && !stream_started) {
92 if (*p_last_component_contains_wcard) {
93 return NT_STATUS_OBJECT_NAME_INVALID;
94 }
95 /* Stream names allow more characters than file names.
96 We're overloading posix_path here to allow a wider
97 range of characters. If stream_started is true this
98 is still a Windows path even if posix_path is true.
99 JRA.
100 */
101 stream_started = true;
102 start_of_name_component = false;
103 posix_path = true;
104
105 if (s[1] == '\0') {
106 return NT_STATUS_OBJECT_NAME_INVALID;
107 }
108 }
109
110 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
111 /*
112 * Safe to assume is not the second part of a mb char
113 * as this is handled below.
114 */
115 /* Eat multiple '/' or '\\' */
116 while (IS_PATH_SEP(*s,posix_path)) {
117 s++;
118 }
119 if ((d != path) && (*s != '\0')) {
120 /* We only care about non-leading or trailing '/' or '\\' */
121 *d++ = '/';
122 }
123
124 start_of_name_component = True;
125 /* New component. */
126 *p_last_component_contains_wcard = False;
127 continue;
128 }
129
130 if (start_of_name_component) {
131 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
132 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
133
134 /*
135 * No mb char starts with '.' so we're safe checking the directory separator here.
136 */
137
138 /* If we just added a '/' - delete it */
139 if ((d > path) && (*(d-1) == '/')) {
140 *(d-1) = '\0';
141 d--;
142 }
143
144 /* Are we at the start ? Can't go back further if so. */
145 if (d <= path) {
146 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
147 break;
148 }
149 /* Go back one level... */
150 /* We know this is safe as '/' cannot be part of a mb sequence. */
151 /* NOTE - if this assumption is invalid we are not in good shape... */
152 /* Decrement d first as d points to the *next* char to write into. */
153 for (d--; d > path; d--) {
154 if (*d == '/')
155 break;
156 }
157 s += 2; /* Else go past the .. */
158 /* We're still at the start of a name component, just the previous one. */
159 continue;
160
161 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
162 if (posix_path) {
163 /* Eat the '.' */
164 s++;
165 continue;
166 }
167 }
168
169 }
170
171 if (!(*s & 0x80)) {
172 if (!posix_path) {
173 if (*s <= 0x1f || *s == '|') {
174 return NT_STATUS_OBJECT_NAME_INVALID;
175 }
176 switch (*s) {
177 case '*':
178 case '?':
179 case '<':
180 case '>':
181 case '"':
182 *p_last_component_contains_wcard = True;
183 break;
184 default:
185 break;
186 }
187 }
188 *d++ = *s++;
189 } else {
190 size_t siz;
191 /* Get the size of the next MB character. */
192 next_codepoint(s,&siz);
193 switch(siz) {
194 case 5:
195 *d++ = *s++;
196 FALL_THROUGH;
197 case 4:
198 *d++ = *s++;
199 FALL_THROUGH;
200 case 3:
201 *d++ = *s++;
202 FALL_THROUGH;
203 case 2:
204 *d++ = *s++;
205 FALL_THROUGH;
206 case 1:
207 *d++ = *s++;
208 break;
209 default:
210 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
211 *d = '\0';
212 return NT_STATUS_INVALID_PARAMETER;
213 }
214 }
215 start_of_name_component = False;
216 }
217
218 *d = '\0';
219
220 return ret;
221 }
222
223 /****************************************************************************
224 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
225 No wildcards allowed.
226 ****************************************************************************/
227
check_path_syntax(char * path)228 NTSTATUS check_path_syntax(char *path)
229 {
230 bool ignore;
231 return check_path_syntax_internal(path, False, &ignore);
232 }
233
234 /****************************************************************************
235 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
236 Wildcards allowed - p_contains_wcard returns true if the last component contained
237 a wildcard.
238 ****************************************************************************/
239
check_path_syntax_wcard(char * path,bool * p_contains_wcard)240 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
241 {
242 return check_path_syntax_internal(path, False, p_contains_wcard);
243 }
244
245 /****************************************************************************
246 Check the path for a POSIX client.
247 We're assuming here that '/' is not the second byte in any multibyte char
248 set (a safe assumption).
249 ****************************************************************************/
250
check_path_syntax_posix(char * path)251 NTSTATUS check_path_syntax_posix(char *path)
252 {
253 bool ignore;
254 return check_path_syntax_internal(path, True, &ignore);
255 }
256
257 /****************************************************************************
258 Pull a string and check the path allowing a wildcard - provide for error return.
259 Passes in posix flag.
260 ****************************************************************************/
261
srvstr_get_path_wcard_internal(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,bool posix_pathnames,NTSTATUS * err,bool * contains_wcard)262 static size_t srvstr_get_path_wcard_internal(TALLOC_CTX *ctx,
263 const char *base_ptr,
264 uint16_t smb_flags2,
265 char **pp_dest,
266 const char *src,
267 size_t src_len,
268 int flags,
269 bool posix_pathnames,
270 NTSTATUS *err,
271 bool *contains_wcard)
272 {
273 size_t ret;
274
275 *pp_dest = NULL;
276
277 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
278 src_len, flags);
279
280 if (!*pp_dest) {
281 *err = NT_STATUS_INVALID_PARAMETER;
282 return ret;
283 }
284
285 *contains_wcard = False;
286
287 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
288 /*
289 * For a DFS path the function parse_dfs_path()
290 * will do the path processing, just make a copy.
291 */
292 *err = NT_STATUS_OK;
293 return ret;
294 }
295
296 if (posix_pathnames) {
297 *err = check_path_syntax_posix(*pp_dest);
298 } else {
299 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
300 }
301
302 return ret;
303 }
304
305 /****************************************************************************
306 Pull a string and check the path allowing a wildcard - provide for error return.
307 ****************************************************************************/
308
srvstr_get_path_wcard(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err,bool * contains_wcard)309 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
310 const char *base_ptr,
311 uint16_t smb_flags2,
312 char **pp_dest,
313 const char *src,
314 size_t src_len,
315 int flags,
316 NTSTATUS *err,
317 bool *contains_wcard)
318 {
319 return srvstr_get_path_wcard_internal(ctx,
320 base_ptr,
321 smb_flags2,
322 pp_dest,
323 src,
324 src_len,
325 flags,
326 false,
327 err,
328 contains_wcard);
329 }
330
331 /****************************************************************************
332 Pull a string and check the path allowing a wildcard - provide for error return.
333 posix_pathnames version.
334 ****************************************************************************/
335
srvstr_get_path_wcard_posix(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err,bool * contains_wcard)336 size_t srvstr_get_path_wcard_posix(TALLOC_CTX *ctx,
337 const char *base_ptr,
338 uint16_t smb_flags2,
339 char **pp_dest,
340 const char *src,
341 size_t src_len,
342 int flags,
343 NTSTATUS *err,
344 bool *contains_wcard)
345 {
346 return srvstr_get_path_wcard_internal(ctx,
347 base_ptr,
348 smb_flags2,
349 pp_dest,
350 src,
351 src_len,
352 flags,
353 true,
354 err,
355 contains_wcard);
356 }
357
358 /****************************************************************************
359 Pull a string and check the path - provide for error return.
360 ****************************************************************************/
361
srvstr_get_path(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err)362 size_t srvstr_get_path(TALLOC_CTX *ctx,
363 const char *base_ptr,
364 uint16_t smb_flags2,
365 char **pp_dest,
366 const char *src,
367 size_t src_len,
368 int flags,
369 NTSTATUS *err)
370 {
371 bool ignore;
372 return srvstr_get_path_wcard_internal(ctx,
373 base_ptr,
374 smb_flags2,
375 pp_dest,
376 src,
377 src_len,
378 flags,
379 false,
380 err,
381 &ignore);
382 }
383
384 /****************************************************************************
385 Pull a string and check the path - provide for error return.
386 posix_pathnames version.
387 ****************************************************************************/
388
srvstr_get_path_posix(TALLOC_CTX * ctx,const char * base_ptr,uint16_t smb_flags2,char ** pp_dest,const char * src,size_t src_len,int flags,NTSTATUS * err)389 size_t srvstr_get_path_posix(TALLOC_CTX *ctx,
390 const char *base_ptr,
391 uint16_t smb_flags2,
392 char **pp_dest,
393 const char *src,
394 size_t src_len,
395 int flags,
396 NTSTATUS *err)
397 {
398 bool ignore;
399 return srvstr_get_path_wcard_internal(ctx,
400 base_ptr,
401 smb_flags2,
402 pp_dest,
403 src,
404 src_len,
405 flags,
406 true,
407 err,
408 &ignore);
409 }
410
411
srvstr_get_path_req_wcard(TALLOC_CTX * mem_ctx,struct smb_request * req,char ** pp_dest,const char * src,int flags,NTSTATUS * err,bool * contains_wcard)412 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
413 char **pp_dest, const char *src, int flags,
414 NTSTATUS *err, bool *contains_wcard)
415 {
416 ssize_t bufrem = smbreq_bufrem(req, src);
417
418 if (bufrem < 0) {
419 *err = NT_STATUS_INVALID_PARAMETER;
420 return 0;
421 }
422
423 if (req->posix_pathnames) {
424 return srvstr_get_path_wcard_internal(mem_ctx,
425 (const char *)req->inbuf,
426 req->flags2,
427 pp_dest,
428 src,
429 bufrem,
430 flags,
431 true,
432 err,
433 contains_wcard);
434 } else {
435 return srvstr_get_path_wcard_internal(mem_ctx,
436 (const char *)req->inbuf,
437 req->flags2,
438 pp_dest,
439 src,
440 bufrem,
441 flags,
442 false,
443 err,
444 contains_wcard);
445 }
446 }
447
srvstr_get_path_req(TALLOC_CTX * mem_ctx,struct smb_request * req,char ** pp_dest,const char * src,int flags,NTSTATUS * err)448 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
449 char **pp_dest, const char *src, int flags,
450 NTSTATUS *err)
451 {
452 bool ignore;
453 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
454 flags, err, &ignore);
455 }
456
457 /**
458 * pull a string from the smb_buf part of a packet. In this case the
459 * string can either be null terminated or it can be terminated by the
460 * end of the smbbuf area
461 */
srvstr_pull_req_talloc(TALLOC_CTX * ctx,struct smb_request * req,char ** dest,const uint8_t * src,int flags)462 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
463 char **dest, const uint8_t *src, int flags)
464 {
465 ssize_t bufrem = smbreq_bufrem(req, src);
466
467 if (bufrem < 0) {
468 return 0;
469 }
470
471 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
472 bufrem, flags);
473 }
474
475 /****************************************************************************
476 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
477 ****************************************************************************/
478
check_fsp_open(connection_struct * conn,struct smb_request * req,files_struct * fsp)479 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
480 files_struct *fsp)
481 {
482 if ((fsp == NULL) || (conn == NULL)) {
483 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
484 return False;
485 }
486 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
487 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
488 return False;
489 }
490 return True;
491 }
492
493 /****************************************************************************
494 Check if we have a correct fsp pointing to a file.
495 ****************************************************************************/
496
check_fsp(connection_struct * conn,struct smb_request * req,files_struct * fsp)497 bool check_fsp(connection_struct *conn, struct smb_request *req,
498 files_struct *fsp)
499 {
500 if (!check_fsp_open(conn, req, fsp)) {
501 return False;
502 }
503 if (fsp->is_directory) {
504 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
505 return False;
506 }
507 if (fsp->fh->fd == -1) {
508 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
509 return False;
510 }
511 fsp->num_smb_operations++;
512 return True;
513 }
514
515 /****************************************************************************
516 Check if we have a correct fsp pointing to a quota fake file. Replacement for
517 the CHECK_NTQUOTA_HANDLE_OK macro.
518 ****************************************************************************/
519
check_fsp_ntquota_handle(connection_struct * conn,struct smb_request * req,files_struct * fsp)520 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
521 files_struct *fsp)
522 {
523 if (!check_fsp_open(conn, req, fsp)) {
524 return false;
525 }
526
527 if (fsp->is_directory) {
528 return false;
529 }
530
531 if (fsp->fake_file_handle == NULL) {
532 return false;
533 }
534
535 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
536 return false;
537 }
538
539 if (fsp->fake_file_handle->private_data == NULL) {
540 return false;
541 }
542
543 return true;
544 }
545
netbios_session_retarget(struct smbXsrv_connection * xconn,const char * name,int name_type)546 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
547 const char *name, int name_type)
548 {
549 char *trim_name;
550 char *trim_name_type;
551 const char *retarget_parm;
552 char *retarget;
553 char *p;
554 int retarget_type = 0x20;
555 int retarget_port = NBT_SMB_PORT;
556 struct sockaddr_storage retarget_addr;
557 struct sockaddr_in *in_addr;
558 bool ret = false;
559 uint8_t outbuf[10];
560
561 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
562 return false;
563 }
564
565 trim_name = talloc_strdup(talloc_tos(), name);
566 if (trim_name == NULL) {
567 goto fail;
568 }
569 trim_char(trim_name, ' ', ' ');
570
571 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
572 name_type);
573 if (trim_name_type == NULL) {
574 goto fail;
575 }
576
577 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
578 trim_name_type, NULL);
579 if (retarget_parm == NULL) {
580 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
581 trim_name, NULL);
582 }
583 if (retarget_parm == NULL) {
584 goto fail;
585 }
586
587 retarget = talloc_strdup(trim_name, retarget_parm);
588 if (retarget == NULL) {
589 goto fail;
590 }
591
592 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
593
594 p = strchr(retarget, ':');
595 if (p != NULL) {
596 *p++ = '\0';
597 retarget_port = atoi(p);
598 }
599
600 p = strchr_m(retarget, '#');
601 if (p != NULL) {
602 *p++ = '\0';
603 if (sscanf(p, "%x", &retarget_type) != 1) {
604 goto fail;
605 }
606 }
607
608 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
609 if (!ret) {
610 DEBUG(10, ("could not resolve %s\n", retarget));
611 goto fail;
612 }
613
614 if (retarget_addr.ss_family != AF_INET) {
615 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
616 goto fail;
617 }
618
619 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
620
621 _smb_setlen(outbuf, 6);
622 SCVAL(outbuf, 0, 0x84);
623 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
624 *(uint16_t *)(outbuf+8) = htons(retarget_port);
625
626 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
627 NULL)) {
628 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
629 "failed.");
630 }
631
632 ret = true;
633 fail:
634 TALLOC_FREE(trim_name);
635 return ret;
636 }
637
reply_called_name_not_present(char * outbuf)638 static void reply_called_name_not_present(char *outbuf)
639 {
640 smb_setlen(outbuf, 1);
641 SCVAL(outbuf, 0, 0x83);
642 SCVAL(outbuf, 4, 0x82);
643 }
644
645 /****************************************************************************
646 Reply to a (netbios-level) special message.
647 ****************************************************************************/
648
reply_special(struct smbXsrv_connection * xconn,char * inbuf,size_t inbuf_size)649 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
650 {
651 struct smbd_server_connection *sconn = xconn->client->sconn;
652 int msg_type = CVAL(inbuf,0);
653 int msg_flags = CVAL(inbuf,1);
654 /*
655 * We only really use 4 bytes of the outbuf, but for the smb_setlen
656 * calculation & friends (srv_send_smb uses that) we need the full smb
657 * header.
658 */
659 char outbuf[smb_size];
660
661 memset(outbuf, '\0', sizeof(outbuf));
662
663 smb_setlen(outbuf,0);
664
665 switch (msg_type) {
666 case NBSSrequest: /* session request */
667 {
668 /* inbuf_size is guarenteed to be at least 4. */
669 fstring name1,name2;
670 int name_type1, name_type2;
671 int name_len1, name_len2;
672
673 *name1 = *name2 = 0;
674
675 if (xconn->transport.nbt.got_session) {
676 exit_server_cleanly("multiple session request not permitted");
677 }
678
679 SCVAL(outbuf,0,NBSSpositive);
680 SCVAL(outbuf,3,0);
681
682 /* inbuf_size is guaranteed to be at least 4. */
683 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
684 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
685 DEBUG(0,("Invalid name length in session request\n"));
686 reply_called_name_not_present(outbuf);
687 break;
688 }
689 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
690 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
691 DEBUG(0,("Invalid name length in session request\n"));
692 reply_called_name_not_present(outbuf);
693 break;
694 }
695
696 name_type1 = name_extract((unsigned char *)inbuf,
697 inbuf_size,(unsigned int)4,name1);
698 name_type2 = name_extract((unsigned char *)inbuf,
699 inbuf_size,(unsigned int)(4 + name_len1),name2);
700
701 if (name_type1 == -1 || name_type2 == -1) {
702 DEBUG(0,("Invalid name type in session request\n"));
703 reply_called_name_not_present(outbuf);
704 break;
705 }
706
707 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
708 name1, name_type1, name2, name_type2));
709
710 if (netbios_session_retarget(xconn, name1, name_type1)) {
711 exit_server_cleanly("retargeted client");
712 }
713
714 /*
715 * Windows NT/2k uses "*SMBSERVER" and XP uses
716 * "*SMBSERV" arrggg!!!
717 */
718 if (strequal(name1, "*SMBSERVER ")
719 || strequal(name1, "*SMBSERV ")) {
720 char *raddr;
721
722 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
723 talloc_tos());
724 if (raddr == NULL) {
725 exit_server_cleanly("could not allocate raddr");
726 }
727
728 fstrcpy(name1, raddr);
729 }
730
731 set_local_machine_name(name1, True);
732 set_remote_machine_name(name2, True);
733
734 if (is_ipaddress(sconn->remote_hostname)) {
735 char *p = discard_const_p(char, sconn->remote_hostname);
736
737 talloc_free(p);
738
739 sconn->remote_hostname = talloc_strdup(sconn,
740 get_remote_machine_name());
741 if (sconn->remote_hostname == NULL) {
742 exit_server_cleanly("could not copy remote name");
743 }
744 xconn->remote_hostname = sconn->remote_hostname;
745 }
746
747 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
748 get_local_machine_name(), get_remote_machine_name(),
749 name_type2));
750
751 if (name_type2 == 'R') {
752 /* We are being asked for a pathworks session ---
753 no thanks! */
754 reply_called_name_not_present(outbuf);
755 break;
756 }
757
758 reload_services(sconn, conn_snum_used, true);
759 reopen_logs();
760
761 xconn->transport.nbt.got_session = true;
762 break;
763 }
764
765 case 0x89: /* session keepalive request
766 (some old clients produce this?) */
767 SCVAL(outbuf,0,NBSSkeepalive);
768 SCVAL(outbuf,3,0);
769 break;
770
771 case NBSSpositive: /* positive session response */
772 case NBSSnegative: /* negative session response */
773 case NBSSretarget: /* retarget session response */
774 DEBUG(0,("Unexpected session response\n"));
775 break;
776
777 case NBSSkeepalive: /* session keepalive */
778 default:
779 return;
780 }
781
782 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
783 msg_type, msg_flags));
784
785 if (!srv_send_smb(xconn, outbuf, false, 0, false, NULL)) {
786 exit_server_cleanly("reply_special: srv_send_smb failed.");
787 }
788
789 if (CVAL(outbuf, 0) != 0x82) {
790 exit_server_cleanly("invalid netbios session");
791 }
792 return;
793 }
794
795 /****************************************************************************
796 Reply to a tcon.
797 conn POINTER CAN BE NULL HERE !
798 ****************************************************************************/
799
reply_tcon(struct smb_request * req)800 void reply_tcon(struct smb_request *req)
801 {
802 connection_struct *conn = req->conn;
803 const char *service;
804 char *service_buf = NULL;
805 char *password = NULL;
806 char *dev = NULL;
807 int pwlen=0;
808 NTSTATUS nt_status;
809 const uint8_t *p;
810 const char *p2;
811 TALLOC_CTX *ctx = talloc_tos();
812 struct smbXsrv_connection *xconn = req->xconn;
813 NTTIME now = timeval_to_nttime(&req->request_time);
814
815 START_PROFILE(SMBtcon);
816
817 if (req->buflen < 4) {
818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
819 END_PROFILE(SMBtcon);
820 return;
821 }
822
823 p = req->buf + 1;
824 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
825 p += 1;
826 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
827 p += pwlen+1;
828 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
829 p += 1;
830
831 if (service_buf == NULL || password == NULL || dev == NULL) {
832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
833 END_PROFILE(SMBtcon);
834 return;
835 }
836 p2 = strrchr_m(service_buf,'\\');
837 if (p2) {
838 service = p2+1;
839 } else {
840 service = service_buf;
841 }
842
843 conn = make_connection(req, now, service, dev,
844 req->vuid,&nt_status);
845 req->conn = conn;
846
847 if (!conn) {
848 reply_nterror(req, nt_status);
849 END_PROFILE(SMBtcon);
850 return;
851 }
852
853 reply_outbuf(req, 2, 0);
854 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
855 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
856 SSVAL(req->outbuf,smb_tid,conn->cnum);
857
858 DEBUG(3,("tcon service=%s cnum=%d\n",
859 service, conn->cnum));
860
861 END_PROFILE(SMBtcon);
862 return;
863 }
864
865 /****************************************************************************
866 Reply to a tcon and X.
867 conn POINTER CAN BE NULL HERE !
868 ****************************************************************************/
869
reply_tcon_and_X(struct smb_request * req)870 void reply_tcon_and_X(struct smb_request *req)
871 {
872 const struct loadparm_substitution *lp_sub =
873 loadparm_s3_global_substitution();
874 connection_struct *conn = req->conn;
875 const char *service = NULL;
876 TALLOC_CTX *ctx = talloc_tos();
877 /* what the client thinks the device is */
878 char *client_devicetype = NULL;
879 /* what the server tells the client the share represents */
880 const char *server_devicetype;
881 NTSTATUS nt_status;
882 int passlen;
883 char *path = NULL;
884 const uint8_t *p;
885 const char *q;
886 uint16_t tcon_flags;
887 struct smbXsrv_session *session = NULL;
888 NTTIME now = timeval_to_nttime(&req->request_time);
889 bool session_key_updated = false;
890 uint16_t optional_support = 0;
891 struct smbXsrv_connection *xconn = req->xconn;
892
893 START_PROFILE(SMBtconX);
894
895 if (req->wct < 4) {
896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
897 END_PROFILE(SMBtconX);
898 return;
899 }
900
901 passlen = SVAL(req->vwv+3, 0);
902 tcon_flags = SVAL(req->vwv+2, 0);
903
904 /* we might have to close an old one */
905 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
906 struct smbXsrv_tcon *tcon;
907 NTSTATUS status;
908
909 tcon = conn->tcon;
910 req->conn = NULL;
911 conn = NULL;
912
913 /*
914 * TODO: cancel all outstanding requests on the tcon
915 */
916 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
917 if (!NT_STATUS_IS_OK(status)) {
918 DEBUG(0, ("reply_tcon_and_X: "
919 "smbXsrv_tcon_disconnect() failed: %s\n",
920 nt_errstr(status)));
921 /*
922 * If we hit this case, there is something completely
923 * wrong, so we better disconnect the transport connection.
924 */
925 END_PROFILE(SMBtconX);
926 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
927 return;
928 }
929
930 TALLOC_FREE(tcon);
931 /*
932 * This tree id is gone. Make sure we can't re-use it
933 * by accident.
934 */
935 req->tid = 0;
936 }
937
938 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
939 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
940 END_PROFILE(SMBtconX);
941 return;
942 }
943
944 if (xconn->smb1.negprot.encrypted_passwords) {
945 p = req->buf + passlen;
946 } else {
947 p = req->buf + passlen + 1;
948 }
949
950 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
951
952 if (path == NULL) {
953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
954 END_PROFILE(SMBtconX);
955 return;
956 }
957
958 /*
959 * the service name can be either: \\server\share
960 * or share directly like on the DELL PowerVault 705
961 */
962 if (*path=='\\') {
963 q = strchr_m(path+2,'\\');
964 if (!q) {
965 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
966 END_PROFILE(SMBtconX);
967 return;
968 }
969 service = q+1;
970 } else {
971 service = path;
972 }
973
974 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
975 &client_devicetype, p,
976 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
977
978 if (client_devicetype == NULL) {
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
980 END_PROFILE(SMBtconX);
981 return;
982 }
983
984 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
985
986 nt_status = smb1srv_session_lookup(xconn,
987 req->vuid, now, &session);
988 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
989 reply_force_doserror(req, ERRSRV, ERRbaduid);
990 END_PROFILE(SMBtconX);
991 return;
992 }
993 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
994 reply_nterror(req, nt_status);
995 END_PROFILE(SMBtconX);
996 return;
997 }
998 if (!NT_STATUS_IS_OK(nt_status)) {
999 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1000 END_PROFILE(SMBtconX);
1001 return;
1002 }
1003
1004 if (session->global->auth_session_info == NULL) {
1005 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1006 END_PROFILE(SMBtconX);
1007 return;
1008 }
1009
1010 /*
1011 * If there is no application key defined yet
1012 * we create one.
1013 *
1014 * This means we setup the application key on the
1015 * first tcon that happens via the given session.
1016 *
1017 * Once the application key is defined, it does not
1018 * change any more.
1019 */
1020 if (session->global->application_key.length == 0 &&
1021 smb2_signing_key_valid(session->global->signing_key))
1022 {
1023 struct smbXsrv_session *x = session;
1024 struct auth_session_info *session_info =
1025 session->global->auth_session_info;
1026 uint8_t session_key[16];
1027
1028 ZERO_STRUCT(session_key);
1029 memcpy(session_key, x->global->signing_key->blob.data,
1030 MIN(x->global->signing_key->blob.length, sizeof(session_key)));
1031
1032 /*
1033 * The application key is truncated/padded to 16 bytes
1034 */
1035 x->global->application_key = data_blob_talloc(x->global,
1036 session_key,
1037 sizeof(session_key));
1038 ZERO_STRUCT(session_key);
1039 if (x->global->application_key.data == NULL) {
1040 reply_nterror(req, NT_STATUS_NO_MEMORY);
1041 END_PROFILE(SMBtconX);
1042 return;
1043 }
1044
1045 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
1046 NTSTATUS status;
1047
1048 status = smb_key_derivation(x->global->application_key.data,
1049 x->global->application_key.length,
1050 x->global->application_key.data);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 DBG_ERR("smb_key_derivation failed: %s\n",
1053 nt_errstr(status));
1054 END_PROFILE(SMBtconX);
1055 return;
1056 }
1057 optional_support |= SMB_EXTENDED_SIGNATURES;
1058 }
1059
1060 /*
1061 * Place the application key into the session_info
1062 */
1063 data_blob_clear_free(&session_info->session_key);
1064 session_info->session_key = data_blob_dup_talloc(session_info,
1065 x->global->application_key);
1066 if (session_info->session_key.data == NULL) {
1067 data_blob_clear_free(&x->global->application_key);
1068 reply_nterror(req, NT_STATUS_NO_MEMORY);
1069 END_PROFILE(SMBtconX);
1070 return;
1071 }
1072 session_key_updated = true;
1073 }
1074
1075 conn = make_connection(req, now, service, client_devicetype,
1076 req->vuid, &nt_status);
1077 req->conn =conn;
1078
1079 if (!conn) {
1080 if (session_key_updated) {
1081 struct smbXsrv_session *x = session;
1082 struct auth_session_info *session_info =
1083 session->global->auth_session_info;
1084 data_blob_clear_free(&x->global->application_key);
1085 data_blob_clear_free(&session_info->session_key);
1086 }
1087 reply_nterror(req, nt_status);
1088 END_PROFILE(SMBtconX);
1089 return;
1090 }
1091
1092 if ( IS_IPC(conn) )
1093 server_devicetype = "IPC";
1094 else if ( IS_PRINT(conn) )
1095 server_devicetype = "LPT1:";
1096 else
1097 server_devicetype = "A:";
1098
1099 if (get_Protocol() < PROTOCOL_NT1) {
1100 reply_outbuf(req, 2, 0);
1101 if (message_push_string(&req->outbuf, server_devicetype,
1102 STR_TERMINATE|STR_ASCII) == -1) {
1103 reply_nterror(req, NT_STATUS_NO_MEMORY);
1104 END_PROFILE(SMBtconX);
1105 return;
1106 }
1107 } else {
1108 /* NT sets the fstype of IPC$ to the null string */
1109 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
1110
1111 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
1112 /* Return permissions. */
1113 uint32_t perm1 = 0;
1114 uint32_t perm2 = 0;
1115
1116 reply_outbuf(req, 7, 0);
1117
1118 if (IS_IPC(conn)) {
1119 perm1 = FILE_ALL_ACCESS;
1120 perm2 = FILE_ALL_ACCESS;
1121 } else {
1122 perm1 = conn->share_access;
1123 }
1124
1125 SIVAL(req->outbuf, smb_vwv3, perm1);
1126 SIVAL(req->outbuf, smb_vwv5, perm2);
1127 } else {
1128 reply_outbuf(req, 3, 0);
1129 }
1130
1131 if ((message_push_string(&req->outbuf, server_devicetype,
1132 STR_TERMINATE|STR_ASCII) == -1)
1133 || (message_push_string(&req->outbuf, fstype,
1134 STR_TERMINATE) == -1)) {
1135 reply_nterror(req, NT_STATUS_NO_MEMORY);
1136 END_PROFILE(SMBtconX);
1137 return;
1138 }
1139
1140 /* what does setting this bit do? It is set by NT4 and
1141 may affect the ability to autorun mounted cdroms */
1142 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1143 optional_support |=
1144 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1145
1146 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1147 DEBUG(2,("Serving %s as a Dfs root\n",
1148 lp_servicename(ctx, lp_sub, SNUM(conn)) ));
1149 optional_support |= SMB_SHARE_IN_DFS;
1150 }
1151
1152 SSVAL(req->outbuf, smb_vwv2, optional_support);
1153 }
1154
1155 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1156 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1157
1158 DEBUG(3,("tconX service=%s \n",
1159 service));
1160
1161 /* set the incoming and outgoing tid to the just created one */
1162 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1163 SSVAL(req->outbuf,smb_tid,conn->cnum);
1164
1165 END_PROFILE(SMBtconX);
1166
1167 req->tid = conn->cnum;
1168 }
1169
1170 /****************************************************************************
1171 Reply to an unknown type.
1172 ****************************************************************************/
1173
reply_unknown_new(struct smb_request * req,uint8_t type)1174 void reply_unknown_new(struct smb_request *req, uint8_t type)
1175 {
1176 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1177 smb_fn_name(type), type, type));
1178 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1179 return;
1180 }
1181
1182 /****************************************************************************
1183 Reply to an ioctl.
1184 conn POINTER CAN BE NULL HERE !
1185 ****************************************************************************/
1186
reply_ioctl(struct smb_request * req)1187 void reply_ioctl(struct smb_request *req)
1188 {
1189 const struct loadparm_substitution *lp_sub =
1190 loadparm_s3_global_substitution();
1191 connection_struct *conn = req->conn;
1192 uint16_t device;
1193 uint16_t function;
1194 uint32_t ioctl_code;
1195 int replysize;
1196 char *p;
1197
1198 START_PROFILE(SMBioctl);
1199
1200 if (req->wct < 3) {
1201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1202 END_PROFILE(SMBioctl);
1203 return;
1204 }
1205
1206 device = SVAL(req->vwv+1, 0);
1207 function = SVAL(req->vwv+2, 0);
1208 ioctl_code = (device << 16) + function;
1209
1210 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1211
1212 switch (ioctl_code) {
1213 case IOCTL_QUERY_JOB_INFO:
1214 replysize = 32;
1215 break;
1216 default:
1217 reply_force_doserror(req, ERRSRV, ERRnosupport);
1218 END_PROFILE(SMBioctl);
1219 return;
1220 }
1221
1222 reply_outbuf(req, 8, replysize+1);
1223 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1224 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1225 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1226 p = smb_buf(req->outbuf);
1227 memset(p, '\0', replysize+1); /* valgrind-safe. */
1228 p += 1; /* Allow for alignment */
1229
1230 switch (ioctl_code) {
1231 case IOCTL_QUERY_JOB_INFO:
1232 {
1233 NTSTATUS status;
1234 size_t len = 0;
1235 files_struct *fsp = file_fsp(
1236 req, SVAL(req->vwv+0, 0));
1237 if (!fsp) {
1238 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1239 END_PROFILE(SMBioctl);
1240 return;
1241 }
1242 /* Job number */
1243 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1244
1245 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1246 lp_netbios_name(), 15,
1247 STR_TERMINATE|STR_ASCII, &len);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 reply_nterror(req, status);
1250 END_PROFILE(SMBioctl);
1251 return;
1252 }
1253 if (conn) {
1254 status = srvstr_push((char *)req->outbuf, req->flags2,
1255 p+18,
1256 lp_servicename(talloc_tos(),
1257 lp_sub,
1258 SNUM(conn)),
1259 13, STR_TERMINATE|STR_ASCII, &len);
1260 if (!NT_STATUS_IS_OK(status)) {
1261 reply_nterror(req, status);
1262 END_PROFILE(SMBioctl);
1263 return;
1264 }
1265 } else {
1266 memset(p+18, 0, 13);
1267 }
1268 break;
1269 }
1270 }
1271
1272 END_PROFILE(SMBioctl);
1273 return;
1274 }
1275
1276 /****************************************************************************
1277 Strange checkpath NTSTATUS mapping.
1278 ****************************************************************************/
1279
map_checkpath_error(uint16_t flags2,NTSTATUS status)1280 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1281 {
1282 /* Strange DOS error code semantics only for checkpath... */
1283 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1284 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1285 /* We need to map to ERRbadpath */
1286 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1287 }
1288 }
1289 return status;
1290 }
1291
1292 /****************************************************************************
1293 Reply to a checkpath.
1294 ****************************************************************************/
1295
reply_checkpath(struct smb_request * req)1296 void reply_checkpath(struct smb_request *req)
1297 {
1298 connection_struct *conn = req->conn;
1299 struct smb_filename *smb_fname = NULL;
1300 char *name = NULL;
1301 NTSTATUS status;
1302 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1303 TALLOC_CTX *ctx = talloc_tos();
1304
1305 START_PROFILE(SMBcheckpath);
1306
1307 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1308 STR_TERMINATE, &status);
1309
1310 if (!NT_STATUS_IS_OK(status)) {
1311 status = map_checkpath_error(req->flags2, status);
1312 reply_nterror(req, status);
1313 END_PROFILE(SMBcheckpath);
1314 return;
1315 }
1316
1317 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1318
1319 status = filename_convert(ctx,
1320 conn,
1321 name,
1322 ucf_flags,
1323 NULL,
1324 NULL,
1325 &smb_fname);
1326
1327 if (!NT_STATUS_IS_OK(status)) {
1328 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1329 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1330 ERRSRV, ERRbadpath);
1331 END_PROFILE(SMBcheckpath);
1332 return;
1333 }
1334 goto path_err;
1335 }
1336
1337 if (!VALID_STAT(smb_fname->st) &&
1338 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1339 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1340 smb_fname_str_dbg(smb_fname), strerror(errno)));
1341 status = map_nt_error_from_unix(errno);
1342 goto path_err;
1343 }
1344
1345 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1346 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1347 ERRDOS, ERRbadpath);
1348 goto out;
1349 }
1350
1351 reply_outbuf(req, 0, 0);
1352
1353 path_err:
1354 /* We special case this - as when a Windows machine
1355 is parsing a path is steps through the components
1356 one at a time - if a component fails it expects
1357 ERRbadpath, not ERRbadfile.
1358 */
1359 status = map_checkpath_error(req->flags2, status);
1360 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1361 /*
1362 * Windows returns different error codes if
1363 * the parent directory is valid but not the
1364 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1365 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1366 * if the path is invalid.
1367 */
1368 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1369 ERRDOS, ERRbadpath);
1370 goto out;
1371 }
1372
1373 reply_nterror(req, status);
1374
1375 out:
1376 TALLOC_FREE(smb_fname);
1377 END_PROFILE(SMBcheckpath);
1378 return;
1379 }
1380
1381 /****************************************************************************
1382 Reply to a getatr.
1383 ****************************************************************************/
1384
reply_getatr(struct smb_request * req)1385 void reply_getatr(struct smb_request *req)
1386 {
1387 connection_struct *conn = req->conn;
1388 struct smb_filename *smb_fname = NULL;
1389 char *fname = NULL;
1390 int mode=0;
1391 off_t size=0;
1392 time_t mtime=0;
1393 const char *p;
1394 NTSTATUS status;
1395 TALLOC_CTX *ctx = talloc_tos();
1396 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1397
1398 START_PROFILE(SMBgetatr);
1399
1400 p = (const char *)req->buf + 1;
1401 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1402 if (!NT_STATUS_IS_OK(status)) {
1403 reply_nterror(req, status);
1404 goto out;
1405 }
1406
1407 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1408 under WfWg - weird! */
1409 if (*fname == '\0') {
1410 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1411 if (!CAN_WRITE(conn)) {
1412 mode |= FILE_ATTRIBUTE_READONLY;
1413 }
1414 size = 0;
1415 mtime = 0;
1416 } else {
1417 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1418 status = filename_convert(ctx,
1419 conn,
1420 fname,
1421 ucf_flags,
1422 NULL,
1423 NULL,
1424 &smb_fname);
1425 if (!NT_STATUS_IS_OK(status)) {
1426 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1427 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1428 ERRSRV, ERRbadpath);
1429 goto out;
1430 }
1431 reply_nterror(req, status);
1432 goto out;
1433 }
1434 if (!VALID_STAT(smb_fname->st) &&
1435 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1436 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1437 smb_fname_str_dbg(smb_fname),
1438 strerror(errno)));
1439 reply_nterror(req, map_nt_error_from_unix(errno));
1440 goto out;
1441 }
1442
1443 mode = dos_mode(conn, smb_fname);
1444 size = smb_fname->st.st_ex_size;
1445
1446 if (ask_sharemode) {
1447 struct timespec write_time_ts;
1448 struct file_id fileid;
1449
1450 ZERO_STRUCT(write_time_ts);
1451 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1452 get_file_infos(fileid, 0, NULL, &write_time_ts);
1453 if (!is_omit_timespec(&write_time_ts)) {
1454 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1455 }
1456 }
1457
1458 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1459 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1460 size = 0;
1461 }
1462 }
1463
1464 reply_outbuf(req, 10, 0);
1465
1466 SSVAL(req->outbuf,smb_vwv0,mode);
1467 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1468 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1469 } else {
1470 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1471 }
1472 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1473
1474 if (get_Protocol() >= PROTOCOL_NT1) {
1475 SSVAL(req->outbuf, smb_flg2,
1476 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1477 }
1478
1479 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1480 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1481
1482 out:
1483 TALLOC_FREE(smb_fname);
1484 TALLOC_FREE(fname);
1485 END_PROFILE(SMBgetatr);
1486 return;
1487 }
1488
1489 /****************************************************************************
1490 Reply to a setatr.
1491 ****************************************************************************/
1492
reply_setatr(struct smb_request * req)1493 void reply_setatr(struct smb_request *req)
1494 {
1495 struct smb_file_time ft;
1496 connection_struct *conn = req->conn;
1497 struct smb_filename *smb_fname = NULL;
1498 char *fname = NULL;
1499 int mode;
1500 time_t mtime;
1501 const char *p;
1502 NTSTATUS status;
1503 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1504 TALLOC_CTX *ctx = talloc_tos();
1505
1506 START_PROFILE(SMBsetatr);
1507 init_smb_file_time(&ft);
1508
1509 if (req->wct < 2) {
1510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1511 goto out;
1512 }
1513
1514 p = (const char *)req->buf + 1;
1515 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 reply_nterror(req, status);
1518 goto out;
1519 }
1520
1521 status = filename_convert(ctx,
1522 conn,
1523 fname,
1524 ucf_flags,
1525 NULL,
1526 NULL,
1527 &smb_fname);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1530 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1531 ERRSRV, ERRbadpath);
1532 goto out;
1533 }
1534 reply_nterror(req, status);
1535 goto out;
1536 }
1537
1538 if (ISDOT(smb_fname->base_name)) {
1539 /*
1540 * Not sure here is the right place to catch this
1541 * condition. Might be moved to somewhere else later -- vl
1542 */
1543 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1544 goto out;
1545 }
1546
1547 mode = SVAL(req->vwv+0, 0);
1548 mtime = srv_make_unix_date3(req->vwv+1);
1549
1550 if (mode != FILE_ATTRIBUTE_NORMAL) {
1551 if (VALID_STAT_OF_DIR(smb_fname->st))
1552 mode |= FILE_ATTRIBUTE_DIRECTORY;
1553 else
1554 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1555
1556 status = smbd_check_access_rights(
1557 conn, smb_fname, false, FILE_WRITE_ATTRIBUTES);
1558 if (!NT_STATUS_IS_OK(status)) {
1559 reply_nterror(req, status);
1560 goto out;
1561 }
1562
1563 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1564 false) != 0) {
1565 reply_nterror(req, map_nt_error_from_unix(errno));
1566 goto out;
1567 }
1568 }
1569
1570 ft.mtime = time_t_to_full_timespec(mtime);
1571
1572 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1573 if (!NT_STATUS_IS_OK(status)) {
1574 reply_nterror(req, status);
1575 goto out;
1576 }
1577
1578 reply_outbuf(req, 0, 0);
1579
1580 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1581 mode));
1582 out:
1583 TALLOC_FREE(smb_fname);
1584 END_PROFILE(SMBsetatr);
1585 return;
1586 }
1587
1588 /****************************************************************************
1589 Reply to a dskattr.
1590 ****************************************************************************/
1591
reply_dskattr(struct smb_request * req)1592 void reply_dskattr(struct smb_request *req)
1593 {
1594 connection_struct *conn = req->conn;
1595 uint64_t ret;
1596 uint64_t dfree,dsize,bsize;
1597 struct smb_filename smb_fname;
1598 START_PROFILE(SMBdskattr);
1599
1600 ZERO_STRUCT(smb_fname);
1601 smb_fname.base_name = discard_const_p(char, ".");
1602
1603 if (SMB_VFS_STAT(conn, &smb_fname) != 0) {
1604 reply_nterror(req, map_nt_error_from_unix(errno));
1605 DBG_WARNING("stat of . failed (%s)\n", strerror(errno));
1606 END_PROFILE(SMBdskattr);
1607 return;
1608 }
1609
1610 ret = get_dfree_info(conn, &smb_fname, &bsize, &dfree, &dsize);
1611 if (ret == (uint64_t)-1) {
1612 reply_nterror(req, map_nt_error_from_unix(errno));
1613 END_PROFILE(SMBdskattr);
1614 return;
1615 }
1616
1617 /*
1618 * Force max to fit in 16 bit fields.
1619 */
1620 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1621 dfree /= 2;
1622 dsize /= 2;
1623 bsize *= 2;
1624 if (bsize > (WORDMAX*512)) {
1625 bsize = (WORDMAX*512);
1626 if (dsize > WORDMAX)
1627 dsize = WORDMAX;
1628 if (dfree > WORDMAX)
1629 dfree = WORDMAX;
1630 break;
1631 }
1632 }
1633
1634 reply_outbuf(req, 5, 0);
1635
1636 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1637 double total_space, free_space;
1638 /* we need to scale this to a number that DOS6 can handle. We
1639 use floating point so we can handle large drives on systems
1640 that don't have 64 bit integers
1641
1642 we end up displaying a maximum of 2G to DOS systems
1643 */
1644 total_space = dsize * (double)bsize;
1645 free_space = dfree * (double)bsize;
1646
1647 dsize = (uint64_t)((total_space+63*512) / (64*512));
1648 dfree = (uint64_t)((free_space+63*512) / (64*512));
1649
1650 if (dsize > 0xFFFF) dsize = 0xFFFF;
1651 if (dfree > 0xFFFF) dfree = 0xFFFF;
1652
1653 SSVAL(req->outbuf,smb_vwv0,dsize);
1654 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1655 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1656 SSVAL(req->outbuf,smb_vwv3,dfree);
1657 } else {
1658 SSVAL(req->outbuf,smb_vwv0,dsize);
1659 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1660 SSVAL(req->outbuf,smb_vwv2,512);
1661 SSVAL(req->outbuf,smb_vwv3,dfree);
1662 }
1663
1664 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1665
1666 END_PROFILE(SMBdskattr);
1667 return;
1668 }
1669
1670 /*
1671 * Utility function to split the filename from the directory.
1672 */
split_fname_dir_mask(TALLOC_CTX * ctx,const char * fname_in,char ** fname_dir_out,char ** fname_mask_out)1673 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1674 char **fname_dir_out,
1675 char **fname_mask_out)
1676 {
1677 const char *p = NULL;
1678 char *fname_dir = NULL;
1679 char *fname_mask = NULL;
1680
1681 p = strrchr_m(fname_in, '/');
1682 if (!p) {
1683 fname_dir = talloc_strdup(ctx, ".");
1684 fname_mask = talloc_strdup(ctx, fname_in);
1685 } else {
1686 fname_dir = talloc_strndup(ctx, fname_in,
1687 PTR_DIFF(p, fname_in));
1688 fname_mask = talloc_strdup(ctx, p+1);
1689 }
1690
1691 if (!fname_dir || !fname_mask) {
1692 TALLOC_FREE(fname_dir);
1693 TALLOC_FREE(fname_mask);
1694 return NT_STATUS_NO_MEMORY;
1695 }
1696
1697 *fname_dir_out = fname_dir;
1698 *fname_mask_out = fname_mask;
1699 return NT_STATUS_OK;
1700 }
1701
1702 /****************************************************************************
1703 Make a dir struct.
1704 ****************************************************************************/
1705
make_dir_struct(TALLOC_CTX * ctx,char * buf,const char * mask,const char * fname,off_t size,uint32_t mode,time_t date,bool uc)1706 static bool make_dir_struct(TALLOC_CTX *ctx,
1707 char *buf,
1708 const char *mask,
1709 const char *fname,
1710 off_t size,
1711 uint32_t mode,
1712 time_t date,
1713 bool uc)
1714 {
1715 char *p;
1716 char *mask2 = talloc_strdup(ctx, mask);
1717
1718 if (!mask2) {
1719 return False;
1720 }
1721
1722 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1723 size = 0;
1724 }
1725
1726 memset(buf+1,' ',11);
1727 if ((p = strchr_m(mask2,'.')) != NULL) {
1728 *p = 0;
1729 push_ascii(buf+1,mask2,8, 0);
1730 push_ascii(buf+9,p+1,3, 0);
1731 *p = '.';
1732 } else {
1733 push_ascii(buf+1,mask2,11, 0);
1734 }
1735
1736 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1737 SCVAL(buf,21,mode);
1738 srv_put_dos_date(buf,22,date);
1739 SSVAL(buf,26,size & 0xFFFF);
1740 SSVAL(buf,28,(size >> 16)&0xFFFF);
1741 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1742 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1743 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1744 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1745 return True;
1746 }
1747
1748 /****************************************************************************
1749 Reply to a search.
1750 Can be called from SMBsearch, SMBffirst or SMBfunique.
1751 ****************************************************************************/
1752
reply_search(struct smb_request * req)1753 void reply_search(struct smb_request *req)
1754 {
1755 connection_struct *conn = req->conn;
1756 char *path = NULL;
1757 char *mask = NULL;
1758 char *directory = NULL;
1759 struct smb_filename *smb_fname = NULL;
1760 char *fname = NULL;
1761 off_t size;
1762 uint32_t mode;
1763 struct timespec date;
1764 uint32_t dirtype;
1765 unsigned int numentries = 0;
1766 unsigned int maxentries = 0;
1767 bool finished = False;
1768 const char *p;
1769 int status_len;
1770 char status[21];
1771 int dptr_num= -1;
1772 bool check_descend = False;
1773 bool expect_close = False;
1774 NTSTATUS nt_status;
1775 bool mask_contains_wcard = False;
1776 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1777 TALLOC_CTX *ctx = talloc_tos();
1778 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
1779 struct smbXsrv_connection *xconn = req->xconn;
1780 struct smbd_server_connection *sconn = req->sconn;
1781 files_struct *fsp = NULL;
1782 const struct loadparm_substitution *lp_sub =
1783 loadparm_s3_global_substitution();
1784
1785 START_PROFILE(SMBsearch);
1786
1787 if (req->wct < 2) {
1788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1789 goto out;
1790 }
1791
1792 if (req->posix_pathnames) {
1793 reply_unknown_new(req, req->cmd);
1794 goto out;
1795 }
1796
1797 /* If we were called as SMBffirst then we must expect close. */
1798 if(req->cmd == SMBffirst) {
1799 expect_close = True;
1800 }
1801
1802 reply_outbuf(req, 1, 3);
1803 maxentries = SVAL(req->vwv+0, 0);
1804 dirtype = SVAL(req->vwv+1, 0);
1805 p = (const char *)req->buf + 1;
1806 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1807 &nt_status, &mask_contains_wcard);
1808 if (!NT_STATUS_IS_OK(nt_status)) {
1809 reply_nterror(req, nt_status);
1810 goto out;
1811 }
1812
1813 if (smbreq_bufrem(req, p) < 3) {
1814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1815 goto out;
1816 }
1817
1818 p++;
1819 status_len = SVAL(p, 0);
1820 p += 2;
1821
1822 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1823
1824 if (status_len == 0) {
1825 int ret;
1826 struct smb_filename *smb_dname = NULL;
1827 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
1828 ucf_flags_from_smb_request(req);
1829 nt_status = filename_convert(ctx, conn,
1830 path,
1831 ucf_flags,
1832 NULL,
1833 &mask_contains_wcard,
1834 &smb_fname);
1835 if (!NT_STATUS_IS_OK(nt_status)) {
1836 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1837 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1838 ERRSRV, ERRbadpath);
1839 goto out;
1840 }
1841 reply_nterror(req, nt_status);
1842 goto out;
1843 }
1844
1845 directory = smb_fname->base_name;
1846
1847 p = strrchr_m(directory,'/');
1848 if ((p != NULL) && (*directory != '/')) {
1849 mask = talloc_strdup(ctx, p + 1);
1850 directory = talloc_strndup(ctx, directory,
1851 PTR_DIFF(p, directory));
1852 } else {
1853 mask = talloc_strdup(ctx, directory);
1854 directory = talloc_strdup(ctx,".");
1855 }
1856
1857 if (!directory) {
1858 reply_nterror(req, NT_STATUS_NO_MEMORY);
1859 goto out;
1860 }
1861
1862 memset((char *)status,'\0',21);
1863 SCVAL(status,0,(dirtype & 0x1F));
1864
1865 smb_dname = synthetic_smb_fname(talloc_tos(),
1866 directory,
1867 NULL,
1868 NULL,
1869 smb_fname->flags);
1870 if (smb_dname == NULL) {
1871 reply_nterror(req, NT_STATUS_NO_MEMORY);
1872 goto out;
1873 }
1874
1875 /*
1876 * As we've cut off the last component from
1877 * smb_fname we need to re-stat smb_dname
1878 * so FILE_OPEN disposition knows the directory
1879 * exists.
1880 */
1881 if (req->posix_pathnames) {
1882 ret = SMB_VFS_LSTAT(conn, smb_dname);
1883 } else {
1884 ret = SMB_VFS_STAT(conn, smb_dname);
1885 }
1886 if (ret == -1) {
1887 nt_status = map_nt_error_from_unix(errno);
1888 reply_nterror(req, nt_status);
1889 goto out;
1890 }
1891
1892 /*
1893 * Open an fsp on this directory for the dptr.
1894 */
1895 nt_status = SMB_VFS_CREATE_FILE(
1896 conn, /* conn */
1897 req, /* req */
1898 0, /* root_dir_fid */
1899 smb_dname, /* dname */
1900 FILE_LIST_DIRECTORY, /* access_mask */
1901 FILE_SHARE_READ|
1902 FILE_SHARE_WRITE, /* share_access */
1903 FILE_OPEN, /* create_disposition*/
1904 FILE_DIRECTORY_FILE, /* create_options */
1905 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
1906 NO_OPLOCK, /* oplock_request */
1907 NULL, /* lease */
1908 0, /* allocation_size */
1909 0, /* private_flags */
1910 NULL, /* sd */
1911 NULL, /* ea_list */
1912 &fsp, /* result */
1913 NULL, /* pinfo */
1914 NULL, /* in_context */
1915 NULL);/* out_context */
1916
1917 if (!NT_STATUS_IS_OK(nt_status)) {
1918 DBG_ERR("failed to open directory %s\n",
1919 smb_fname_str_dbg(smb_dname));
1920 reply_nterror(req, nt_status);
1921 goto out;
1922 }
1923
1924 nt_status = dptr_create(conn,
1925 NULL, /* req */
1926 fsp, /* fsp */
1927 True,
1928 expect_close,
1929 req->smbpid,
1930 mask,
1931 mask_contains_wcard,
1932 dirtype,
1933 &fsp->dptr);
1934
1935 TALLOC_FREE(smb_dname);
1936
1937 if (!NT_STATUS_IS_OK(nt_status)) {
1938 /*
1939 * Use NULL here for the first parameter (req)
1940 * as this is not a client visible handle so
1941 * can'tbe part of an SMB1 chain.
1942 */
1943 close_file(NULL, fsp, NORMAL_CLOSE);
1944 fsp = NULL;
1945 reply_nterror(req, nt_status);
1946 goto out;
1947 }
1948
1949 dptr_num = dptr_dnum(fsp->dptr);
1950
1951 } else {
1952 int status_dirtype;
1953 const char *dirpath;
1954
1955 if (smbreq_bufrem(req, p) < 21) {
1956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1957 goto out;
1958 }
1959
1960 memcpy(status,p,21);
1961 status_dirtype = CVAL(status,0) & 0x1F;
1962 if (status_dirtype != (dirtype & 0x1F)) {
1963 dirtype = status_dirtype;
1964 }
1965
1966 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
1967 if (fsp == NULL) {
1968 goto SearchEmpty;
1969 }
1970 dirpath = dptr_path(sconn, dptr_num);
1971 directory = talloc_strdup(ctx, dirpath);
1972 if (!directory) {
1973 reply_nterror(req, NT_STATUS_NO_MEMORY);
1974 goto out;
1975 }
1976
1977 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1978 if (!mask) {
1979 goto SearchEmpty;
1980 }
1981 /*
1982 * For a 'continue' search we have no string. So
1983 * check from the initial saved string.
1984 */
1985 if (!req->posix_pathnames) {
1986 mask_contains_wcard = ms_has_wild(mask);
1987 }
1988 dirtype = dptr_attr(sconn, dptr_num);
1989 }
1990
1991 DEBUG(4,("dptr_num is %d\n",dptr_num));
1992
1993 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1994 char buf[DIR_STRUCT_SIZE];
1995 memcpy(buf,status,21);
1996 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1997 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1998 reply_nterror(req, NT_STATUS_NO_MEMORY);
1999 goto out;
2000 }
2001 dptr_fill(sconn, buf+12,dptr_num);
2002 if (dptr_zero(buf+12) && (status_len==0)) {
2003 numentries = 1;
2004 } else {
2005 numentries = 0;
2006 }
2007 if (message_push_blob(&req->outbuf,
2008 data_blob_const(buf, sizeof(buf)))
2009 == -1) {
2010 reply_nterror(req, NT_STATUS_NO_MEMORY);
2011 goto out;
2012 }
2013 } else {
2014 unsigned int i;
2015 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
2016 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
2017
2018 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
2019
2020 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2021 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
2022 if (in_list(directory, lp_dont_descend(ctx, lp_sub, SNUM(conn)),True)) {
2023 check_descend = True;
2024 }
2025
2026 for (i=numentries;(i<maxentries) && !finished;i++) {
2027 finished = !get_dir_entry(ctx,
2028 fsp->dptr,
2029 mask,
2030 dirtype,
2031 &fname,
2032 &size,
2033 &mode,
2034 &date,
2035 check_descend,
2036 ask_sharemode);
2037 if (!finished) {
2038 char buf[DIR_STRUCT_SIZE];
2039 memcpy(buf,status,21);
2040 if (!make_dir_struct(ctx,
2041 buf,
2042 mask,
2043 fname,
2044 size,
2045 mode,
2046 convert_timespec_to_time_t(date),
2047 !allow_long_path_components)) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2049 goto out;
2050 }
2051 if (!dptr_fill(sconn, buf+12,dptr_num)) {
2052 break;
2053 }
2054 if (message_push_blob(&req->outbuf,
2055 data_blob_const(buf, sizeof(buf)))
2056 == -1) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2058 goto out;
2059 }
2060 numentries++;
2061 }
2062 }
2063 }
2064
2065 SearchEmpty:
2066
2067 /* If we were called as SMBffirst with smb_search_id == NULL
2068 and no entries were found then return error and close fsp->dptr
2069 (X/Open spec) */
2070
2071 if (numentries == 0) {
2072 dptr_num = -1;
2073 if (fsp != NULL) {
2074 close_file(NULL, fsp, NORMAL_CLOSE);
2075 fsp = NULL;
2076 }
2077 } else if(expect_close && status_len == 0) {
2078 /* Close the dptr - we know it's gone */
2079 dptr_num = -1;
2080 if (fsp != NULL) {
2081 close_file(NULL, fsp, NORMAL_CLOSE);
2082 fsp = NULL;
2083 }
2084 }
2085
2086 /* If we were called as SMBfunique, then we can close the fsp->dptr now ! */
2087 if(dptr_num >= 0 && req->cmd == SMBfunique) {
2088 dptr_num = -1;
2089 /* fsp may have been closed above. */
2090 if (fsp != NULL) {
2091 close_file(NULL, fsp, NORMAL_CLOSE);
2092 fsp = NULL;
2093 }
2094 }
2095
2096 if ((numentries == 0) && !mask_contains_wcard) {
2097 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
2098 goto out;
2099 }
2100
2101 SSVAL(req->outbuf,smb_vwv0,numentries);
2102 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
2103 SCVAL(smb_buf(req->outbuf),0,5);
2104 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
2105
2106 /* The replies here are never long name. */
2107 SSVAL(req->outbuf, smb_flg2,
2108 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
2109 if (!allow_long_path_components) {
2110 SSVAL(req->outbuf, smb_flg2,
2111 SVAL(req->outbuf, smb_flg2)
2112 & (~FLAGS2_LONG_PATH_COMPONENTS));
2113 }
2114
2115 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
2116 SSVAL(req->outbuf, smb_flg2,
2117 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
2118
2119 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
2120 smb_fn_name(req->cmd),
2121 mask,
2122 directory,
2123 dirtype,
2124 numentries,
2125 maxentries ));
2126 out:
2127 TALLOC_FREE(directory);
2128 TALLOC_FREE(mask);
2129 TALLOC_FREE(smb_fname);
2130 END_PROFILE(SMBsearch);
2131 return;
2132 }
2133
2134 /****************************************************************************
2135 Reply to a fclose (stop directory search).
2136 ****************************************************************************/
2137
reply_fclose(struct smb_request * req)2138 void reply_fclose(struct smb_request *req)
2139 {
2140 int status_len;
2141 char status[21];
2142 int dptr_num= -2;
2143 const char *p;
2144 char *path = NULL;
2145 NTSTATUS err;
2146 bool path_contains_wcard = False;
2147 TALLOC_CTX *ctx = talloc_tos();
2148 struct smbd_server_connection *sconn = req->sconn;
2149 files_struct *fsp = NULL;
2150
2151 START_PROFILE(SMBfclose);
2152
2153 if (req->posix_pathnames) {
2154 reply_unknown_new(req, req->cmd);
2155 END_PROFILE(SMBfclose);
2156 return;
2157 }
2158
2159 p = (const char *)req->buf + 1;
2160 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
2161 &err, &path_contains_wcard);
2162 if (!NT_STATUS_IS_OK(err)) {
2163 reply_nterror(req, err);
2164 END_PROFILE(SMBfclose);
2165 return;
2166 }
2167
2168 if (smbreq_bufrem(req, p) < 3) {
2169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2170 END_PROFILE(SMBfclose);
2171 return;
2172 }
2173
2174 p++;
2175 status_len = SVAL(p,0);
2176 p += 2;
2177
2178 if (status_len == 0) {
2179 reply_force_doserror(req, ERRSRV, ERRsrverror);
2180 END_PROFILE(SMBfclose);
2181 return;
2182 }
2183
2184 if (smbreq_bufrem(req, p) < 21) {
2185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2186 END_PROFILE(SMBfclose);
2187 return;
2188 }
2189
2190 memcpy(status,p,21);
2191
2192 fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num);
2193 if(fsp != NULL) {
2194 /* Close the file - we know it's gone */
2195 close_file(NULL, fsp, NORMAL_CLOSE);
2196 fsp = NULL;
2197 dptr_num = -1;
2198 }
2199
2200 reply_outbuf(req, 1, 0);
2201 SSVAL(req->outbuf,smb_vwv0,0);
2202
2203 DEBUG(3,("search close\n"));
2204
2205 END_PROFILE(SMBfclose);
2206 return;
2207 }
2208
2209 /****************************************************************************
2210 Reply to an open.
2211 ****************************************************************************/
2212
reply_open(struct smb_request * req)2213 void reply_open(struct smb_request *req)
2214 {
2215 connection_struct *conn = req->conn;
2216 struct smb_filename *smb_fname = NULL;
2217 char *fname = NULL;
2218 uint32_t fattr=0;
2219 off_t size = 0;
2220 time_t mtime=0;
2221 int info;
2222 files_struct *fsp;
2223 int oplock_request;
2224 int deny_mode;
2225 uint32_t dos_attr;
2226 uint32_t access_mask;
2227 uint32_t share_mode;
2228 uint32_t create_disposition;
2229 uint32_t create_options = 0;
2230 uint32_t private_flags = 0;
2231 NTSTATUS status;
2232 uint32_t ucf_flags;
2233 TALLOC_CTX *ctx = talloc_tos();
2234
2235 START_PROFILE(SMBopen);
2236
2237 if (req->wct < 2) {
2238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2239 goto out;
2240 }
2241
2242 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2243 deny_mode = SVAL(req->vwv+0, 0);
2244 dos_attr = SVAL(req->vwv+1, 0);
2245
2246 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2247 STR_TERMINATE, &status);
2248 if (!NT_STATUS_IS_OK(status)) {
2249 reply_nterror(req, status);
2250 goto out;
2251 }
2252
2253 if (!map_open_params_to_ntcreate(fname, deny_mode,
2254 OPENX_FILE_EXISTS_OPEN, &access_mask,
2255 &share_mode, &create_disposition,
2256 &create_options, &private_flags)) {
2257 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2258 goto out;
2259 }
2260
2261 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2262
2263 status = filename_convert(ctx,
2264 conn,
2265 fname,
2266 ucf_flags,
2267 NULL,
2268 NULL,
2269 &smb_fname);
2270 if (!NT_STATUS_IS_OK(status)) {
2271 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2272 reply_botherror(req,
2273 NT_STATUS_PATH_NOT_COVERED,
2274 ERRSRV, ERRbadpath);
2275 goto out;
2276 }
2277 reply_nterror(req, status);
2278 goto out;
2279 }
2280
2281 status = SMB_VFS_CREATE_FILE(
2282 conn, /* conn */
2283 req, /* req */
2284 0, /* root_dir_fid */
2285 smb_fname, /* fname */
2286 access_mask, /* access_mask */
2287 share_mode, /* share_access */
2288 create_disposition, /* create_disposition*/
2289 create_options, /* create_options */
2290 dos_attr, /* file_attributes */
2291 oplock_request, /* oplock_request */
2292 NULL, /* lease */
2293 0, /* allocation_size */
2294 private_flags,
2295 NULL, /* sd */
2296 NULL, /* ea_list */
2297 &fsp, /* result */
2298 &info, /* pinfo */
2299 NULL, NULL); /* create context */
2300
2301 if (!NT_STATUS_IS_OK(status)) {
2302 if (open_was_deferred(req->xconn, req->mid)) {
2303 /* We have re-scheduled this call. */
2304 goto out;
2305 }
2306
2307 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2308 reply_openerror(req, status);
2309 goto out;
2310 }
2311
2312 fsp = fcb_or_dos_open(
2313 req,
2314 smb_fname,
2315 access_mask,
2316 create_options,
2317 private_flags);
2318 if (fsp == NULL) {
2319 bool ok = defer_smb1_sharing_violation(req);
2320 if (ok) {
2321 goto out;
2322 }
2323 reply_openerror(req, status);
2324 goto out;
2325 }
2326 }
2327
2328 /* Ensure we're pointing at the correct stat struct. */
2329 TALLOC_FREE(smb_fname);
2330 smb_fname = fsp->fsp_name;
2331
2332 size = smb_fname->st.st_ex_size;
2333 fattr = dos_mode(conn, smb_fname);
2334
2335 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2336
2337 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2338 DEBUG(3,("attempt to open a directory %s\n",
2339 fsp_str_dbg(fsp)));
2340 close_file(req, fsp, ERROR_CLOSE);
2341 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2342 ERRDOS, ERRnoaccess);
2343 goto out;
2344 }
2345
2346 reply_outbuf(req, 7, 0);
2347 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2348 SSVAL(req->outbuf,smb_vwv1,fattr);
2349 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2350 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2351 } else {
2352 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2353 }
2354 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2355 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2356
2357 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2358 SCVAL(req->outbuf,smb_flg,
2359 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2360 }
2361
2362 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2363 SCVAL(req->outbuf,smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2365 }
2366 out:
2367 END_PROFILE(SMBopen);
2368 return;
2369 }
2370
2371 /****************************************************************************
2372 Reply to an open and X.
2373 ****************************************************************************/
2374
reply_open_and_X(struct smb_request * req)2375 void reply_open_and_X(struct smb_request *req)
2376 {
2377 connection_struct *conn = req->conn;
2378 struct smb_filename *smb_fname = NULL;
2379 char *fname = NULL;
2380 uint16_t open_flags;
2381 int deny_mode;
2382 uint32_t smb_attr;
2383 /* Breakout the oplock request bits so we can set the
2384 reply bits separately. */
2385 int ex_oplock_request;
2386 int core_oplock_request;
2387 int oplock_request;
2388 #if 0
2389 int smb_sattr = SVAL(req->vwv+4, 0);
2390 uint32_t smb_time = make_unix_date3(req->vwv+6);
2391 #endif
2392 int smb_ofun;
2393 uint32_t fattr=0;
2394 int mtime=0;
2395 int smb_action = 0;
2396 files_struct *fsp;
2397 NTSTATUS status;
2398 uint64_t allocation_size;
2399 ssize_t retval = -1;
2400 uint32_t access_mask;
2401 uint32_t share_mode;
2402 uint32_t create_disposition;
2403 uint32_t create_options = 0;
2404 uint32_t private_flags = 0;
2405 uint32_t ucf_flags;
2406 TALLOC_CTX *ctx = talloc_tos();
2407
2408 START_PROFILE(SMBopenX);
2409
2410 if (req->wct < 15) {
2411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2412 goto out;
2413 }
2414
2415 open_flags = SVAL(req->vwv+2, 0);
2416 deny_mode = SVAL(req->vwv+3, 0);
2417 smb_attr = SVAL(req->vwv+5, 0);
2418 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2419 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2420 oplock_request = ex_oplock_request | core_oplock_request;
2421 smb_ofun = SVAL(req->vwv+8, 0);
2422 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2423
2424 /* If it's an IPC, pass off the pipe handler. */
2425 if (IS_IPC(conn)) {
2426 if (lp_nt_pipe_support()) {
2427 reply_open_pipe_and_X(conn, req);
2428 } else {
2429 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2430 }
2431 goto out;
2432 }
2433
2434 /* XXXX we need to handle passed times, sattr and flags */
2435 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2436 STR_TERMINATE, &status);
2437 if (!NT_STATUS_IS_OK(status)) {
2438 reply_nterror(req, status);
2439 goto out;
2440 }
2441
2442 if (!map_open_params_to_ntcreate(fname, deny_mode,
2443 smb_ofun,
2444 &access_mask, &share_mode,
2445 &create_disposition,
2446 &create_options,
2447 &private_flags)) {
2448 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2449 goto out;
2450 }
2451
2452 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2453
2454 status = filename_convert(ctx,
2455 conn,
2456 fname,
2457 ucf_flags,
2458 NULL,
2459 NULL,
2460 &smb_fname);
2461 if (!NT_STATUS_IS_OK(status)) {
2462 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2463 reply_botherror(req,
2464 NT_STATUS_PATH_NOT_COVERED,
2465 ERRSRV, ERRbadpath);
2466 goto out;
2467 }
2468 reply_nterror(req, status);
2469 goto out;
2470 }
2471
2472 status = SMB_VFS_CREATE_FILE(
2473 conn, /* conn */
2474 req, /* req */
2475 0, /* root_dir_fid */
2476 smb_fname, /* fname */
2477 access_mask, /* access_mask */
2478 share_mode, /* share_access */
2479 create_disposition, /* create_disposition*/
2480 create_options, /* create_options */
2481 smb_attr, /* file_attributes */
2482 oplock_request, /* oplock_request */
2483 NULL, /* lease */
2484 0, /* allocation_size */
2485 private_flags,
2486 NULL, /* sd */
2487 NULL, /* ea_list */
2488 &fsp, /* result */
2489 &smb_action, /* pinfo */
2490 NULL, NULL); /* create context */
2491
2492 if (!NT_STATUS_IS_OK(status)) {
2493 if (open_was_deferred(req->xconn, req->mid)) {
2494 /* We have re-scheduled this call. */
2495 goto out;
2496 }
2497
2498 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2499 reply_openerror(req, status);
2500 goto out;
2501 }
2502
2503 fsp = fcb_or_dos_open(
2504 req,
2505 smb_fname,
2506 access_mask,
2507 create_options,
2508 private_flags);
2509 if (fsp == NULL) {
2510 bool ok = defer_smb1_sharing_violation(req);
2511 if (ok) {
2512 goto out;
2513 }
2514 reply_openerror(req, status);
2515 goto out;
2516 }
2517
2518
2519 smb_action = FILE_WAS_OPENED;
2520 }
2521
2522 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2523 if the file is truncated or created. */
2524 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2525 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2526 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2527 close_file(req, fsp, ERROR_CLOSE);
2528 reply_nterror(req, NT_STATUS_DISK_FULL);
2529 goto out;
2530 }
2531 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2532 if (retval < 0) {
2533 close_file(req, fsp, ERROR_CLOSE);
2534 reply_nterror(req, NT_STATUS_DISK_FULL);
2535 goto out;
2536 }
2537 status = vfs_stat_fsp(fsp);
2538 if (!NT_STATUS_IS_OK(status)) {
2539 close_file(req, fsp, ERROR_CLOSE);
2540 reply_nterror(req, status);
2541 goto out;
2542 }
2543 }
2544
2545 fattr = dos_mode(conn, fsp->fsp_name);
2546 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2547 close_file(req, fsp, ERROR_CLOSE);
2548 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2549 goto out;
2550 }
2551 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2552
2553 /* If the caller set the extended oplock request bit
2554 and we granted one (by whatever means) - set the
2555 correct bit for extended oplock reply.
2556 */
2557
2558 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2559 smb_action |= EXTENDED_OPLOCK_GRANTED;
2560 }
2561
2562 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2563 smb_action |= EXTENDED_OPLOCK_GRANTED;
2564 }
2565
2566 /* If the caller set the core oplock request bit
2567 and we granted one (by whatever means) - set the
2568 correct bit for core oplock reply.
2569 */
2570
2571 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2572 reply_outbuf(req, 19, 0);
2573 } else {
2574 reply_outbuf(req, 15, 0);
2575 }
2576
2577 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2578 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2579
2580 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2581 SCVAL(req->outbuf, smb_flg,
2582 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2583 }
2584
2585 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2586 SCVAL(req->outbuf, smb_flg,
2587 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2588 }
2589
2590 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2591 SSVAL(req->outbuf,smb_vwv3,fattr);
2592 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2593 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2594 } else {
2595 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2596 }
2597 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2598 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2599 SSVAL(req->outbuf,smb_vwv11,smb_action);
2600
2601 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2602 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2603 }
2604
2605 out:
2606 TALLOC_FREE(smb_fname);
2607 END_PROFILE(SMBopenX);
2608 return;
2609 }
2610
2611 /****************************************************************************
2612 Reply to a SMBulogoffX.
2613 ****************************************************************************/
2614
2615 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2616 struct smbXsrv_session *session);
2617 static void reply_ulogoffX_done(struct tevent_req *req);
2618
reply_ulogoffX(struct smb_request * smb1req)2619 void reply_ulogoffX(struct smb_request *smb1req)
2620 {
2621 struct timeval now = timeval_current();
2622 struct smbXsrv_session *session = NULL;
2623 struct tevent_req *req;
2624 NTSTATUS status;
2625
2626 /*
2627 * Don't setup the profile charge here, take
2628 * it in reply_ulogoffX_done(). Not strictly correct
2629 * but better than the other SMB1 async
2630 * code that double-charges at the moment.
2631 */
2632
2633 status = smb1srv_session_lookup(smb1req->xconn,
2634 smb1req->vuid,
2635 timeval_to_nttime(&now),
2636 &session);
2637 if (!NT_STATUS_IS_OK(status)) {
2638 /* Not going async, profile here. */
2639 START_PROFILE(SMBulogoffX);
2640 DBG_WARNING("ulogoff, vuser id %llu does not map to user.\n",
2641 (unsigned long long)smb1req->vuid);
2642
2643 smb1req->vuid = UID_FIELD_INVALID;
2644 reply_force_doserror(smb1req, ERRSRV, ERRbaduid);
2645 END_PROFILE(SMBulogoffX);
2646 return;
2647 }
2648
2649 req = reply_ulogoffX_send(smb1req, session);
2650 if (req == NULL) {
2651 /* Not going async, profile here. */
2652 START_PROFILE(SMBulogoffX);
2653 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
2654 END_PROFILE(SMBulogoffX);
2655 return;
2656 }
2657
2658 /* We're async. This will complete later. */
2659 tevent_req_set_callback(req, reply_ulogoffX_done, smb1req);
2660 return;
2661 }
2662
2663 struct reply_ulogoffX_state {
2664 struct tevent_queue *wait_queue;
2665 struct smbXsrv_session *session;
2666 };
2667
2668 static void reply_ulogoffX_wait_done(struct tevent_req *subreq);
2669
2670 /****************************************************************************
2671 Async SMB1 ulogoffX.
2672 Note, on failure here we deallocate and return NULL to allow the caller to
2673 SMB1 return an error of ERRnomem immediately.
2674 ****************************************************************************/
2675
reply_ulogoffX_send(struct smb_request * smb1req,struct smbXsrv_session * session)2676 static struct tevent_req *reply_ulogoffX_send(struct smb_request *smb1req,
2677 struct smbXsrv_session *session)
2678 {
2679 struct tevent_req *req;
2680 struct reply_ulogoffX_state *state;
2681 struct tevent_req *subreq;
2682 files_struct *fsp;
2683 struct smbd_server_connection *sconn = session->client->sconn;
2684 uint64_t vuid = session->global->session_wire_id;
2685
2686 req = tevent_req_create(smb1req, &state,
2687 struct reply_ulogoffX_state);
2688 if (req == NULL) {
2689 return NULL;
2690 }
2691 state->wait_queue = tevent_queue_create(state,
2692 "reply_ulogoffX_wait_queue");
2693 if (tevent_req_nomem(state->wait_queue, req)) {
2694 TALLOC_FREE(req);
2695 return NULL;
2696 }
2697 state->session = session;
2698
2699 /*
2700 * Make sure that no new request will be able to use this session.
2701 * This ensures that once all outstanding fsp->aio_requests
2702 * on this session are done, we are safe to close it.
2703 */
2704 session->status = NT_STATUS_USER_SESSION_DELETED;
2705
2706 for (fsp = sconn->files; fsp; fsp = fsp->next) {
2707 if (fsp->vuid != vuid) {
2708 continue;
2709 }
2710 /*
2711 * Flag the file as close in progress.
2712 * This will prevent any more IO being
2713 * done on it.
2714 */
2715 fsp->closing = true;
2716
2717 if (fsp->num_aio_requests > 0) {
2718 /*
2719 * Now wait until all aio requests on this fsp are
2720 * finished.
2721 *
2722 * We don't set a callback, as we just want to block the
2723 * wait queue and the talloc_free() of fsp->aio_request
2724 * will remove the item from the wait queue.
2725 */
2726 subreq = tevent_queue_wait_send(fsp->aio_requests,
2727 sconn->ev_ctx,
2728 state->wait_queue);
2729 if (tevent_req_nomem(subreq, req)) {
2730 TALLOC_FREE(req);
2731 return NULL;
2732 }
2733 }
2734 }
2735
2736 /*
2737 * Now we add our own waiter to the end of the queue,
2738 * this way we get notified when all pending requests are finished
2739 * and reply to the outstanding SMB1 request.
2740 */
2741 subreq = tevent_queue_wait_send(state,
2742 sconn->ev_ctx,
2743 state->wait_queue);
2744 if (tevent_req_nomem(subreq, req)) {
2745 TALLOC_FREE(req);
2746 return NULL;
2747 }
2748
2749 /*
2750 * We're really going async - move the SMB1 request from
2751 * a talloc stackframe above us to the sconn talloc-context.
2752 * We need this to stick around until the wait_done
2753 * callback is invoked.
2754 */
2755 smb1req = talloc_move(sconn, &smb1req);
2756
2757 tevent_req_set_callback(subreq, reply_ulogoffX_wait_done, req);
2758
2759 return req;
2760 }
2761
reply_ulogoffX_wait_done(struct tevent_req * subreq)2762 static void reply_ulogoffX_wait_done(struct tevent_req *subreq)
2763 {
2764 struct tevent_req *req = tevent_req_callback_data(
2765 subreq, struct tevent_req);
2766
2767 tevent_queue_wait_recv(subreq);
2768 TALLOC_FREE(subreq);
2769 tevent_req_done(req);
2770 }
2771
reply_ulogoffX_recv(struct tevent_req * req)2772 static NTSTATUS reply_ulogoffX_recv(struct tevent_req *req)
2773 {
2774 return tevent_req_simple_recv_ntstatus(req);
2775 }
2776
reply_ulogoffX_done(struct tevent_req * req)2777 static void reply_ulogoffX_done(struct tevent_req *req)
2778 {
2779 struct smb_request *smb1req = tevent_req_callback_data(
2780 req, struct smb_request);
2781 struct reply_ulogoffX_state *state = tevent_req_data(req,
2782 struct reply_ulogoffX_state);
2783 struct smbXsrv_session *session = state->session;
2784 NTSTATUS status;
2785
2786 /*
2787 * Take the profile charge here. Not strictly
2788 * correct but better than the other SMB1 async
2789 * code that double-charges at the moment.
2790 */
2791 START_PROFILE(SMBulogoffX);
2792
2793 status = reply_ulogoffX_recv(req);
2794 TALLOC_FREE(req);
2795 if (!NT_STATUS_IS_OK(status)) {
2796 TALLOC_FREE(smb1req);
2797 END_PROFILE(SMBulogoffX);
2798 exit_server(__location__ ": reply_ulogoffX_recv failed");
2799 return;
2800 }
2801
2802 status = smbXsrv_session_logoff(session);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 TALLOC_FREE(smb1req);
2805 END_PROFILE(SMBulogoffX);
2806 exit_server(__location__ ": smbXsrv_session_logoff failed");
2807 return;
2808 }
2809
2810 TALLOC_FREE(session);
2811
2812 reply_outbuf(smb1req, 2, 0);
2813 SSVAL(smb1req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2814 SSVAL(smb1req->outbuf, smb_vwv1, 0); /* no andx offset */
2815
2816 DBG_NOTICE("ulogoffX vuid=%llu\n",
2817 (unsigned long long)smb1req->vuid);
2818
2819 smb1req->vuid = UID_FIELD_INVALID;
2820 /*
2821 * The following call is needed to push the
2822 * reply data back out the socket after async
2823 * return. Plus it frees smb1req.
2824 */
2825 smb_request_done(smb1req);
2826 END_PROFILE(SMBulogoffX);
2827 }
2828
2829 /****************************************************************************
2830 Reply to a mknew or a create.
2831 ****************************************************************************/
2832
reply_mknew(struct smb_request * req)2833 void reply_mknew(struct smb_request *req)
2834 {
2835 connection_struct *conn = req->conn;
2836 struct smb_filename *smb_fname = NULL;
2837 char *fname = NULL;
2838 uint32_t fattr = 0;
2839 struct smb_file_time ft;
2840 files_struct *fsp;
2841 int oplock_request = 0;
2842 NTSTATUS status;
2843 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2844 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2845 uint32_t create_disposition;
2846 uint32_t create_options = 0;
2847 uint32_t ucf_flags;
2848 TALLOC_CTX *ctx = talloc_tos();
2849
2850 START_PROFILE(SMBcreate);
2851 init_smb_file_time(&ft);
2852
2853 if (req->wct < 3) {
2854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2855 goto out;
2856 }
2857
2858 fattr = SVAL(req->vwv+0, 0);
2859 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2860
2861 if (req->cmd == SMBmknew) {
2862 /* We should fail if file exists. */
2863 create_disposition = FILE_CREATE;
2864 } else {
2865 /* Create if file doesn't exist, truncate if it does. */
2866 create_disposition = FILE_OVERWRITE_IF;
2867 }
2868
2869 /* mtime. */
2870 ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
2871
2872 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2873 STR_TERMINATE, &status);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 reply_nterror(req, status);
2876 goto out;
2877 }
2878
2879 ucf_flags = filename_create_ucf_flags(req, create_disposition);
2880 status = filename_convert(ctx,
2881 conn,
2882 fname,
2883 ucf_flags,
2884 NULL,
2885 NULL,
2886 &smb_fname);
2887 if (!NT_STATUS_IS_OK(status)) {
2888 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2889 reply_botherror(req,
2890 NT_STATUS_PATH_NOT_COVERED,
2891 ERRSRV, ERRbadpath);
2892 goto out;
2893 }
2894 reply_nterror(req, status);
2895 goto out;
2896 }
2897
2898 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2899 DEBUG(0,("Attempt to create file (%s) with volid set - "
2900 "please report this\n",
2901 smb_fname_str_dbg(smb_fname)));
2902 }
2903
2904 status = SMB_VFS_CREATE_FILE(
2905 conn, /* conn */
2906 req, /* req */
2907 0, /* root_dir_fid */
2908 smb_fname, /* fname */
2909 access_mask, /* access_mask */
2910 share_mode, /* share_access */
2911 create_disposition, /* create_disposition*/
2912 create_options, /* create_options */
2913 fattr, /* file_attributes */
2914 oplock_request, /* oplock_request */
2915 NULL, /* lease */
2916 0, /* allocation_size */
2917 0, /* private_flags */
2918 NULL, /* sd */
2919 NULL, /* ea_list */
2920 &fsp, /* result */
2921 NULL, /* pinfo */
2922 NULL, NULL); /* create context */
2923
2924 if (!NT_STATUS_IS_OK(status)) {
2925 if (open_was_deferred(req->xconn, req->mid)) {
2926 /* We have re-scheduled this call. */
2927 goto out;
2928 }
2929 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
2930 bool ok = defer_smb1_sharing_violation(req);
2931 if (ok) {
2932 goto out;
2933 }
2934 }
2935 reply_openerror(req, status);
2936 goto out;
2937 }
2938
2939 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2940 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2941 if (!NT_STATUS_IS_OK(status)) {
2942 END_PROFILE(SMBcreate);
2943 goto out;
2944 }
2945
2946 reply_outbuf(req, 1, 0);
2947 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2948
2949 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2950 SCVAL(req->outbuf,smb_flg,
2951 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2952 }
2953
2954 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2955 SCVAL(req->outbuf,smb_flg,
2956 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2957 }
2958
2959 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2960 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2961 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2962 (unsigned int)fattr));
2963
2964 out:
2965 TALLOC_FREE(smb_fname);
2966 END_PROFILE(SMBcreate);
2967 return;
2968 }
2969
2970 /****************************************************************************
2971 Reply to a create temporary file.
2972 ****************************************************************************/
2973
reply_ctemp(struct smb_request * req)2974 void reply_ctemp(struct smb_request *req)
2975 {
2976 connection_struct *conn = req->conn;
2977 struct smb_filename *smb_fname = NULL;
2978 char *wire_name = NULL;
2979 char *fname = NULL;
2980 uint32_t fattr;
2981 files_struct *fsp;
2982 int oplock_request;
2983 char *s;
2984 NTSTATUS status;
2985 int i;
2986 uint32_t ucf_flags;
2987 TALLOC_CTX *ctx = talloc_tos();
2988
2989 START_PROFILE(SMBctemp);
2990
2991 if (req->wct < 3) {
2992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2993 goto out;
2994 }
2995
2996 fattr = SVAL(req->vwv+0, 0);
2997 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2998
2999 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
3000 STR_TERMINATE, &status);
3001 if (!NT_STATUS_IS_OK(status)) {
3002 reply_nterror(req, status);
3003 goto out;
3004 }
3005
3006 for (i = 0; i < 10; i++) {
3007 if (*wire_name) {
3008 fname = talloc_asprintf(ctx,
3009 "%s/TMP%s",
3010 wire_name,
3011 generate_random_str_list(ctx, 5, "0123456789"));
3012 } else {
3013 fname = talloc_asprintf(ctx,
3014 "TMP%s",
3015 generate_random_str_list(ctx, 5, "0123456789"));
3016 }
3017
3018 if (!fname) {
3019 reply_nterror(req, NT_STATUS_NO_MEMORY);
3020 goto out;
3021 }
3022
3023 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
3024 status = filename_convert(ctx, conn,
3025 fname,
3026 ucf_flags,
3027 NULL,
3028 NULL,
3029 &smb_fname);
3030 if (!NT_STATUS_IS_OK(status)) {
3031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3032 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3033 ERRSRV, ERRbadpath);
3034 goto out;
3035 }
3036 reply_nterror(req, status);
3037 goto out;
3038 }
3039
3040 /* Create the file. */
3041 status = SMB_VFS_CREATE_FILE(
3042 conn, /* conn */
3043 req, /* req */
3044 0, /* root_dir_fid */
3045 smb_fname, /* fname */
3046 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
3047 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
3048 FILE_CREATE, /* create_disposition*/
3049 0, /* create_options */
3050 fattr, /* file_attributes */
3051 oplock_request, /* oplock_request */
3052 NULL, /* lease */
3053 0, /* allocation_size */
3054 0, /* private_flags */
3055 NULL, /* sd */
3056 NULL, /* ea_list */
3057 &fsp, /* result */
3058 NULL, /* pinfo */
3059 NULL, NULL); /* create context */
3060
3061 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
3062 TALLOC_FREE(fname);
3063 TALLOC_FREE(smb_fname);
3064 continue;
3065 }
3066
3067 if (!NT_STATUS_IS_OK(status)) {
3068 if (open_was_deferred(req->xconn, req->mid)) {
3069 /* We have re-scheduled this call. */
3070 goto out;
3071 }
3072 if (NT_STATUS_EQUAL(
3073 status, NT_STATUS_SHARING_VIOLATION)) {
3074 bool ok = defer_smb1_sharing_violation(req);
3075 if (ok) {
3076 goto out;
3077 }
3078 }
3079 reply_openerror(req, status);
3080 goto out;
3081 }
3082
3083 break;
3084 }
3085
3086 if (i == 10) {
3087 /* Collision after 10 times... */
3088 reply_nterror(req, status);
3089 goto out;
3090 }
3091
3092 reply_outbuf(req, 1, 0);
3093 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
3094
3095 /* the returned filename is relative to the directory */
3096 s = strrchr_m(fsp->fsp_name->base_name, '/');
3097 if (!s) {
3098 s = fsp->fsp_name->base_name;
3099 } else {
3100 s++;
3101 }
3102
3103 #if 0
3104 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
3105 thing in the byte section. JRA */
3106 SSVALS(p, 0, -1); /* what is this? not in spec */
3107 #endif
3108 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
3109 == -1) {
3110 reply_nterror(req, NT_STATUS_NO_MEMORY);
3111 goto out;
3112 }
3113
3114 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
3115 SCVAL(req->outbuf, smb_flg,
3116 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3117 }
3118
3119 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3120 SCVAL(req->outbuf, smb_flg,
3121 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
3122 }
3123
3124 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
3125 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
3126 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
3127 out:
3128 TALLOC_FREE(smb_fname);
3129 TALLOC_FREE(wire_name);
3130 END_PROFILE(SMBctemp);
3131 return;
3132 }
3133
3134 /*******************************************************************
3135 Check if a user is allowed to rename a file.
3136 ********************************************************************/
3137
can_rename(connection_struct * conn,files_struct * fsp,uint16_t dirtype)3138 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
3139 uint16_t dirtype)
3140 {
3141 if (!CAN_WRITE(conn)) {
3142 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3143 }
3144
3145 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
3146 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3147 /* Only bother to read the DOS attribute if we might deny the
3148 rename on the grounds of attribute mismatch. */
3149 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
3150 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
3151 return NT_STATUS_NO_SUCH_FILE;
3152 }
3153 }
3154
3155 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3156 if (fsp->posix_flags & FSP_POSIX_FLAGS_RENAME) {
3157 return NT_STATUS_OK;
3158 }
3159
3160 /* If no pathnames are open below this
3161 directory, allow the rename. */
3162
3163 if (lp_strict_rename(SNUM(conn))) {
3164 /*
3165 * Strict rename, check open file db.
3166 */
3167 if (have_file_open_below(fsp->conn, fsp->fsp_name)) {
3168 return NT_STATUS_ACCESS_DENIED;
3169 }
3170 } else if (file_find_subpath(fsp)) {
3171 /*
3172 * No strict rename, just look in local process.
3173 */
3174 return NT_STATUS_ACCESS_DENIED;
3175 }
3176 return NT_STATUS_OK;
3177 }
3178
3179 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
3180 return NT_STATUS_OK;
3181 }
3182
3183 return NT_STATUS_ACCESS_DENIED;
3184 }
3185
3186 /*******************************************************************
3187 * unlink a file with all relevant access checks
3188 *******************************************************************/
3189
do_unlink(connection_struct * conn,struct smb_request * req,struct smb_filename * smb_fname,uint32_t dirtype)3190 static NTSTATUS do_unlink(connection_struct *conn,
3191 struct smb_request *req,
3192 struct smb_filename *smb_fname,
3193 uint32_t dirtype)
3194 {
3195 uint32_t fattr;
3196 files_struct *fsp;
3197 uint32_t dirtype_orig = dirtype;
3198 NTSTATUS status;
3199 int ret;
3200 bool posix_paths = (req != NULL && req->posix_pathnames);
3201
3202 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
3203 smb_fname_str_dbg(smb_fname),
3204 dirtype));
3205
3206 if (!CAN_WRITE(conn)) {
3207 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3208 }
3209
3210 if (posix_paths) {
3211 ret = SMB_VFS_LSTAT(conn, smb_fname);
3212 } else {
3213 ret = SMB_VFS_STAT(conn, smb_fname);
3214 }
3215 if (ret != 0) {
3216 return map_nt_error_from_unix(errno);
3217 }
3218
3219 fattr = dos_mode(conn, smb_fname);
3220
3221 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
3222 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
3223 }
3224
3225 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
3226 if (!dirtype) {
3227 return NT_STATUS_NO_SUCH_FILE;
3228 }
3229
3230 if (!dir_check_ftype(fattr, dirtype)) {
3231 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3232 return NT_STATUS_FILE_IS_A_DIRECTORY;
3233 }
3234 return NT_STATUS_NO_SUCH_FILE;
3235 }
3236
3237 if (dirtype_orig & 0x8000) {
3238 /* These will never be set for POSIX. */
3239 return NT_STATUS_NO_SUCH_FILE;
3240 }
3241
3242 #if 0
3243 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
3244 return NT_STATUS_FILE_IS_A_DIRECTORY;
3245 }
3246
3247 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
3248 return NT_STATUS_NO_SUCH_FILE;
3249 }
3250
3251 if (dirtype & 0xFF00) {
3252 /* These will never be set for POSIX. */
3253 return NT_STATUS_NO_SUCH_FILE;
3254 }
3255
3256 dirtype &= 0xFF;
3257 if (!dirtype) {
3258 return NT_STATUS_NO_SUCH_FILE;
3259 }
3260
3261 /* Can't delete a directory. */
3262 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
3263 return NT_STATUS_FILE_IS_A_DIRECTORY;
3264 }
3265 #endif
3266
3267 #if 0 /* JRATEST */
3268 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
3269 return NT_STATUS_OBJECT_NAME_INVALID;
3270 #endif /* JRATEST */
3271
3272 /* On open checks the open itself will check the share mode, so
3273 don't do it here as we'll get it wrong. */
3274
3275 status = SMB_VFS_CREATE_FILE
3276 (conn, /* conn */
3277 req, /* req */
3278 0, /* root_dir_fid */
3279 smb_fname, /* fname */
3280 DELETE_ACCESS, /* access_mask */
3281 FILE_SHARE_NONE, /* share_access */
3282 FILE_OPEN, /* create_disposition*/
3283 FILE_NON_DIRECTORY_FILE, /* create_options */
3284 /* file_attributes */
3285 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
3286 FILE_ATTRIBUTE_NORMAL,
3287 0, /* oplock_request */
3288 NULL, /* lease */
3289 0, /* allocation_size */
3290 0, /* private_flags */
3291 NULL, /* sd */
3292 NULL, /* ea_list */
3293 &fsp, /* result */
3294 NULL, /* pinfo */
3295 NULL, NULL); /* create context */
3296
3297 if (!NT_STATUS_IS_OK(status)) {
3298 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
3299 nt_errstr(status)));
3300 return status;
3301 }
3302
3303 status = can_set_delete_on_close(fsp, fattr);
3304 if (!NT_STATUS_IS_OK(status)) {
3305 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
3306 "(%s)\n",
3307 smb_fname_str_dbg(smb_fname),
3308 nt_errstr(status)));
3309 close_file(req, fsp, NORMAL_CLOSE);
3310 return status;
3311 }
3312
3313 /* The set is across all open files on this dev/inode pair. */
3314 if (!set_delete_on_close(fsp, True,
3315 conn->session_info->security_token,
3316 conn->session_info->unix_token)) {
3317 close_file(req, fsp, NORMAL_CLOSE);
3318 return NT_STATUS_ACCESS_DENIED;
3319 }
3320
3321 return close_file(req, fsp, NORMAL_CLOSE);
3322 }
3323
3324 /****************************************************************************
3325 The guts of the unlink command, split out so it may be called by the NT SMB
3326 code.
3327 ****************************************************************************/
3328
unlink_internals(connection_struct * conn,struct smb_request * req,uint32_t dirtype,struct smb_filename * smb_fname,bool has_wild)3329 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
3330 uint32_t dirtype, struct smb_filename *smb_fname,
3331 bool has_wild)
3332 {
3333 char *fname_dir = NULL;
3334 char *fname_mask = NULL;
3335 int count=0;
3336 NTSTATUS status = NT_STATUS_OK;
3337 struct smb_filename *smb_fname_dir = NULL;
3338 TALLOC_CTX *ctx = talloc_tos();
3339
3340 /* Split up the directory from the filename/mask. */
3341 status = split_fname_dir_mask(ctx, smb_fname->base_name,
3342 &fname_dir, &fname_mask);
3343 if (!NT_STATUS_IS_OK(status)) {
3344 goto out;
3345 }
3346
3347 /*
3348 * We should only check the mangled cache
3349 * here if unix_convert failed. This means
3350 * that the path in 'mask' doesn't exist
3351 * on the file system and so we need to look
3352 * for a possible mangle. This patch from
3353 * Tine Smukavec <valentin.smukavec@hermes.si>.
3354 */
3355
3356 if (!VALID_STAT(smb_fname->st) &&
3357 mangle_is_mangled(fname_mask, conn->params)) {
3358 char *new_mask = NULL;
3359 mangle_lookup_name_from_8_3(ctx, fname_mask,
3360 &new_mask, conn->params);
3361 if (new_mask) {
3362 TALLOC_FREE(fname_mask);
3363 fname_mask = new_mask;
3364 }
3365 }
3366
3367 if (!has_wild) {
3368
3369 /*
3370 * Only one file needs to be unlinked. Append the mask back
3371 * onto the directory.
3372 */
3373 TALLOC_FREE(smb_fname->base_name);
3374 if (ISDOT(fname_dir)) {
3375 /* Ensure we use canonical names on open. */
3376 smb_fname->base_name = talloc_asprintf(smb_fname,
3377 "%s",
3378 fname_mask);
3379 } else {
3380 smb_fname->base_name = talloc_asprintf(smb_fname,
3381 "%s/%s",
3382 fname_dir,
3383 fname_mask);
3384 }
3385 if (!smb_fname->base_name) {
3386 status = NT_STATUS_NO_MEMORY;
3387 goto out;
3388 }
3389 if (dirtype == 0) {
3390 dirtype = FILE_ATTRIBUTE_NORMAL;
3391 }
3392
3393 status = check_name(conn, smb_fname);
3394 if (!NT_STATUS_IS_OK(status)) {
3395 goto out;
3396 }
3397
3398 status = do_unlink(conn, req, smb_fname, dirtype);
3399 if (!NT_STATUS_IS_OK(status)) {
3400 goto out;
3401 }
3402
3403 count++;
3404 } else {
3405 struct smb_Dir *dir_hnd = NULL;
3406 long offset = 0;
3407 const char *dname = NULL;
3408 char *talloced = NULL;
3409
3410 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
3411 status = NT_STATUS_OBJECT_NAME_INVALID;
3412 goto out;
3413 }
3414 if (dirtype == 0) {
3415 dirtype = FILE_ATTRIBUTE_NORMAL;
3416 }
3417
3418 if (strequal(fname_mask,"????????.???")) {
3419 TALLOC_FREE(fname_mask);
3420 fname_mask = talloc_strdup(ctx, "*");
3421 if (!fname_mask) {
3422 status = NT_STATUS_NO_MEMORY;
3423 goto out;
3424 }
3425 }
3426
3427 smb_fname_dir = synthetic_smb_fname(talloc_tos(),
3428 fname_dir,
3429 NULL,
3430 NULL,
3431 smb_fname->flags);
3432 if (smb_fname_dir == NULL) {
3433 status = NT_STATUS_NO_MEMORY;
3434 goto out;
3435 }
3436
3437 status = check_name(conn, smb_fname_dir);
3438 if (!NT_STATUS_IS_OK(status)) {
3439 goto out;
3440 }
3441
3442 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
3443 dirtype);
3444 if (dir_hnd == NULL) {
3445 status = map_nt_error_from_unix(errno);
3446 goto out;
3447 }
3448
3449 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
3450 the pattern matches against the long name, otherwise the short name
3451 We don't implement this yet XXXX
3452 */
3453
3454 status = NT_STATUS_NO_SUCH_FILE;
3455
3456 while ((dname = ReadDirName(dir_hnd, &offset,
3457 &smb_fname->st, &talloced))) {
3458 TALLOC_CTX *frame = talloc_stackframe();
3459
3460 if (!is_visible_file(conn, fname_dir, dname,
3461 &smb_fname->st, true)) {
3462 TALLOC_FREE(frame);
3463 TALLOC_FREE(talloced);
3464 continue;
3465 }
3466
3467 /* Quick check for "." and ".." */
3468 if (ISDOT(dname) || ISDOTDOT(dname)) {
3469 TALLOC_FREE(frame);
3470 TALLOC_FREE(talloced);
3471 continue;
3472 }
3473
3474 if(!mask_match(dname, fname_mask,
3475 conn->case_sensitive)) {
3476 TALLOC_FREE(frame);
3477 TALLOC_FREE(talloced);
3478 continue;
3479 }
3480
3481 TALLOC_FREE(smb_fname->base_name);
3482 if (ISDOT(fname_dir)) {
3483 /* Ensure we use canonical names on open. */
3484 smb_fname->base_name =
3485 talloc_asprintf(smb_fname, "%s",
3486 dname);
3487 } else {
3488 smb_fname->base_name =
3489 talloc_asprintf(smb_fname, "%s/%s",
3490 fname_dir, dname);
3491 }
3492
3493 if (!smb_fname->base_name) {
3494 TALLOC_FREE(dir_hnd);
3495 status = NT_STATUS_NO_MEMORY;
3496 TALLOC_FREE(frame);
3497 TALLOC_FREE(talloced);
3498 goto out;
3499 }
3500
3501 status = check_name(conn, smb_fname);
3502 if (!NT_STATUS_IS_OK(status)) {
3503 TALLOC_FREE(dir_hnd);
3504 TALLOC_FREE(frame);
3505 TALLOC_FREE(talloced);
3506 goto out;
3507 }
3508
3509 status = do_unlink(conn, req, smb_fname, dirtype);
3510 if (!NT_STATUS_IS_OK(status)) {
3511 TALLOC_FREE(dir_hnd);
3512 TALLOC_FREE(frame);
3513 TALLOC_FREE(talloced);
3514 goto out;
3515 }
3516
3517 count++;
3518 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3519 smb_fname->base_name));
3520
3521 TALLOC_FREE(frame);
3522 TALLOC_FREE(talloced);
3523 }
3524 TALLOC_FREE(dir_hnd);
3525 }
3526
3527 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3528 status = map_nt_error_from_unix(errno);
3529 }
3530
3531 out:
3532 TALLOC_FREE(smb_fname_dir);
3533 TALLOC_FREE(fname_dir);
3534 TALLOC_FREE(fname_mask);
3535 return status;
3536 }
3537
3538 /****************************************************************************
3539 Reply to a unlink
3540 ****************************************************************************/
3541
reply_unlink(struct smb_request * req)3542 void reply_unlink(struct smb_request *req)
3543 {
3544 connection_struct *conn = req->conn;
3545 char *name = NULL;
3546 struct smb_filename *smb_fname = NULL;
3547 uint32_t dirtype;
3548 NTSTATUS status;
3549 bool path_contains_wcard = False;
3550 uint32_t ucf_flags = UCF_COND_ALLOW_WCARD_LCOMP |
3551 ucf_flags_from_smb_request(req);
3552 TALLOC_CTX *ctx = talloc_tos();
3553
3554 START_PROFILE(SMBunlink);
3555
3556 if (req->wct < 1) {
3557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3558 goto out;
3559 }
3560
3561 dirtype = SVAL(req->vwv+0, 0);
3562
3563 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3564 STR_TERMINATE, &status,
3565 &path_contains_wcard);
3566 if (!NT_STATUS_IS_OK(status)) {
3567 reply_nterror(req, status);
3568 goto out;
3569 }
3570
3571 status = filename_convert(ctx, conn,
3572 name,
3573 ucf_flags,
3574 NULL,
3575 &path_contains_wcard,
3576 &smb_fname);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3579 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3580 ERRSRV, ERRbadpath);
3581 goto out;
3582 }
3583 reply_nterror(req, status);
3584 goto out;
3585 }
3586
3587 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3588
3589 status = unlink_internals(conn, req, dirtype, smb_fname,
3590 path_contains_wcard);
3591 if (!NT_STATUS_IS_OK(status)) {
3592 if (open_was_deferred(req->xconn, req->mid)) {
3593 /* We have re-scheduled this call. */
3594 goto out;
3595 }
3596 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
3597 bool ok = defer_smb1_sharing_violation(req);
3598 if (ok) {
3599 goto out;
3600 }
3601 }
3602 reply_nterror(req, status);
3603 goto out;
3604 }
3605
3606 reply_outbuf(req, 0, 0);
3607 out:
3608 TALLOC_FREE(smb_fname);
3609 END_PROFILE(SMBunlink);
3610 return;
3611 }
3612
3613 /****************************************************************************
3614 Fail for readbraw.
3615 ****************************************************************************/
3616
fail_readraw(void)3617 static void fail_readraw(void)
3618 {
3619 const char *errstr = talloc_asprintf(talloc_tos(),
3620 "FAIL ! reply_readbraw: socket write fail (%s)",
3621 strerror(errno));
3622 if (!errstr) {
3623 errstr = "";
3624 }
3625 exit_server_cleanly(errstr);
3626 }
3627
3628 /****************************************************************************
3629 Fake (read/write) sendfile. Returns -1 on read or write fail.
3630 ****************************************************************************/
3631
fake_sendfile(struct smbXsrv_connection * xconn,files_struct * fsp,off_t startpos,size_t nread)3632 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3633 off_t startpos, size_t nread)
3634 {
3635 size_t bufsize;
3636 size_t tosend = nread;
3637 char *buf;
3638
3639 if (nread == 0) {
3640 return 0;
3641 }
3642
3643 bufsize = MIN(nread, 65536);
3644
3645 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3646 return -1;
3647 }
3648
3649 while (tosend > 0) {
3650 ssize_t ret;
3651 size_t cur_read;
3652
3653 cur_read = MIN(tosend, bufsize);
3654 ret = read_file(fsp,buf,startpos,cur_read);
3655 if (ret == -1) {
3656 SAFE_FREE(buf);
3657 return -1;
3658 }
3659
3660 /* If we had a short read, fill with zeros. */
3661 if (ret < cur_read) {
3662 memset(buf + ret, '\0', cur_read - ret);
3663 }
3664
3665 ret = write_data(xconn->transport.sock, buf, cur_read);
3666 if (ret != cur_read) {
3667 int saved_errno = errno;
3668 /*
3669 * Try and give an error message saying what
3670 * client failed.
3671 */
3672 DEBUG(0, ("write_data failed for client %s. "
3673 "Error %s\n",
3674 smbXsrv_connection_dbg(xconn),
3675 strerror(saved_errno)));
3676 SAFE_FREE(buf);
3677 errno = saved_errno;
3678 return -1;
3679 }
3680 tosend -= cur_read;
3681 startpos += cur_read;
3682 }
3683
3684 SAFE_FREE(buf);
3685 return (ssize_t)nread;
3686 }
3687
3688 /****************************************************************************
3689 Deal with the case of sendfile reading less bytes from the file than
3690 requested. Fill with zeros (all we can do). Returns 0 on success
3691 ****************************************************************************/
3692
sendfile_short_send(struct smbXsrv_connection * xconn,files_struct * fsp,ssize_t nread,size_t headersize,size_t smb_maxcnt)3693 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3694 files_struct *fsp,
3695 ssize_t nread,
3696 size_t headersize,
3697 size_t smb_maxcnt)
3698 {
3699 #define SHORT_SEND_BUFSIZE 1024
3700 if (nread < headersize) {
3701 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3702 "header for file %s (%s). Terminating\n",
3703 fsp_str_dbg(fsp), strerror(errno)));
3704 return -1;
3705 }
3706
3707 nread -= headersize;
3708
3709 if (nread < smb_maxcnt) {
3710 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3711 if (!buf) {
3712 DEBUG(0,("sendfile_short_send: malloc failed "
3713 "for file %s (%s). Terminating\n",
3714 fsp_str_dbg(fsp), strerror(errno)));
3715 return -1;
3716 }
3717
3718 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3719 "with zeros !\n", fsp_str_dbg(fsp)));
3720
3721 while (nread < smb_maxcnt) {
3722 /*
3723 * We asked for the real file size and told sendfile
3724 * to not go beyond the end of the file. But it can
3725 * happen that in between our fstat call and the
3726 * sendfile call the file was truncated. This is very
3727 * bad because we have already announced the larger
3728 * number of bytes to the client.
3729 *
3730 * The best we can do now is to send 0-bytes, just as
3731 * a read from a hole in a sparse file would do.
3732 *
3733 * This should happen rarely enough that I don't care
3734 * about efficiency here :-)
3735 */
3736 size_t to_write;
3737 ssize_t ret;
3738
3739 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3740 ret = write_data(xconn->transport.sock, buf, to_write);
3741 if (ret != to_write) {
3742 int saved_errno = errno;
3743 /*
3744 * Try and give an error message saying what
3745 * client failed.
3746 */
3747 DEBUG(0, ("write_data failed for client %s. "
3748 "Error %s\n",
3749 smbXsrv_connection_dbg(xconn),
3750 strerror(saved_errno)));
3751 errno = saved_errno;
3752 return -1;
3753 }
3754 nread += to_write;
3755 }
3756 SAFE_FREE(buf);
3757 }
3758
3759 return 0;
3760 }
3761
3762 /****************************************************************************
3763 Return a readbraw error (4 bytes of zero).
3764 ****************************************************************************/
3765
reply_readbraw_error(struct smbXsrv_connection * xconn)3766 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3767 {
3768 char header[4];
3769
3770 SIVAL(header,0,0);
3771
3772 smbd_lock_socket(xconn);
3773 if (write_data(xconn->transport.sock,header,4) != 4) {
3774 int saved_errno = errno;
3775 /*
3776 * Try and give an error message saying what
3777 * client failed.
3778 */
3779 DEBUG(0, ("write_data failed for client %s. "
3780 "Error %s\n",
3781 smbXsrv_connection_dbg(xconn),
3782 strerror(saved_errno)));
3783 errno = saved_errno;
3784
3785 fail_readraw();
3786 }
3787 smbd_unlock_socket(xconn);
3788 }
3789
3790 /*******************************************************************
3791 Ensure we don't use sendfile if server smb signing is active.
3792 ********************************************************************/
3793
lp_use_sendfile(int snum,struct smb_signing_state * signing_state)3794 static bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
3795 {
3796 bool sign_active = false;
3797
3798 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
3799 if (get_Protocol() < PROTOCOL_NT1) {
3800 return false;
3801 }
3802 if (signing_state) {
3803 sign_active = smb_signing_is_active(signing_state);
3804 }
3805 return (lp__use_sendfile(snum) &&
3806 (get_remote_arch() != RA_WIN95) &&
3807 !sign_active);
3808 }
3809 /****************************************************************************
3810 Use sendfile in readbraw.
3811 ****************************************************************************/
3812
send_file_readbraw(connection_struct * conn,struct smb_request * req,files_struct * fsp,off_t startpos,size_t nread,ssize_t mincount)3813 static void send_file_readbraw(connection_struct *conn,
3814 struct smb_request *req,
3815 files_struct *fsp,
3816 off_t startpos,
3817 size_t nread,
3818 ssize_t mincount)
3819 {
3820 struct smbXsrv_connection *xconn = req->xconn;
3821 char *outbuf = NULL;
3822 ssize_t ret=0;
3823
3824 /*
3825 * We can only use sendfile on a non-chained packet
3826 * but we can use on a non-oplocked file. tridge proved this
3827 * on a train in Germany :-). JRA.
3828 * reply_readbraw has already checked the length.
3829 */
3830
3831 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3832 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3833 ssize_t sendfile_read = -1;
3834 char header[4];
3835 DATA_BLOB header_blob;
3836
3837 _smb_setlen(header,nread);
3838 header_blob = data_blob_const(header, 4);
3839
3840 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3841 &header_blob, startpos,
3842 nread);
3843 if (sendfile_read == -1) {
3844 /* Returning ENOSYS means no data at all was sent.
3845 * Do this as a normal read. */
3846 if (errno == ENOSYS) {
3847 goto normal_readbraw;
3848 }
3849
3850 /*
3851 * Special hack for broken Linux with no working sendfile. If we
3852 * return EINTR we sent the header but not the rest of the data.
3853 * Fake this up by doing read/write calls.
3854 */
3855 if (errno == EINTR) {
3856 /* Ensure we don't do this again. */
3857 set_use_sendfile(SNUM(conn), False);
3858 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3859
3860 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3861 DEBUG(0,("send_file_readbraw: "
3862 "fake_sendfile failed for "
3863 "file %s (%s).\n",
3864 fsp_str_dbg(fsp),
3865 strerror(errno)));
3866 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3867 }
3868 return;
3869 }
3870
3871 DEBUG(0,("send_file_readbraw: sendfile failed for "
3872 "file %s (%s). Terminating\n",
3873 fsp_str_dbg(fsp), strerror(errno)));
3874 exit_server_cleanly("send_file_readbraw sendfile failed");
3875 } else if (sendfile_read == 0) {
3876 /*
3877 * Some sendfile implementations return 0 to indicate
3878 * that there was a short read, but nothing was
3879 * actually written to the socket. In this case,
3880 * fallback to the normal read path so the header gets
3881 * the correct byte count.
3882 */
3883 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3884 "bytes falling back to the normal read: "
3885 "%s\n", fsp_str_dbg(fsp)));
3886 goto normal_readbraw;
3887 }
3888
3889 /* Deal with possible short send. */
3890 if (sendfile_read != 4+nread) {
3891 ret = sendfile_short_send(xconn, fsp,
3892 sendfile_read, 4, nread);
3893 if (ret == -1) {
3894 fail_readraw();
3895 }
3896 }
3897 return;
3898 }
3899
3900 normal_readbraw:
3901
3902 outbuf = talloc_array(NULL, char, nread+4);
3903 if (!outbuf) {
3904 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3905 (unsigned)(nread+4)));
3906 reply_readbraw_error(xconn);
3907 return;
3908 }
3909
3910 if (nread > 0) {
3911 ret = read_file(fsp,outbuf+4,startpos,nread);
3912 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3913 if (ret < mincount)
3914 ret = 0;
3915 #else
3916 if (ret < nread)
3917 ret = 0;
3918 #endif
3919 }
3920
3921 _smb_setlen(outbuf,ret);
3922 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3923 int saved_errno = errno;
3924 /*
3925 * Try and give an error message saying what
3926 * client failed.
3927 */
3928 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3929 smbXsrv_connection_dbg(xconn),
3930 strerror(saved_errno)));
3931 errno = saved_errno;
3932
3933 fail_readraw();
3934 }
3935
3936 TALLOC_FREE(outbuf);
3937 }
3938
3939 /****************************************************************************
3940 Reply to a readbraw (core+ protocol).
3941 ****************************************************************************/
3942
reply_readbraw(struct smb_request * req)3943 void reply_readbraw(struct smb_request *req)
3944 {
3945 connection_struct *conn = req->conn;
3946 struct smbXsrv_connection *xconn = req->xconn;
3947 ssize_t maxcount,mincount;
3948 size_t nread = 0;
3949 off_t startpos;
3950 files_struct *fsp;
3951 struct lock_struct lock;
3952 off_t size = 0;
3953 NTSTATUS status;
3954
3955 START_PROFILE(SMBreadbraw);
3956
3957 if (srv_is_signing_active(xconn) || req->encrypted) {
3958 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3959 "raw reads/writes are disallowed.");
3960 }
3961
3962 if (req->wct < 8) {
3963 reply_readbraw_error(xconn);
3964 END_PROFILE(SMBreadbraw);
3965 return;
3966 }
3967
3968 if (xconn->smb1.echo_handler.trusted_fde) {
3969 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3970 "'async smb echo handler = yes'\n"));
3971 reply_readbraw_error(xconn);
3972 END_PROFILE(SMBreadbraw);
3973 return;
3974 }
3975
3976 /*
3977 * Special check if an oplock break has been issued
3978 * and the readraw request croses on the wire, we must
3979 * return a zero length response here.
3980 */
3981
3982 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3983
3984 /*
3985 * We have to do a check_fsp by hand here, as
3986 * we must always return 4 zero bytes on error,
3987 * not a NTSTATUS.
3988 */
3989
3990 if (!fsp || !conn || conn != fsp->conn ||
3991 req->vuid != fsp->vuid ||
3992 fsp->is_directory || fsp->fh->fd == -1) {
3993 /*
3994 * fsp could be NULL here so use the value from the packet. JRA.
3995 */
3996 DEBUG(3,("reply_readbraw: fnum %d not valid "
3997 "- cache prime?\n",
3998 (int)SVAL(req->vwv+0, 0)));
3999 reply_readbraw_error(xconn);
4000 END_PROFILE(SMBreadbraw);
4001 return;
4002 }
4003
4004 /* Do a "by hand" version of CHECK_READ. */
4005 if (!(fsp->can_read ||
4006 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
4007 (fsp->access_mask & FILE_EXECUTE)))) {
4008 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
4009 (int)SVAL(req->vwv+0, 0)));
4010 reply_readbraw_error(xconn);
4011 END_PROFILE(SMBreadbraw);
4012 return;
4013 }
4014
4015 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
4016 if(req->wct == 10) {
4017 /*
4018 * This is a large offset (64 bit) read.
4019 */
4020
4021 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
4022
4023 if(startpos < 0) {
4024 DEBUG(0,("reply_readbraw: negative 64 bit "
4025 "readraw offset (%.0f) !\n",
4026 (double)startpos ));
4027 reply_readbraw_error(xconn);
4028 END_PROFILE(SMBreadbraw);
4029 return;
4030 }
4031 }
4032
4033 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
4034 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
4035
4036 /* ensure we don't overrun the packet size */
4037 maxcount = MIN(65535,maxcount);
4038
4039 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4040 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
4041 &lock);
4042
4043 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4044 reply_readbraw_error(xconn);
4045 END_PROFILE(SMBreadbraw);
4046 return;
4047 }
4048
4049 status = vfs_stat_fsp(fsp);
4050 if (NT_STATUS_IS_OK(status)) {
4051 size = fsp->fsp_name->st.st_ex_size;
4052 }
4053
4054 if (startpos >= size) {
4055 nread = 0;
4056 } else {
4057 nread = MIN(maxcount,(size - startpos));
4058 }
4059
4060 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
4061 if (nread < mincount)
4062 nread = 0;
4063 #endif
4064
4065 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
4066 "min=%lu nread=%lu\n",
4067 fsp_fnum_dbg(fsp), (double)startpos,
4068 (unsigned long)maxcount,
4069 (unsigned long)mincount,
4070 (unsigned long)nread ) );
4071
4072 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
4073
4074 DEBUG(5,("reply_readbraw finished\n"));
4075
4076 END_PROFILE(SMBreadbraw);
4077 return;
4078 }
4079
4080 #undef DBGC_CLASS
4081 #define DBGC_CLASS DBGC_LOCKING
4082
4083 /****************************************************************************
4084 Reply to a lockread (core+ protocol).
4085 ****************************************************************************/
4086
4087 static void reply_lockread_locked(struct tevent_req *subreq);
4088
reply_lockread(struct smb_request * req)4089 void reply_lockread(struct smb_request *req)
4090 {
4091 struct tevent_req *subreq = NULL;
4092 connection_struct *conn = req->conn;
4093 files_struct *fsp;
4094 struct smbd_lock_element *lck = NULL;
4095
4096 START_PROFILE(SMBlockread);
4097
4098 if (req->wct < 5) {
4099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4100 END_PROFILE(SMBlockread);
4101 return;
4102 }
4103
4104 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4105
4106 if (!check_fsp(conn, req, fsp)) {
4107 END_PROFILE(SMBlockread);
4108 return;
4109 }
4110
4111 if (!CHECK_READ(fsp,req)) {
4112 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4113 END_PROFILE(SMBlockread);
4114 return;
4115 }
4116
4117 lck = talloc(req, struct smbd_lock_element);
4118 if (lck == NULL) {
4119 reply_nterror(req, NT_STATUS_NO_MEMORY);
4120 END_PROFILE(SMBlockread);
4121 return;
4122 }
4123
4124 /*
4125 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
4126 * protocol request that predates the read/write lock concept.
4127 * Thus instead of asking for a read lock here we need to ask
4128 * for a write lock. JRA.
4129 * Note that the requested lock size is unaffected by max_send.
4130 */
4131
4132 *lck = (struct smbd_lock_element) {
4133 .req_guid = smbd_request_guid(req, 0),
4134 .smblctx = req->smbpid,
4135 .brltype = WRITE_LOCK,
4136 .count = SVAL(req->vwv+1, 0),
4137 .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0),
4138 };
4139
4140 subreq = smbd_smb1_do_locks_send(
4141 fsp,
4142 req->sconn->ev_ctx,
4143 &req,
4144 fsp,
4145 0,
4146 false, /* large_offset */
4147 WINDOWS_LOCK,
4148 1,
4149 lck);
4150 if (subreq == NULL) {
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4152 END_PROFILE(SMBlockread);
4153 return;
4154 }
4155 tevent_req_set_callback(subreq, reply_lockread_locked, NULL);
4156 END_PROFILE(SMBlockread);
4157 }
4158
reply_lockread_locked(struct tevent_req * subreq)4159 static void reply_lockread_locked(struct tevent_req *subreq)
4160 {
4161 struct smb_request *req = NULL;
4162 ssize_t nread = -1;
4163 char *data = NULL;
4164 NTSTATUS status;
4165 bool ok;
4166 off_t startpos;
4167 size_t numtoread, maxtoread;
4168 struct files_struct *fsp = NULL;
4169 char *p = NULL;
4170
4171 START_PROFILE(SMBlockread);
4172
4173 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
4174 SMB_ASSERT(ok);
4175
4176 status = smbd_smb1_do_locks_recv(subreq);
4177 TALLOC_FREE(subreq);
4178
4179 if (!NT_STATUS_IS_OK(status)) {
4180 reply_nterror(req, status);
4181 goto send;
4182 }
4183
4184 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4185 if (fsp == NULL) {
4186 reply_nterror(req, NT_STATUS_INTERNAL_ERROR);
4187 goto send;
4188 }
4189
4190 numtoread = SVAL(req->vwv+1, 0);
4191 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4192
4193 /*
4194 * However the requested READ size IS affected by max_send. Insanity.... JRA.
4195 */
4196 maxtoread = req->xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4197
4198 if (numtoread > maxtoread) {
4199 DBG_WARNING("requested read size (%zu) is greater than "
4200 "maximum allowed (%zu/%d). "
4201 "Returning short read of maximum allowed for "
4202 "compatibility with Windows 2000.\n",
4203 numtoread,
4204 maxtoread,
4205 req->xconn->smb1.sessions.max_send);
4206 numtoread = maxtoread;
4207 }
4208
4209 reply_outbuf(req, 5, numtoread + 3);
4210
4211 data = smb_buf(req->outbuf) + 3;
4212
4213 nread = read_file(fsp,data,startpos,numtoread);
4214
4215 if (nread < 0) {
4216 reply_nterror(req, map_nt_error_from_unix(errno));
4217 goto send;
4218 }
4219
4220 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4221
4222 SSVAL(req->outbuf,smb_vwv0,nread);
4223 SSVAL(req->outbuf,smb_vwv5,nread+3);
4224 p = smb_buf(req->outbuf);
4225 SCVAL(p,0,0); /* pad byte. */
4226 SSVAL(p,1,nread);
4227
4228 DEBUG(3,("lockread %s num=%d nread=%d\n",
4229 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4230
4231 send:
4232 ok = srv_send_smb(req->xconn,
4233 (char *)req->outbuf,
4234 true,
4235 req->seqnum+1,
4236 IS_CONN_ENCRYPTED(req->conn),
4237 NULL);
4238 if (!ok) {
4239 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
4240 }
4241 TALLOC_FREE(req);
4242 END_PROFILE(SMBlockread);
4243 return;
4244 }
4245
4246 #undef DBGC_CLASS
4247 #define DBGC_CLASS DBGC_ALL
4248
4249 /****************************************************************************
4250 Reply to a read.
4251 ****************************************************************************/
4252
reply_read(struct smb_request * req)4253 void reply_read(struct smb_request *req)
4254 {
4255 connection_struct *conn = req->conn;
4256 size_t numtoread;
4257 size_t maxtoread;
4258 ssize_t nread = 0;
4259 char *data;
4260 off_t startpos;
4261 files_struct *fsp;
4262 struct lock_struct lock;
4263 struct smbXsrv_connection *xconn = req->xconn;
4264
4265 START_PROFILE(SMBread);
4266
4267 if (req->wct < 3) {
4268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4269 END_PROFILE(SMBread);
4270 return;
4271 }
4272
4273 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4274
4275 if (!check_fsp(conn, req, fsp)) {
4276 END_PROFILE(SMBread);
4277 return;
4278 }
4279
4280 if (!CHECK_READ(fsp,req)) {
4281 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4282 END_PROFILE(SMBread);
4283 return;
4284 }
4285
4286 numtoread = SVAL(req->vwv+1, 0);
4287 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4288
4289 /*
4290 * The requested read size cannot be greater than max_send. JRA.
4291 */
4292 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
4293
4294 if (numtoread > maxtoread) {
4295 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
4296 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
4297 (unsigned int)numtoread, (unsigned int)maxtoread,
4298 (unsigned int)xconn->smb1.sessions.max_send));
4299 numtoread = maxtoread;
4300 }
4301
4302 reply_outbuf(req, 5, numtoread+3);
4303
4304 data = smb_buf(req->outbuf) + 3;
4305
4306 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4307 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
4308 &lock);
4309
4310 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4311 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4312 END_PROFILE(SMBread);
4313 return;
4314 }
4315
4316 if (numtoread > 0)
4317 nread = read_file(fsp,data,startpos,numtoread);
4318
4319 if (nread < 0) {
4320 reply_nterror(req, map_nt_error_from_unix(errno));
4321 goto out;
4322 }
4323
4324 srv_set_message((char *)req->outbuf, 5, nread+3, False);
4325
4326 SSVAL(req->outbuf,smb_vwv0,nread);
4327 SSVAL(req->outbuf,smb_vwv5,nread+3);
4328 SCVAL(smb_buf(req->outbuf),0,1);
4329 SSVAL(smb_buf(req->outbuf),1,nread);
4330
4331 DEBUG(3, ("read %s num=%d nread=%d\n",
4332 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
4333
4334 out:
4335 END_PROFILE(SMBread);
4336 return;
4337 }
4338
4339 /****************************************************************************
4340 Setup readX header.
4341 ****************************************************************************/
4342
setup_readX_header(char * outbuf,size_t smb_maxcnt)4343 size_t setup_readX_header(char *outbuf, size_t smb_maxcnt)
4344 {
4345 size_t outsize;
4346
4347 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
4348 False);
4349
4350 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
4351
4352 SCVAL(outbuf,smb_vwv0,0xFF);
4353 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
4354 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
4355 SSVAL(outbuf,smb_vwv6,
4356 (smb_wct - 4) /* offset from smb header to wct */
4357 + 1 /* the wct field */
4358 + 12 * sizeof(uint16_t) /* vwv */
4359 + 2 /* the buflen field */
4360 + 1); /* padding byte */
4361 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
4362 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
4363 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
4364 _smb_setlen_large(outbuf,
4365 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
4366 return outsize;
4367 }
4368
4369 /****************************************************************************
4370 Reply to a read and X - possibly using sendfile.
4371 ****************************************************************************/
4372
send_file_readX(connection_struct * conn,struct smb_request * req,files_struct * fsp,off_t startpos,size_t smb_maxcnt)4373 static void send_file_readX(connection_struct *conn, struct smb_request *req,
4374 files_struct *fsp, off_t startpos,
4375 size_t smb_maxcnt)
4376 {
4377 struct smbXsrv_connection *xconn = req->xconn;
4378 ssize_t nread = -1;
4379 struct lock_struct lock;
4380 int saved_errno = 0;
4381 NTSTATUS status;
4382
4383 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4384 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
4385 &lock);
4386
4387 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4388 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4389 return;
4390 }
4391
4392 /*
4393 * We can only use sendfile on a non-chained packet
4394 * but we can use on a non-oplocked file. tridge proved this
4395 * on a train in Germany :-). JRA.
4396 */
4397
4398 if (!req_is_in_chain(req) &&
4399 !req->encrypted &&
4400 (fsp->base_fsp == NULL) &&
4401 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
4402 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
4403 DATA_BLOB header;
4404
4405 status = vfs_stat_fsp(fsp);
4406 if (!NT_STATUS_IS_OK(status)) {
4407 reply_nterror(req, status);
4408 goto out;
4409 }
4410
4411 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4412 (startpos > fsp->fsp_name->st.st_ex_size) ||
4413 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4414 /*
4415 * We already know that we would do a short read, so don't
4416 * try the sendfile() path.
4417 */
4418 goto nosendfile_read;
4419 }
4420
4421 /*
4422 * Set up the packet header before send. We
4423 * assume here the sendfile will work (get the
4424 * correct amount of data).
4425 */
4426
4427 header = data_blob_const(headerbuf, sizeof(headerbuf));
4428
4429 construct_reply_common_req(req, (char *)headerbuf);
4430 setup_readX_header((char *)headerbuf, smb_maxcnt);
4431
4432 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
4433 startpos, smb_maxcnt);
4434 if (nread == -1) {
4435 saved_errno = errno;
4436
4437 /* Returning ENOSYS means no data at all was sent.
4438 Do this as a normal read. */
4439 if (errno == ENOSYS) {
4440 goto normal_read;
4441 }
4442
4443 /*
4444 * Special hack for broken Linux with no working sendfile. If we
4445 * return EINTR we sent the header but not the rest of the data.
4446 * Fake this up by doing read/write calls.
4447 */
4448
4449 if (errno == EINTR) {
4450 /* Ensure we don't do this again. */
4451 set_use_sendfile(SNUM(conn), False);
4452 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
4453 nread = fake_sendfile(xconn, fsp, startpos,
4454 smb_maxcnt);
4455 if (nread == -1) {
4456 saved_errno = errno;
4457 DEBUG(0,("send_file_readX: "
4458 "fake_sendfile failed for "
4459 "file %s (%s) for client %s. "
4460 "Terminating\n",
4461 fsp_str_dbg(fsp),
4462 smbXsrv_connection_dbg(xconn),
4463 strerror(saved_errno)));
4464 errno = saved_errno;
4465 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4466 }
4467 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
4468 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4469 /* No outbuf here means successful sendfile. */
4470 goto out;
4471 }
4472
4473 DEBUG(0,("send_file_readX: sendfile failed for file "
4474 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
4475 strerror(errno)));
4476 exit_server_cleanly("send_file_readX sendfile failed");
4477 } else if (nread == 0) {
4478 /*
4479 * Some sendfile implementations return 0 to indicate
4480 * that there was a short read, but nothing was
4481 * actually written to the socket. In this case,
4482 * fallback to the normal read path so the header gets
4483 * the correct byte count.
4484 */
4485 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
4486 "falling back to the normal read: %s\n",
4487 fsp_str_dbg(fsp)));
4488 goto normal_read;
4489 }
4490
4491 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
4492 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4493
4494 /* Deal with possible short send. */
4495 if (nread != smb_maxcnt + sizeof(headerbuf)) {
4496 ssize_t ret;
4497
4498 ret = sendfile_short_send(xconn, fsp, nread,
4499 sizeof(headerbuf), smb_maxcnt);
4500 if (ret == -1) {
4501 const char *r;
4502 r = "send_file_readX: sendfile_short_send failed";
4503 DEBUG(0,("%s for file %s (%s).\n",
4504 r, fsp_str_dbg(fsp), strerror(errno)));
4505 exit_server_cleanly(r);
4506 }
4507 }
4508 /* No outbuf here means successful sendfile. */
4509 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
4510 SMB_PERFCOUNT_END(&req->pcd);
4511 goto out;
4512 }
4513
4514 normal_read:
4515
4516 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
4517 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
4518 ssize_t ret;
4519
4520 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
4521 (startpos > fsp->fsp_name->st.st_ex_size) ||
4522 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
4523 /*
4524 * We already know that we would do a short
4525 * read, so don't try the sendfile() path.
4526 */
4527 goto nosendfile_read;
4528 }
4529
4530 construct_reply_common_req(req, (char *)headerbuf);
4531 setup_readX_header((char *)headerbuf, smb_maxcnt);
4532
4533 /* Send out the header. */
4534 ret = write_data(xconn->transport.sock, (char *)headerbuf,
4535 sizeof(headerbuf));
4536 if (ret != sizeof(headerbuf)) {
4537 saved_errno = errno;
4538 /*
4539 * Try and give an error message saying what
4540 * client failed.
4541 */
4542 DEBUG(0,("send_file_readX: write_data failed for file "
4543 "%s (%s) for client %s. Terminating\n",
4544 fsp_str_dbg(fsp),
4545 smbXsrv_connection_dbg(xconn),
4546 strerror(saved_errno)));
4547 errno = saved_errno;
4548 exit_server_cleanly("send_file_readX sendfile failed");
4549 }
4550 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
4551 if (nread == -1) {
4552 saved_errno = errno;
4553 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
4554 "%s (%s) for client %s. Terminating\n",
4555 fsp_str_dbg(fsp),
4556 smbXsrv_connection_dbg(xconn),
4557 strerror(saved_errno)));
4558 errno = saved_errno;
4559 exit_server_cleanly("send_file_readX: fake_sendfile failed");
4560 }
4561 goto out;
4562 }
4563
4564 nosendfile_read:
4565
4566 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
4567 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4568 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4569
4570 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
4571 startpos, smb_maxcnt);
4572 saved_errno = errno;
4573
4574 if (nread < 0) {
4575 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4576 return;
4577 }
4578
4579 setup_readX_header((char *)req->outbuf, nread);
4580
4581 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
4582 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
4583 return;
4584
4585 out:
4586 TALLOC_FREE(req->outbuf);
4587 return;
4588 }
4589
4590 /****************************************************************************
4591 Work out how much space we have for a read return.
4592 ****************************************************************************/
4593
calc_max_read_pdu(const struct smb_request * req)4594 static size_t calc_max_read_pdu(const struct smb_request *req)
4595 {
4596 struct smbXsrv_connection *xconn = req->xconn;
4597
4598 if (xconn->protocol < PROTOCOL_NT1) {
4599 return xconn->smb1.sessions.max_send;
4600 }
4601
4602 if (!lp_large_readwrite()) {
4603 return xconn->smb1.sessions.max_send;
4604 }
4605
4606 if (req_is_in_chain(req)) {
4607 return xconn->smb1.sessions.max_send;
4608 }
4609
4610 if (req->encrypted) {
4611 /*
4612 * Don't take encrypted traffic up to the
4613 * limit. There are padding considerations
4614 * that make that tricky.
4615 */
4616 return xconn->smb1.sessions.max_send;
4617 }
4618
4619 if (srv_is_signing_active(xconn)) {
4620 return 0x1FFFF;
4621 }
4622
4623 if (!lp_unix_extensions()) {
4624 return 0x1FFFF;
4625 }
4626
4627 /*
4628 * We can do ultra-large POSIX reads.
4629 */
4630 return 0xFFFFFF;
4631 }
4632
4633 /****************************************************************************
4634 Calculate how big a read can be. Copes with all clients. It's always
4635 safe to return a short read - Windows does this.
4636 ****************************************************************************/
4637
calc_read_size(const struct smb_request * req,size_t upper_size,size_t lower_size)4638 static size_t calc_read_size(const struct smb_request *req,
4639 size_t upper_size,
4640 size_t lower_size)
4641 {
4642 struct smbXsrv_connection *xconn = req->xconn;
4643 size_t max_pdu = calc_max_read_pdu(req);
4644 size_t total_size = 0;
4645 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4646 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4647
4648 /*
4649 * Windows explicitly ignores upper size of 0xFFFF.
4650 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4651 * We must do the same as these will never fit even in
4652 * an extended size NetBIOS packet.
4653 */
4654 if (upper_size == 0xFFFF) {
4655 upper_size = 0;
4656 }
4657
4658 if (xconn->protocol < PROTOCOL_NT1) {
4659 upper_size = 0;
4660 }
4661
4662 total_size = ((upper_size<<16) | lower_size);
4663
4664 /*
4665 * LARGE_READX test shows it's always safe to return
4666 * a short read. Windows does so.
4667 */
4668 return MIN(total_size, max_len);
4669 }
4670
4671 /****************************************************************************
4672 Reply to a read and X.
4673 ****************************************************************************/
4674
reply_read_and_X(struct smb_request * req)4675 void reply_read_and_X(struct smb_request *req)
4676 {
4677 connection_struct *conn = req->conn;
4678 files_struct *fsp;
4679 off_t startpos;
4680 size_t smb_maxcnt;
4681 size_t upper_size;
4682 bool big_readX = False;
4683 #if 0
4684 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4685 #endif
4686
4687 START_PROFILE(SMBreadX);
4688
4689 if ((req->wct != 10) && (req->wct != 12)) {
4690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4691 return;
4692 }
4693
4694 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4695 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4696 smb_maxcnt = SVAL(req->vwv+5, 0);
4697
4698 /* If it's an IPC, pass off the pipe handler. */
4699 if (IS_IPC(conn)) {
4700 reply_pipe_read_and_X(req);
4701 END_PROFILE(SMBreadX);
4702 return;
4703 }
4704
4705 if (!check_fsp(conn, req, fsp)) {
4706 END_PROFILE(SMBreadX);
4707 return;
4708 }
4709
4710 if (!CHECK_READ(fsp,req)) {
4711 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4712 END_PROFILE(SMBreadX);
4713 return;
4714 }
4715
4716 upper_size = SVAL(req->vwv+7, 0);
4717 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4718 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4719 /*
4720 * This is a heuristic to avoid keeping large
4721 * outgoing buffers around over long-lived aio
4722 * requests.
4723 */
4724 big_readX = True;
4725 }
4726
4727 if (req->wct == 12) {
4728 /*
4729 * This is a large offset (64 bit) read.
4730 */
4731 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4732
4733 }
4734
4735 if (!big_readX) {
4736 NTSTATUS status = schedule_aio_read_and_X(conn,
4737 req,
4738 fsp,
4739 startpos,
4740 smb_maxcnt);
4741 if (NT_STATUS_IS_OK(status)) {
4742 /* Read scheduled - we're done. */
4743 goto out;
4744 }
4745 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4746 /* Real error - report to client. */
4747 END_PROFILE(SMBreadX);
4748 reply_nterror(req, status);
4749 return;
4750 }
4751 /* NT_STATUS_RETRY - fall back to sync read. */
4752 }
4753
4754 smbd_lock_socket(req->xconn);
4755 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4756 smbd_unlock_socket(req->xconn);
4757
4758 out:
4759 END_PROFILE(SMBreadX);
4760 return;
4761 }
4762
4763 /****************************************************************************
4764 Error replies to writebraw must have smb_wct == 1. Fix this up.
4765 ****************************************************************************/
4766
error_to_writebrawerr(struct smb_request * req)4767 void error_to_writebrawerr(struct smb_request *req)
4768 {
4769 uint8_t *old_outbuf = req->outbuf;
4770
4771 reply_outbuf(req, 1, 0);
4772
4773 memcpy(req->outbuf, old_outbuf, smb_size);
4774 TALLOC_FREE(old_outbuf);
4775 }
4776
4777 /****************************************************************************
4778 Read 4 bytes of a smb packet and return the smb length of the packet.
4779 Store the result in the buffer. This version of the function will
4780 never return a session keepalive (length of zero).
4781 Timeout is in milliseconds.
4782 ****************************************************************************/
4783
read_smb_length(int fd,char * inbuf,unsigned int timeout,size_t * len)4784 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4785 size_t *len)
4786 {
4787 uint8_t msgtype = NBSSkeepalive;
4788
4789 while (msgtype == NBSSkeepalive) {
4790 NTSTATUS status;
4791
4792 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4793 len);
4794 if (!NT_STATUS_IS_OK(status)) {
4795 char addr[INET6_ADDRSTRLEN];
4796 /* Try and give an error message
4797 * saying what client failed. */
4798 DEBUG(0, ("read_smb_length_return_keepalive failed for "
4799 "client %s read error = %s.\n",
4800 get_peer_addr(fd,addr,sizeof(addr)),
4801 nt_errstr(status)));
4802 return status;
4803 }
4804
4805 msgtype = CVAL(inbuf, 0);
4806 }
4807
4808 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4809 (unsigned long)len));
4810
4811 return NT_STATUS_OK;
4812 }
4813
4814 /****************************************************************************
4815 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4816 ****************************************************************************/
4817
reply_writebraw(struct smb_request * req)4818 void reply_writebraw(struct smb_request *req)
4819 {
4820 connection_struct *conn = req->conn;
4821 struct smbXsrv_connection *xconn = req->xconn;
4822 char *buf = NULL;
4823 ssize_t nwritten=0;
4824 ssize_t total_written=0;
4825 size_t numtowrite=0;
4826 size_t tcount;
4827 off_t startpos;
4828 const char *data=NULL;
4829 bool write_through;
4830 files_struct *fsp;
4831 struct lock_struct lock;
4832 NTSTATUS status;
4833
4834 START_PROFILE(SMBwritebraw);
4835
4836 /*
4837 * If we ever reply with an error, it must have the SMB command
4838 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4839 * we're finished.
4840 */
4841 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4842
4843 if (srv_is_signing_active(xconn)) {
4844 END_PROFILE(SMBwritebraw);
4845 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4846 "raw reads/writes are disallowed.");
4847 }
4848
4849 if (req->wct < 12) {
4850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4851 error_to_writebrawerr(req);
4852 END_PROFILE(SMBwritebraw);
4853 return;
4854 }
4855
4856 if (xconn->smb1.echo_handler.trusted_fde) {
4857 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4858 "'async smb echo handler = yes'\n"));
4859 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4860 error_to_writebrawerr(req);
4861 END_PROFILE(SMBwritebraw);
4862 return;
4863 }
4864
4865 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4866 if (!check_fsp(conn, req, fsp)) {
4867 error_to_writebrawerr(req);
4868 END_PROFILE(SMBwritebraw);
4869 return;
4870 }
4871
4872 if (!CHECK_WRITE(fsp)) {
4873 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4874 error_to_writebrawerr(req);
4875 END_PROFILE(SMBwritebraw);
4876 return;
4877 }
4878
4879 tcount = IVAL(req->vwv+1, 0);
4880 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4881 write_through = BITSETW(req->vwv+7,0);
4882
4883 /* We have to deal with slightly different formats depending
4884 on whether we are using the core+ or lanman1.0 protocol */
4885
4886 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4887 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4888 data = smb_buf_const(req->inbuf);
4889 } else {
4890 numtowrite = SVAL(req->vwv+10, 0);
4891 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4892 }
4893
4894 /* Ensure we don't write bytes past the end of this packet. */
4895 /*
4896 * This already protects us against CVE-2017-12163.
4897 */
4898 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 error_to_writebrawerr(req);
4901 END_PROFILE(SMBwritebraw);
4902 return;
4903 }
4904
4905 if (!fsp->print_file) {
4906 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4907 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4908 &lock);
4909
4910 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
4911 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4912 error_to_writebrawerr(req);
4913 END_PROFILE(SMBwritebraw);
4914 return;
4915 }
4916 }
4917
4918 if (numtowrite>0) {
4919 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4920 }
4921
4922 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4923 "wrote=%d sync=%d\n",
4924 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4925 (int)nwritten, (int)write_through));
4926
4927 if (nwritten < (ssize_t)numtowrite) {
4928 reply_nterror(req, NT_STATUS_DISK_FULL);
4929 error_to_writebrawerr(req);
4930 goto out;
4931 }
4932
4933 total_written = nwritten;
4934
4935 /* Allocate a buffer of 64k + length. */
4936 buf = talloc_array(NULL, char, 65540);
4937 if (!buf) {
4938 reply_nterror(req, NT_STATUS_NO_MEMORY);
4939 error_to_writebrawerr(req);
4940 goto out;
4941 }
4942
4943 /* Return a SMBwritebraw message to the redirector to tell
4944 * it to send more bytes */
4945
4946 memcpy(buf, req->inbuf, smb_size);
4947 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4948 SCVAL(buf,smb_com,SMBwritebraw);
4949 SSVALS(buf,smb_vwv0,0xFFFF);
4950 show_msg(buf);
4951 if (!srv_send_smb(req->xconn,
4952 buf,
4953 false, 0, /* no signing */
4954 IS_CONN_ENCRYPTED(conn),
4955 &req->pcd)) {
4956 exit_server_cleanly("reply_writebraw: srv_send_smb "
4957 "failed.");
4958 }
4959
4960 /* Now read the raw data into the buffer and write it */
4961 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4962 &numtowrite);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 exit_server_cleanly("secondary writebraw failed");
4965 }
4966
4967 /* Set up outbuf to return the correct size */
4968 reply_outbuf(req, 1, 0);
4969
4970 if (numtowrite != 0) {
4971
4972 if (numtowrite > 0xFFFF) {
4973 DEBUG(0,("reply_writebraw: Oversize secondary write "
4974 "raw requested (%u). Terminating\n",
4975 (unsigned int)numtowrite ));
4976 exit_server_cleanly("secondary writebraw failed");
4977 }
4978
4979 if (tcount > nwritten+numtowrite) {
4980 DEBUG(3,("reply_writebraw: Client overestimated the "
4981 "write %d %d %d\n",
4982 (int)tcount,(int)nwritten,(int)numtowrite));
4983 }
4984
4985 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4986 numtowrite);
4987
4988 if (!NT_STATUS_IS_OK(status)) {
4989 /* Try and give an error message
4990 * saying what client failed. */
4991 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4992 "raw read failed (%s) for client %s. "
4993 "Terminating\n", nt_errstr(status),
4994 smbXsrv_connection_dbg(xconn)));
4995 exit_server_cleanly("secondary writebraw failed");
4996 }
4997
4998 /*
4999 * We are not vulnerable to CVE-2017-12163
5000 * here as we are guaranteed to have numtowrite
5001 * bytes available - we just read from the client.
5002 */
5003 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
5004 if (nwritten == -1) {
5005 TALLOC_FREE(buf);
5006 reply_nterror(req, map_nt_error_from_unix(errno));
5007 error_to_writebrawerr(req);
5008 goto out;
5009 }
5010
5011 if (nwritten < (ssize_t)numtowrite) {
5012 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5013 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5014 }
5015
5016 if (nwritten > 0) {
5017 total_written += nwritten;
5018 }
5019 }
5020
5021 TALLOC_FREE(buf);
5022 SSVAL(req->outbuf,smb_vwv0,total_written);
5023
5024 status = sync_file(conn, fsp, write_through);
5025 if (!NT_STATUS_IS_OK(status)) {
5026 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
5027 fsp_str_dbg(fsp), nt_errstr(status)));
5028 reply_nterror(req, status);
5029 error_to_writebrawerr(req);
5030 goto out;
5031 }
5032
5033 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
5034 "wrote=%d\n",
5035 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
5036 (int)total_written));
5037
5038 /* We won't return a status if write through is not selected - this
5039 * follows what WfWg does */
5040 END_PROFILE(SMBwritebraw);
5041
5042 if (!write_through && total_written==tcount) {
5043
5044 #if RABBIT_PELLET_FIX
5045 /*
5046 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
5047 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
5048 * JRA.
5049 */
5050 if (!send_keepalive(xconn->transport.sock)) {
5051 exit_server_cleanly("reply_writebraw: send of "
5052 "keepalive failed");
5053 }
5054 #endif
5055 TALLOC_FREE(req->outbuf);
5056 }
5057 return;
5058
5059 out:
5060 END_PROFILE(SMBwritebraw);
5061 return;
5062 }
5063
5064 #undef DBGC_CLASS
5065 #define DBGC_CLASS DBGC_LOCKING
5066
5067 /****************************************************************************
5068 Reply to a writeunlock (core+).
5069 ****************************************************************************/
5070
reply_writeunlock(struct smb_request * req)5071 void reply_writeunlock(struct smb_request *req)
5072 {
5073 connection_struct *conn = req->conn;
5074 ssize_t nwritten = -1;
5075 size_t numtowrite;
5076 size_t remaining;
5077 off_t startpos;
5078 const char *data;
5079 NTSTATUS status = NT_STATUS_OK;
5080 files_struct *fsp;
5081 struct lock_struct lock;
5082 int saved_errno = 0;
5083
5084 START_PROFILE(SMBwriteunlock);
5085
5086 if (req->wct < 5) {
5087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 END_PROFILE(SMBwriteunlock);
5089 return;
5090 }
5091
5092 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5093
5094 if (!check_fsp(conn, req, fsp)) {
5095 END_PROFILE(SMBwriteunlock);
5096 return;
5097 }
5098
5099 if (!CHECK_WRITE(fsp)) {
5100 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5101 END_PROFILE(SMBwriteunlock);
5102 return;
5103 }
5104
5105 numtowrite = SVAL(req->vwv+1, 0);
5106 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5107 data = (const char *)req->buf + 3;
5108
5109 /*
5110 * Ensure client isn't asking us to write more than
5111 * they sent. CVE-2017-12163.
5112 */
5113 remaining = smbreq_bufrem(req, data);
5114 if (numtowrite > remaining) {
5115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5116 END_PROFILE(SMBwriteunlock);
5117 return;
5118 }
5119
5120 if (!fsp->print_file && numtowrite > 0) {
5121 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5122 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5123 &lock);
5124
5125 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5126 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5127 END_PROFILE(SMBwriteunlock);
5128 return;
5129 }
5130 }
5131
5132 /* The special X/Open SMB protocol handling of
5133 zero length writes is *NOT* done for
5134 this call */
5135 if(numtowrite == 0) {
5136 nwritten = 0;
5137 } else {
5138 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5139 saved_errno = errno;
5140 }
5141
5142 status = sync_file(conn, fsp, False /* write through */);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
5145 fsp_str_dbg(fsp), nt_errstr(status)));
5146 reply_nterror(req, status);
5147 goto out;
5148 }
5149
5150 if(nwritten < 0) {
5151 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5152 goto out;
5153 }
5154
5155 if((nwritten < numtowrite) && (numtowrite != 0)) {
5156 reply_nterror(req, NT_STATUS_DISK_FULL);
5157 goto out;
5158 }
5159
5160 if (numtowrite && !fsp->print_file) {
5161 struct smbd_lock_element l = {
5162 .req_guid = smbd_request_guid(req, 0),
5163 .smblctx = req->smbpid,
5164 .brltype = UNLOCK_LOCK,
5165 .offset = startpos,
5166 .count = numtowrite,
5167 };
5168 status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK);
5169 if (NT_STATUS_V(status)) {
5170 reply_nterror(req, status);
5171 goto out;
5172 }
5173 }
5174
5175 reply_outbuf(req, 1, 0);
5176
5177 SSVAL(req->outbuf,smb_vwv0,nwritten);
5178
5179 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
5180 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5181
5182 out:
5183 END_PROFILE(SMBwriteunlock);
5184 return;
5185 }
5186
5187 #undef DBGC_CLASS
5188 #define DBGC_CLASS DBGC_ALL
5189
5190 /****************************************************************************
5191 Reply to a write.
5192 ****************************************************************************/
5193
reply_write(struct smb_request * req)5194 void reply_write(struct smb_request *req)
5195 {
5196 connection_struct *conn = req->conn;
5197 size_t numtowrite;
5198 size_t remaining;
5199 ssize_t nwritten = -1;
5200 off_t startpos;
5201 const char *data;
5202 files_struct *fsp;
5203 struct lock_struct lock;
5204 NTSTATUS status;
5205 int saved_errno = 0;
5206
5207 START_PROFILE(SMBwrite);
5208
5209 if (req->wct < 5) {
5210 END_PROFILE(SMBwrite);
5211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5212 return;
5213 }
5214
5215 /* If it's an IPC, pass off the pipe handler. */
5216 if (IS_IPC(conn)) {
5217 reply_pipe_write(req);
5218 END_PROFILE(SMBwrite);
5219 return;
5220 }
5221
5222 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5223
5224 if (!check_fsp(conn, req, fsp)) {
5225 END_PROFILE(SMBwrite);
5226 return;
5227 }
5228
5229 if (!CHECK_WRITE(fsp)) {
5230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5231 END_PROFILE(SMBwrite);
5232 return;
5233 }
5234
5235 numtowrite = SVAL(req->vwv+1, 0);
5236 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5237 data = (const char *)req->buf + 3;
5238
5239 /*
5240 * Ensure client isn't asking us to write more than
5241 * they sent. CVE-2017-12163.
5242 */
5243 remaining = smbreq_bufrem(req, data);
5244 if (numtowrite > remaining) {
5245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5246 END_PROFILE(SMBwrite);
5247 return;
5248 }
5249
5250 if (!fsp->print_file) {
5251 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5252 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5253 &lock);
5254
5255 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5256 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5257 END_PROFILE(SMBwrite);
5258 return;
5259 }
5260 }
5261
5262 /*
5263 * X/Open SMB protocol says that if smb_vwv1 is
5264 * zero then the file size should be extended or
5265 * truncated to the size given in smb_vwv[2-3].
5266 */
5267
5268 if(numtowrite == 0) {
5269 /*
5270 * This is actually an allocate call, and set EOF. JRA.
5271 */
5272 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
5273 if (nwritten < 0) {
5274 reply_nterror(req, NT_STATUS_DISK_FULL);
5275 goto out;
5276 }
5277 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
5278 if (nwritten < 0) {
5279 reply_nterror(req, NT_STATUS_DISK_FULL);
5280 goto out;
5281 }
5282 trigger_write_time_update_immediate(fsp);
5283 } else {
5284 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5285 }
5286
5287 status = sync_file(conn, fsp, False);
5288 if (!NT_STATUS_IS_OK(status)) {
5289 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
5290 fsp_str_dbg(fsp), nt_errstr(status)));
5291 reply_nterror(req, status);
5292 goto out;
5293 }
5294
5295 if(nwritten < 0) {
5296 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5297 goto out;
5298 }
5299
5300 if((nwritten == 0) && (numtowrite != 0)) {
5301 reply_nterror(req, NT_STATUS_DISK_FULL);
5302 goto out;
5303 }
5304
5305 reply_outbuf(req, 1, 0);
5306
5307 SSVAL(req->outbuf,smb_vwv0,nwritten);
5308
5309 if (nwritten < (ssize_t)numtowrite) {
5310 SCVAL(req->outbuf,smb_rcls,ERRHRD);
5311 SSVAL(req->outbuf,smb_err,ERRdiskfull);
5312 }
5313
5314 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5315
5316 out:
5317 END_PROFILE(SMBwrite);
5318 return;
5319 }
5320
5321 /****************************************************************************
5322 Ensure a buffer is a valid writeX for recvfile purposes.
5323 ****************************************************************************/
5324
5325 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
5326 (2*14) + /* word count (including bcc) */ \
5327 1 /* pad byte */)
5328
is_valid_writeX_buffer(struct smbXsrv_connection * xconn,const uint8_t * inbuf)5329 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
5330 const uint8_t *inbuf)
5331 {
5332 size_t numtowrite;
5333 unsigned int doff = 0;
5334 size_t len = smb_len_large(inbuf);
5335 uint16_t fnum;
5336 struct smbXsrv_open *op = NULL;
5337 struct files_struct *fsp = NULL;
5338 NTSTATUS status;
5339
5340 if (is_encrypted_packet(inbuf)) {
5341 /* Can't do this on encrypted
5342 * connections. */
5343 return false;
5344 }
5345
5346 if (CVAL(inbuf,smb_com) != SMBwriteX) {
5347 return false;
5348 }
5349
5350 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
5351 CVAL(inbuf,smb_wct) != 14) {
5352 DEBUG(10,("is_valid_writeX_buffer: chained or "
5353 "invalid word length.\n"));
5354 return false;
5355 }
5356
5357 fnum = SVAL(inbuf, smb_vwv2);
5358 status = smb1srv_open_lookup(xconn,
5359 fnum,
5360 0, /* now */
5361 &op);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
5364 return false;
5365 }
5366 fsp = op->compat;
5367 if (fsp == NULL) {
5368 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
5369 return false;
5370 }
5371 if (fsp->conn == NULL) {
5372 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
5373 return false;
5374 }
5375
5376 if (IS_IPC(fsp->conn)) {
5377 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
5378 return false;
5379 }
5380 if (IS_PRINT(fsp->conn)) {
5381 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
5382 return false;
5383 }
5384 if (fsp->base_fsp != NULL) {
5385 DEBUG(10,("is_valid_writeX_buffer: stream fsp\n"));
5386 return false;
5387 }
5388 doff = SVAL(inbuf,smb_vwv11);
5389
5390 numtowrite = SVAL(inbuf,smb_vwv10);
5391
5392 if (len > doff && len - doff > 0xFFFF) {
5393 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
5394 }
5395
5396 if (numtowrite == 0) {
5397 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
5398 return false;
5399 }
5400
5401 /* Ensure the sizes match up. */
5402 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
5403 /* no pad byte...old smbclient :-( */
5404 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
5405 (unsigned int)doff,
5406 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
5407 return false;
5408 }
5409
5410 if (len - doff != numtowrite) {
5411 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
5412 "len = %u, doff = %u, numtowrite = %u\n",
5413 (unsigned int)len,
5414 (unsigned int)doff,
5415 (unsigned int)numtowrite ));
5416 return false;
5417 }
5418
5419 DEBUG(10,("is_valid_writeX_buffer: true "
5420 "len = %u, doff = %u, numtowrite = %u\n",
5421 (unsigned int)len,
5422 (unsigned int)doff,
5423 (unsigned int)numtowrite ));
5424
5425 return true;
5426 }
5427
5428 /****************************************************************************
5429 Reply to a write and X.
5430 ****************************************************************************/
5431
reply_write_and_X(struct smb_request * req)5432 void reply_write_and_X(struct smb_request *req)
5433 {
5434 connection_struct *conn = req->conn;
5435 struct smbXsrv_connection *xconn = req->xconn;
5436 files_struct *fsp;
5437 struct lock_struct lock;
5438 off_t startpos;
5439 size_t numtowrite;
5440 bool write_through;
5441 ssize_t nwritten;
5442 unsigned int smb_doff;
5443 unsigned int smblen;
5444 const char *data;
5445 NTSTATUS status;
5446 int saved_errno = 0;
5447
5448 START_PROFILE(SMBwriteX);
5449
5450 if ((req->wct != 12) && (req->wct != 14)) {
5451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5452 goto out;
5453 }
5454
5455 numtowrite = SVAL(req->vwv+10, 0);
5456 smb_doff = SVAL(req->vwv+11, 0);
5457 smblen = smb_len(req->inbuf);
5458
5459 if (req->unread_bytes > 0xFFFF ||
5460 (smblen > smb_doff &&
5461 smblen - smb_doff > 0xFFFF)) {
5462 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
5463 }
5464
5465 if (req->unread_bytes) {
5466 /* Can't do a recvfile write on IPC$ */
5467 if (IS_IPC(conn)) {
5468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5469 goto out;
5470 }
5471 if (numtowrite != req->unread_bytes) {
5472 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5473 goto out;
5474 }
5475 } else {
5476 /*
5477 * This already protects us against CVE-2017-12163.
5478 */
5479 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
5480 smb_doff + numtowrite > smblen) {
5481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5482 goto out;
5483 }
5484 }
5485
5486 /* If it's an IPC, pass off the pipe handler. */
5487 if (IS_IPC(conn)) {
5488 if (req->unread_bytes) {
5489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5490 goto out;
5491 }
5492 reply_pipe_write_and_X(req);
5493 goto out;
5494 }
5495
5496 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
5497 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
5498 write_through = BITSETW(req->vwv+7,0);
5499
5500 if (!check_fsp(conn, req, fsp)) {
5501 goto out;
5502 }
5503
5504 if (!CHECK_WRITE(fsp)) {
5505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5506 goto out;
5507 }
5508
5509 data = smb_base(req->inbuf) + smb_doff;
5510
5511 if(req->wct == 14) {
5512 /*
5513 * This is a large offset (64 bit) write.
5514 */
5515 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
5516
5517 }
5518
5519 /* X/Open SMB protocol says that, unlike SMBwrite
5520 if the length is zero then NO truncation is
5521 done, just a write of zero. To truncate a file,
5522 use SMBwrite. */
5523
5524 if(numtowrite == 0) {
5525 nwritten = 0;
5526 } else {
5527 if (req->unread_bytes == 0) {
5528 status = schedule_aio_write_and_X(conn,
5529 req,
5530 fsp,
5531 data,
5532 startpos,
5533 numtowrite);
5534
5535 if (NT_STATUS_IS_OK(status)) {
5536 /* write scheduled - we're done. */
5537 goto out;
5538 }
5539 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
5540 /* Real error - report to client. */
5541 reply_nterror(req, status);
5542 goto out;
5543 }
5544 /* NT_STATUS_RETRY - fall through to sync write. */
5545 }
5546
5547 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5548 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5549 &lock);
5550
5551 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
5552 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5553 goto out;
5554 }
5555
5556 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5557 saved_errno = errno;
5558 }
5559
5560 if(nwritten < 0) {
5561 reply_nterror(req, map_nt_error_from_unix(saved_errno));
5562 goto out;
5563 }
5564
5565 if((nwritten == 0) && (numtowrite != 0)) {
5566 reply_nterror(req, NT_STATUS_DISK_FULL);
5567 goto out;
5568 }
5569
5570 reply_outbuf(req, 6, 0);
5571 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
5572 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
5573 SSVAL(req->outbuf,smb_vwv2,nwritten);
5574 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
5575
5576 DEBUG(3,("writeX %s num=%d wrote=%d\n",
5577 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
5578
5579 status = sync_file(conn, fsp, write_through);
5580 if (!NT_STATUS_IS_OK(status)) {
5581 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
5582 fsp_str_dbg(fsp), nt_errstr(status)));
5583 reply_nterror(req, status);
5584 goto out;
5585 }
5586
5587 END_PROFILE(SMBwriteX);
5588 return;
5589
5590 out:
5591 if (req->unread_bytes) {
5592 /* writeX failed. drain socket. */
5593 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
5594 req->unread_bytes) {
5595 smb_panic("failed to drain pending bytes");
5596 }
5597 req->unread_bytes = 0;
5598 }
5599
5600 END_PROFILE(SMBwriteX);
5601 return;
5602 }
5603
5604 /****************************************************************************
5605 Reply to a lseek.
5606 ****************************************************************************/
5607
reply_lseek(struct smb_request * req)5608 void reply_lseek(struct smb_request *req)
5609 {
5610 connection_struct *conn = req->conn;
5611 off_t startpos;
5612 off_t res= -1;
5613 int mode,umode;
5614 files_struct *fsp;
5615 NTSTATUS status;
5616
5617 START_PROFILE(SMBlseek);
5618
5619 if (req->wct < 4) {
5620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5621 END_PROFILE(SMBlseek);
5622 return;
5623 }
5624
5625 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5626
5627 if (!check_fsp(conn, req, fsp)) {
5628 return;
5629 }
5630
5631 mode = SVAL(req->vwv+1, 0) & 3;
5632 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5633 startpos = (off_t)IVALS(req->vwv+2, 0);
5634
5635 switch (mode) {
5636 case 0:
5637 umode = SEEK_SET;
5638 res = startpos;
5639 break;
5640 case 1:
5641 umode = SEEK_CUR;
5642 res = fsp->fh->pos + startpos;
5643 break;
5644 case 2:
5645 umode = SEEK_END;
5646 break;
5647 default:
5648 umode = SEEK_SET;
5649 res = startpos;
5650 break;
5651 }
5652
5653 if (umode == SEEK_END) {
5654 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5655 if(errno == EINVAL) {
5656 off_t current_pos = startpos;
5657
5658 status = vfs_stat_fsp(fsp);
5659 if (!NT_STATUS_IS_OK(status)) {
5660 reply_nterror(req, status);
5661 END_PROFILE(SMBlseek);
5662 return;
5663 }
5664
5665 current_pos += fsp->fsp_name->st.st_ex_size;
5666 if(current_pos < 0)
5667 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5668 }
5669 }
5670
5671 if(res == -1) {
5672 reply_nterror(req, map_nt_error_from_unix(errno));
5673 END_PROFILE(SMBlseek);
5674 return;
5675 }
5676 }
5677
5678 fsp->fh->pos = res;
5679
5680 reply_outbuf(req, 2, 0);
5681 SIVAL(req->outbuf,smb_vwv0,res);
5682
5683 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5684 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5685
5686 END_PROFILE(SMBlseek);
5687 return;
5688 }
5689
file_sync_one_fn(struct files_struct * fsp,void * private_data)5690 static struct files_struct *file_sync_one_fn(struct files_struct *fsp,
5691 void *private_data)
5692 {
5693 connection_struct *conn = talloc_get_type_abort(
5694 private_data, connection_struct);
5695
5696 if (conn != fsp->conn) {
5697 return NULL;
5698 }
5699 if (fsp->fh->fd == -1) {
5700 return NULL;
5701 }
5702 sync_file(conn, fsp, True /* write through */);
5703
5704 if (fsp->modified) {
5705 trigger_write_time_update_immediate(fsp);
5706 }
5707
5708 return NULL;
5709 }
5710
5711 /****************************************************************************
5712 Reply to a flush.
5713 ****************************************************************************/
5714
reply_flush(struct smb_request * req)5715 void reply_flush(struct smb_request *req)
5716 {
5717 connection_struct *conn = req->conn;
5718 uint16_t fnum;
5719 files_struct *fsp;
5720
5721 START_PROFILE(SMBflush);
5722
5723 if (req->wct < 1) {
5724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5725 return;
5726 }
5727
5728 fnum = SVAL(req->vwv+0, 0);
5729 fsp = file_fsp(req, fnum);
5730
5731 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5732 return;
5733 }
5734
5735 if (!fsp) {
5736 files_forall(req->sconn, file_sync_one_fn, conn);
5737 } else {
5738 NTSTATUS status = sync_file(conn, fsp, True);
5739 if (!NT_STATUS_IS_OK(status)) {
5740 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5741 fsp_str_dbg(fsp), nt_errstr(status)));
5742 reply_nterror(req, status);
5743 END_PROFILE(SMBflush);
5744 return;
5745 }
5746 if (fsp->modified) {
5747 trigger_write_time_update_immediate(fsp);
5748 }
5749 }
5750
5751 reply_outbuf(req, 0, 0);
5752
5753 DEBUG(3,("flush\n"));
5754 END_PROFILE(SMBflush);
5755 return;
5756 }
5757
5758 /****************************************************************************
5759 Reply to a exit.
5760 conn POINTER CAN BE NULL HERE !
5761 ****************************************************************************/
5762
5763 static struct tevent_req *reply_exit_send(struct smb_request *smb1req);
5764 static void reply_exit_done(struct tevent_req *req);
5765
reply_exit(struct smb_request * smb1req)5766 void reply_exit(struct smb_request *smb1req)
5767 {
5768 struct tevent_req *req;
5769
5770 /*
5771 * Don't setup the profile charge here, take
5772 * it in reply_exit_done(). Not strictly correct
5773 * but better than the other SMB1 async
5774 * code that double-charges at the moment.
5775 */
5776 req = reply_exit_send(smb1req);
5777 if (req == NULL) {
5778 /* Not going async, profile here. */
5779 START_PROFILE(SMBexit);
5780 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
5781 END_PROFILE(SMBexit);
5782 return;
5783 }
5784
5785 /* We're async. This will complete later. */
5786 tevent_req_set_callback(req, reply_exit_done, smb1req);
5787 return;
5788 }
5789
5790 struct reply_exit_state {
5791 struct tevent_queue *wait_queue;
5792 };
5793
5794 static void reply_exit_wait_done(struct tevent_req *subreq);
5795
5796 /****************************************************************************
5797 Async SMB1 exit.
5798 Note, on failure here we deallocate and return NULL to allow the caller to
5799 SMB1 return an error of ERRnomem immediately.
5800 ****************************************************************************/
5801
reply_exit_send(struct smb_request * smb1req)5802 static struct tevent_req *reply_exit_send(struct smb_request *smb1req)
5803 {
5804 struct tevent_req *req;
5805 struct reply_exit_state *state;
5806 struct tevent_req *subreq;
5807 files_struct *fsp;
5808 struct smbd_server_connection *sconn = smb1req->sconn;
5809
5810 req = tevent_req_create(smb1req, &state,
5811 struct reply_exit_state);
5812 if (req == NULL) {
5813 return NULL;
5814 }
5815 state->wait_queue = tevent_queue_create(state,
5816 "reply_exit_wait_queue");
5817 if (tevent_req_nomem(state->wait_queue, req)) {
5818 TALLOC_FREE(req);
5819 return NULL;
5820 }
5821
5822 for (fsp = sconn->files; fsp; fsp = fsp->next) {
5823 if (fsp->file_pid != smb1req->smbpid) {
5824 continue;
5825 }
5826 if (fsp->vuid != smb1req->vuid) {
5827 continue;
5828 }
5829 /*
5830 * Flag the file as close in progress.
5831 * This will prevent any more IO being
5832 * done on it.
5833 */
5834 fsp->closing = true;
5835
5836 if (fsp->num_aio_requests > 0) {
5837 /*
5838 * Now wait until all aio requests on this fsp are
5839 * finished.
5840 *
5841 * We don't set a callback, as we just want to block the
5842 * wait queue and the talloc_free() of fsp->aio_request
5843 * will remove the item from the wait queue.
5844 */
5845 subreq = tevent_queue_wait_send(fsp->aio_requests,
5846 sconn->ev_ctx,
5847 state->wait_queue);
5848 if (tevent_req_nomem(subreq, req)) {
5849 TALLOC_FREE(req);
5850 return NULL;
5851 }
5852 }
5853 }
5854
5855 /*
5856 * Now we add our own waiter to the end of the queue,
5857 * this way we get notified when all pending requests are finished
5858 * and reply to the outstanding SMB1 request.
5859 */
5860 subreq = tevent_queue_wait_send(state,
5861 sconn->ev_ctx,
5862 state->wait_queue);
5863 if (tevent_req_nomem(subreq, req)) {
5864 TALLOC_FREE(req);
5865 return NULL;
5866 }
5867
5868 /*
5869 * We're really going async - move the SMB1 request from
5870 * a talloc stackframe above us to the conn talloc-context.
5871 * We need this to stick around until the wait_done
5872 * callback is invoked.
5873 */
5874 smb1req = talloc_move(sconn, &smb1req);
5875
5876 tevent_req_set_callback(subreq, reply_exit_wait_done, req);
5877
5878 return req;
5879 }
5880
reply_exit_wait_done(struct tevent_req * subreq)5881 static void reply_exit_wait_done(struct tevent_req *subreq)
5882 {
5883 struct tevent_req *req = tevent_req_callback_data(
5884 subreq, struct tevent_req);
5885
5886 tevent_queue_wait_recv(subreq);
5887 TALLOC_FREE(subreq);
5888 tevent_req_done(req);
5889 }
5890
reply_exit_recv(struct tevent_req * req)5891 static NTSTATUS reply_exit_recv(struct tevent_req *req)
5892 {
5893 return tevent_req_simple_recv_ntstatus(req);
5894 }
5895
reply_exit_done(struct tevent_req * req)5896 static void reply_exit_done(struct tevent_req *req)
5897 {
5898 struct smb_request *smb1req = tevent_req_callback_data(
5899 req, struct smb_request);
5900 struct smbd_server_connection *sconn = smb1req->sconn;
5901 struct smbXsrv_connection *xconn = smb1req->xconn;
5902 NTTIME now = timeval_to_nttime(&smb1req->request_time);
5903 struct smbXsrv_session *session = NULL;
5904 files_struct *fsp, *next;
5905 NTSTATUS status;
5906
5907 /*
5908 * Take the profile charge here. Not strictly
5909 * correct but better than the other SMB1 async
5910 * code that double-charges at the moment.
5911 */
5912 START_PROFILE(SMBexit);
5913
5914 status = reply_exit_recv(req);
5915 TALLOC_FREE(req);
5916 if (!NT_STATUS_IS_OK(status)) {
5917 TALLOC_FREE(smb1req);
5918 END_PROFILE(SMBexit);
5919 exit_server(__location__ ": reply_exit_recv failed");
5920 return;
5921 }
5922
5923 /*
5924 * Ensure the session is still valid.
5925 */
5926 status = smb1srv_session_lookup(xconn,
5927 smb1req->vuid,
5928 now,
5929 &session);
5930 if (!NT_STATUS_IS_OK(status)) {
5931 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5932 smb_request_done(smb1req);
5933 END_PROFILE(SMBexit);
5934 }
5935
5936 /*
5937 * Ensure the vuid is still valid - no one
5938 * called reply_ulogoffX() in the meantime.
5939 * reply_exit() doesn't have AS_USER set, so
5940 * use set_current_user_info() directly.
5941 * This is the same logic as in switch_message().
5942 */
5943 if (session->global->auth_session_info != NULL) {
5944 set_current_user_info(
5945 session->global->auth_session_info->unix_info->sanitized_username,
5946 session->global->auth_session_info->unix_info->unix_name,
5947 session->global->auth_session_info->info->domain_name);
5948 }
5949
5950 /* No more aio - do the actual closes. */
5951 for (fsp = sconn->files; fsp; fsp = next) {
5952 bool ok;
5953 next = fsp->next;
5954
5955 if (fsp->file_pid != smb1req->smbpid) {
5956 continue;
5957 }
5958 if (fsp->vuid != smb1req->vuid) {
5959 continue;
5960 }
5961 if (!fsp->closing) {
5962 continue;
5963 }
5964
5965 /*
5966 * reply_exit() has the DO_CHDIR flag set.
5967 */
5968 ok = chdir_current_service(fsp->conn);
5969 if (!ok) {
5970 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
5971 smb_request_done(smb1req);
5972 END_PROFILE(SMBexit);
5973 }
5974 close_file(NULL, fsp, SHUTDOWN_CLOSE);
5975 }
5976
5977 reply_outbuf(smb1req, 0, 0);
5978 /*
5979 * The following call is needed to push the
5980 * reply data back out the socket after async
5981 * return. Plus it frees smb1req.
5982 */
5983 smb_request_done(smb1req);
5984 DBG_INFO("reply_exit complete\n");
5985 END_PROFILE(SMBexit);
5986 return;
5987 }
5988
5989 struct reply_close_state {
5990 files_struct *fsp;
5991 struct smb_request *smbreq;
5992 };
5993
5994 static void do_smb1_close(struct tevent_req *req);
5995
reply_close(struct smb_request * req)5996 void reply_close(struct smb_request *req)
5997 {
5998 connection_struct *conn = req->conn;
5999 NTSTATUS status = NT_STATUS_OK;
6000 files_struct *fsp = NULL;
6001 START_PROFILE(SMBclose);
6002
6003 if (req->wct < 3) {
6004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6005 END_PROFILE(SMBclose);
6006 return;
6007 }
6008
6009 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6010
6011 /*
6012 * We can only use check_fsp if we know it's not a directory.
6013 */
6014
6015 if (!check_fsp_open(conn, req, fsp)) {
6016 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6017 END_PROFILE(SMBclose);
6018 return;
6019 }
6020
6021 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
6022 fsp->is_directory ? "directory" : "file",
6023 fsp->fh->fd, fsp_fnum_dbg(fsp),
6024 conn->num_files_open));
6025
6026 if (!fsp->is_directory) {
6027 time_t t;
6028
6029 /*
6030 * Take care of any time sent in the close.
6031 */
6032
6033 t = srv_make_unix_date3(req->vwv+1);
6034 set_close_write_time(fsp, time_t_to_full_timespec(t));
6035 }
6036
6037 if (fsp->num_aio_requests != 0) {
6038
6039 struct reply_close_state *state;
6040
6041 DEBUG(10, ("closing with aio %u requests pending\n",
6042 fsp->num_aio_requests));
6043
6044 /*
6045 * Flag the file as close in progress.
6046 * This will prevent any more IO being
6047 * done on it.
6048 */
6049 fsp->closing = true;
6050
6051 /*
6052 * We depend on the aio_extra destructor to take care of this
6053 * close request once fsp->num_aio_request drops to 0.
6054 */
6055
6056 fsp->deferred_close = tevent_wait_send(
6057 fsp, fsp->conn->sconn->ev_ctx);
6058 if (fsp->deferred_close == NULL) {
6059 status = NT_STATUS_NO_MEMORY;
6060 goto done;
6061 }
6062
6063 state = talloc(fsp, struct reply_close_state);
6064 if (state == NULL) {
6065 TALLOC_FREE(fsp->deferred_close);
6066 status = NT_STATUS_NO_MEMORY;
6067 goto done;
6068 }
6069 state->fsp = fsp;
6070 state->smbreq = talloc_move(fsp, &req);
6071 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
6072 state);
6073 END_PROFILE(SMBclose);
6074 return;
6075 }
6076
6077 /*
6078 * close_file() returns the unix errno if an error was detected on
6079 * close - normally this is due to a disk full error. If not then it
6080 * was probably an I/O error.
6081 */
6082
6083 status = close_file(req, fsp, NORMAL_CLOSE);
6084 done:
6085 if (!NT_STATUS_IS_OK(status)) {
6086 reply_nterror(req, status);
6087 END_PROFILE(SMBclose);
6088 return;
6089 }
6090
6091 reply_outbuf(req, 0, 0);
6092 END_PROFILE(SMBclose);
6093 return;
6094 }
6095
do_smb1_close(struct tevent_req * req)6096 static void do_smb1_close(struct tevent_req *req)
6097 {
6098 struct reply_close_state *state = tevent_req_callback_data(
6099 req, struct reply_close_state);
6100 struct smb_request *smbreq;
6101 NTSTATUS status;
6102 int ret;
6103
6104 ret = tevent_wait_recv(req);
6105 TALLOC_FREE(req);
6106 if (ret != 0) {
6107 DEBUG(10, ("tevent_wait_recv returned %s\n",
6108 strerror(ret)));
6109 /*
6110 * Continue anyway, this should never happen
6111 */
6112 }
6113
6114 /*
6115 * fsp->smb2_close_request right now is a talloc grandchild of
6116 * fsp. When we close_file(fsp), it would go with it. No chance to
6117 * reply...
6118 */
6119 smbreq = talloc_move(talloc_tos(), &state->smbreq);
6120
6121 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
6122 if (NT_STATUS_IS_OK(status)) {
6123 reply_outbuf(smbreq, 0, 0);
6124 } else {
6125 reply_nterror(smbreq, status);
6126 }
6127 if (!srv_send_smb(smbreq->xconn,
6128 (char *)smbreq->outbuf,
6129 true,
6130 smbreq->seqnum+1,
6131 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
6132 NULL)) {
6133 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
6134 "failed.");
6135 }
6136 TALLOC_FREE(smbreq);
6137 }
6138
6139 /****************************************************************************
6140 Reply to a writeclose (Core+ protocol).
6141 ****************************************************************************/
6142
reply_writeclose(struct smb_request * req)6143 void reply_writeclose(struct smb_request *req)
6144 {
6145 connection_struct *conn = req->conn;
6146 size_t numtowrite;
6147 size_t remaining;
6148 ssize_t nwritten = -1;
6149 NTSTATUS close_status = NT_STATUS_OK;
6150 off_t startpos;
6151 const char *data;
6152 struct timespec mtime;
6153 files_struct *fsp;
6154 struct lock_struct lock;
6155
6156 START_PROFILE(SMBwriteclose);
6157
6158 if (req->wct < 6) {
6159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6160 END_PROFILE(SMBwriteclose);
6161 return;
6162 }
6163
6164 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6165
6166 if (!check_fsp(conn, req, fsp)) {
6167 END_PROFILE(SMBwriteclose);
6168 return;
6169 }
6170 if (!CHECK_WRITE(fsp)) {
6171 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6172 END_PROFILE(SMBwriteclose);
6173 return;
6174 }
6175
6176 numtowrite = SVAL(req->vwv+1, 0);
6177 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
6178 mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
6179 data = (const char *)req->buf + 1;
6180
6181 /*
6182 * Ensure client isn't asking us to write more than
6183 * they sent. CVE-2017-12163.
6184 */
6185 remaining = smbreq_bufrem(req, data);
6186 if (numtowrite > remaining) {
6187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6188 END_PROFILE(SMBwriteclose);
6189 return;
6190 }
6191
6192 if (fsp->print_file == NULL) {
6193 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
6194 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
6195 &lock);
6196
6197 if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) {
6198 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
6199 END_PROFILE(SMBwriteclose);
6200 return;
6201 }
6202 }
6203
6204 nwritten = write_file(req,fsp,data,startpos,numtowrite);
6205
6206 set_close_write_time(fsp, mtime);
6207
6208 /*
6209 * More insanity. W2K only closes the file if writelen > 0.
6210 * JRA.
6211 */
6212
6213 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
6214 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
6215 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
6216
6217 if (numtowrite) {
6218 DEBUG(3,("reply_writeclose: zero length write doesn't close "
6219 "file %s\n", fsp_str_dbg(fsp)));
6220 close_status = close_file(req, fsp, NORMAL_CLOSE);
6221 fsp = NULL;
6222 }
6223
6224 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
6225 reply_nterror(req, NT_STATUS_DISK_FULL);
6226 goto out;
6227 }
6228
6229 if(!NT_STATUS_IS_OK(close_status)) {
6230 reply_nterror(req, close_status);
6231 goto out;
6232 }
6233
6234 reply_outbuf(req, 1, 0);
6235
6236 SSVAL(req->outbuf,smb_vwv0,nwritten);
6237
6238 out:
6239
6240 END_PROFILE(SMBwriteclose);
6241 return;
6242 }
6243
6244 #undef DBGC_CLASS
6245 #define DBGC_CLASS DBGC_LOCKING
6246
6247 /****************************************************************************
6248 Reply to a lock.
6249 ****************************************************************************/
6250
6251 static void reply_lock_done(struct tevent_req *subreq);
6252
reply_lock(struct smb_request * req)6253 void reply_lock(struct smb_request *req)
6254 {
6255 struct tevent_req *subreq = NULL;
6256 connection_struct *conn = req->conn;
6257 files_struct *fsp;
6258 struct smbd_lock_element *lck = NULL;
6259
6260 START_PROFILE(SMBlock);
6261
6262 if (req->wct < 5) {
6263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6264 END_PROFILE(SMBlock);
6265 return;
6266 }
6267
6268 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6269
6270 if (!check_fsp(conn, req, fsp)) {
6271 END_PROFILE(SMBlock);
6272 return;
6273 }
6274
6275 lck = talloc(req, struct smbd_lock_element);
6276 if (lck == NULL) {
6277 reply_nterror(req, NT_STATUS_NO_MEMORY);
6278 END_PROFILE(SMBlock);
6279 return;
6280 }
6281
6282 *lck = (struct smbd_lock_element) {
6283 .req_guid = smbd_request_guid(req, 0),
6284 .smblctx = req->smbpid,
6285 .brltype = WRITE_LOCK,
6286 .count = IVAL(req->vwv+1, 0),
6287 .offset = IVAL(req->vwv+3, 0),
6288 };
6289
6290 DBG_NOTICE("lock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6291 fsp->fh->fd,
6292 fsp_fnum_dbg(fsp),
6293 lck->offset,
6294 lck->count);
6295
6296 subreq = smbd_smb1_do_locks_send(
6297 fsp,
6298 req->sconn->ev_ctx,
6299 &req,
6300 fsp,
6301 0,
6302 false, /* large_offset */
6303 WINDOWS_LOCK,
6304 1,
6305 lck);
6306 if (subreq == NULL) {
6307 reply_nterror(req, NT_STATUS_NO_MEMORY);
6308 END_PROFILE(SMBlock);
6309 return;
6310 }
6311 tevent_req_set_callback(subreq, reply_lock_done, NULL);
6312 END_PROFILE(SMBlock);
6313 }
6314
reply_lock_done(struct tevent_req * subreq)6315 static void reply_lock_done(struct tevent_req *subreq)
6316 {
6317 struct smb_request *req = NULL;
6318 NTSTATUS status;
6319 bool ok;
6320
6321 START_PROFILE(SMBlock);
6322
6323 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
6324 SMB_ASSERT(ok);
6325
6326 status = smbd_smb1_do_locks_recv(subreq);
6327 TALLOC_FREE(subreq);
6328
6329 if (NT_STATUS_IS_OK(status)) {
6330 reply_outbuf(req, 0, 0);
6331 } else {
6332 reply_nterror(req, status);
6333 }
6334
6335 ok = srv_send_smb(req->xconn,
6336 (char *)req->outbuf,
6337 true,
6338 req->seqnum+1,
6339 IS_CONN_ENCRYPTED(req->conn),
6340 NULL);
6341 if (!ok) {
6342 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
6343 }
6344 TALLOC_FREE(req);
6345 END_PROFILE(SMBlock);
6346 }
6347
6348 /****************************************************************************
6349 Reply to a unlock.
6350 ****************************************************************************/
6351
reply_unlock(struct smb_request * req)6352 void reply_unlock(struct smb_request *req)
6353 {
6354 connection_struct *conn = req->conn;
6355 NTSTATUS status;
6356 files_struct *fsp;
6357 struct smbd_lock_element lck;
6358
6359 START_PROFILE(SMBunlock);
6360
6361 if (req->wct < 5) {
6362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6363 END_PROFILE(SMBunlock);
6364 return;
6365 }
6366
6367 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6368
6369 if (!check_fsp(conn, req, fsp)) {
6370 END_PROFILE(SMBunlock);
6371 return;
6372 }
6373
6374 lck = (struct smbd_lock_element) {
6375 .req_guid = smbd_request_guid(req, 0),
6376 .smblctx = req->smbpid,
6377 .brltype = UNLOCK_LOCK,
6378 .offset = IVAL(req->vwv+3, 0),
6379 .count = IVAL(req->vwv+1, 0),
6380 };
6381
6382 status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK);
6383
6384 if (!NT_STATUS_IS_OK(status)) {
6385 reply_nterror(req, status);
6386 END_PROFILE(SMBunlock);
6387 return;
6388 }
6389
6390 DBG_NOTICE("unlock fd=%d %s offset=%"PRIu64" count=%"PRIu64"\n",
6391 fsp->fh->fd,
6392 fsp_fnum_dbg(fsp),
6393 lck.offset,
6394 lck.count);
6395
6396 reply_outbuf(req, 0, 0);
6397
6398 END_PROFILE(SMBunlock);
6399 return;
6400 }
6401
6402 #undef DBGC_CLASS
6403 #define DBGC_CLASS DBGC_ALL
6404
6405 /****************************************************************************
6406 Reply to a tdis.
6407 conn POINTER CAN BE NULL HERE !
6408 ****************************************************************************/
6409
6410 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req);
6411 static void reply_tdis_done(struct tevent_req *req);
6412
reply_tdis(struct smb_request * smb1req)6413 void reply_tdis(struct smb_request *smb1req)
6414 {
6415 connection_struct *conn = smb1req->conn;
6416 struct tevent_req *req;
6417
6418 /*
6419 * Don't setup the profile charge here, take
6420 * it in reply_tdis_done(). Not strictly correct
6421 * but better than the other SMB1 async
6422 * code that double-charges at the moment.
6423 */
6424
6425 if (conn == NULL) {
6426 /* Not going async, profile here. */
6427 START_PROFILE(SMBtdis);
6428 DBG_INFO("Invalid connection in tdis\n");
6429 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6430 END_PROFILE(SMBtdis);
6431 return;
6432 }
6433
6434 req = reply_tdis_send(smb1req);
6435 if (req == NULL) {
6436 /* Not going async, profile here. */
6437 START_PROFILE(SMBtdis);
6438 reply_force_doserror(smb1req, ERRDOS, ERRnomem);
6439 END_PROFILE(SMBtdis);
6440 return;
6441 }
6442 /* We're async. This will complete later. */
6443 tevent_req_set_callback(req, reply_tdis_done, smb1req);
6444 return;
6445 }
6446
6447 struct reply_tdis_state {
6448 struct tevent_queue *wait_queue;
6449 };
6450
6451 static void reply_tdis_wait_done(struct tevent_req *subreq);
6452
6453 /****************************************************************************
6454 Async SMB1 tdis.
6455 Note, on failure here we deallocate and return NULL to allow the caller to
6456 SMB1 return an error of ERRnomem immediately.
6457 ****************************************************************************/
6458
reply_tdis_send(struct smb_request * smb1req)6459 static struct tevent_req *reply_tdis_send(struct smb_request *smb1req)
6460 {
6461 struct tevent_req *req;
6462 struct reply_tdis_state *state;
6463 struct tevent_req *subreq;
6464 connection_struct *conn = smb1req->conn;
6465 files_struct *fsp;
6466
6467 req = tevent_req_create(smb1req, &state,
6468 struct reply_tdis_state);
6469 if (req == NULL) {
6470 return NULL;
6471 }
6472 state->wait_queue = tevent_queue_create(state, "reply_tdis_wait_queue");
6473 if (tevent_req_nomem(state->wait_queue, req)) {
6474 TALLOC_FREE(req);
6475 return NULL;
6476 }
6477
6478 /*
6479 * Make sure that no new request will be able to use this tcon.
6480 * This ensures that once all outstanding fsp->aio_requests
6481 * on this tcon are done, we are safe to close it.
6482 */
6483 conn->tcon->status = NT_STATUS_NETWORK_NAME_DELETED;
6484
6485 for (fsp = conn->sconn->files; fsp; fsp = fsp->next) {
6486 if (fsp->conn != conn) {
6487 continue;
6488 }
6489 /*
6490 * Flag the file as close in progress.
6491 * This will prevent any more IO being
6492 * done on it. Not strictly needed, but
6493 * doesn't hurt to flag it as closing.
6494 */
6495 fsp->closing = true;
6496
6497 if (fsp->num_aio_requests > 0) {
6498 /*
6499 * Now wait until all aio requests on this fsp are
6500 * finished.
6501 *
6502 * We don't set a callback, as we just want to block the
6503 * wait queue and the talloc_free() of fsp->aio_request
6504 * will remove the item from the wait queue.
6505 */
6506 subreq = tevent_queue_wait_send(fsp->aio_requests,
6507 conn->sconn->ev_ctx,
6508 state->wait_queue);
6509 if (tevent_req_nomem(subreq, req)) {
6510 TALLOC_FREE(req);
6511 return NULL;
6512 }
6513 }
6514 }
6515
6516 /*
6517 * Now we add our own waiter to the end of the queue,
6518 * this way we get notified when all pending requests are finished
6519 * and reply to the outstanding SMB1 request.
6520 */
6521 subreq = tevent_queue_wait_send(state,
6522 conn->sconn->ev_ctx,
6523 state->wait_queue);
6524 if (tevent_req_nomem(subreq, req)) {
6525 TALLOC_FREE(req);
6526 return NULL;
6527 }
6528
6529 /*
6530 * We're really going async - move the SMB1 request from
6531 * a talloc stackframe above us to the sconn talloc-context.
6532 * We need this to stick around until the wait_done
6533 * callback is invoked.
6534 */
6535 smb1req = talloc_move(smb1req->sconn, &smb1req);
6536
6537 tevent_req_set_callback(subreq, reply_tdis_wait_done, req);
6538
6539 return req;
6540 }
6541
reply_tdis_wait_done(struct tevent_req * subreq)6542 static void reply_tdis_wait_done(struct tevent_req *subreq)
6543 {
6544 struct tevent_req *req = tevent_req_callback_data(
6545 subreq, struct tevent_req);
6546
6547 tevent_queue_wait_recv(subreq);
6548 TALLOC_FREE(subreq);
6549 tevent_req_done(req);
6550 }
6551
reply_tdis_recv(struct tevent_req * req)6552 static NTSTATUS reply_tdis_recv(struct tevent_req *req)
6553 {
6554 return tevent_req_simple_recv_ntstatus(req);
6555 }
6556
reply_tdis_done(struct tevent_req * req)6557 static void reply_tdis_done(struct tevent_req *req)
6558 {
6559 struct smb_request *smb1req = tevent_req_callback_data(
6560 req, struct smb_request);
6561 NTSTATUS status;
6562 struct smbXsrv_tcon *tcon = smb1req->conn->tcon;
6563 bool ok;
6564
6565 /*
6566 * Take the profile charge here. Not strictly
6567 * correct but better than the other SMB1 async
6568 * code that double-charges at the moment.
6569 */
6570 START_PROFILE(SMBtdis);
6571
6572 status = reply_tdis_recv(req);
6573 TALLOC_FREE(req);
6574 if (!NT_STATUS_IS_OK(status)) {
6575 TALLOC_FREE(smb1req);
6576 END_PROFILE(SMBtdis);
6577 exit_server(__location__ ": reply_tdis_recv failed");
6578 return;
6579 }
6580
6581 /*
6582 * As we've been awoken, we may have changed
6583 * directory in the meantime.
6584 * reply_tdis() has the DO_CHDIR flag set.
6585 */
6586 ok = chdir_current_service(smb1req->conn);
6587 if (!ok) {
6588 reply_force_doserror(smb1req, ERRSRV, ERRinvnid);
6589 smb_request_done(smb1req);
6590 END_PROFILE(SMBtdis);
6591 }
6592
6593 status = smbXsrv_tcon_disconnect(tcon,
6594 smb1req->vuid);
6595 if (!NT_STATUS_IS_OK(status)) {
6596 TALLOC_FREE(smb1req);
6597 END_PROFILE(SMBtdis);
6598 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
6599 return;
6600 }
6601
6602 /* smbXsrv_tcon_disconnect frees smb1req->conn. */
6603 smb1req->conn = NULL;
6604
6605 TALLOC_FREE(tcon);
6606
6607 reply_outbuf(smb1req, 0, 0);
6608 /*
6609 * The following call is needed to push the
6610 * reply data back out the socket after async
6611 * return. Plus it frees smb1req.
6612 */
6613 smb_request_done(smb1req);
6614 END_PROFILE(SMBtdis);
6615 }
6616
6617 /****************************************************************************
6618 Reply to a echo.
6619 conn POINTER CAN BE NULL HERE !
6620 ****************************************************************************/
6621
reply_echo(struct smb_request * req)6622 void reply_echo(struct smb_request *req)
6623 {
6624 connection_struct *conn = req->conn;
6625 struct smb_perfcount_data local_pcd;
6626 struct smb_perfcount_data *cur_pcd;
6627 int smb_reverb;
6628 int seq_num;
6629
6630 START_PROFILE(SMBecho);
6631
6632 smb_init_perfcount_data(&local_pcd);
6633
6634 if (req->wct < 1) {
6635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6636 END_PROFILE(SMBecho);
6637 return;
6638 }
6639
6640 smb_reverb = SVAL(req->vwv+0, 0);
6641
6642 reply_outbuf(req, 1, req->buflen);
6643
6644 /* copy any incoming data back out */
6645 if (req->buflen > 0) {
6646 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
6647 }
6648
6649 if (smb_reverb > 100) {
6650 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
6651 smb_reverb = 100;
6652 }
6653
6654 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
6655
6656 /* this makes sure we catch the request pcd */
6657 if (seq_num == smb_reverb) {
6658 cur_pcd = &req->pcd;
6659 } else {
6660 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
6661 cur_pcd = &local_pcd;
6662 }
6663
6664 SSVAL(req->outbuf,smb_vwv0,seq_num);
6665
6666 show_msg((char *)req->outbuf);
6667 if (!srv_send_smb(req->xconn,
6668 (char *)req->outbuf,
6669 true, req->seqnum+1,
6670 IS_CONN_ENCRYPTED(conn)||req->encrypted,
6671 cur_pcd))
6672 exit_server_cleanly("reply_echo: srv_send_smb failed.");
6673 }
6674
6675 DEBUG(3,("echo %d times\n", smb_reverb));
6676
6677 TALLOC_FREE(req->outbuf);
6678
6679 END_PROFILE(SMBecho);
6680 return;
6681 }
6682
6683 /****************************************************************************
6684 Reply to a printopen.
6685 ****************************************************************************/
6686
reply_printopen(struct smb_request * req)6687 void reply_printopen(struct smb_request *req)
6688 {
6689 connection_struct *conn = req->conn;
6690 files_struct *fsp;
6691 NTSTATUS status;
6692
6693 START_PROFILE(SMBsplopen);
6694
6695 if (req->wct < 2) {
6696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6697 END_PROFILE(SMBsplopen);
6698 return;
6699 }
6700
6701 if (!CAN_PRINT(conn)) {
6702 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6703 END_PROFILE(SMBsplopen);
6704 return;
6705 }
6706
6707 status = file_new(req, conn, &fsp);
6708 if(!NT_STATUS_IS_OK(status)) {
6709 reply_nterror(req, status);
6710 END_PROFILE(SMBsplopen);
6711 return;
6712 }
6713
6714 /* Open for exclusive use, write only. */
6715 status = print_spool_open(fsp, NULL, req->vuid);
6716
6717 if (!NT_STATUS_IS_OK(status)) {
6718 file_free(req, fsp);
6719 reply_nterror(req, status);
6720 END_PROFILE(SMBsplopen);
6721 return;
6722 }
6723
6724 reply_outbuf(req, 1, 0);
6725 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
6726
6727 DEBUG(3,("openprint fd=%d %s\n",
6728 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6729
6730 END_PROFILE(SMBsplopen);
6731 return;
6732 }
6733
6734 /****************************************************************************
6735 Reply to a printclose.
6736 ****************************************************************************/
6737
reply_printclose(struct smb_request * req)6738 void reply_printclose(struct smb_request *req)
6739 {
6740 connection_struct *conn = req->conn;
6741 files_struct *fsp;
6742 NTSTATUS status;
6743
6744 START_PROFILE(SMBsplclose);
6745
6746 if (req->wct < 1) {
6747 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6748 END_PROFILE(SMBsplclose);
6749 return;
6750 }
6751
6752 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6753
6754 if (!check_fsp(conn, req, fsp)) {
6755 END_PROFILE(SMBsplclose);
6756 return;
6757 }
6758
6759 if (!CAN_PRINT(conn)) {
6760 reply_force_doserror(req, ERRSRV, ERRerror);
6761 END_PROFILE(SMBsplclose);
6762 return;
6763 }
6764
6765 DEBUG(3,("printclose fd=%d %s\n",
6766 fsp->fh->fd, fsp_fnum_dbg(fsp)));
6767
6768 status = close_file(req, fsp, NORMAL_CLOSE);
6769
6770 if(!NT_STATUS_IS_OK(status)) {
6771 reply_nterror(req, status);
6772 END_PROFILE(SMBsplclose);
6773 return;
6774 }
6775
6776 reply_outbuf(req, 0, 0);
6777
6778 END_PROFILE(SMBsplclose);
6779 return;
6780 }
6781
6782 /****************************************************************************
6783 Reply to a printqueue.
6784 ****************************************************************************/
6785
reply_printqueue(struct smb_request * req)6786 void reply_printqueue(struct smb_request *req)
6787 {
6788 const struct loadparm_substitution *lp_sub =
6789 loadparm_s3_global_substitution();
6790 connection_struct *conn = req->conn;
6791 int max_count;
6792 int start_index;
6793
6794 START_PROFILE(SMBsplretq);
6795
6796 if (req->wct < 2) {
6797 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6798 END_PROFILE(SMBsplretq);
6799 return;
6800 }
6801
6802 max_count = SVAL(req->vwv+0, 0);
6803 start_index = SVAL(req->vwv+1, 0);
6804
6805 /* we used to allow the client to get the cnum wrong, but that
6806 is really quite gross and only worked when there was only
6807 one printer - I think we should now only accept it if they
6808 get it right (tridge) */
6809 if (!CAN_PRINT(conn)) {
6810 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6811 END_PROFILE(SMBsplretq);
6812 return;
6813 }
6814
6815 reply_outbuf(req, 2, 3);
6816 SSVAL(req->outbuf,smb_vwv0,0);
6817 SSVAL(req->outbuf,smb_vwv1,0);
6818 SCVAL(smb_buf(req->outbuf),0,1);
6819 SSVAL(smb_buf(req->outbuf),1,0);
6820
6821 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
6822 start_index, max_count));
6823
6824 {
6825 TALLOC_CTX *mem_ctx = talloc_tos();
6826 NTSTATUS status;
6827 WERROR werr;
6828 const char *sharename = lp_servicename(mem_ctx, lp_sub, SNUM(conn));
6829 struct rpc_pipe_client *cli = NULL;
6830 struct dcerpc_binding_handle *b = NULL;
6831 struct policy_handle handle;
6832 struct spoolss_DevmodeContainer devmode_ctr;
6833 union spoolss_JobInfo *info;
6834 uint32_t count;
6835 uint32_t num_to_get;
6836 uint32_t first;
6837 uint32_t i;
6838
6839 ZERO_STRUCT(handle);
6840
6841 status = rpc_pipe_open_interface(mem_ctx,
6842 &ndr_table_spoolss,
6843 conn->session_info,
6844 conn->sconn->remote_address,
6845 conn->sconn->local_address,
6846 conn->sconn->msg_ctx,
6847 &cli);
6848 if (!NT_STATUS_IS_OK(status)) {
6849 DEBUG(0, ("reply_printqueue: "
6850 "could not connect to spoolss: %s\n",
6851 nt_errstr(status)));
6852 reply_nterror(req, status);
6853 goto out;
6854 }
6855 b = cli->binding_handle;
6856
6857 ZERO_STRUCT(devmode_ctr);
6858
6859 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
6860 sharename,
6861 NULL, devmode_ctr,
6862 SEC_FLAG_MAXIMUM_ALLOWED,
6863 &handle,
6864 &werr);
6865 if (!NT_STATUS_IS_OK(status)) {
6866 reply_nterror(req, status);
6867 goto out;
6868 }
6869 if (!W_ERROR_IS_OK(werr)) {
6870 reply_nterror(req, werror_to_ntstatus(werr));
6871 goto out;
6872 }
6873
6874 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
6875 &handle,
6876 0, /* firstjob */
6877 0xff, /* numjobs */
6878 2, /* level */
6879 0, /* offered */
6880 &count,
6881 &info);
6882 if (!W_ERROR_IS_OK(werr)) {
6883 reply_nterror(req, werror_to_ntstatus(werr));
6884 goto out;
6885 }
6886
6887 if (max_count > 0) {
6888 first = start_index;
6889 } else {
6890 first = start_index + max_count + 1;
6891 }
6892
6893 if (first >= count) {
6894 num_to_get = first;
6895 } else {
6896 num_to_get = first + MIN(ABS(max_count), count - first);
6897 }
6898
6899 for (i = first; i < num_to_get; i++) {
6900 char blob[28];
6901 char *p = blob;
6902 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
6903 int qstatus;
6904 size_t len = 0;
6905 uint16_t qrapjobid = pjobid_to_rap(sharename,
6906 info[i].info2.job_id);
6907
6908 if (info[i].info2.status == JOB_STATUS_PRINTING) {
6909 qstatus = 2;
6910 } else {
6911 qstatus = 3;
6912 }
6913
6914 srv_put_dos_date2(p, 0, qtime);
6915 SCVAL(p, 4, qstatus);
6916 SSVAL(p, 5, qrapjobid);
6917 SIVAL(p, 7, info[i].info2.size);
6918 SCVAL(p, 11, 0);
6919 status = srvstr_push(blob, req->flags2, p+12,
6920 info[i].info2.notify_name, 16, STR_ASCII, &len);
6921 if (!NT_STATUS_IS_OK(status)) {
6922 reply_nterror(req, status);
6923 goto out;
6924 }
6925 if (message_push_blob(
6926 &req->outbuf,
6927 data_blob_const(
6928 blob, sizeof(blob))) == -1) {
6929 reply_nterror(req, NT_STATUS_NO_MEMORY);
6930 goto out;
6931 }
6932 }
6933
6934 if (count > 0) {
6935 SSVAL(req->outbuf,smb_vwv0,count);
6936 SSVAL(req->outbuf,smb_vwv1,
6937 (max_count>0?first+count:first-1));
6938 SCVAL(smb_buf(req->outbuf),0,1);
6939 SSVAL(smb_buf(req->outbuf),1,28*count);
6940 }
6941
6942
6943 DEBUG(3, ("%u entries returned in queue\n",
6944 (unsigned)count));
6945
6946 out:
6947 if (b && is_valid_policy_hnd(&handle)) {
6948 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
6949 }
6950
6951 }
6952
6953 END_PROFILE(SMBsplretq);
6954 return;
6955 }
6956
6957 /****************************************************************************
6958 Reply to a printwrite.
6959 ****************************************************************************/
6960
reply_printwrite(struct smb_request * req)6961 void reply_printwrite(struct smb_request *req)
6962 {
6963 connection_struct *conn = req->conn;
6964 int numtowrite;
6965 const char *data;
6966 files_struct *fsp;
6967
6968 START_PROFILE(SMBsplwr);
6969
6970 if (req->wct < 1) {
6971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6972 END_PROFILE(SMBsplwr);
6973 return;
6974 }
6975
6976 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
6977
6978 if (!check_fsp(conn, req, fsp)) {
6979 END_PROFILE(SMBsplwr);
6980 return;
6981 }
6982
6983 if (!fsp->print_file) {
6984 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6985 END_PROFILE(SMBsplwr);
6986 return;
6987 }
6988
6989 if (!CHECK_WRITE(fsp)) {
6990 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6991 END_PROFILE(SMBsplwr);
6992 return;
6993 }
6994
6995 numtowrite = SVAL(req->buf, 1);
6996
6997 /*
6998 * This already protects us against CVE-2017-12163.
6999 */
7000 if (req->buflen < numtowrite + 3) {
7001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7002 END_PROFILE(SMBsplwr);
7003 return;
7004 }
7005
7006 data = (const char *)req->buf + 3;
7007
7008 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
7009 reply_nterror(req, map_nt_error_from_unix(errno));
7010 END_PROFILE(SMBsplwr);
7011 return;
7012 }
7013
7014 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
7015
7016 END_PROFILE(SMBsplwr);
7017 return;
7018 }
7019
7020 /****************************************************************************
7021 Reply to a mkdir.
7022 ****************************************************************************/
7023
reply_mkdir(struct smb_request * req)7024 void reply_mkdir(struct smb_request *req)
7025 {
7026 connection_struct *conn = req->conn;
7027 struct smb_filename *smb_dname = NULL;
7028 char *directory = NULL;
7029 NTSTATUS status;
7030 uint32_t ucf_flags;
7031 TALLOC_CTX *ctx = talloc_tos();
7032
7033 START_PROFILE(SMBmkdir);
7034
7035 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7036 STR_TERMINATE, &status);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 reply_nterror(req, status);
7039 goto out;
7040 }
7041
7042 ucf_flags = filename_create_ucf_flags(req, FILE_CREATE);
7043 status = filename_convert(ctx, conn,
7044 directory,
7045 ucf_flags,
7046 NULL,
7047 NULL,
7048 &smb_dname);
7049 if (!NT_STATUS_IS_OK(status)) {
7050 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7051 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7052 ERRSRV, ERRbadpath);
7053 goto out;
7054 }
7055 reply_nterror(req, status);
7056 goto out;
7057 }
7058
7059 status = create_directory(conn, req, smb_dname);
7060
7061 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
7062
7063 if (!NT_STATUS_IS_OK(status)) {
7064
7065 if (!use_nt_status()
7066 && NT_STATUS_EQUAL(status,
7067 NT_STATUS_OBJECT_NAME_COLLISION)) {
7068 /*
7069 * Yes, in the DOS error code case we get a
7070 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
7071 * samba4 torture test.
7072 */
7073 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
7074 }
7075
7076 reply_nterror(req, status);
7077 goto out;
7078 }
7079
7080 reply_outbuf(req, 0, 0);
7081
7082 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
7083 out:
7084 TALLOC_FREE(smb_dname);
7085 END_PROFILE(SMBmkdir);
7086 return;
7087 }
7088
7089 /****************************************************************************
7090 Reply to a rmdir.
7091 ****************************************************************************/
7092
reply_rmdir(struct smb_request * req)7093 void reply_rmdir(struct smb_request *req)
7094 {
7095 connection_struct *conn = req->conn;
7096 struct smb_filename *smb_dname = NULL;
7097 char *directory = NULL;
7098 NTSTATUS status;
7099 TALLOC_CTX *ctx = talloc_tos();
7100 files_struct *fsp = NULL;
7101 int info = 0;
7102 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7103
7104 START_PROFILE(SMBrmdir);
7105
7106 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
7107 STR_TERMINATE, &status);
7108 if (!NT_STATUS_IS_OK(status)) {
7109 reply_nterror(req, status);
7110 goto out;
7111 }
7112
7113 status = filename_convert(ctx, conn,
7114 directory,
7115 ucf_flags,
7116 NULL,
7117 NULL,
7118 &smb_dname);
7119 if (!NT_STATUS_IS_OK(status)) {
7120 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7121 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7122 ERRSRV, ERRbadpath);
7123 goto out;
7124 }
7125 reply_nterror(req, status);
7126 goto out;
7127 }
7128
7129 if (is_ntfs_stream_smb_fname(smb_dname)) {
7130 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
7131 goto out;
7132 }
7133
7134 status = SMB_VFS_CREATE_FILE(
7135 conn, /* conn */
7136 req, /* req */
7137 0, /* root_dir_fid */
7138 smb_dname, /* fname */
7139 DELETE_ACCESS, /* access_mask */
7140 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7141 FILE_SHARE_DELETE),
7142 FILE_OPEN, /* create_disposition*/
7143 FILE_DIRECTORY_FILE, /* create_options */
7144 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
7145 0, /* oplock_request */
7146 NULL, /* lease */
7147 0, /* allocation_size */
7148 0, /* private_flags */
7149 NULL, /* sd */
7150 NULL, /* ea_list */
7151 &fsp, /* result */
7152 &info, /* pinfo */
7153 NULL, NULL); /* create context */
7154
7155 if (!NT_STATUS_IS_OK(status)) {
7156 if (open_was_deferred(req->xconn, req->mid)) {
7157 /* We have re-scheduled this call. */
7158 goto out;
7159 }
7160 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
7161 bool ok = defer_smb1_sharing_violation(req);
7162 if (ok) {
7163 goto out;
7164 }
7165 }
7166 reply_nterror(req, status);
7167 goto out;
7168 }
7169
7170 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
7171 if (!NT_STATUS_IS_OK(status)) {
7172 close_file(req, fsp, ERROR_CLOSE);
7173 reply_nterror(req, status);
7174 goto out;
7175 }
7176
7177 if (!set_delete_on_close(fsp, true,
7178 conn->session_info->security_token,
7179 conn->session_info->unix_token)) {
7180 close_file(req, fsp, ERROR_CLOSE);
7181 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7182 goto out;
7183 }
7184
7185 status = close_file(req, fsp, NORMAL_CLOSE);
7186 if (!NT_STATUS_IS_OK(status)) {
7187 reply_nterror(req, status);
7188 } else {
7189 reply_outbuf(req, 0, 0);
7190 }
7191
7192 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
7193 out:
7194 TALLOC_FREE(smb_dname);
7195 END_PROFILE(SMBrmdir);
7196 return;
7197 }
7198
7199 /*******************************************************************
7200 Resolve wildcards in a filename rename.
7201 ********************************************************************/
7202
resolve_wildcards(TALLOC_CTX * ctx,const char * name1,const char * name2,char ** pp_newname)7203 static bool resolve_wildcards(TALLOC_CTX *ctx,
7204 const char *name1,
7205 const char *name2,
7206 char **pp_newname)
7207 {
7208 char *name2_copy = NULL;
7209 char *root1 = NULL;
7210 char *root2 = NULL;
7211 char *ext1 = NULL;
7212 char *ext2 = NULL;
7213 char *p,*p2, *pname1, *pname2;
7214
7215 name2_copy = talloc_strdup(ctx, name2);
7216 if (!name2_copy) {
7217 return False;
7218 }
7219
7220 pname1 = strrchr_m(name1,'/');
7221 pname2 = strrchr_m(name2_copy,'/');
7222
7223 if (!pname1 || !pname2) {
7224 return False;
7225 }
7226
7227 /* Truncate the copy of name2 at the last '/' */
7228 *pname2 = '\0';
7229
7230 /* Now go past the '/' */
7231 pname1++;
7232 pname2++;
7233
7234 root1 = talloc_strdup(ctx, pname1);
7235 root2 = talloc_strdup(ctx, pname2);
7236
7237 if (!root1 || !root2) {
7238 return False;
7239 }
7240
7241 p = strrchr_m(root1,'.');
7242 if (p) {
7243 *p = 0;
7244 ext1 = talloc_strdup(ctx, p+1);
7245 } else {
7246 ext1 = talloc_strdup(ctx, "");
7247 }
7248 p = strrchr_m(root2,'.');
7249 if (p) {
7250 *p = 0;
7251 ext2 = talloc_strdup(ctx, p+1);
7252 } else {
7253 ext2 = talloc_strdup(ctx, "");
7254 }
7255
7256 if (!ext1 || !ext2) {
7257 return False;
7258 }
7259
7260 p = root1;
7261 p2 = root2;
7262 while (*p2) {
7263 if (*p2 == '?') {
7264 /* Hmmm. Should this be mb-aware ? */
7265 *p2 = *p;
7266 p2++;
7267 } else if (*p2 == '*') {
7268 *p2 = '\0';
7269 root2 = talloc_asprintf(ctx, "%s%s",
7270 root2,
7271 p);
7272 if (!root2) {
7273 return False;
7274 }
7275 break;
7276 } else {
7277 p2++;
7278 }
7279 if (*p) {
7280 p++;
7281 }
7282 }
7283
7284 p = ext1;
7285 p2 = ext2;
7286 while (*p2) {
7287 if (*p2 == '?') {
7288 /* Hmmm. Should this be mb-aware ? */
7289 *p2 = *p;
7290 p2++;
7291 } else if (*p2 == '*') {
7292 *p2 = '\0';
7293 ext2 = talloc_asprintf(ctx, "%s%s",
7294 ext2,
7295 p);
7296 if (!ext2) {
7297 return False;
7298 }
7299 break;
7300 } else {
7301 p2++;
7302 }
7303 if (*p) {
7304 p++;
7305 }
7306 }
7307
7308 if (*ext2) {
7309 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
7310 name2_copy,
7311 root2,
7312 ext2);
7313 } else {
7314 *pp_newname = talloc_asprintf(ctx, "%s/%s",
7315 name2_copy,
7316 root2);
7317 }
7318
7319 if (!*pp_newname) {
7320 return False;
7321 }
7322
7323 return True;
7324 }
7325
7326 /****************************************************************************
7327 Ensure open files have their names updated. Updated to notify other smbd's
7328 asynchronously.
7329 ****************************************************************************/
7330
rename_open_files(connection_struct * conn,struct share_mode_lock * lck,struct file_id id,uint32_t orig_name_hash,const struct smb_filename * smb_fname_dst)7331 static void rename_open_files(connection_struct *conn,
7332 struct share_mode_lock *lck,
7333 struct file_id id,
7334 uint32_t orig_name_hash,
7335 const struct smb_filename *smb_fname_dst)
7336 {
7337 files_struct *fsp;
7338 bool did_rename = False;
7339 NTSTATUS status;
7340 uint32_t new_name_hash = 0;
7341
7342 for(fsp = file_find_di_first(conn->sconn, id); fsp;
7343 fsp = file_find_di_next(fsp)) {
7344 struct file_id_buf idbuf;
7345 /* fsp_name is a relative path under the fsp. To change this for other
7346 sharepaths we need to manipulate relative paths. */
7347 /* TODO - create the absolute path and manipulate the newname
7348 relative to the sharepath. */
7349 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
7350 continue;
7351 }
7352 if (fsp->name_hash != orig_name_hash) {
7353 continue;
7354 }
7355 DBG_DEBUG("renaming file %s "
7356 "(file_id %s) from %s -> %s\n",
7357 fsp_fnum_dbg(fsp),
7358 file_id_str_buf(fsp->file_id, &idbuf),
7359 fsp_str_dbg(fsp),
7360 smb_fname_str_dbg(smb_fname_dst));
7361
7362 status = fsp_set_smb_fname(fsp, smb_fname_dst);
7363 if (NT_STATUS_IS_OK(status)) {
7364 did_rename = True;
7365 new_name_hash = fsp->name_hash;
7366 }
7367 }
7368
7369 if (!did_rename) {
7370 struct file_id_buf idbuf;
7371 DBG_DEBUG("no open files on file_id %s "
7372 "for %s\n",
7373 file_id_str_buf(id, &idbuf),
7374 smb_fname_str_dbg(smb_fname_dst));
7375 }
7376
7377 /* Send messages to all smbd's (not ourself) that the name has changed. */
7378 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
7379 orig_name_hash, new_name_hash,
7380 smb_fname_dst);
7381
7382 }
7383
7384 /****************************************************************************
7385 We need to check if the source path is a parent directory of the destination
7386 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
7387 refuse the rename with a sharing violation. Under UNIX the above call can
7388 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
7389 probably need to check that the client is a Windows one before disallowing
7390 this as a UNIX client (one with UNIX extensions) can know the source is a
7391 symlink and make this decision intelligently. Found by an excellent bug
7392 report from <AndyLiebman@aol.com>.
7393 ****************************************************************************/
7394
rename_path_prefix_equal(const struct smb_filename * smb_fname_src,const struct smb_filename * smb_fname_dst)7395 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
7396 const struct smb_filename *smb_fname_dst)
7397 {
7398 const char *psrc = smb_fname_src->base_name;
7399 const char *pdst = smb_fname_dst->base_name;
7400 size_t slen;
7401
7402 if (psrc[0] == '.' && psrc[1] == '/') {
7403 psrc += 2;
7404 }
7405 if (pdst[0] == '.' && pdst[1] == '/') {
7406 pdst += 2;
7407 }
7408 if ((slen = strlen(psrc)) > strlen(pdst)) {
7409 return False;
7410 }
7411 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
7412 }
7413
7414 /*
7415 * Do the notify calls from a rename
7416 */
7417
notify_rename(connection_struct * conn,bool is_dir,const struct smb_filename * smb_fname_src,const struct smb_filename * smb_fname_dst)7418 static void notify_rename(connection_struct *conn, bool is_dir,
7419 const struct smb_filename *smb_fname_src,
7420 const struct smb_filename *smb_fname_dst)
7421 {
7422 char *parent_dir_src = NULL;
7423 char *parent_dir_dst = NULL;
7424 uint32_t mask;
7425
7426 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
7427 : FILE_NOTIFY_CHANGE_FILE_NAME;
7428
7429 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
7430 &parent_dir_src, NULL) ||
7431 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
7432 &parent_dir_dst, NULL)) {
7433 goto out;
7434 }
7435
7436 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
7437 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
7438 smb_fname_src->base_name);
7439 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
7440 smb_fname_dst->base_name);
7441 }
7442 else {
7443 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
7444 smb_fname_src->base_name);
7445 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
7446 smb_fname_dst->base_name);
7447 }
7448
7449 /* this is a strange one. w2k3 gives an additional event for
7450 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
7451 files, but not directories */
7452 if (!is_dir) {
7453 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7454 FILE_NOTIFY_CHANGE_ATTRIBUTES
7455 |FILE_NOTIFY_CHANGE_CREATION,
7456 smb_fname_dst->base_name);
7457 }
7458 out:
7459 TALLOC_FREE(parent_dir_src);
7460 TALLOC_FREE(parent_dir_dst);
7461 }
7462
7463 /****************************************************************************
7464 Returns an error if the parent directory for a filename is open in an
7465 incompatible way.
7466 ****************************************************************************/
7467
parent_dirname_compatible_open(connection_struct * conn,const struct smb_filename * smb_fname_dst_in)7468 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
7469 const struct smb_filename *smb_fname_dst_in)
7470 {
7471 char *parent_dir = NULL;
7472 struct smb_filename smb_fname_parent;
7473 struct file_id id;
7474 files_struct *fsp = NULL;
7475 int ret;
7476
7477 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
7478 &parent_dir, NULL)) {
7479 return NT_STATUS_NO_MEMORY;
7480 }
7481 ZERO_STRUCT(smb_fname_parent);
7482 smb_fname_parent.base_name = parent_dir;
7483
7484 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
7485 if (ret == -1) {
7486 return map_nt_error_from_unix(errno);
7487 }
7488
7489 /*
7490 * We're only checking on this smbd here, mostly good
7491 * enough.. and will pass tests.
7492 */
7493
7494 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
7495 for (fsp = file_find_di_first(conn->sconn, id); fsp;
7496 fsp = file_find_di_next(fsp)) {
7497 if (fsp->access_mask & DELETE_ACCESS) {
7498 return NT_STATUS_SHARING_VIOLATION;
7499 }
7500 }
7501 return NT_STATUS_OK;
7502 }
7503
7504 /****************************************************************************
7505 Rename an open file - given an fsp.
7506 ****************************************************************************/
7507
rename_internals_fsp(connection_struct * conn,files_struct * fsp,const struct smb_filename * smb_fname_dst_in,uint32_t attrs,bool replace_if_exists)7508 NTSTATUS rename_internals_fsp(connection_struct *conn,
7509 files_struct *fsp,
7510 const struct smb_filename *smb_fname_dst_in,
7511 uint32_t attrs,
7512 bool replace_if_exists)
7513 {
7514 TALLOC_CTX *ctx = talloc_tos();
7515 struct smb_filename *smb_fname_dst = NULL;
7516 NTSTATUS status = NT_STATUS_OK;
7517 struct share_mode_lock *lck = NULL;
7518 uint32_t access_mask = SEC_DIR_ADD_FILE;
7519 bool dst_exists, old_is_stream, new_is_stream;
7520 int ret;
7521
7522 status = check_name(conn, smb_fname_dst_in);
7523 if (!NT_STATUS_IS_OK(status)) {
7524 return status;
7525 }
7526
7527 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
7528 if (!NT_STATUS_IS_OK(status)) {
7529 return status;
7530 }
7531
7532 if (file_has_open_streams(fsp)) {
7533 return NT_STATUS_ACCESS_DENIED;
7534 }
7535
7536 /* Make a copy of the dst smb_fname structs */
7537
7538 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
7539 if (smb_fname_dst == NULL) {
7540 status = NT_STATUS_NO_MEMORY;
7541 goto out;
7542 }
7543
7544 /*
7545 * Check for special case with case preserving and not
7546 * case sensitive. If the new last component differs from the original
7547 * last component only by case, then we should allow
7548 * the rename (user is trying to change the case of the
7549 * filename).
7550 */
7551 if (!conn->case_sensitive && conn->case_preserve &&
7552 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7553 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
7554 char *fname_dst_parent = NULL;
7555 const char *fname_dst_lcomp = NULL;
7556 char *orig_lcomp_path = NULL;
7557 char *orig_lcomp_stream = NULL;
7558 bool ok = true;
7559
7560 /*
7561 * Split off the last component of the processed
7562 * destination name. We will compare this to
7563 * the split components of smb_fname_dst->original_lcomp.
7564 */
7565 if (!parent_dirname(ctx,
7566 smb_fname_dst->base_name,
7567 &fname_dst_parent,
7568 &fname_dst_lcomp)) {
7569 status = NT_STATUS_NO_MEMORY;
7570 goto out;
7571 }
7572
7573 /*
7574 * The original_lcomp component contains
7575 * the last_component of the path + stream
7576 * name (if a stream exists).
7577 *
7578 * Split off the stream name so we
7579 * can check them separately.
7580 */
7581
7582 if (fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) {
7583 /* POSIX - no stream component. */
7584 orig_lcomp_path = talloc_strdup(ctx,
7585 smb_fname_dst->original_lcomp);
7586 if (orig_lcomp_path == NULL) {
7587 ok = false;
7588 }
7589 } else {
7590 ok = split_stream_filename(ctx,
7591 smb_fname_dst->original_lcomp,
7592 &orig_lcomp_path,
7593 &orig_lcomp_stream);
7594 }
7595
7596 if (!ok) {
7597 TALLOC_FREE(fname_dst_parent);
7598 status = NT_STATUS_NO_MEMORY;
7599 goto out;
7600 }
7601
7602 /* If the base names only differ by case, use original. */
7603 if(!strcsequal(fname_dst_lcomp, orig_lcomp_path)) {
7604 char *tmp;
7605 /*
7606 * Replace the modified last component with the
7607 * original.
7608 */
7609 if (!ISDOT(fname_dst_parent)) {
7610 tmp = talloc_asprintf(smb_fname_dst,
7611 "%s/%s",
7612 fname_dst_parent,
7613 orig_lcomp_path);
7614 } else {
7615 tmp = talloc_strdup(smb_fname_dst,
7616 orig_lcomp_path);
7617 }
7618 if (tmp == NULL) {
7619 status = NT_STATUS_NO_MEMORY;
7620 TALLOC_FREE(fname_dst_parent);
7621 TALLOC_FREE(orig_lcomp_path);
7622 TALLOC_FREE(orig_lcomp_stream);
7623 goto out;
7624 }
7625 TALLOC_FREE(smb_fname_dst->base_name);
7626 smb_fname_dst->base_name = tmp;
7627 }
7628
7629 /* If the stream_names only differ by case, use original. */
7630 if(!strcsequal(smb_fname_dst->stream_name,
7631 orig_lcomp_stream)) {
7632 /* Use the original stream. */
7633 char *tmp = talloc_strdup(smb_fname_dst,
7634 orig_lcomp_stream);
7635 if (tmp == NULL) {
7636 status = NT_STATUS_NO_MEMORY;
7637 TALLOC_FREE(fname_dst_parent);
7638 TALLOC_FREE(orig_lcomp_path);
7639 TALLOC_FREE(orig_lcomp_stream);
7640 goto out;
7641 }
7642 TALLOC_FREE(smb_fname_dst->stream_name);
7643 smb_fname_dst->stream_name = tmp;
7644 }
7645 TALLOC_FREE(fname_dst_parent);
7646 TALLOC_FREE(orig_lcomp_path);
7647 TALLOC_FREE(orig_lcomp_stream);
7648 }
7649
7650 /*
7651 * If the src and dest names are identical - including case,
7652 * don't do the rename, just return success.
7653 */
7654
7655 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
7656 strcsequal(fsp->fsp_name->stream_name,
7657 smb_fname_dst->stream_name)) {
7658 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
7659 "- returning success\n",
7660 smb_fname_str_dbg(smb_fname_dst)));
7661 status = NT_STATUS_OK;
7662 goto out;
7663 }
7664
7665 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
7666 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
7667
7668 /* Return the correct error code if both names aren't streams. */
7669 if (!old_is_stream && new_is_stream) {
7670 status = NT_STATUS_OBJECT_NAME_INVALID;
7671 goto out;
7672 }
7673
7674 if (old_is_stream && !new_is_stream) {
7675 status = NT_STATUS_INVALID_PARAMETER;
7676 goto out;
7677 }
7678
7679 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
7680
7681 if(!replace_if_exists && dst_exists) {
7682 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
7683 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7684 smb_fname_str_dbg(smb_fname_dst)));
7685 status = NT_STATUS_OBJECT_NAME_COLLISION;
7686 goto out;
7687 }
7688
7689 if (dst_exists) {
7690 struct file_id fileid = vfs_file_id_from_sbuf(conn,
7691 &smb_fname_dst->st);
7692 files_struct *dst_fsp = file_find_di_first(conn->sconn,
7693 fileid);
7694 /* The file can be open when renaming a stream */
7695 if (dst_fsp && !new_is_stream) {
7696 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
7697 status = NT_STATUS_ACCESS_DENIED;
7698 goto out;
7699 }
7700 }
7701
7702 /* Ensure we have a valid stat struct for the source. */
7703 status = vfs_stat_fsp(fsp);
7704 if (!NT_STATUS_IS_OK(status)) {
7705 goto out;
7706 }
7707
7708 status = can_rename(conn, fsp, attrs);
7709
7710 if (!NT_STATUS_IS_OK(status)) {
7711 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7712 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7713 smb_fname_str_dbg(smb_fname_dst)));
7714 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
7715 status = NT_STATUS_ACCESS_DENIED;
7716 goto out;
7717 }
7718
7719 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
7720 status = NT_STATUS_ACCESS_DENIED;
7721 goto out;
7722 }
7723
7724 /* Do we have rights to move into the destination ? */
7725 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
7726 /* We're moving a directory. */
7727 access_mask = SEC_DIR_ADD_SUBDIR;
7728 }
7729 status = check_parent_access(conn,
7730 smb_fname_dst,
7731 access_mask);
7732 if (!NT_STATUS_IS_OK(status)) {
7733 DBG_INFO("check_parent_access on "
7734 "dst %s returned %s\n",
7735 smb_fname_str_dbg(smb_fname_dst),
7736 nt_errstr(status));
7737 goto out;
7738 }
7739
7740 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7741
7742 /*
7743 * We have the file open ourselves, so not being able to get the
7744 * corresponding share mode lock is a fatal error.
7745 */
7746
7747 SMB_ASSERT(lck != NULL);
7748
7749 ret = SMB_VFS_RENAMEAT(conn,
7750 conn->cwd_fsp,
7751 fsp->fsp_name,
7752 conn->cwd_fsp,
7753 smb_fname_dst);
7754 if (ret == 0) {
7755 uint32_t create_options = fsp->fh->private_options;
7756
7757 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
7758 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
7759 smb_fname_str_dbg(smb_fname_dst)));
7760
7761 if (!fsp->is_directory &&
7762 !(fsp->posix_flags & FSP_POSIX_FLAGS_PATHNAMES) &&
7763 (lp_map_archive(SNUM(conn)) ||
7764 lp_store_dos_attributes(SNUM(conn)))) {
7765 /* We must set the archive bit on the newly
7766 renamed file. */
7767 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
7768 uint32_t old_dosmode = dos_mode(conn,
7769 smb_fname_dst);
7770 file_set_dosmode(conn,
7771 smb_fname_dst,
7772 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
7773 NULL,
7774 true);
7775 }
7776 }
7777
7778 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
7779 smb_fname_dst);
7780
7781 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
7782 smb_fname_dst);
7783
7784 /*
7785 * A rename acts as a new file create w.r.t. allowing an initial delete
7786 * on close, probably because in Windows there is a new handle to the
7787 * new file. If initial delete on close was requested but not
7788 * originally set, we need to set it here. This is probably not 100% correct,
7789 * but will work for the CIFSFS client which in non-posix mode
7790 * depends on these semantics. JRA.
7791 */
7792
7793 if (create_options & FILE_DELETE_ON_CLOSE) {
7794 status = can_set_delete_on_close(fsp, 0);
7795
7796 if (NT_STATUS_IS_OK(status)) {
7797 /* Note that here we set the *initial* delete on close flag,
7798 * not the regular one. The magic gets handled in close. */
7799 fsp->initial_delete_on_close = True;
7800 }
7801 }
7802 TALLOC_FREE(lck);
7803 status = NT_STATUS_OK;
7804 goto out;
7805 }
7806
7807 TALLOC_FREE(lck);
7808
7809 if (errno == ENOTDIR || errno == EISDIR) {
7810 status = NT_STATUS_OBJECT_NAME_COLLISION;
7811 } else {
7812 status = map_nt_error_from_unix(errno);
7813 }
7814
7815 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
7816 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
7817 smb_fname_str_dbg(smb_fname_dst)));
7818
7819 out:
7820 TALLOC_FREE(smb_fname_dst);
7821
7822 return status;
7823 }
7824
7825 /****************************************************************************
7826 The guts of the rename command, split out so it may be called by the NT SMB
7827 code.
7828 ****************************************************************************/
7829
rename_internals(TALLOC_CTX * ctx,connection_struct * conn,struct smb_request * req,struct smb_filename * smb_fname_src,struct smb_filename * smb_fname_dst,uint32_t attrs,bool replace_if_exists,bool src_has_wild,bool dest_has_wild,uint32_t access_mask)7830 NTSTATUS rename_internals(TALLOC_CTX *ctx,
7831 connection_struct *conn,
7832 struct smb_request *req,
7833 struct smb_filename *smb_fname_src,
7834 struct smb_filename *smb_fname_dst,
7835 uint32_t attrs,
7836 bool replace_if_exists,
7837 bool src_has_wild,
7838 bool dest_has_wild,
7839 uint32_t access_mask)
7840 {
7841 char *fname_src_dir = NULL;
7842 struct smb_filename *smb_fname_src_dir = NULL;
7843 char *fname_src_mask = NULL;
7844 int count=0;
7845 NTSTATUS status = NT_STATUS_OK;
7846 struct smb_Dir *dir_hnd = NULL;
7847 const char *dname = NULL;
7848 char *talloced = NULL;
7849 long offset = 0;
7850 int create_options = 0;
7851 bool posix_pathnames = (req != NULL && req->posix_pathnames);
7852 int rc;
7853
7854 /*
7855 * Split the old name into directory and last component
7856 * strings. Note that unix_convert may have stripped off a
7857 * leading ./ from both name and newname if the rename is
7858 * at the root of the share. We need to make sure either both
7859 * name and newname contain a / character or neither of them do
7860 * as this is checked in resolve_wildcards().
7861 */
7862
7863 /* Split up the directory from the filename/mask. */
7864 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7865 &fname_src_dir, &fname_src_mask);
7866 if (!NT_STATUS_IS_OK(status)) {
7867 status = NT_STATUS_NO_MEMORY;
7868 goto out;
7869 }
7870
7871 /*
7872 * We should only check the mangled cache
7873 * here if unix_convert failed. This means
7874 * that the path in 'mask' doesn't exist
7875 * on the file system and so we need to look
7876 * for a possible mangle. This patch from
7877 * Tine Smukavec <valentin.smukavec@hermes.si>.
7878 */
7879
7880 if (!VALID_STAT(smb_fname_src->st) &&
7881 mangle_is_mangled(fname_src_mask, conn->params)) {
7882 char *new_mask = NULL;
7883 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
7884 conn->params);
7885 if (new_mask) {
7886 TALLOC_FREE(fname_src_mask);
7887 fname_src_mask = new_mask;
7888 }
7889 }
7890
7891 if (!src_has_wild) {
7892 files_struct *fsp;
7893
7894 /*
7895 * Only one file needs to be renamed. Append the mask back
7896 * onto the directory.
7897 */
7898 TALLOC_FREE(smb_fname_src->base_name);
7899 if (ISDOT(fname_src_dir)) {
7900 /* Ensure we use canonical names on open. */
7901 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7902 "%s",
7903 fname_src_mask);
7904 } else {
7905 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7906 "%s/%s",
7907 fname_src_dir,
7908 fname_src_mask);
7909 }
7910 if (!smb_fname_src->base_name) {
7911 status = NT_STATUS_NO_MEMORY;
7912 goto out;
7913 }
7914
7915 DEBUG(3, ("rename_internals: case_sensitive = %d, "
7916 "case_preserve = %d, short case preserve = %d, "
7917 "directory = %s, newname = %s, "
7918 "last_component_dest = %s\n",
7919 conn->case_sensitive, conn->case_preserve,
7920 conn->short_case_preserve,
7921 smb_fname_str_dbg(smb_fname_src),
7922 smb_fname_str_dbg(smb_fname_dst),
7923 smb_fname_dst->original_lcomp));
7924
7925 /* The dest name still may have wildcards. */
7926 if (dest_has_wild) {
7927 char *fname_dst_mod = NULL;
7928 if (!resolve_wildcards(smb_fname_dst,
7929 smb_fname_src->base_name,
7930 smb_fname_dst->base_name,
7931 &fname_dst_mod)) {
7932 DEBUG(6, ("rename_internals: resolve_wildcards "
7933 "%s %s failed\n",
7934 smb_fname_src->base_name,
7935 smb_fname_dst->base_name));
7936 status = NT_STATUS_NO_MEMORY;
7937 goto out;
7938 }
7939 TALLOC_FREE(smb_fname_dst->base_name);
7940 smb_fname_dst->base_name = fname_dst_mod;
7941 }
7942
7943 ZERO_STRUCT(smb_fname_src->st);
7944 if (posix_pathnames) {
7945 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
7946 } else {
7947 rc = SMB_VFS_STAT(conn, smb_fname_src);
7948 }
7949 if (rc == -1) {
7950 status = map_nt_error_from_unix_common(errno);
7951 goto out;
7952 }
7953
7954 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
7955 create_options |= FILE_DIRECTORY_FILE;
7956 }
7957
7958 status = SMB_VFS_CREATE_FILE(
7959 conn, /* conn */
7960 req, /* req */
7961 0, /* root_dir_fid */
7962 smb_fname_src, /* fname */
7963 access_mask, /* access_mask */
7964 (FILE_SHARE_READ | /* share_access */
7965 FILE_SHARE_WRITE),
7966 FILE_OPEN, /* create_disposition*/
7967 create_options, /* create_options */
7968 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
7969 0, /* oplock_request */
7970 NULL, /* lease */
7971 0, /* allocation_size */
7972 0, /* private_flags */
7973 NULL, /* sd */
7974 NULL, /* ea_list */
7975 &fsp, /* result */
7976 NULL, /* pinfo */
7977 NULL, NULL); /* create context */
7978
7979 if (!NT_STATUS_IS_OK(status)) {
7980 DEBUG(3, ("Could not open rename source %s: %s\n",
7981 smb_fname_str_dbg(smb_fname_src),
7982 nt_errstr(status)));
7983 goto out;
7984 }
7985
7986 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7987 attrs, replace_if_exists);
7988
7989 close_file(req, fsp, NORMAL_CLOSE);
7990
7991 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
7992 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
7993 smb_fname_str_dbg(smb_fname_dst)));
7994
7995 goto out;
7996 }
7997
7998 /*
7999 * Wildcards - process each file that matches.
8000 */
8001 if (strequal(fname_src_mask, "????????.???")) {
8002 TALLOC_FREE(fname_src_mask);
8003 fname_src_mask = talloc_strdup(ctx, "*");
8004 if (!fname_src_mask) {
8005 status = NT_STATUS_NO_MEMORY;
8006 goto out;
8007 }
8008 }
8009
8010 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8011 fname_src_dir,
8012 NULL,
8013 NULL,
8014 smb_fname_src->flags);
8015 if (smb_fname_src_dir == NULL) {
8016 status = NT_STATUS_NO_MEMORY;
8017 goto out;
8018 }
8019
8020 status = check_name(conn, smb_fname_src_dir);
8021 if (!NT_STATUS_IS_OK(status)) {
8022 goto out;
8023 }
8024
8025 dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
8026 attrs);
8027 if (dir_hnd == NULL) {
8028 status = map_nt_error_from_unix(errno);
8029 goto out;
8030 }
8031
8032 status = NT_STATUS_NO_SUCH_FILE;
8033 /*
8034 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
8035 * - gentest fix. JRA
8036 */
8037
8038 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
8039 &talloced))) {
8040 files_struct *fsp = NULL;
8041 char *destname = NULL;
8042 bool sysdir_entry = False;
8043
8044 /* Quick check for "." and ".." */
8045 if (ISDOT(dname) || ISDOTDOT(dname)) {
8046 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
8047 sysdir_entry = True;
8048 } else {
8049 TALLOC_FREE(talloced);
8050 continue;
8051 }
8052 }
8053
8054 if (!is_visible_file(conn, fname_src_dir, dname,
8055 &smb_fname_src->st, false)) {
8056 TALLOC_FREE(talloced);
8057 continue;
8058 }
8059
8060 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
8061 TALLOC_FREE(talloced);
8062 continue;
8063 }
8064
8065 if (sysdir_entry) {
8066 status = NT_STATUS_OBJECT_NAME_INVALID;
8067 break;
8068 }
8069
8070 TALLOC_FREE(smb_fname_src->base_name);
8071 if (ISDOT(fname_src_dir)) {
8072 /* Ensure we use canonical names on open. */
8073 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8074 "%s",
8075 dname);
8076 } else {
8077 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8078 "%s/%s",
8079 fname_src_dir,
8080 dname);
8081 }
8082 if (!smb_fname_src->base_name) {
8083 status = NT_STATUS_NO_MEMORY;
8084 goto out;
8085 }
8086
8087 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8088 smb_fname_dst->base_name,
8089 &destname)) {
8090 DEBUG(6, ("resolve_wildcards %s %s failed\n",
8091 smb_fname_src->base_name, destname));
8092 TALLOC_FREE(talloced);
8093 continue;
8094 }
8095 if (!destname) {
8096 status = NT_STATUS_NO_MEMORY;
8097 goto out;
8098 }
8099
8100 TALLOC_FREE(smb_fname_dst->base_name);
8101 smb_fname_dst->base_name = destname;
8102
8103 ZERO_STRUCT(smb_fname_src->st);
8104 if (posix_pathnames) {
8105 SMB_VFS_LSTAT(conn, smb_fname_src);
8106 } else {
8107 SMB_VFS_STAT(conn, smb_fname_src);
8108 }
8109
8110 create_options = 0;
8111
8112 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
8113 create_options |= FILE_DIRECTORY_FILE;
8114 }
8115
8116 status = SMB_VFS_CREATE_FILE(
8117 conn, /* conn */
8118 req, /* req */
8119 0, /* root_dir_fid */
8120 smb_fname_src, /* fname */
8121 access_mask, /* access_mask */
8122 (FILE_SHARE_READ | /* share_access */
8123 FILE_SHARE_WRITE),
8124 FILE_OPEN, /* create_disposition*/
8125 create_options, /* create_options */
8126 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
8127 0, /* oplock_request */
8128 NULL, /* lease */
8129 0, /* allocation_size */
8130 0, /* private_flags */
8131 NULL, /* sd */
8132 NULL, /* ea_list */
8133 &fsp, /* result */
8134 NULL, /* pinfo */
8135 NULL, NULL); /* create context */
8136
8137 if (!NT_STATUS_IS_OK(status)) {
8138 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
8139 "returned %s rename %s -> %s\n",
8140 nt_errstr(status),
8141 smb_fname_str_dbg(smb_fname_src),
8142 smb_fname_str_dbg(smb_fname_dst)));
8143 break;
8144 }
8145
8146 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
8147 dname);
8148 if (!smb_fname_dst->original_lcomp) {
8149 status = NT_STATUS_NO_MEMORY;
8150 goto out;
8151 }
8152
8153 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
8154 attrs, replace_if_exists);
8155
8156 close_file(req, fsp, NORMAL_CLOSE);
8157
8158 if (!NT_STATUS_IS_OK(status)) {
8159 DEBUG(3, ("rename_internals_fsp returned %s for "
8160 "rename %s -> %s\n", nt_errstr(status),
8161 smb_fname_str_dbg(smb_fname_src),
8162 smb_fname_str_dbg(smb_fname_dst)));
8163 break;
8164 }
8165
8166 count++;
8167
8168 DEBUG(3,("rename_internals: doing rename on %s -> "
8169 "%s\n", smb_fname_str_dbg(smb_fname_src),
8170 smb_fname_str_dbg(smb_fname_src)));
8171 TALLOC_FREE(talloced);
8172 }
8173 TALLOC_FREE(dir_hnd);
8174
8175 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
8176 status = map_nt_error_from_unix(errno);
8177 }
8178
8179 out:
8180 TALLOC_FREE(talloced);
8181 TALLOC_FREE(smb_fname_src_dir);
8182 TALLOC_FREE(fname_src_dir);
8183 TALLOC_FREE(fname_src_mask);
8184 return status;
8185 }
8186
8187 /****************************************************************************
8188 Reply to a mv.
8189 ****************************************************************************/
8190
reply_mv(struct smb_request * req)8191 void reply_mv(struct smb_request *req)
8192 {
8193 connection_struct *conn = req->conn;
8194 char *name = NULL;
8195 char *newname = NULL;
8196 const char *p;
8197 uint32_t attrs;
8198 NTSTATUS status;
8199 bool src_has_wcard = False;
8200 bool dest_has_wcard = False;
8201 TALLOC_CTX *ctx = talloc_tos();
8202 struct smb_filename *smb_fname_src = NULL;
8203 struct smb_filename *smb_fname_dst = NULL;
8204 uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) |
8205 (req->posix_pathnames ?
8206 UCF_UNIX_NAME_LOOKUP :
8207 UCF_COND_ALLOW_WCARD_LCOMP);
8208 uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) |
8209 UCF_SAVE_LCOMP |
8210 (req->posix_pathnames ?
8211 0 :
8212 UCF_COND_ALLOW_WCARD_LCOMP);
8213 bool stream_rename = false;
8214
8215 START_PROFILE(SMBmv);
8216
8217 if (req->wct < 1) {
8218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8219 goto out;
8220 }
8221
8222 attrs = SVAL(req->vwv+0, 0);
8223
8224 p = (const char *)req->buf + 1;
8225 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
8226 &status, &src_has_wcard);
8227 if (!NT_STATUS_IS_OK(status)) {
8228 reply_nterror(req, status);
8229 goto out;
8230 }
8231 p++;
8232 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
8233 &status, &dest_has_wcard);
8234 if (!NT_STATUS_IS_OK(status)) {
8235 reply_nterror(req, status);
8236 goto out;
8237 }
8238
8239 if (!req->posix_pathnames) {
8240 /* The newname must begin with a ':' if the
8241 name contains a ':'. */
8242 if (strchr_m(name, ':')) {
8243 if (newname[0] != ':') {
8244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8245 goto out;
8246 }
8247 stream_rename = true;
8248 }
8249 }
8250
8251 status = filename_convert(ctx,
8252 conn,
8253 name,
8254 src_ucf_flags,
8255 NULL,
8256 &src_has_wcard,
8257 &smb_fname_src);
8258
8259 if (!NT_STATUS_IS_OK(status)) {
8260 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8261 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8262 ERRSRV, ERRbadpath);
8263 goto out;
8264 }
8265 reply_nterror(req, status);
8266 goto out;
8267 }
8268
8269 status = filename_convert(ctx,
8270 conn,
8271 newname,
8272 dst_ucf_flags,
8273 NULL,
8274 &dest_has_wcard,
8275 &smb_fname_dst);
8276
8277 if (!NT_STATUS_IS_OK(status)) {
8278 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8279 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8280 ERRSRV, ERRbadpath);
8281 goto out;
8282 }
8283 reply_nterror(req, status);
8284 goto out;
8285 }
8286
8287 if (stream_rename) {
8288 /* smb_fname_dst->base_name must be the same as
8289 smb_fname_src->base_name. */
8290 TALLOC_FREE(smb_fname_dst->base_name);
8291 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
8292 smb_fname_src->base_name);
8293 if (!smb_fname_dst->base_name) {
8294 reply_nterror(req, NT_STATUS_NO_MEMORY);
8295 goto out;
8296 }
8297 }
8298
8299 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
8300 smb_fname_str_dbg(smb_fname_dst)));
8301
8302 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
8303 attrs, False, src_has_wcard, dest_has_wcard,
8304 DELETE_ACCESS);
8305 if (!NT_STATUS_IS_OK(status)) {
8306 if (open_was_deferred(req->xconn, req->mid)) {
8307 /* We have re-scheduled this call. */
8308 goto out;
8309 }
8310 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
8311 bool ok = defer_smb1_sharing_violation(req);
8312 if (ok) {
8313 goto out;
8314 }
8315 }
8316 reply_nterror(req, status);
8317 goto out;
8318 }
8319
8320 reply_outbuf(req, 0, 0);
8321 out:
8322 TALLOC_FREE(smb_fname_src);
8323 TALLOC_FREE(smb_fname_dst);
8324 END_PROFILE(SMBmv);
8325 return;
8326 }
8327
8328 /*******************************************************************
8329 Copy a file as part of a reply_copy.
8330 ******************************************************************/
8331
8332 /*
8333 * TODO: check error codes on all callers
8334 */
8335
copy_file(TALLOC_CTX * ctx,connection_struct * conn,struct smb_filename * smb_fname_src,struct smb_filename * smb_fname_dst,int ofun,int count,bool target_is_directory)8336 NTSTATUS copy_file(TALLOC_CTX *ctx,
8337 connection_struct *conn,
8338 struct smb_filename *smb_fname_src,
8339 struct smb_filename *smb_fname_dst,
8340 int ofun,
8341 int count,
8342 bool target_is_directory)
8343 {
8344 struct smb_filename *smb_fname_dst_tmp = NULL;
8345 off_t ret=-1;
8346 files_struct *fsp1,*fsp2;
8347 uint32_t dosattrs;
8348 uint32_t new_create_disposition;
8349 NTSTATUS status;
8350
8351
8352 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
8353 if (smb_fname_dst_tmp == NULL) {
8354 return NT_STATUS_NO_MEMORY;
8355 }
8356
8357 /*
8358 * If the target is a directory, extract the last component from the
8359 * src filename and append it to the dst filename
8360 */
8361 if (target_is_directory) {
8362 const char *p;
8363
8364 /* dest/target can't be a stream if it's a directory. */
8365 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
8366
8367 p = strrchr_m(smb_fname_src->base_name,'/');
8368 if (p) {
8369 p++;
8370 } else {
8371 p = smb_fname_src->base_name;
8372 }
8373 smb_fname_dst_tmp->base_name =
8374 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
8375 p);
8376 if (!smb_fname_dst_tmp->base_name) {
8377 status = NT_STATUS_NO_MEMORY;
8378 goto out;
8379 }
8380 }
8381
8382 status = vfs_file_exist(conn, smb_fname_src);
8383 if (!NT_STATUS_IS_OK(status)) {
8384 goto out;
8385 }
8386
8387 if (!target_is_directory && count) {
8388 new_create_disposition = FILE_OPEN;
8389 } else {
8390 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
8391 0, ofun,
8392 NULL, NULL,
8393 &new_create_disposition,
8394 NULL,
8395 NULL)) {
8396 status = NT_STATUS_INVALID_PARAMETER;
8397 goto out;
8398 }
8399 }
8400
8401 /* Open the src file for reading. */
8402 status = SMB_VFS_CREATE_FILE(
8403 conn, /* conn */
8404 NULL, /* req */
8405 0, /* root_dir_fid */
8406 smb_fname_src, /* fname */
8407 FILE_GENERIC_READ, /* access_mask */
8408 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8409 FILE_OPEN, /* create_disposition*/
8410 0, /* create_options */
8411 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8412 INTERNAL_OPEN_ONLY, /* oplock_request */
8413 NULL, /* lease */
8414 0, /* allocation_size */
8415 0, /* private_flags */
8416 NULL, /* sd */
8417 NULL, /* ea_list */
8418 &fsp1, /* result */
8419 NULL, /* psbuf */
8420 NULL, NULL); /* create context */
8421
8422 if (!NT_STATUS_IS_OK(status)) {
8423 goto out;
8424 }
8425
8426 dosattrs = dos_mode(conn, smb_fname_src);
8427
8428 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
8429 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
8430 }
8431
8432 /* Open the dst file for writing. */
8433 status = SMB_VFS_CREATE_FILE(
8434 conn, /* conn */
8435 NULL, /* req */
8436 0, /* root_dir_fid */
8437 smb_fname_dst, /* fname */
8438 FILE_GENERIC_WRITE, /* access_mask */
8439 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
8440 new_create_disposition, /* create_disposition*/
8441 0, /* create_options */
8442 dosattrs, /* file_attributes */
8443 INTERNAL_OPEN_ONLY, /* oplock_request */
8444 NULL, /* lease */
8445 0, /* allocation_size */
8446 0, /* private_flags */
8447 NULL, /* sd */
8448 NULL, /* ea_list */
8449 &fsp2, /* result */
8450 NULL, /* psbuf */
8451 NULL, NULL); /* create context */
8452
8453 if (!NT_STATUS_IS_OK(status)) {
8454 close_file(NULL, fsp1, ERROR_CLOSE);
8455 goto out;
8456 }
8457
8458 if (ofun & OPENX_FILE_EXISTS_OPEN) {
8459 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
8460 if (ret == -1) {
8461 DEBUG(0, ("error - vfs lseek returned error %s\n",
8462 strerror(errno)));
8463 status = map_nt_error_from_unix(errno);
8464 close_file(NULL, fsp1, ERROR_CLOSE);
8465 close_file(NULL, fsp2, ERROR_CLOSE);
8466 goto out;
8467 }
8468 }
8469
8470 /* Do the actual copy. */
8471 if (smb_fname_src->st.st_ex_size) {
8472 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
8473 } else {
8474 ret = 0;
8475 }
8476
8477 close_file(NULL, fsp1, NORMAL_CLOSE);
8478
8479 /* Ensure the modtime is set correctly on the destination file. */
8480 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
8481
8482 /*
8483 * As we are opening fsp1 read-only we only expect
8484 * an error on close on fsp2 if we are out of space.
8485 * Thus we don't look at the error return from the
8486 * close of fsp1.
8487 */
8488 status = close_file(NULL, fsp2, NORMAL_CLOSE);
8489
8490 if (!NT_STATUS_IS_OK(status)) {
8491 goto out;
8492 }
8493
8494 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
8495 status = NT_STATUS_DISK_FULL;
8496 goto out;
8497 }
8498
8499 status = NT_STATUS_OK;
8500
8501 out:
8502 TALLOC_FREE(smb_fname_dst_tmp);
8503 return status;
8504 }
8505
8506 /****************************************************************************
8507 Reply to a file copy.
8508 ****************************************************************************/
8509
reply_copy(struct smb_request * req)8510 void reply_copy(struct smb_request *req)
8511 {
8512 connection_struct *conn = req->conn;
8513 struct smb_filename *smb_fname_src = NULL;
8514 struct smb_filename *smb_fname_src_dir = NULL;
8515 struct smb_filename *smb_fname_dst = NULL;
8516 char *fname_src = NULL;
8517 char *fname_dst = NULL;
8518 char *fname_src_mask = NULL;
8519 char *fname_src_dir = NULL;
8520 const char *p;
8521 int count=0;
8522 int error = ERRnoaccess;
8523 int tid2;
8524 int ofun;
8525 int flags;
8526 bool target_is_directory=False;
8527 bool source_has_wild = False;
8528 bool dest_has_wild = False;
8529 NTSTATUS status;
8530 uint32_t ucf_flags_src = UCF_COND_ALLOW_WCARD_LCOMP |
8531 ucf_flags_from_smb_request(req);
8532 uint32_t ucf_flags_dst = UCF_COND_ALLOW_WCARD_LCOMP |
8533 ucf_flags_from_smb_request(req);
8534 TALLOC_CTX *ctx = talloc_tos();
8535
8536 START_PROFILE(SMBcopy);
8537
8538 if (req->wct < 3) {
8539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8540 goto out;
8541 }
8542
8543 tid2 = SVAL(req->vwv+0, 0);
8544 ofun = SVAL(req->vwv+1, 0);
8545 flags = SVAL(req->vwv+2, 0);
8546
8547 p = (const char *)req->buf;
8548 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
8549 &status, &source_has_wild);
8550 if (!NT_STATUS_IS_OK(status)) {
8551 reply_nterror(req, status);
8552 goto out;
8553 }
8554 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
8555 &status, &dest_has_wild);
8556 if (!NT_STATUS_IS_OK(status)) {
8557 reply_nterror(req, status);
8558 goto out;
8559 }
8560
8561 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
8562
8563 if (tid2 != conn->cnum) {
8564 /* can't currently handle inter share copies XXXX */
8565 DEBUG(3,("Rejecting inter-share copy\n"));
8566 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
8567 goto out;
8568 }
8569
8570 status = filename_convert(ctx, conn,
8571 fname_src,
8572 ucf_flags_src,
8573 NULL,
8574 &source_has_wild,
8575 &smb_fname_src);
8576 if (!NT_STATUS_IS_OK(status)) {
8577 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8578 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8579 ERRSRV, ERRbadpath);
8580 goto out;
8581 }
8582 reply_nterror(req, status);
8583 goto out;
8584 }
8585
8586 status = filename_convert(ctx, conn,
8587 fname_dst,
8588 ucf_flags_dst,
8589 NULL,
8590 &dest_has_wild,
8591 &smb_fname_dst);
8592 if (!NT_STATUS_IS_OK(status)) {
8593 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8594 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8595 ERRSRV, ERRbadpath);
8596 goto out;
8597 }
8598 reply_nterror(req, status);
8599 goto out;
8600 }
8601
8602 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
8603
8604 if ((flags&1) && target_is_directory) {
8605 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
8606 goto out;
8607 }
8608
8609 if ((flags&2) && !target_is_directory) {
8610 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
8611 goto out;
8612 }
8613
8614 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
8615 /* wants a tree copy! XXXX */
8616 DEBUG(3,("Rejecting tree copy\n"));
8617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8618 goto out;
8619 }
8620
8621 /* Split up the directory from the filename/mask. */
8622 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
8623 &fname_src_dir, &fname_src_mask);
8624 if (!NT_STATUS_IS_OK(status)) {
8625 reply_nterror(req, NT_STATUS_NO_MEMORY);
8626 goto out;
8627 }
8628
8629 /*
8630 * We should only check the mangled cache
8631 * here if unix_convert failed. This means
8632 * that the path in 'mask' doesn't exist
8633 * on the file system and so we need to look
8634 * for a possible mangle. This patch from
8635 * Tine Smukavec <valentin.smukavec@hermes.si>.
8636 */
8637 if (!VALID_STAT(smb_fname_src->st) &&
8638 mangle_is_mangled(fname_src_mask, conn->params)) {
8639 char *new_mask = NULL;
8640 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
8641 &new_mask, conn->params);
8642
8643 /* Use demangled name if one was successfully found. */
8644 if (new_mask) {
8645 TALLOC_FREE(fname_src_mask);
8646 fname_src_mask = new_mask;
8647 }
8648 }
8649
8650 if (!source_has_wild) {
8651
8652 /*
8653 * Only one file needs to be copied. Append the mask back onto
8654 * the directory.
8655 */
8656 TALLOC_FREE(smb_fname_src->base_name);
8657 if (ISDOT(fname_src_dir)) {
8658 /* Ensure we use canonical names on open. */
8659 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8660 "%s",
8661 fname_src_mask);
8662 } else {
8663 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
8664 "%s/%s",
8665 fname_src_dir,
8666 fname_src_mask);
8667 }
8668 if (!smb_fname_src->base_name) {
8669 reply_nterror(req, NT_STATUS_NO_MEMORY);
8670 goto out;
8671 }
8672
8673 if (dest_has_wild) {
8674 char *fname_dst_mod = NULL;
8675 if (!resolve_wildcards(smb_fname_dst,
8676 smb_fname_src->base_name,
8677 smb_fname_dst->base_name,
8678 &fname_dst_mod)) {
8679 reply_nterror(req, NT_STATUS_NO_MEMORY);
8680 goto out;
8681 }
8682 TALLOC_FREE(smb_fname_dst->base_name);
8683 smb_fname_dst->base_name = fname_dst_mod;
8684 }
8685
8686 status = check_name(conn, smb_fname_src);
8687 if (!NT_STATUS_IS_OK(status)) {
8688 reply_nterror(req, status);
8689 goto out;
8690 }
8691
8692 status = check_name(conn, smb_fname_dst);
8693 if (!NT_STATUS_IS_OK(status)) {
8694 reply_nterror(req, status);
8695 goto out;
8696 }
8697
8698 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
8699 ofun, count, target_is_directory);
8700
8701 if(!NT_STATUS_IS_OK(status)) {
8702 reply_nterror(req, status);
8703 goto out;
8704 } else {
8705 count++;
8706 }
8707 } else {
8708 struct smb_Dir *dir_hnd = NULL;
8709 const char *dname = NULL;
8710 char *talloced = NULL;
8711 long offset = 0;
8712
8713 /*
8714 * There is a wildcard that requires us to actually read the
8715 * src dir and copy each file matching the mask to the dst.
8716 * Right now streams won't be copied, but this could
8717 * presumably be added with a nested loop for reach dir entry.
8718 */
8719 SMB_ASSERT(!smb_fname_src->stream_name);
8720 SMB_ASSERT(!smb_fname_dst->stream_name);
8721
8722 smb_fname_src->stream_name = NULL;
8723 smb_fname_dst->stream_name = NULL;
8724
8725 if (strequal(fname_src_mask,"????????.???")) {
8726 TALLOC_FREE(fname_src_mask);
8727 fname_src_mask = talloc_strdup(ctx, "*");
8728 if (!fname_src_mask) {
8729 reply_nterror(req, NT_STATUS_NO_MEMORY);
8730 goto out;
8731 }
8732 }
8733
8734 smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
8735 fname_src_dir,
8736 NULL,
8737 NULL,
8738 smb_fname_src->flags);
8739 if (smb_fname_src_dir == NULL) {
8740 reply_nterror(req, NT_STATUS_NO_MEMORY);
8741 goto out;
8742 }
8743
8744 status = check_name(conn, smb_fname_src_dir);
8745 if (!NT_STATUS_IS_OK(status)) {
8746 reply_nterror(req, status);
8747 goto out;
8748 }
8749
8750 dir_hnd = OpenDir(ctx,
8751 conn,
8752 smb_fname_src_dir,
8753 fname_src_mask,
8754 0);
8755 if (dir_hnd == NULL) {
8756 status = map_nt_error_from_unix(errno);
8757 reply_nterror(req, status);
8758 goto out;
8759 }
8760
8761 error = ERRbadfile;
8762
8763 /* Iterate over the src dir copying each entry to the dst. */
8764 while ((dname = ReadDirName(dir_hnd, &offset,
8765 &smb_fname_src->st, &talloced))) {
8766 char *destname = NULL;
8767
8768 if (ISDOT(dname) || ISDOTDOT(dname)) {
8769 TALLOC_FREE(talloced);
8770 continue;
8771 }
8772
8773 if (!is_visible_file(conn, fname_src_dir, dname,
8774 &smb_fname_src->st, false)) {
8775 TALLOC_FREE(talloced);
8776 continue;
8777 }
8778
8779 if(!mask_match(dname, fname_src_mask,
8780 conn->case_sensitive)) {
8781 TALLOC_FREE(talloced);
8782 continue;
8783 }
8784
8785 error = ERRnoaccess;
8786
8787 /* Get the src smb_fname struct setup. */
8788 TALLOC_FREE(smb_fname_src->base_name);
8789 if (ISDOT(fname_src_dir)) {
8790 /* Ensure we use canonical names on open. */
8791 smb_fname_src->base_name =
8792 talloc_asprintf(smb_fname_src, "%s",
8793 dname);
8794 } else {
8795 smb_fname_src->base_name =
8796 talloc_asprintf(smb_fname_src, "%s/%s",
8797 fname_src_dir, dname);
8798 }
8799
8800 if (!smb_fname_src->base_name) {
8801 TALLOC_FREE(dir_hnd);
8802 TALLOC_FREE(talloced);
8803 reply_nterror(req, NT_STATUS_NO_MEMORY);
8804 goto out;
8805 }
8806
8807 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
8808 smb_fname_dst->base_name,
8809 &destname)) {
8810 TALLOC_FREE(talloced);
8811 continue;
8812 }
8813 if (!destname) {
8814 TALLOC_FREE(dir_hnd);
8815 TALLOC_FREE(talloced);
8816 reply_nterror(req, NT_STATUS_NO_MEMORY);
8817 goto out;
8818 }
8819
8820 TALLOC_FREE(smb_fname_dst->base_name);
8821 smb_fname_dst->base_name = destname;
8822
8823 status = check_name(conn, smb_fname_src);
8824 if (!NT_STATUS_IS_OK(status)) {
8825 TALLOC_FREE(dir_hnd);
8826 TALLOC_FREE(talloced);
8827 reply_nterror(req, status);
8828 goto out;
8829 }
8830
8831 status = check_name(conn, smb_fname_dst);
8832 if (!NT_STATUS_IS_OK(status)) {
8833 TALLOC_FREE(dir_hnd);
8834 TALLOC_FREE(talloced);
8835 reply_nterror(req, status);
8836 goto out;
8837 }
8838
8839 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
8840 smb_fname_src->base_name,
8841 smb_fname_dst->base_name));
8842
8843 status = copy_file(ctx, conn, smb_fname_src,
8844 smb_fname_dst, ofun, count,
8845 target_is_directory);
8846 if (NT_STATUS_IS_OK(status)) {
8847 count++;
8848 }
8849
8850 TALLOC_FREE(talloced);
8851 }
8852 TALLOC_FREE(dir_hnd);
8853 }
8854
8855 if (count == 0) {
8856 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
8857 goto out;
8858 }
8859
8860 reply_outbuf(req, 1, 0);
8861 SSVAL(req->outbuf,smb_vwv0,count);
8862 out:
8863 TALLOC_FREE(smb_fname_src);
8864 TALLOC_FREE(smb_fname_src_dir);
8865 TALLOC_FREE(smb_fname_dst);
8866 TALLOC_FREE(fname_src);
8867 TALLOC_FREE(fname_dst);
8868 TALLOC_FREE(fname_src_mask);
8869 TALLOC_FREE(fname_src_dir);
8870
8871 END_PROFILE(SMBcopy);
8872 return;
8873 }
8874
8875 #undef DBGC_CLASS
8876 #define DBGC_CLASS DBGC_LOCKING
8877
8878 /****************************************************************************
8879 Get a lock pid, dealing with large count requests.
8880 ****************************************************************************/
8881
get_lock_pid(const uint8_t * data,int data_offset,bool large_file_format)8882 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
8883 bool large_file_format)
8884 {
8885 if(!large_file_format)
8886 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
8887 else
8888 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
8889 }
8890
8891 /****************************************************************************
8892 Get a lock count, dealing with large count requests.
8893 ****************************************************************************/
8894
get_lock_count(const uint8_t * data,int data_offset,bool large_file_format)8895 uint64_t get_lock_count(const uint8_t *data, int data_offset,
8896 bool large_file_format)
8897 {
8898 uint64_t count = 0;
8899
8900 if(!large_file_format) {
8901 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
8902 } else {
8903 /*
8904 * No BVAL, this is reversed!
8905 */
8906 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
8907 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
8908 }
8909
8910 return count;
8911 }
8912
8913 /****************************************************************************
8914 Get a lock offset, dealing with large offset requests.
8915 ****************************************************************************/
8916
get_lock_offset(const uint8_t * data,int data_offset,bool large_file_format)8917 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
8918 bool large_file_format)
8919 {
8920 uint64_t offset = 0;
8921
8922 if(!large_file_format) {
8923 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
8924 } else {
8925 /*
8926 * No BVAL, this is reversed!
8927 */
8928 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
8929 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
8930 }
8931
8932 return offset;
8933 }
8934
8935 struct smbd_do_unlocking_state {
8936 struct files_struct *fsp;
8937 uint16_t num_ulocks;
8938 struct smbd_lock_element *ulocks;
8939 enum brl_flavour lock_flav;
8940 NTSTATUS status;
8941 };
8942
smbd_do_unlocking_fn(TDB_DATA value,bool * pmodified_dependent,void * private_data)8943 static void smbd_do_unlocking_fn(
8944 TDB_DATA value, bool *pmodified_dependent, void *private_data)
8945 {
8946 struct smbd_do_unlocking_state *state = private_data;
8947 struct files_struct *fsp = state->fsp;
8948 enum brl_flavour lock_flav = state->lock_flav;
8949 uint16_t i;
8950
8951 for (i = 0; i < state->num_ulocks; i++) {
8952 struct smbd_lock_element *e = &state->ulocks[i];
8953
8954 DBG_DEBUG("unlock start=%"PRIu64", len=%"PRIu64" for "
8955 "pid %"PRIu64", file %s\n",
8956 e->offset,
8957 e->count,
8958 e->smblctx,
8959 fsp_str_dbg(fsp));
8960
8961 if (e->brltype != UNLOCK_LOCK) {
8962 /* this can only happen with SMB2 */
8963 state->status = NT_STATUS_INVALID_PARAMETER;
8964 return;
8965 }
8966
8967 state->status = do_unlock(
8968 fsp, e->smblctx, e->count, e->offset, lock_flav);
8969
8970 DBG_DEBUG("do_unlock returned %s\n",
8971 nt_errstr(state->status));
8972
8973 if (!NT_STATUS_IS_OK(state->status)) {
8974 return;
8975 }
8976 }
8977
8978 *pmodified_dependent = true;
8979 }
8980
smbd_do_unlocking(struct smb_request * req,files_struct * fsp,uint16_t num_ulocks,struct smbd_lock_element * ulocks,enum brl_flavour lock_flav)8981 NTSTATUS smbd_do_unlocking(struct smb_request *req,
8982 files_struct *fsp,
8983 uint16_t num_ulocks,
8984 struct smbd_lock_element *ulocks,
8985 enum brl_flavour lock_flav)
8986 {
8987 struct smbd_do_unlocking_state state = {
8988 .fsp = fsp,
8989 .num_ulocks = num_ulocks,
8990 .ulocks = ulocks,
8991 .lock_flav = lock_flav,
8992 };
8993 NTSTATUS status;
8994
8995 DBG_NOTICE("%s num_ulocks=%"PRIu16"\n", fsp_fnum_dbg(fsp), num_ulocks);
8996
8997 status = share_mode_do_locked(
8998 fsp->file_id, smbd_do_unlocking_fn, &state);
8999
9000 if (!NT_STATUS_IS_OK(status)) {
9001 DBG_DEBUG("share_mode_do_locked failed: %s\n",
9002 nt_errstr(status));
9003 return status;
9004 }
9005 if (!NT_STATUS_IS_OK(state.status)) {
9006 DBG_DEBUG("smbd_do_unlocking_fn failed: %s\n",
9007 nt_errstr(status));
9008 return state.status;
9009 }
9010
9011 return NT_STATUS_OK;
9012 }
9013
9014 /****************************************************************************
9015 Reply to a lockingX request.
9016 ****************************************************************************/
9017
9018 static void reply_lockingx_done(struct tevent_req *subreq);
9019
reply_lockingX(struct smb_request * req)9020 void reply_lockingX(struct smb_request *req)
9021 {
9022 connection_struct *conn = req->conn;
9023 files_struct *fsp;
9024 unsigned char locktype;
9025 enum brl_type brltype;
9026 unsigned char oplocklevel;
9027 uint16_t num_ulocks;
9028 uint16_t num_locks;
9029 int32_t lock_timeout;
9030 uint16_t i;
9031 const uint8_t *data;
9032 bool large_file_format;
9033 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
9034 struct smbd_lock_element *locks = NULL;
9035 struct tevent_req *subreq = NULL;
9036
9037 START_PROFILE(SMBlockingX);
9038
9039 if (req->wct < 8) {
9040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9041 END_PROFILE(SMBlockingX);
9042 return;
9043 }
9044
9045 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
9046 locktype = CVAL(req->vwv+3, 0);
9047 oplocklevel = CVAL(req->vwv+3, 1);
9048 num_ulocks = SVAL(req->vwv+6, 0);
9049 num_locks = SVAL(req->vwv+7, 0);
9050 lock_timeout = IVAL(req->vwv+4, 0);
9051 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
9052
9053 if (!check_fsp(conn, req, fsp)) {
9054 END_PROFILE(SMBlockingX);
9055 return;
9056 }
9057
9058 data = req->buf;
9059
9060 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
9061 /* we don't support these - and CANCEL_LOCK makes w2k
9062 and XP reboot so I don't really want to be
9063 compatible! (tridge) */
9064 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
9065 END_PROFILE(SMBlockingX);
9066 return;
9067 }
9068
9069 /* Check if this is an oplock break on a file
9070 we have granted an oplock on.
9071 */
9072 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
9073 /* Client can insist on breaking to none. */
9074 bool break_to_none = (oplocklevel == 0);
9075 bool result;
9076
9077 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
9078 "for %s\n", (unsigned int)oplocklevel,
9079 fsp_fnum_dbg(fsp)));
9080
9081 /*
9082 * Make sure we have granted an exclusive or batch oplock on
9083 * this file.
9084 */
9085
9086 if (fsp->oplock_type == 0) {
9087
9088 /* The Samba4 nbench simulator doesn't understand
9089 the difference between break to level2 and break
9090 to none from level2 - it sends oplock break
9091 replies in both cases. Don't keep logging an error
9092 message here - just ignore it. JRA. */
9093
9094 DEBUG(5,("reply_lockingX: Error : oplock break from "
9095 "client for %s (oplock=%d) and no "
9096 "oplock granted on this file (%s).\n",
9097 fsp_fnum_dbg(fsp), fsp->oplock_type,
9098 fsp_str_dbg(fsp)));
9099
9100 /* if this is a pure oplock break request then don't
9101 * send a reply */
9102 if (num_locks == 0 && num_ulocks == 0) {
9103 END_PROFILE(SMBlockingX);
9104 return;
9105 }
9106
9107 END_PROFILE(SMBlockingX);
9108 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
9109 return;
9110 }
9111
9112 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
9113 (break_to_none)) {
9114 result = remove_oplock(fsp);
9115 } else {
9116 result = downgrade_oplock(fsp);
9117 }
9118
9119 if (!result) {
9120 DEBUG(0, ("reply_lockingX: error in removing "
9121 "oplock on file %s\n", fsp_str_dbg(fsp)));
9122 /* Hmmm. Is this panic justified? */
9123 smb_panic("internal tdb error");
9124 }
9125
9126 /* if this is a pure oplock break request then don't send a
9127 * reply */
9128 if (num_locks == 0 && num_ulocks == 0) {
9129 /* Sanity check - ensure a pure oplock break is not a
9130 chained request. */
9131 if (CVAL(req->vwv+0, 0) != 0xff) {
9132 DEBUG(0,("reply_lockingX: Error : pure oplock "
9133 "break is a chained %d request !\n",
9134 (unsigned int)CVAL(req->vwv+0, 0)));
9135 }
9136 END_PROFILE(SMBlockingX);
9137 return;
9138 }
9139 }
9140
9141 if (req->buflen <
9142 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
9143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9144 END_PROFILE(SMBlockingX);
9145 return;
9146 }
9147
9148 if (num_ulocks != 0) {
9149 struct smbd_lock_element *ulocks = NULL;
9150 bool ok;
9151
9152 ulocks = talloc_array(
9153 req, struct smbd_lock_element, num_ulocks);
9154 if (ulocks == NULL) {
9155 reply_nterror(req, NT_STATUS_NO_MEMORY);
9156 END_PROFILE(SMBlockingX);
9157 return;
9158 }
9159
9160 /*
9161 * Data now points at the beginning of the list of
9162 * smb_unlkrng structs
9163 */
9164 for (i = 0; i < num_ulocks; i++) {
9165 ulocks[i].req_guid = smbd_request_guid(req,
9166 UINT16_MAX - i),
9167 ulocks[i].smblctx = get_lock_pid(
9168 data, i, large_file_format);
9169 ulocks[i].count = get_lock_count(
9170 data, i, large_file_format);
9171 ulocks[i].offset = get_lock_offset(
9172 data, i, large_file_format);
9173 ulocks[i].brltype = UNLOCK_LOCK;
9174 }
9175
9176 /*
9177 * Unlock cancels pending locks
9178 */
9179
9180 ok = smbd_smb1_brl_finish_by_lock(
9181 fsp,
9182 large_file_format,
9183 WINDOWS_LOCK,
9184 ulocks[0],
9185 NT_STATUS_OK);
9186 if (ok) {
9187 reply_outbuf(req, 2, 0);
9188 SSVAL(req->outbuf, smb_vwv0, 0xff);
9189 SSVAL(req->outbuf, smb_vwv1, 0);
9190 END_PROFILE(SMBlockingX);
9191 return;
9192 }
9193
9194 status = smbd_do_unlocking(
9195 req, fsp, num_ulocks, ulocks, WINDOWS_LOCK);
9196 TALLOC_FREE(ulocks);
9197 if (!NT_STATUS_IS_OK(status)) {
9198 END_PROFILE(SMBlockingX);
9199 reply_nterror(req, status);
9200 return;
9201 }
9202 }
9203
9204 /* Now do any requested locks */
9205 data += ((large_file_format ? 20 : 10)*num_ulocks);
9206
9207 /* Data now points at the beginning of the list
9208 of smb_lkrng structs */
9209
9210 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
9211 brltype = READ_LOCK;
9212 } else {
9213 brltype = WRITE_LOCK;
9214 }
9215
9216 locks = talloc_array(req, struct smbd_lock_element, num_locks);
9217 if (locks == NULL) {
9218 reply_nterror(req, NT_STATUS_NO_MEMORY);
9219 END_PROFILE(SMBlockingX);
9220 return;
9221 }
9222
9223 for (i = 0; i < num_locks; i++) {
9224 locks[i].req_guid = smbd_request_guid(req, i),
9225 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
9226 locks[i].count = get_lock_count(data, i, large_file_format);
9227 locks[i].offset = get_lock_offset(data, i, large_file_format);
9228 locks[i].brltype = brltype;
9229 }
9230
9231 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
9232
9233 bool ok;
9234
9235 if (num_locks == 0) {
9236 /* See smbtorture3 lock11 test */
9237 reply_outbuf(req, 2, 0);
9238 /* andx chain ends */
9239 SSVAL(req->outbuf, smb_vwv0, 0xff);
9240 SSVAL(req->outbuf, smb_vwv1, 0);
9241 END_PROFILE(SMBlockingX);
9242 return;
9243 }
9244
9245 ok = smbd_smb1_brl_finish_by_lock(
9246 fsp,
9247 large_file_format,
9248 WINDOWS_LOCK,
9249 locks[0], /* Windows only cancels the first lock */
9250 NT_STATUS_FILE_LOCK_CONFLICT);
9251
9252 if (!ok) {
9253 reply_force_doserror(req, ERRDOS, ERRcancelviolation);
9254 END_PROFILE(SMBlockingX);
9255 return;
9256 }
9257
9258 reply_outbuf(req, 2, 0);
9259 SSVAL(req->outbuf, smb_vwv0, 0xff);
9260 SSVAL(req->outbuf, smb_vwv1, 0);
9261 END_PROFILE(SMBlockingX);
9262 return;
9263 }
9264
9265 subreq = smbd_smb1_do_locks_send(
9266 fsp,
9267 req->sconn->ev_ctx,
9268 &req,
9269 fsp,
9270 lock_timeout,
9271 large_file_format,
9272 WINDOWS_LOCK,
9273 num_locks,
9274 locks);
9275 if (subreq == NULL) {
9276 reply_nterror(req, NT_STATUS_NO_MEMORY);
9277 END_PROFILE(SMBlockingX);
9278 return;
9279 }
9280 tevent_req_set_callback(subreq, reply_lockingx_done, NULL);
9281 END_PROFILE(SMBlockingX);
9282 }
9283
reply_lockingx_done(struct tevent_req * subreq)9284 static void reply_lockingx_done(struct tevent_req *subreq)
9285 {
9286 struct smb_request *req = NULL;
9287 NTSTATUS status;
9288 bool ok;
9289
9290 START_PROFILE(SMBlockingX);
9291
9292 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
9293 SMB_ASSERT(ok);
9294
9295 status = smbd_smb1_do_locks_recv(subreq);
9296 TALLOC_FREE(subreq);
9297
9298 DBG_DEBUG("smbd_smb1_do_locks_recv returned %s\n", nt_errstr(status));
9299
9300 if (NT_STATUS_IS_OK(status)) {
9301 reply_outbuf(req, 2, 0);
9302 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
9303 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
9304 } else {
9305 reply_nterror(req, status);
9306 }
9307
9308 ok = srv_send_smb(req->xconn,
9309 (char *)req->outbuf,
9310 true,
9311 req->seqnum+1,
9312 IS_CONN_ENCRYPTED(req->conn),
9313 NULL);
9314 if (!ok) {
9315 exit_server_cleanly("reply_lock_done: srv_send_smb failed.");
9316 }
9317 TALLOC_FREE(req);
9318 END_PROFILE(SMBlockingX);
9319 }
9320
9321 #undef DBGC_CLASS
9322 #define DBGC_CLASS DBGC_ALL
9323
9324 /****************************************************************************
9325 Reply to a SMBreadbmpx (read block multiplex) request.
9326 Always reply with an error, if someone has a platform really needs this,
9327 please contact vl@samba.org
9328 ****************************************************************************/
9329
reply_readbmpx(struct smb_request * req)9330 void reply_readbmpx(struct smb_request *req)
9331 {
9332 START_PROFILE(SMBreadBmpx);
9333 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9334 END_PROFILE(SMBreadBmpx);
9335 return;
9336 }
9337
9338 /****************************************************************************
9339 Reply to a SMBreadbs (read block multiplex secondary) request.
9340 Always reply with an error, if someone has a platform really needs this,
9341 please contact vl@samba.org
9342 ****************************************************************************/
9343
reply_readbs(struct smb_request * req)9344 void reply_readbs(struct smb_request *req)
9345 {
9346 START_PROFILE(SMBreadBs);
9347 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9348 END_PROFILE(SMBreadBs);
9349 return;
9350 }
9351
9352 /****************************************************************************
9353 Reply to a SMBsetattrE.
9354 ****************************************************************************/
9355
reply_setattrE(struct smb_request * req)9356 void reply_setattrE(struct smb_request *req)
9357 {
9358 connection_struct *conn = req->conn;
9359 struct smb_file_time ft;
9360 files_struct *fsp;
9361 NTSTATUS status;
9362
9363 START_PROFILE(SMBsetattrE);
9364 init_smb_file_time(&ft);
9365
9366 if (req->wct < 7) {
9367 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9368 goto out;
9369 }
9370
9371 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9372
9373 if(!fsp || (fsp->conn != conn)) {
9374 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9375 goto out;
9376 }
9377
9378 /*
9379 * Convert the DOS times into unix times.
9380 */
9381
9382 ft.atime = time_t_to_full_timespec(
9383 srv_make_unix_date2(req->vwv+3));
9384 ft.mtime = time_t_to_full_timespec(
9385 srv_make_unix_date2(req->vwv+5));
9386 ft.create_time = time_t_to_full_timespec(
9387 srv_make_unix_date2(req->vwv+1));
9388
9389 reply_outbuf(req, 0, 0);
9390
9391 /*
9392 * Patch from Ray Frush <frush@engr.colostate.edu>
9393 * Sometimes times are sent as zero - ignore them.
9394 */
9395
9396 /* Ensure we have a valid stat struct for the source. */
9397 status = vfs_stat_fsp(fsp);
9398 if (!NT_STATUS_IS_OK(status)) {
9399 reply_nterror(req, status);
9400 goto out;
9401 }
9402
9403 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
9404 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9405 goto out;
9406 }
9407
9408 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
9409 if (!NT_STATUS_IS_OK(status)) {
9410 reply_nterror(req, status);
9411 goto out;
9412 }
9413
9414 if (fsp->modified) {
9415 trigger_write_time_update_immediate(fsp);
9416 }
9417
9418 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
9419 " createtime=%u\n",
9420 fsp_fnum_dbg(fsp),
9421 (unsigned int)ft.atime.tv_sec,
9422 (unsigned int)ft.mtime.tv_sec,
9423 (unsigned int)ft.create_time.tv_sec
9424 ));
9425 out:
9426 END_PROFILE(SMBsetattrE);
9427 return;
9428 }
9429
9430
9431 /* Back from the dead for OS/2..... JRA. */
9432
9433 /****************************************************************************
9434 Reply to a SMBwritebmpx (write block multiplex primary) request.
9435 Always reply with an error, if someone has a platform really needs this,
9436 please contact vl@samba.org
9437 ****************************************************************************/
9438
reply_writebmpx(struct smb_request * req)9439 void reply_writebmpx(struct smb_request *req)
9440 {
9441 START_PROFILE(SMBwriteBmpx);
9442 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9443 END_PROFILE(SMBwriteBmpx);
9444 return;
9445 }
9446
9447 /****************************************************************************
9448 Reply to a SMBwritebs (write block multiplex secondary) request.
9449 Always reply with an error, if someone has a platform really needs this,
9450 please contact vl@samba.org
9451 ****************************************************************************/
9452
reply_writebs(struct smb_request * req)9453 void reply_writebs(struct smb_request *req)
9454 {
9455 START_PROFILE(SMBwriteBs);
9456 reply_force_doserror(req, ERRSRV, ERRuseSTD);
9457 END_PROFILE(SMBwriteBs);
9458 return;
9459 }
9460
9461 /****************************************************************************
9462 Reply to a SMBgetattrE.
9463 ****************************************************************************/
9464
reply_getattrE(struct smb_request * req)9465 void reply_getattrE(struct smb_request *req)
9466 {
9467 connection_struct *conn = req->conn;
9468 int mode;
9469 files_struct *fsp;
9470 struct timespec create_ts;
9471 NTSTATUS status;
9472
9473 START_PROFILE(SMBgetattrE);
9474
9475 if (req->wct < 1) {
9476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9477 END_PROFILE(SMBgetattrE);
9478 return;
9479 }
9480
9481 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
9482
9483 if(!fsp || (fsp->conn != conn)) {
9484 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9485 END_PROFILE(SMBgetattrE);
9486 return;
9487 }
9488
9489 /* Do an fstat on this file */
9490 status = vfs_stat_fsp(fsp);
9491 if (!NT_STATUS_IS_OK(status)) {
9492 reply_nterror(req, status);
9493 END_PROFILE(SMBgetattrE);
9494 return;
9495 }
9496
9497 mode = dos_mode(conn, fsp->fsp_name);
9498
9499 /*
9500 * Convert the times into dos times. Set create
9501 * date to be last modify date as UNIX doesn't save
9502 * this.
9503 */
9504
9505 reply_outbuf(req, 11, 0);
9506
9507 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
9508 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
9509 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
9510 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
9511 /* Should we check pending modtime here ? JRA */
9512 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
9513 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
9514
9515 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
9516 SIVAL(req->outbuf, smb_vwv6, 0);
9517 SIVAL(req->outbuf, smb_vwv8, 0);
9518 } else {
9519 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
9520 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
9521 SIVAL(req->outbuf, smb_vwv8, allocation_size);
9522 }
9523 SSVAL(req->outbuf,smb_vwv10, mode);
9524
9525 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
9526
9527 END_PROFILE(SMBgetattrE);
9528 return;
9529 }
9530