source: trunk/server/source3/smbd/reply.c

Last change on this file was 862, checked in by Silvan Scherrer, 11 years ago

Samba Server: update trunk to 3.6.23

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