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

Last change on this file since 757 was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

File size: 208.8 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 status = filename_convert(ctx,
1752 conn,
1753 req->flags2 & FLAGS2_DFS_PATHNAMES,
1754 fname,
1755 0,
1756 NULL,
1757 &smb_fname);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1760 reply_botherror(req,
1761 NT_STATUS_PATH_NOT_COVERED,
1762 ERRSRV, ERRbadpath);
1763 goto out;
1764 }
1765 reply_nterror(req, status);
1766 goto out;
1767 }
1768
1769 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1770 OPENX_FILE_EXISTS_OPEN, &access_mask,
1771 &share_mode, &create_disposition,
1772 &create_options, &private_flags)) {
1773 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1774 goto out;
1775 }
1776
1777 status = SMB_VFS_CREATE_FILE(
1778 conn, /* conn */
1779 req, /* req */
1780 0, /* root_dir_fid */
1781 smb_fname, /* fname */
1782 access_mask, /* access_mask */
1783 share_mode, /* share_access */
1784 create_disposition, /* create_disposition*/
1785 create_options, /* create_options */
1786 dos_attr, /* file_attributes */
1787 oplock_request, /* oplock_request */
1788 0, /* allocation_size */
1789 private_flags,
1790 NULL, /* sd */
1791 NULL, /* ea_list */
1792 &fsp, /* result */
1793 &info); /* pinfo */
1794
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (open_was_deferred(req->mid)) {
1797 /* We have re-scheduled this call. */
1798 goto out;
1799 }
1800 reply_openerror(req, status);
1801 goto out;
1802 }
1803
1804 size = smb_fname->st.st_ex_size;
1805 fattr = dos_mode(conn, smb_fname);
1806
1807 /* Deal with other possible opens having a modified
1808 write time. JRA. */
1809 if (ask_sharemode) {
1810 struct timespec write_time_ts;
1811
1812 ZERO_STRUCT(write_time_ts);
1813 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1814 if (!null_timespec(write_time_ts)) {
1815 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1816 }
1817 }
1818
1819 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1820
1821 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1822 DEBUG(3,("attempt to open a directory %s\n",
1823 fsp_str_dbg(fsp)));
1824 close_file(req, fsp, ERROR_CLOSE);
1825 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1826 ERRDOS, ERRnoaccess);
1827 goto out;
1828 }
1829
1830 reply_outbuf(req, 7, 0);
1831 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1832 SSVAL(req->outbuf,smb_vwv1,fattr);
1833 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1834 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1835 } else {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1837 }
1838 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1839 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1840
1841 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1842 SCVAL(req->outbuf,smb_flg,
1843 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1844 }
1845
1846 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1847 SCVAL(req->outbuf,smb_flg,
1848 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1849 }
1850 out:
1851 TALLOC_FREE(smb_fname);
1852 END_PROFILE(SMBopen);
1853 return;
1854}
1855
1856/****************************************************************************
1857 Reply to an open and X.
1858****************************************************************************/
1859
1860void reply_open_and_X(struct smb_request *req)
1861{
1862 connection_struct *conn = req->conn;
1863 struct smb_filename *smb_fname = NULL;
1864 char *fname = NULL;
1865 uint16 open_flags;
1866 int deny_mode;
1867 uint32 smb_attr;
1868 /* Breakout the oplock request bits so we can set the
1869 reply bits separately. */
1870 int ex_oplock_request;
1871 int core_oplock_request;
1872 int oplock_request;
1873#if 0
1874 int smb_sattr = SVAL(req->vwv+4, 0);
1875 uint32 smb_time = make_unix_date3(req->vwv+6);
1876#endif
1877 int smb_ofun;
1878 uint32 fattr=0;
1879 int mtime=0;
1880 int smb_action = 0;
1881 files_struct *fsp;
1882 NTSTATUS status;
1883 uint64_t allocation_size;
1884 ssize_t retval = -1;
1885 uint32 access_mask;
1886 uint32 share_mode;
1887 uint32 create_disposition;
1888 uint32 create_options = 0;
1889 uint32_t private_flags = 0;
1890 TALLOC_CTX *ctx = talloc_tos();
1891
1892 START_PROFILE(SMBopenX);
1893
1894 if (req->wct < 15) {
1895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1896 goto out;
1897 }
1898
1899 open_flags = SVAL(req->vwv+2, 0);
1900 deny_mode = SVAL(req->vwv+3, 0);
1901 smb_attr = SVAL(req->vwv+5, 0);
1902 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1903 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1904 oplock_request = ex_oplock_request | core_oplock_request;
1905 smb_ofun = SVAL(req->vwv+8, 0);
1906 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1907
1908 /* If it's an IPC, pass off the pipe handler. */
1909 if (IS_IPC(conn)) {
1910 if (lp_nt_pipe_support()) {
1911 reply_open_pipe_and_X(conn, req);
1912 } else {
1913 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1914 }
1915 goto out;
1916 }
1917
1918 /* XXXX we need to handle passed times, sattr and flags */
1919 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1920 STR_TERMINATE, &status);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 reply_nterror(req, status);
1923 goto out;
1924 }
1925
1926 status = filename_convert(ctx,
1927 conn,
1928 req->flags2 & FLAGS2_DFS_PATHNAMES,
1929 fname,
1930 0,
1931 NULL,
1932 &smb_fname);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1935 reply_botherror(req,
1936 NT_STATUS_PATH_NOT_COVERED,
1937 ERRSRV, ERRbadpath);
1938 goto out;
1939 }
1940 reply_nterror(req, status);
1941 goto out;
1942 }
1943
1944 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1945 smb_ofun,
1946 &access_mask, &share_mode,
1947 &create_disposition,
1948 &create_options,
1949 &private_flags)) {
1950 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1951 goto out;
1952 }
1953
1954 status = SMB_VFS_CREATE_FILE(
1955 conn, /* conn */
1956 req, /* req */
1957 0, /* root_dir_fid */
1958 smb_fname, /* fname */
1959 access_mask, /* access_mask */
1960 share_mode, /* share_access */
1961 create_disposition, /* create_disposition*/
1962 create_options, /* create_options */
1963 smb_attr, /* file_attributes */
1964 oplock_request, /* oplock_request */
1965 0, /* allocation_size */
1966 private_flags,
1967 NULL, /* sd */
1968 NULL, /* ea_list */
1969 &fsp, /* result */
1970 &smb_action); /* pinfo */
1971
1972 if (!NT_STATUS_IS_OK(status)) {
1973 if (open_was_deferred(req->mid)) {
1974 /* We have re-scheduled this call. */
1975 goto out;
1976 }
1977 reply_openerror(req, status);
1978 goto out;
1979 }
1980
1981 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1982 if the file is truncated or created. */
1983 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1984 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1985 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1986 close_file(req, fsp, ERROR_CLOSE);
1987 reply_nterror(req, NT_STATUS_DISK_FULL);
1988 goto out;
1989 }
1990 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1991 if (retval < 0) {
1992 close_file(req, fsp, ERROR_CLOSE);
1993 reply_nterror(req, NT_STATUS_DISK_FULL);
1994 goto out;
1995 }
1996 status = vfs_stat_fsp(fsp);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 close_file(req, fsp, ERROR_CLOSE);
1999 reply_nterror(req, status);
2000 goto out;
2001 }
2002 }
2003
2004 fattr = dos_mode(conn, fsp->fsp_name);
2005 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2006 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2007 close_file(req, fsp, ERROR_CLOSE);
2008 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2009 goto out;
2010 }
2011
2012 /* If the caller set the extended oplock request bit
2013 and we granted one (by whatever means) - set the
2014 correct bit for extended oplock reply.
2015 */
2016
2017 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018 smb_action |= EXTENDED_OPLOCK_GRANTED;
2019 }
2020
2021 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2022 smb_action |= EXTENDED_OPLOCK_GRANTED;
2023 }
2024
2025 /* If the caller set the core oplock request bit
2026 and we granted one (by whatever means) - set the
2027 correct bit for core oplock reply.
2028 */
2029
2030 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2031 reply_outbuf(req, 19, 0);
2032 } else {
2033 reply_outbuf(req, 15, 0);
2034 }
2035
2036 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2037 SCVAL(req->outbuf, smb_flg,
2038 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2039 }
2040
2041 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2042 SCVAL(req->outbuf, smb_flg,
2043 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2044 }
2045
2046 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2047 SSVAL(req->outbuf,smb_vwv3,fattr);
2048 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2049 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2050 } else {
2051 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2052 }
2053 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2054 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2055 SSVAL(req->outbuf,smb_vwv11,smb_action);
2056
2057 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2058 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2059 }
2060
2061 chain_reply(req);
2062 out:
2063 TALLOC_FREE(smb_fname);
2064 END_PROFILE(SMBopenX);
2065 return;
2066}
2067
2068/****************************************************************************
2069 Reply to a SMBulogoffX.
2070****************************************************************************/
2071
2072void reply_ulogoffX(struct smb_request *req)
2073{
2074 struct smbd_server_connection *sconn = req->sconn;
2075 user_struct *vuser;
2076
2077 START_PROFILE(SMBulogoffX);
2078
2079 vuser = get_valid_user_struct(sconn, req->vuid);
2080
2081 if(vuser == NULL) {
2082 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2083 req->vuid));
2084 }
2085
2086 /* in user level security we are supposed to close any files
2087 open by this user */
2088 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2089 file_close_user(sconn, req->vuid);
2090 }
2091
2092 invalidate_vuid(sconn, req->vuid);
2093
2094 reply_outbuf(req, 2, 0);
2095
2096 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2097
2098 END_PROFILE(SMBulogoffX);
2099 req->vuid = UID_FIELD_INVALID;
2100 chain_reply(req);
2101}
2102
2103/****************************************************************************
2104 Reply to a mknew or a create.
2105****************************************************************************/
2106
2107void reply_mknew(struct smb_request *req)
2108{
2109 connection_struct *conn = req->conn;
2110 struct smb_filename *smb_fname = NULL;
2111 char *fname = NULL;
2112 uint32 fattr = 0;
2113 struct smb_file_time ft;
2114 files_struct *fsp;
2115 int oplock_request = 0;
2116 NTSTATUS status;
2117 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2118 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2119 uint32 create_disposition;
2120 uint32 create_options = 0;
2121 TALLOC_CTX *ctx = talloc_tos();
2122
2123 START_PROFILE(SMBcreate);
2124 ZERO_STRUCT(ft);
2125
2126 if (req->wct < 3) {
2127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2128 goto out;
2129 }
2130
2131 fattr = SVAL(req->vwv+0, 0);
2132 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2133
2134 /* mtime. */
2135 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2136
2137 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2138 STR_TERMINATE, &status);
2139 if (!NT_STATUS_IS_OK(status)) {
2140 reply_nterror(req, status);
2141 goto out;
2142 }
2143
2144 status = filename_convert(ctx,
2145 conn,
2146 req->flags2 & FLAGS2_DFS_PATHNAMES,
2147 fname,
2148 0,
2149 NULL,
2150 &smb_fname);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2153 reply_botherror(req,
2154 NT_STATUS_PATH_NOT_COVERED,
2155 ERRSRV, ERRbadpath);
2156 goto out;
2157 }
2158 reply_nterror(req, status);
2159 goto out;
2160 }
2161
2162 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2163 DEBUG(0,("Attempt to create file (%s) with volid set - "
2164 "please report this\n",
2165 smb_fname_str_dbg(smb_fname)));
2166 }
2167
2168 if(req->cmd == SMBmknew) {
2169 /* We should fail if file exists. */
2170 create_disposition = FILE_CREATE;
2171 } else {
2172 /* Create if file doesn't exist, truncate if it does. */
2173 create_disposition = FILE_OVERWRITE_IF;
2174 }
2175
2176 status = SMB_VFS_CREATE_FILE(
2177 conn, /* conn */
2178 req, /* req */
2179 0, /* root_dir_fid */
2180 smb_fname, /* fname */
2181 access_mask, /* access_mask */
2182 share_mode, /* share_access */
2183 create_disposition, /* create_disposition*/
2184 create_options, /* create_options */
2185 fattr, /* file_attributes */
2186 oplock_request, /* oplock_request */
2187 0, /* allocation_size */
2188 0, /* private_flags */
2189 NULL, /* sd */
2190 NULL, /* ea_list */
2191 &fsp, /* result */
2192 NULL); /* pinfo */
2193
2194 if (!NT_STATUS_IS_OK(status)) {
2195 if (open_was_deferred(req->mid)) {
2196 /* We have re-scheduled this call. */
2197 goto out;
2198 }
2199 reply_openerror(req, status);
2200 goto out;
2201 }
2202
2203 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2204 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2205 if (!NT_STATUS_IS_OK(status)) {
2206 END_PROFILE(SMBcreate);
2207 goto out;
2208 }
2209
2210 reply_outbuf(req, 1, 0);
2211 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2212
2213 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2214 SCVAL(req->outbuf,smb_flg,
2215 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2216 }
2217
2218 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2219 SCVAL(req->outbuf,smb_flg,
2220 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2221 }
2222
2223 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2224 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2225 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2226 (unsigned int)fattr));
2227
2228 out:
2229 TALLOC_FREE(smb_fname);
2230 END_PROFILE(SMBcreate);
2231 return;
2232}
2233
2234/****************************************************************************
2235 Reply to a create temporary file.
2236****************************************************************************/
2237
2238void reply_ctemp(struct smb_request *req)
2239{
2240 connection_struct *conn = req->conn;
2241 struct smb_filename *smb_fname = NULL;
2242 char *fname = NULL;
2243 uint32 fattr;
2244 files_struct *fsp;
2245 int oplock_request;
2246 int tmpfd;
2247 char *s;
2248 NTSTATUS status;
2249 TALLOC_CTX *ctx = talloc_tos();
2250
2251 START_PROFILE(SMBctemp);
2252
2253 if (req->wct < 3) {
2254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2255 goto out;
2256 }
2257
2258 fattr = SVAL(req->vwv+0, 0);
2259 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2260
2261 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2262 STR_TERMINATE, &status);
2263 if (!NT_STATUS_IS_OK(status)) {
2264 reply_nterror(req, status);
2265 goto out;
2266 }
2267 if (*fname) {
2268 fname = talloc_asprintf(ctx,
2269 "%s/TMXXXXXX",
2270 fname);
2271 } else {
2272 fname = talloc_strdup(ctx, "TMXXXXXX");
2273 }
2274
2275 if (!fname) {
2276 reply_nterror(req, NT_STATUS_NO_MEMORY);
2277 goto out;
2278 }
2279
2280 status = filename_convert(ctx, conn,
2281 req->flags2 & FLAGS2_DFS_PATHNAMES,
2282 fname,
2283 0,
2284 NULL,
2285 &smb_fname);
2286 if (!NT_STATUS_IS_OK(status)) {
2287 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2288 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2289 ERRSRV, ERRbadpath);
2290 goto out;
2291 }
2292 reply_nterror(req, status);
2293 goto out;
2294 }
2295
2296 tmpfd = mkstemp(smb_fname->base_name);
2297 if (tmpfd == -1) {
2298 reply_nterror(req, map_nt_error_from_unix(errno));
2299 goto out;
2300 }
2301
2302 SMB_VFS_STAT(conn, smb_fname);
2303
2304 /* We should fail if file does not exist. */
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_OPEN, /* 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 /* close fd from mkstemp() */
2324 close(tmpfd);
2325
2326 if (!NT_STATUS_IS_OK(status)) {
2327 if (open_was_deferred(req->mid)) {
2328 /* We have re-scheduled this call. */
2329 goto out;
2330 }
2331 reply_openerror(req, status);
2332 goto out;
2333 }
2334
2335 reply_outbuf(req, 1, 0);
2336 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2337
2338 /* the returned filename is relative to the directory */
2339 s = strrchr_m(fsp->fsp_name->base_name, '/');
2340 if (!s) {
2341 s = fsp->fsp_name->base_name;
2342 } else {
2343 s++;
2344 }
2345
2346#if 0
2347 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2348 thing in the byte section. JRA */
2349 SSVALS(p, 0, -1); /* what is this? not in spec */
2350#endif
2351 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2352 == -1) {
2353 reply_nterror(req, NT_STATUS_NO_MEMORY);
2354 goto out;
2355 }
2356
2357 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2358 SCVAL(req->outbuf, smb_flg,
2359 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2360 }
2361
2362 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2363 SCVAL(req->outbuf, smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2365 }
2366
2367 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2368 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2369 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2370 out:
2371 TALLOC_FREE(smb_fname);
2372 END_PROFILE(SMBctemp);
2373 return;
2374}
2375
2376/*******************************************************************
2377 Check if a user is allowed to rename a file.
2378********************************************************************/
2379
2380static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2381 uint16 dirtype)
2382{
2383 if (!CAN_WRITE(conn)) {
2384 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2385 }
2386
2387 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2388 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2389 /* Only bother to read the DOS attribute if we might deny the
2390 rename on the grounds of attribute missmatch. */
2391 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2392 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2393 return NT_STATUS_NO_SUCH_FILE;
2394 }
2395 }
2396
2397 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2398 if (fsp->posix_open) {
2399 return NT_STATUS_OK;
2400 }
2401
2402 /* If no pathnames are open below this
2403 directory, allow the rename. */
2404
2405 if (file_find_subpath(fsp)) {
2406 return NT_STATUS_ACCESS_DENIED;
2407 }
2408 return NT_STATUS_OK;
2409 }
2410
2411 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2412 return NT_STATUS_OK;
2413 }
2414
2415 return NT_STATUS_ACCESS_DENIED;
2416}
2417
2418/*******************************************************************
2419 * unlink a file with all relevant access checks
2420 *******************************************************************/
2421
2422static NTSTATUS do_unlink(connection_struct *conn,
2423 struct smb_request *req,
2424 struct smb_filename *smb_fname,
2425 uint32 dirtype)
2426{
2427 uint32 fattr;
2428 files_struct *fsp;
2429 uint32 dirtype_orig = dirtype;
2430 NTSTATUS status;
2431 int ret;
2432 bool posix_paths = lp_posix_pathnames();
2433
2434 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2435 smb_fname_str_dbg(smb_fname),
2436 dirtype));
2437
2438 if (!CAN_WRITE(conn)) {
2439 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2440 }
2441
2442 if (posix_paths) {
2443 ret = SMB_VFS_LSTAT(conn, smb_fname);
2444 } else {
2445 ret = SMB_VFS_STAT(conn, smb_fname);
2446 }
2447 if (ret != 0) {
2448 return map_nt_error_from_unix(errno);
2449 }
2450
2451 fattr = dos_mode(conn, smb_fname);
2452
2453 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2454 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2455 }
2456
2457 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2458 if (!dirtype) {
2459 return NT_STATUS_NO_SUCH_FILE;
2460 }
2461
2462 if (!dir_check_ftype(conn, fattr, dirtype)) {
2463 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2464 return NT_STATUS_FILE_IS_A_DIRECTORY;
2465 }
2466 return NT_STATUS_NO_SUCH_FILE;
2467 }
2468
2469 if (dirtype_orig & 0x8000) {
2470 /* These will never be set for POSIX. */
2471 return NT_STATUS_NO_SUCH_FILE;
2472 }
2473
2474#if 0
2475 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2476 return NT_STATUS_FILE_IS_A_DIRECTORY;
2477 }
2478
2479 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2480 return NT_STATUS_NO_SUCH_FILE;
2481 }
2482
2483 if (dirtype & 0xFF00) {
2484 /* These will never be set for POSIX. */
2485 return NT_STATUS_NO_SUCH_FILE;
2486 }
2487
2488 dirtype &= 0xFF;
2489 if (!dirtype) {
2490 return NT_STATUS_NO_SUCH_FILE;
2491 }
2492
2493 /* Can't delete a directory. */
2494 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2495 return NT_STATUS_FILE_IS_A_DIRECTORY;
2496 }
2497#endif
2498
2499#if 0 /* JRATEST */
2500 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2501 return NT_STATUS_OBJECT_NAME_INVALID;
2502#endif /* JRATEST */
2503
2504 /* On open checks the open itself will check the share mode, so
2505 don't do it here as we'll get it wrong. */
2506
2507 status = SMB_VFS_CREATE_FILE
2508 (conn, /* conn */
2509 req, /* req */
2510 0, /* root_dir_fid */
2511 smb_fname, /* fname */
2512 DELETE_ACCESS, /* access_mask */
2513 FILE_SHARE_NONE, /* share_access */
2514 FILE_OPEN, /* create_disposition*/
2515 FILE_NON_DIRECTORY_FILE, /* create_options */
2516 /* file_attributes */
2517 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2518 FILE_ATTRIBUTE_NORMAL,
2519 0, /* oplock_request */
2520 0, /* allocation_size */
2521 0, /* private_flags */
2522 NULL, /* sd */
2523 NULL, /* ea_list */
2524 &fsp, /* result */
2525 NULL); /* pinfo */
2526
2527 if (!NT_STATUS_IS_OK(status)) {
2528 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2529 nt_errstr(status)));
2530 return status;
2531 }
2532
2533 status = can_set_delete_on_close(fsp, fattr);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2536 "(%s)\n",
2537 smb_fname_str_dbg(smb_fname),
2538 nt_errstr(status)));
2539 close_file(req, fsp, NORMAL_CLOSE);
2540 return status;
2541 }
2542
2543 /* The set is across all open files on this dev/inode pair. */
2544 if (!set_delete_on_close(fsp, true,
2545 conn->session_info->security_token,
2546 &conn->session_info->utok)) {
2547 close_file(req, fsp, NORMAL_CLOSE);
2548 return NT_STATUS_ACCESS_DENIED;
2549 }
2550
2551 return close_file(req, fsp, NORMAL_CLOSE);
2552}
2553
2554/****************************************************************************
2555 The guts of the unlink command, split out so it may be called by the NT SMB
2556 code.
2557****************************************************************************/
2558
2559NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2560 uint32 dirtype, struct smb_filename *smb_fname,
2561 bool has_wild)
2562{
2563 char *fname_dir = NULL;
2564 char *fname_mask = NULL;
2565 int count=0;
2566 NTSTATUS status = NT_STATUS_OK;
2567 TALLOC_CTX *ctx = talloc_tos();
2568
2569 /* Split up the directory from the filename/mask. */
2570 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2571 &fname_dir, &fname_mask);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 goto out;
2574 }
2575
2576 /*
2577 * We should only check the mangled cache
2578 * here if unix_convert failed. This means
2579 * that the path in 'mask' doesn't exist
2580 * on the file system and so we need to look
2581 * for a possible mangle. This patch from
2582 * Tine Smukavec <valentin.smukavec@hermes.si>.
2583 */
2584
2585 if (!VALID_STAT(smb_fname->st) &&
2586 mangle_is_mangled(fname_mask, conn->params)) {
2587 char *new_mask = NULL;
2588 mangle_lookup_name_from_8_3(ctx, fname_mask,
2589 &new_mask, conn->params);
2590 if (new_mask) {
2591 TALLOC_FREE(fname_mask);
2592 fname_mask = new_mask;
2593 }
2594 }
2595
2596 if (!has_wild) {
2597
2598 /*
2599 * Only one file needs to be unlinked. Append the mask back
2600 * onto the directory.
2601 */
2602 TALLOC_FREE(smb_fname->base_name);
2603 if (ISDOT(fname_dir)) {
2604 /* Ensure we use canonical names on open. */
2605 smb_fname->base_name = talloc_asprintf(smb_fname,
2606 "%s",
2607 fname_mask);
2608 } else {
2609 smb_fname->base_name = talloc_asprintf(smb_fname,
2610 "%s/%s",
2611 fname_dir,
2612 fname_mask);
2613 }
2614 if (!smb_fname->base_name) {
2615 status = NT_STATUS_NO_MEMORY;
2616 goto out;
2617 }
2618 if (dirtype == 0) {
2619 dirtype = FILE_ATTRIBUTE_NORMAL;
2620 }
2621
2622 status = check_name(conn, smb_fname->base_name);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 goto out;
2625 }
2626
2627 status = do_unlink(conn, req, smb_fname, dirtype);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 goto out;
2630 }
2631
2632 count++;
2633 } else {
2634 struct smb_Dir *dir_hnd = NULL;
2635 long offset = 0;
2636 const char *dname = NULL;
2637 char *talloced = NULL;
2638
2639 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2640 status = NT_STATUS_OBJECT_NAME_INVALID;
2641 goto out;
2642 }
2643
2644 if (strequal(fname_mask,"????????.???")) {
2645 TALLOC_FREE(fname_mask);
2646 fname_mask = talloc_strdup(ctx, "*");
2647 if (!fname_mask) {
2648 status = NT_STATUS_NO_MEMORY;
2649 goto out;
2650 }
2651 }
2652
2653 status = check_name(conn, fname_dir);
2654 if (!NT_STATUS_IS_OK(status)) {
2655 goto out;
2656 }
2657
2658 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2659 dirtype);
2660 if (dir_hnd == NULL) {
2661 status = map_nt_error_from_unix(errno);
2662 goto out;
2663 }
2664
2665 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2666 the pattern matches against the long name, otherwise the short name
2667 We don't implement this yet XXXX
2668 */
2669
2670 status = NT_STATUS_NO_SUCH_FILE;
2671
2672 while ((dname = ReadDirName(dir_hnd, &offset,
2673 &smb_fname->st, &talloced))) {
2674 TALLOC_CTX *frame = talloc_stackframe();
2675
2676 if (!is_visible_file(conn, fname_dir, dname,
2677 &smb_fname->st, true)) {
2678 TALLOC_FREE(frame);
2679 TALLOC_FREE(talloced);
2680 continue;
2681 }
2682
2683 /* Quick check for "." and ".." */
2684 if (ISDOT(dname) || ISDOTDOT(dname)) {
2685 TALLOC_FREE(frame);
2686 TALLOC_FREE(talloced);
2687 continue;
2688 }
2689
2690 if(!mask_match(dname, fname_mask,
2691 conn->case_sensitive)) {
2692 TALLOC_FREE(frame);
2693 TALLOC_FREE(talloced);
2694 continue;
2695 }
2696
2697 TALLOC_FREE(smb_fname->base_name);
2698 if (ISDOT(fname_dir)) {
2699 /* Ensure we use canonical names on open. */
2700 smb_fname->base_name =
2701 talloc_asprintf(smb_fname, "%s",
2702 dname);
2703 } else {
2704 smb_fname->base_name =
2705 talloc_asprintf(smb_fname, "%s/%s",
2706 fname_dir, dname);
2707 }
2708
2709 if (!smb_fname->base_name) {
2710 TALLOC_FREE(dir_hnd);
2711 status = NT_STATUS_NO_MEMORY;
2712 TALLOC_FREE(frame);
2713 TALLOC_FREE(talloced);
2714 goto out;
2715 }
2716
2717 status = check_name(conn, smb_fname->base_name);
2718 if (!NT_STATUS_IS_OK(status)) {
2719 TALLOC_FREE(dir_hnd);
2720 TALLOC_FREE(frame);
2721 TALLOC_FREE(talloced);
2722 goto out;
2723 }
2724
2725 status = do_unlink(conn, req, smb_fname, dirtype);
2726 if (!NT_STATUS_IS_OK(status)) {
2727 TALLOC_FREE(frame);
2728 TALLOC_FREE(talloced);
2729 continue;
2730 }
2731
2732 count++;
2733 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2734 smb_fname->base_name));
2735
2736 TALLOC_FREE(frame);
2737 TALLOC_FREE(talloced);
2738 }
2739 TALLOC_FREE(dir_hnd);
2740 }
2741
2742 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2743 status = map_nt_error_from_unix(errno);
2744 }
2745
2746 out:
2747 TALLOC_FREE(fname_dir);
2748 TALLOC_FREE(fname_mask);
2749 return status;
2750}
2751
2752/****************************************************************************
2753 Reply to a unlink
2754****************************************************************************/
2755
2756void reply_unlink(struct smb_request *req)
2757{
2758 connection_struct *conn = req->conn;
2759 char *name = NULL;
2760 struct smb_filename *smb_fname = NULL;
2761 uint32 dirtype;
2762 NTSTATUS status;
2763 bool path_contains_wcard = False;
2764 TALLOC_CTX *ctx = talloc_tos();
2765
2766 START_PROFILE(SMBunlink);
2767
2768 if (req->wct < 1) {
2769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2770 goto out;
2771 }
2772
2773 dirtype = SVAL(req->vwv+0, 0);
2774
2775 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2776 STR_TERMINATE, &status,
2777 &path_contains_wcard);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 reply_nterror(req, status);
2780 goto out;
2781 }
2782
2783 status = filename_convert(ctx, conn,
2784 req->flags2 & FLAGS2_DFS_PATHNAMES,
2785 name,
2786 UCF_COND_ALLOW_WCARD_LCOMP,
2787 &path_contains_wcard,
2788 &smb_fname);
2789 if (!NT_STATUS_IS_OK(status)) {
2790 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2791 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2792 ERRSRV, ERRbadpath);
2793 goto out;
2794 }
2795 reply_nterror(req, status);
2796 goto out;
2797 }
2798
2799 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2800
2801 status = unlink_internals(conn, req, dirtype, smb_fname,
2802 path_contains_wcard);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 if (open_was_deferred(req->mid)) {
2805 /* We have re-scheduled this call. */
2806 goto out;
2807 }
2808 reply_nterror(req, status);
2809 goto out;
2810 }
2811
2812 reply_outbuf(req, 0, 0);
2813 out:
2814 TALLOC_FREE(smb_fname);
2815 END_PROFILE(SMBunlink);
2816 return;
2817}
2818
2819/****************************************************************************
2820 Fail for readbraw.
2821****************************************************************************/
2822
2823static void fail_readraw(void)
2824{
2825 const char *errstr = talloc_asprintf(talloc_tos(),
2826 "FAIL ! reply_readbraw: socket write fail (%s)",
2827 strerror(errno));
2828 if (!errstr) {
2829 errstr = "";
2830 }
2831 exit_server_cleanly(errstr);
2832}
2833
2834/****************************************************************************
2835 Fake (read/write) sendfile. Returns -1 on read or write fail.
2836****************************************************************************/
2837
2838ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2839{
2840 size_t bufsize;
2841 size_t tosend = nread;
2842 char *buf;
2843
2844 if (nread == 0) {
2845 return 0;
2846 }
2847
2848 bufsize = MIN(nread, 65536);
2849
2850 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2851 return -1;
2852 }
2853
2854 while (tosend > 0) {
2855 ssize_t ret;
2856 size_t cur_read;
2857
2858 if (tosend > bufsize) {
2859 cur_read = bufsize;
2860 } else {
2861 cur_read = tosend;
2862 }
2863 ret = read_file(fsp,buf,startpos,cur_read);
2864 if (ret == -1) {
2865 SAFE_FREE(buf);
2866 return -1;
2867 }
2868
2869 /* If we had a short read, fill with zeros. */
2870 if (ret < cur_read) {
2871 memset(buf + ret, '\0', cur_read - ret);
2872 }
2873
2874 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2875 != cur_read) {
2876 char addr[INET6_ADDRSTRLEN];
2877 /*
2878 * Try and give an error message saying what
2879 * client failed.
2880 */
2881 DEBUG(0, ("write_data failed for client %s. "
2882 "Error %s\n",
2883 get_peer_addr(fsp->conn->sconn->sock, addr,
2884 sizeof(addr)),
2885 strerror(errno)));
2886 SAFE_FREE(buf);
2887 return -1;
2888 }
2889 tosend -= cur_read;
2890 startpos += cur_read;
2891 }
2892
2893 SAFE_FREE(buf);
2894 return (ssize_t)nread;
2895}
2896
2897/****************************************************************************
2898 Deal with the case of sendfile reading less bytes from the file than
2899 requested. Fill with zeros (all we can do).
2900****************************************************************************/
2901
2902void sendfile_short_send(files_struct *fsp,
2903 ssize_t nread,
2904 size_t headersize,
2905 size_t smb_maxcnt)
2906{
2907#define SHORT_SEND_BUFSIZE 1024
2908 if (nread < headersize) {
2909 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2910 "header for file %s (%s). Terminating\n",
2911 fsp_str_dbg(fsp), strerror(errno)));
2912 exit_server_cleanly("sendfile_short_send failed");
2913 }
2914
2915 nread -= headersize;
2916
2917 if (nread < smb_maxcnt) {
2918 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2919 if (!buf) {
2920 exit_server_cleanly("sendfile_short_send: "
2921 "malloc failed");
2922 }
2923
2924 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2925 "with zeros !\n", fsp_str_dbg(fsp)));
2926
2927 while (nread < smb_maxcnt) {
2928 /*
2929 * We asked for the real file size and told sendfile
2930 * to not go beyond the end of the file. But it can
2931 * happen that in between our fstat call and the
2932 * sendfile call the file was truncated. This is very
2933 * bad because we have already announced the larger
2934 * number of bytes to the client.
2935 *
2936 * The best we can do now is to send 0-bytes, just as
2937 * a read from a hole in a sparse file would do.
2938 *
2939 * This should happen rarely enough that I don't care
2940 * about efficiency here :-)
2941 */
2942 size_t to_write;
2943
2944 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2945 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2946 != to_write) {
2947 char addr[INET6_ADDRSTRLEN];
2948 /*
2949 * Try and give an error message saying what
2950 * client failed.
2951 */
2952 DEBUG(0, ("write_data failed for client %s. "
2953 "Error %s\n",
2954 get_peer_addr(
2955 fsp->conn->sconn->sock, addr,
2956 sizeof(addr)),
2957 strerror(errno)));
2958 exit_server_cleanly("sendfile_short_send: "
2959 "write_data failed");
2960 }
2961 nread += to_write;
2962 }
2963 SAFE_FREE(buf);
2964 }
2965}
2966
2967/****************************************************************************
2968 Return a readbraw error (4 bytes of zero).
2969****************************************************************************/
2970
2971static void reply_readbraw_error(struct smbd_server_connection *sconn)
2972{
2973 char header[4];
2974
2975 SIVAL(header,0,0);
2976
2977 smbd_lock_socket(sconn);
2978 if (write_data(sconn->sock,header,4) != 4) {
2979 char addr[INET6_ADDRSTRLEN];
2980 /*
2981 * Try and give an error message saying what
2982 * client failed.
2983 */
2984 DEBUG(0, ("write_data failed for client %s. "
2985 "Error %s\n",
2986 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2987 strerror(errno)));
2988
2989 fail_readraw();
2990 }
2991 smbd_unlock_socket(sconn);
2992}
2993
2994/****************************************************************************
2995 Use sendfile in readbraw.
2996****************************************************************************/
2997
2998static void send_file_readbraw(connection_struct *conn,
2999 struct smb_request *req,
3000 files_struct *fsp,
3001 SMB_OFF_T startpos,
3002 size_t nread,
3003 ssize_t mincount)
3004{
3005 struct smbd_server_connection *sconn = req->sconn;
3006 char *outbuf = NULL;
3007 ssize_t ret=0;
3008
3009 /*
3010 * We can only use sendfile on a non-chained packet
3011 * but we can use on a non-oplocked file. tridge proved this
3012 * on a train in Germany :-). JRA.
3013 * reply_readbraw has already checked the length.
3014 */
3015
3016 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3017 (fsp->wcp == NULL) &&
3018 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3019 ssize_t sendfile_read = -1;
3020 char header[4];
3021 DATA_BLOB header_blob;
3022
3023 _smb_setlen(header,nread);
3024 header_blob = data_blob_const(header, 4);
3025
3026 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3027 &header_blob, startpos,
3028 nread);
3029 if (sendfile_read == -1) {
3030 /* Returning ENOSYS means no data at all was sent.
3031 * Do this as a normal read. */
3032 if (errno == ENOSYS) {
3033 goto normal_readbraw;
3034 }
3035
3036 /*
3037 * Special hack for broken Linux with no working sendfile. If we
3038 * return EINTR we sent the header but not the rest of the data.
3039 * Fake this up by doing read/write calls.
3040 */
3041 if (errno == EINTR) {
3042 /* Ensure we don't do this again. */
3043 set_use_sendfile(SNUM(conn), False);
3044 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3045
3046 if (fake_sendfile(fsp, startpos, nread) == -1) {
3047 DEBUG(0,("send_file_readbraw: "
3048 "fake_sendfile failed for "
3049 "file %s (%s).\n",
3050 fsp_str_dbg(fsp),
3051 strerror(errno)));
3052 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3053 }
3054 return;
3055 }
3056
3057 DEBUG(0,("send_file_readbraw: sendfile failed for "
3058 "file %s (%s). Terminating\n",
3059 fsp_str_dbg(fsp), strerror(errno)));
3060 exit_server_cleanly("send_file_readbraw sendfile failed");
3061 } else if (sendfile_read == 0) {
3062 /*
3063 * Some sendfile implementations return 0 to indicate
3064 * that there was a short read, but nothing was
3065 * actually written to the socket. In this case,
3066 * fallback to the normal read path so the header gets
3067 * the correct byte count.
3068 */
3069 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3070 "bytes falling back to the normal read: "
3071 "%s\n", fsp_str_dbg(fsp)));
3072 goto normal_readbraw;
3073 }
3074
3075 /* Deal with possible short send. */
3076 if (sendfile_read != 4+nread) {
3077 sendfile_short_send(fsp, sendfile_read, 4, nread);
3078 }
3079 return;
3080 }
3081
3082normal_readbraw:
3083
3084 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3085 if (!outbuf) {
3086 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3087 (unsigned)(nread+4)));
3088 reply_readbraw_error(sconn);
3089 return;
3090 }
3091
3092 if (nread > 0) {
3093 ret = read_file(fsp,outbuf+4,startpos,nread);
3094#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3095 if (ret < mincount)
3096 ret = 0;
3097#else
3098 if (ret < nread)
3099 ret = 0;
3100#endif
3101 }
3102
3103 _smb_setlen(outbuf,ret);
3104 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3105 char addr[INET6_ADDRSTRLEN];
3106 /*
3107 * Try and give an error message saying what
3108 * client failed.
3109 */
3110 DEBUG(0, ("write_data failed for client %s. "
3111 "Error %s\n",
3112 get_peer_addr(fsp->conn->sconn->sock, addr,
3113 sizeof(addr)),
3114 strerror(errno)));
3115
3116 fail_readraw();
3117 }
3118
3119 TALLOC_FREE(outbuf);
3120}
3121
3122/****************************************************************************
3123 Reply to a readbraw (core+ protocol).
3124****************************************************************************/
3125
3126void reply_readbraw(struct smb_request *req)
3127{
3128 connection_struct *conn = req->conn;
3129 struct smbd_server_connection *sconn = req->sconn;
3130 ssize_t maxcount,mincount;
3131 size_t nread = 0;
3132 SMB_OFF_T startpos;
3133 files_struct *fsp;
3134 struct lock_struct lock;
3135 SMB_OFF_T size = 0;
3136
3137 START_PROFILE(SMBreadbraw);
3138
3139 if (srv_is_signing_active(sconn) ||
3140 is_encrypted_packet(req->inbuf)) {
3141 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3142 "raw reads/writes are disallowed.");
3143 }
3144
3145 if (req->wct < 8) {
3146 reply_readbraw_error(sconn);
3147 END_PROFILE(SMBreadbraw);
3148 return;
3149 }
3150
3151 if (sconn->smb1.echo_handler.trusted_fde) {
3152 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3153 "'async smb echo handler = yes'\n"));
3154 reply_readbraw_error(sconn);
3155 END_PROFILE(SMBreadbraw);
3156 return;
3157 }
3158
3159 /*
3160 * Special check if an oplock break has been issued
3161 * and the readraw request croses on the wire, we must
3162 * return a zero length response here.
3163 */
3164
3165 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3166
3167 /*
3168 * We have to do a check_fsp by hand here, as
3169 * we must always return 4 zero bytes on error,
3170 * not a NTSTATUS.
3171 */
3172
3173 if (!fsp || !conn || conn != fsp->conn ||
3174 req->vuid != fsp->vuid ||
3175 fsp->is_directory || fsp->fh->fd == -1) {
3176 /*
3177 * fsp could be NULL here so use the value from the packet. JRA.
3178 */
3179 DEBUG(3,("reply_readbraw: fnum %d not valid "
3180 "- cache prime?\n",
3181 (int)SVAL(req->vwv+0, 0)));
3182 reply_readbraw_error(sconn);
3183 END_PROFILE(SMBreadbraw);
3184 return;
3185 }
3186
3187 /* Do a "by hand" version of CHECK_READ. */
3188 if (!(fsp->can_read ||
3189 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3190 (fsp->access_mask & FILE_EXECUTE)))) {
3191 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3192 (int)SVAL(req->vwv+0, 0)));
3193 reply_readbraw_error(sconn);
3194 END_PROFILE(SMBreadbraw);
3195 return;
3196 }
3197
3198 flush_write_cache(fsp, READRAW_FLUSH);
3199
3200 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3201 if(req->wct == 10) {
3202 /*
3203 * This is a large offset (64 bit) read.
3204 */
3205#ifdef LARGE_SMB_OFF_T
3206
3207 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3208
3209#else /* !LARGE_SMB_OFF_T */
3210
3211 /*
3212 * Ensure we haven't been sent a >32 bit offset.
3213 */
3214
3215 if(IVAL(req->vwv+8, 0) != 0) {
3216 DEBUG(0,("reply_readbraw: large offset "
3217 "(%x << 32) used and we don't support "
3218 "64 bit offsets.\n",
3219 (unsigned int)IVAL(req->vwv+8, 0) ));
3220 reply_readbraw_error(sconn);
3221 END_PROFILE(SMBreadbraw);
3222 return;
3223 }
3224
3225#endif /* LARGE_SMB_OFF_T */
3226
3227 if(startpos < 0) {
3228 DEBUG(0,("reply_readbraw: negative 64 bit "
3229 "readraw offset (%.0f) !\n",
3230 (double)startpos ));
3231 reply_readbraw_error(sconn);
3232 END_PROFILE(SMBreadbraw);
3233 return;
3234 }
3235 }
3236
3237 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3238 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3239
3240 /* ensure we don't overrun the packet size */
3241 maxcount = MIN(65535,maxcount);
3242
3243 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3244 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3245 &lock);
3246
3247 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3248 reply_readbraw_error(sconn);
3249 END_PROFILE(SMBreadbraw);
3250 return;
3251 }
3252
3253 if (fsp_stat(fsp) == 0) {
3254 size = fsp->fsp_name->st.st_ex_size;
3255 }
3256
3257 if (startpos >= size) {
3258 nread = 0;
3259 } else {
3260 nread = MIN(maxcount,(size - startpos));
3261 }
3262
3263#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3264 if (nread < mincount)
3265 nread = 0;
3266#endif
3267
3268 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3269 "min=%lu nread=%lu\n",
3270 fsp->fnum, (double)startpos,
3271 (unsigned long)maxcount,
3272 (unsigned long)mincount,
3273 (unsigned long)nread ) );
3274
3275 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3276
3277 DEBUG(5,("reply_readbraw finished\n"));
3278
3279 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3280
3281 END_PROFILE(SMBreadbraw);
3282 return;
3283}
3284
3285#undef DBGC_CLASS
3286#define DBGC_CLASS DBGC_LOCKING
3287
3288/****************************************************************************
3289 Reply to a lockread (core+ protocol).
3290****************************************************************************/
3291
3292void reply_lockread(struct smb_request *req)
3293{
3294 connection_struct *conn = req->conn;
3295 ssize_t nread = -1;
3296 char *data;
3297 SMB_OFF_T startpos;
3298 size_t numtoread;
3299 NTSTATUS status;
3300 files_struct *fsp;
3301 struct byte_range_lock *br_lck = NULL;
3302 char *p = NULL;
3303 struct smbd_server_connection *sconn = req->sconn;
3304
3305 START_PROFILE(SMBlockread);
3306
3307 if (req->wct < 5) {
3308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3309 END_PROFILE(SMBlockread);
3310 return;
3311 }
3312
3313 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3314
3315 if (!check_fsp(conn, req, fsp)) {
3316 END_PROFILE(SMBlockread);
3317 return;
3318 }
3319
3320 if (!CHECK_READ(fsp,req)) {
3321 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3322 END_PROFILE(SMBlockread);
3323 return;
3324 }
3325
3326 numtoread = SVAL(req->vwv+1, 0);
3327 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3328
3329 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3330
3331 reply_outbuf(req, 5, numtoread + 3);
3332
3333 data = smb_buf(req->outbuf) + 3;
3334
3335 /*
3336 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3337 * protocol request that predates the read/write lock concept.
3338 * Thus instead of asking for a read lock here we need to ask
3339 * for a write lock. JRA.
3340 * Note that the requested lock size is unaffected by max_recv.
3341 */
3342
3343 br_lck = do_lock(req->sconn->msg_ctx,
3344 fsp,
3345 (uint64_t)req->smbpid,
3346 (uint64_t)numtoread,
3347 (uint64_t)startpos,
3348 WRITE_LOCK,
3349 WINDOWS_LOCK,
3350 False, /* Non-blocking lock. */
3351 &status,
3352 NULL,
3353 NULL);
3354 TALLOC_FREE(br_lck);
3355
3356 if (NT_STATUS_V(status)) {
3357 reply_nterror(req, status);
3358 END_PROFILE(SMBlockread);
3359 return;
3360 }
3361
3362 /*
3363 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3364 */
3365
3366 if (numtoread > sconn->smb1.negprot.max_recv) {
3367 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3368Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3369 (unsigned int)numtoread,
3370 (unsigned int)sconn->smb1.negprot.max_recv));
3371 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3372 }
3373 nread = read_file(fsp,data,startpos,numtoread);
3374
3375 if (nread < 0) {
3376 reply_nterror(req, map_nt_error_from_unix(errno));
3377 END_PROFILE(SMBlockread);
3378 return;
3379 }
3380
3381 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3382
3383 SSVAL(req->outbuf,smb_vwv0,nread);
3384 SSVAL(req->outbuf,smb_vwv5,nread+3);
3385 p = smb_buf(req->outbuf);
3386 SCVAL(p,0,0); /* pad byte. */
3387 SSVAL(p,1,nread);
3388
3389 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3390 fsp->fnum, (int)numtoread, (int)nread));
3391
3392 END_PROFILE(SMBlockread);
3393 return;
3394}
3395
3396#undef DBGC_CLASS
3397#define DBGC_CLASS DBGC_ALL
3398
3399/****************************************************************************
3400 Reply to a read.
3401****************************************************************************/
3402
3403void reply_read(struct smb_request *req)
3404{
3405 connection_struct *conn = req->conn;
3406 size_t numtoread;
3407 ssize_t nread = 0;
3408 char *data;
3409 SMB_OFF_T startpos;
3410 int outsize = 0;
3411 files_struct *fsp;
3412 struct lock_struct lock;
3413 struct smbd_server_connection *sconn = req->sconn;
3414
3415 START_PROFILE(SMBread);
3416
3417 if (req->wct < 3) {
3418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3419 END_PROFILE(SMBread);
3420 return;
3421 }
3422
3423 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3424
3425 if (!check_fsp(conn, req, fsp)) {
3426 END_PROFILE(SMBread);
3427 return;
3428 }
3429
3430 if (!CHECK_READ(fsp,req)) {
3431 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3432 END_PROFILE(SMBread);
3433 return;
3434 }
3435
3436 numtoread = SVAL(req->vwv+1, 0);
3437 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3438
3439 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3440
3441 /*
3442 * The requested read size cannot be greater than max_recv. JRA.
3443 */
3444 if (numtoread > sconn->smb1.negprot.max_recv) {
3445 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3446Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3447 (unsigned int)numtoread,
3448 (unsigned int)sconn->smb1.negprot.max_recv));
3449 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3450 }
3451
3452 reply_outbuf(req, 5, numtoread+3);
3453
3454 data = smb_buf(req->outbuf) + 3;
3455
3456 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3457 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3458 &lock);
3459
3460 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3461 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3462 END_PROFILE(SMBread);
3463 return;
3464 }
3465
3466 if (numtoread > 0)
3467 nread = read_file(fsp,data,startpos,numtoread);
3468
3469 if (nread < 0) {
3470 reply_nterror(req, map_nt_error_from_unix(errno));
3471 goto strict_unlock;
3472 }
3473
3474 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3475
3476 SSVAL(req->outbuf,smb_vwv0,nread);
3477 SSVAL(req->outbuf,smb_vwv5,nread+3);
3478 SCVAL(smb_buf(req->outbuf),0,1);
3479 SSVAL(smb_buf(req->outbuf),1,nread);
3480
3481 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3482 fsp->fnum, (int)numtoread, (int)nread ) );
3483
3484strict_unlock:
3485 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3486
3487 END_PROFILE(SMBread);
3488 return;
3489}
3490
3491/****************************************************************************
3492 Setup readX header.
3493****************************************************************************/
3494
3495static int setup_readX_header(struct smb_request *req, char *outbuf,
3496 size_t smb_maxcnt)
3497{
3498 int outsize;
3499 char *data;
3500
3501 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3502 data = smb_buf(outbuf);
3503
3504 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3505
3506 SCVAL(outbuf,smb_vwv0,0xFF);
3507 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3508 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3509 SSVAL(outbuf,smb_vwv6,
3510 req_wct_ofs(req)
3511 + 1 /* the wct field */
3512 + 12 * sizeof(uint16_t) /* vwv */
3513 + 2); /* the buflen field */
3514 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3515 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3516 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3517 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3518 return outsize;
3519}
3520
3521/****************************************************************************
3522 Reply to a read and X - possibly using sendfile.
3523****************************************************************************/
3524
3525static void send_file_readX(connection_struct *conn, struct smb_request *req,
3526 files_struct *fsp, SMB_OFF_T startpos,
3527 size_t smb_maxcnt)
3528{
3529 ssize_t nread = -1;
3530 struct lock_struct lock;
3531 int saved_errno = 0;
3532
3533 if(fsp_stat(fsp) == -1) {
3534 reply_nterror(req, map_nt_error_from_unix(errno));
3535 return;
3536 }
3537
3538 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3539 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3540 &lock);
3541
3542 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3543 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3544 return;
3545 }
3546
3547 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3548 (startpos > fsp->fsp_name->st.st_ex_size)
3549 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3550 /*
3551 * We already know that we would do a short read, so don't
3552 * try the sendfile() path.
3553 */
3554 goto nosendfile_read;
3555 }
3556
3557 /*
3558 * We can only use sendfile on a non-chained packet
3559 * but we can use on a non-oplocked file. tridge proved this
3560 * on a train in Germany :-). JRA.
3561 */
3562
3563 if (!req_is_in_chain(req) &&
3564 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3565 (fsp->wcp == NULL) &&
3566 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3567 uint8 headerbuf[smb_size + 12 * 2];
3568 DATA_BLOB header;
3569
3570 /*
3571 * Set up the packet header before send. We
3572 * assume here the sendfile will work (get the
3573 * correct amount of data).
3574 */
3575
3576 header = data_blob_const(headerbuf, sizeof(headerbuf));
3577
3578 construct_reply_common_req(req, (char *)headerbuf);
3579 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3580
3581 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3582 startpos, smb_maxcnt);
3583 if (nread == -1) {
3584 /* Returning ENOSYS means no data at all was sent.
3585 Do this as a normal read. */
3586 if (errno == ENOSYS) {
3587 goto normal_read;
3588 }
3589
3590 /*
3591 * Special hack for broken Linux with no working sendfile. If we
3592 * return EINTR we sent the header but not the rest of the data.
3593 * Fake this up by doing read/write calls.
3594 */
3595
3596 if (errno == EINTR) {
3597 /* Ensure we don't do this again. */
3598 set_use_sendfile(SNUM(conn), False);
3599 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3600 nread = fake_sendfile(fsp, startpos,
3601 smb_maxcnt);
3602 if (nread == -1) {
3603 DEBUG(0,("send_file_readX: "
3604 "fake_sendfile failed for "
3605 "file %s (%s).\n",
3606 fsp_str_dbg(fsp),
3607 strerror(errno)));
3608 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3609 }
3610 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3611 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3612 /* No outbuf here means successful sendfile. */
3613 goto strict_unlock;
3614 }
3615
3616 DEBUG(0,("send_file_readX: sendfile failed for file "
3617 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3618 strerror(errno)));
3619 exit_server_cleanly("send_file_readX sendfile failed");
3620 } else if (nread == 0) {
3621 /*
3622 * Some sendfile implementations return 0 to indicate
3623 * that there was a short read, but nothing was
3624 * actually written to the socket. In this case,
3625 * fallback to the normal read path so the header gets
3626 * the correct byte count.
3627 */
3628 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3629 "falling back to the normal read: %s\n",
3630 fsp_str_dbg(fsp)));
3631 goto normal_read;
3632 }
3633
3634 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3635 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3636
3637 /* Deal with possible short send. */
3638 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3639 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3640 }
3641 /* No outbuf here means successful sendfile. */
3642 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3643 SMB_PERFCOUNT_END(&req->pcd);
3644 goto strict_unlock;
3645 }
3646
3647normal_read:
3648
3649 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3650 uint8 headerbuf[smb_size + 2*12];
3651
3652 construct_reply_common_req(req, (char *)headerbuf);
3653 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3654
3655 /* Send out the header. */
3656 if (write_data(req->sconn->sock, (char *)headerbuf,
3657 sizeof(headerbuf)) != sizeof(headerbuf)) {
3658
3659 char addr[INET6_ADDRSTRLEN];
3660 /*
3661 * Try and give an error message saying what
3662 * client failed.
3663 */
3664 DEBUG(0, ("write_data failed for client %s. "
3665 "Error %s\n",
3666 get_peer_addr(req->sconn->sock, addr,
3667 sizeof(addr)),
3668 strerror(errno)));
3669
3670 DEBUG(0,("send_file_readX: write_data failed for file "
3671 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3672 strerror(errno)));
3673 exit_server_cleanly("send_file_readX sendfile failed");
3674 }
3675 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3676 if (nread == -1) {
3677 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3678 "file %s (%s).\n", fsp_str_dbg(fsp),
3679 strerror(errno)));
3680 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3681 }
3682 goto strict_unlock;
3683 }
3684
3685nosendfile_read:
3686
3687 reply_outbuf(req, 12, smb_maxcnt);
3688
3689 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3690 saved_errno = errno;
3691
3692 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3693
3694 if (nread < 0) {
3695 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3696 return;
3697 }
3698
3699 setup_readX_header(req, (char *)req->outbuf, nread);
3700
3701 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3702 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3703
3704 chain_reply(req);
3705 return;
3706
3707 strict_unlock:
3708 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3709 TALLOC_FREE(req->outbuf);
3710 return;
3711}
3712
3713/****************************************************************************
3714 Reply to a read and X.
3715****************************************************************************/
3716
3717void reply_read_and_X(struct smb_request *req)
3718{
3719 connection_struct *conn = req->conn;
3720 files_struct *fsp;
3721 SMB_OFF_T startpos;
3722 size_t smb_maxcnt;
3723 bool big_readX = False;
3724#if 0
3725 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3726#endif
3727
3728 START_PROFILE(SMBreadX);
3729
3730 if ((req->wct != 10) && (req->wct != 12)) {
3731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3732 return;
3733 }
3734
3735 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3736 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3737 smb_maxcnt = SVAL(req->vwv+5, 0);
3738
3739 /* If it's an IPC, pass off the pipe handler. */
3740 if (IS_IPC(conn)) {
3741 reply_pipe_read_and_X(req);
3742 END_PROFILE(SMBreadX);
3743 return;
3744 }
3745
3746 if (!check_fsp(conn, req, fsp)) {
3747 END_PROFILE(SMBreadX);
3748 return;
3749 }
3750
3751 if (!CHECK_READ(fsp,req)) {
3752 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3753 END_PROFILE(SMBreadX);
3754 return;
3755 }
3756
3757 if (global_client_caps & CAP_LARGE_READX) {
3758 size_t upper_size = SVAL(req->vwv+7, 0);
3759 smb_maxcnt |= (upper_size<<16);
3760 if (upper_size > 1) {
3761 /* Can't do this on a chained packet. */
3762 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3763 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3764 END_PROFILE(SMBreadX);
3765 return;
3766 }
3767 /* We currently don't do this on signed or sealed data. */
3768 if (srv_is_signing_active(req->sconn) ||
3769 is_encrypted_packet(req->inbuf)) {
3770 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3771 END_PROFILE(SMBreadX);
3772 return;
3773 }
3774 /* Is there room in the reply for this data ? */
3775 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3776 reply_nterror(req,
3777 NT_STATUS_INVALID_PARAMETER);
3778 END_PROFILE(SMBreadX);
3779 return;
3780 }
3781 big_readX = True;
3782 }
3783 }
3784
3785 if (req->wct == 12) {
3786#ifdef LARGE_SMB_OFF_T
3787 /*
3788 * This is a large offset (64 bit) read.
3789 */
3790 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3791
3792#else /* !LARGE_SMB_OFF_T */
3793
3794 /*
3795 * Ensure we haven't been sent a >32 bit offset.
3796 */
3797
3798 if(IVAL(req->vwv+10, 0) != 0) {
3799 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3800 "used and we don't support 64 bit offsets.\n",
3801 (unsigned int)IVAL(req->vwv+10, 0) ));
3802 END_PROFILE(SMBreadX);
3803 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3804 return;
3805 }
3806
3807#endif /* LARGE_SMB_OFF_T */
3808
3809 }
3810
3811 if (!big_readX) {
3812 NTSTATUS status = schedule_aio_read_and_X(conn,
3813 req,
3814 fsp,
3815 startpos,
3816 smb_maxcnt);
3817 if (NT_STATUS_IS_OK(status)) {
3818 /* Read scheduled - we're done. */
3819 goto out;
3820 }
3821 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3822 /* Real error - report to client. */
3823 END_PROFILE(SMBreadX);
3824 reply_nterror(req, status);
3825 return;
3826 }
3827 /* NT_STATUS_RETRY - fall back to sync read. */
3828 }
3829
3830 smbd_lock_socket(req->sconn);
3831 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3832 smbd_unlock_socket(req->sconn);
3833
3834 out:
3835 END_PROFILE(SMBreadX);
3836 return;
3837}
3838
3839/****************************************************************************
3840 Error replies to writebraw must have smb_wct == 1. Fix this up.
3841****************************************************************************/
3842
3843void error_to_writebrawerr(struct smb_request *req)
3844{
3845 uint8 *old_outbuf = req->outbuf;
3846
3847 reply_outbuf(req, 1, 0);
3848
3849 memcpy(req->outbuf, old_outbuf, smb_size);
3850 TALLOC_FREE(old_outbuf);
3851}
3852
3853/****************************************************************************
3854 Read 4 bytes of a smb packet and return the smb length of the packet.
3855 Store the result in the buffer. This version of the function will
3856 never return a session keepalive (length of zero).
3857 Timeout is in milliseconds.
3858****************************************************************************/
3859
3860static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3861 size_t *len)
3862{
3863 uint8_t msgtype = SMBkeepalive;
3864
3865 while (msgtype == SMBkeepalive) {
3866 NTSTATUS status;
3867
3868 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3869 len);
3870 if (!NT_STATUS_IS_OK(status)) {
3871 char addr[INET6_ADDRSTRLEN];
3872 /* Try and give an error message
3873 * saying what client failed. */
3874 DEBUG(0, ("read_fd_with_timeout failed for "
3875 "client %s read error = %s.\n",
3876 get_peer_addr(fd,addr,sizeof(addr)),
3877 nt_errstr(status)));
3878 return status;
3879 }
3880
3881 msgtype = CVAL(inbuf, 0);
3882 }
3883
3884 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3885 (unsigned long)len));
3886
3887 return NT_STATUS_OK;
3888}
3889
3890/****************************************************************************
3891 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3892****************************************************************************/
3893
3894void reply_writebraw(struct smb_request *req)
3895{
3896 connection_struct *conn = req->conn;
3897 char *buf = NULL;
3898 ssize_t nwritten=0;
3899 ssize_t total_written=0;
3900 size_t numtowrite=0;
3901 size_t tcount;
3902 SMB_OFF_T startpos;
3903 char *data=NULL;
3904 bool write_through;
3905 files_struct *fsp;
3906 struct lock_struct lock;
3907 NTSTATUS status;
3908
3909 START_PROFILE(SMBwritebraw);
3910
3911 /*
3912 * If we ever reply with an error, it must have the SMB command
3913 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3914 * we're finished.
3915 */
3916 SCVAL(req->inbuf,smb_com,SMBwritec);
3917
3918 if (srv_is_signing_active(req->sconn)) {
3919 END_PROFILE(SMBwritebraw);
3920 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3921 "raw reads/writes are disallowed.");
3922 }
3923
3924 if (req->wct < 12) {
3925 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3926 error_to_writebrawerr(req);
3927 END_PROFILE(SMBwritebraw);
3928 return;
3929 }
3930
3931 if (req->sconn->smb1.echo_handler.trusted_fde) {
3932 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3933 "'async smb echo handler = yes'\n"));
3934 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3935 error_to_writebrawerr(req);
3936 END_PROFILE(SMBwritebraw);
3937 return;
3938 }
3939
3940 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3941 if (!check_fsp(conn, req, fsp)) {
3942 error_to_writebrawerr(req);
3943 END_PROFILE(SMBwritebraw);
3944 return;
3945 }
3946
3947 if (!CHECK_WRITE(fsp)) {
3948 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3949 error_to_writebrawerr(req);
3950 END_PROFILE(SMBwritebraw);
3951 return;
3952 }
3953
3954 tcount = IVAL(req->vwv+1, 0);
3955 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3956 write_through = BITSETW(req->vwv+7,0);
3957
3958 /* We have to deal with slightly different formats depending
3959 on whether we are using the core+ or lanman1.0 protocol */
3960
3961 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3962 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3963 data = smb_buf(req->inbuf);
3964 } else {
3965 numtowrite = SVAL(req->vwv+10, 0);
3966 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3967 }
3968
3969 /* Ensure we don't write bytes past the end of this packet. */
3970 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3972 error_to_writebrawerr(req);
3973 END_PROFILE(SMBwritebraw);
3974 return;
3975 }
3976
3977 if (!fsp->print_file) {
3978 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3979 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3980 &lock);
3981
3982 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3983 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3984 error_to_writebrawerr(req);
3985 END_PROFILE(SMBwritebraw);
3986 return;
3987 }
3988 }
3989
3990 if (numtowrite>0) {
3991 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3992 }
3993
3994 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3995 "wrote=%d sync=%d\n",
3996 fsp->fnum, (double)startpos, (int)numtowrite,
3997 (int)nwritten, (int)write_through));
3998
3999 if (nwritten < (ssize_t)numtowrite) {
4000 reply_nterror(req, NT_STATUS_DISK_FULL);
4001 error_to_writebrawerr(req);
4002 goto strict_unlock;
4003 }
4004
4005 total_written = nwritten;
4006
4007 /* Allocate a buffer of 64k + length. */
4008 buf = TALLOC_ARRAY(NULL, char, 65540);
4009 if (!buf) {
4010 reply_nterror(req, NT_STATUS_NO_MEMORY);
4011 error_to_writebrawerr(req);
4012 goto strict_unlock;
4013 }
4014
4015 /* Return a SMBwritebraw message to the redirector to tell
4016 * it to send more bytes */
4017
4018 memcpy(buf, req->inbuf, smb_size);
4019 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4020 SCVAL(buf,smb_com,SMBwritebraw);
4021 SSVALS(buf,smb_vwv0,0xFFFF);
4022 show_msg(buf);
4023 if (!srv_send_smb(req->sconn,
4024 buf,
4025 false, 0, /* no signing */
4026 IS_CONN_ENCRYPTED(conn),
4027 &req->pcd)) {
4028 exit_server_cleanly("reply_writebraw: srv_send_smb "
4029 "failed.");
4030 }
4031
4032 /* Now read the raw data into the buffer and write it */
4033 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4034 &numtowrite);
4035 if (!NT_STATUS_IS_OK(status)) {
4036 exit_server_cleanly("secondary writebraw failed");
4037 }
4038
4039 /* Set up outbuf to return the correct size */
4040 reply_outbuf(req, 1, 0);
4041
4042 if (numtowrite != 0) {
4043
4044 if (numtowrite > 0xFFFF) {
4045 DEBUG(0,("reply_writebraw: Oversize secondary write "
4046 "raw requested (%u). Terminating\n",
4047 (unsigned int)numtowrite ));
4048 exit_server_cleanly("secondary writebraw failed");
4049 }
4050
4051 if (tcount > nwritten+numtowrite) {
4052 DEBUG(3,("reply_writebraw: Client overestimated the "
4053 "write %d %d %d\n",
4054 (int)tcount,(int)nwritten,(int)numtowrite));
4055 }
4056
4057 status = read_data(req->sconn->sock, buf+4, numtowrite);
4058
4059 if (!NT_STATUS_IS_OK(status)) {
4060 char addr[INET6_ADDRSTRLEN];
4061 /* Try and give an error message
4062 * saying what client failed. */
4063 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4064 "raw read failed (%s) for client %s. "
4065 "Terminating\n", nt_errstr(status),
4066 get_peer_addr(req->sconn->sock, addr,
4067 sizeof(addr))));
4068 exit_server_cleanly("secondary writebraw failed");
4069 }
4070
4071 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4072 if (nwritten == -1) {
4073 TALLOC_FREE(buf);
4074 reply_nterror(req, map_nt_error_from_unix(errno));
4075 error_to_writebrawerr(req);
4076 goto strict_unlock;
4077 }
4078
4079 if (nwritten < (ssize_t)numtowrite) {
4080 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4081 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4082 }
4083
4084 if (nwritten > 0) {
4085 total_written += nwritten;
4086 }
4087 }
4088
4089 TALLOC_FREE(buf);
4090 SSVAL(req->outbuf,smb_vwv0,total_written);
4091
4092 status = sync_file(conn, fsp, write_through);
4093 if (!NT_STATUS_IS_OK(status)) {
4094 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4095 fsp_str_dbg(fsp), nt_errstr(status)));
4096 reply_nterror(req, status);
4097 error_to_writebrawerr(req);
4098 goto strict_unlock;
4099 }
4100
4101 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4102 "wrote=%d\n",
4103 fsp->fnum, (double)startpos, (int)numtowrite,
4104 (int)total_written));
4105
4106 if (!fsp->print_file) {
4107 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4108 }
4109
4110 /* We won't return a status if write through is not selected - this
4111 * follows what WfWg does */
4112 END_PROFILE(SMBwritebraw);
4113
4114 if (!write_through && total_written==tcount) {
4115
4116#if RABBIT_PELLET_FIX
4117 /*
4118 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4119 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4120 * JRA.
4121 */
4122 if (!send_keepalive(req->sconn->sock)) {
4123 exit_server_cleanly("reply_writebraw: send of "
4124 "keepalive failed");
4125 }
4126#endif
4127 TALLOC_FREE(req->outbuf);
4128 }
4129 return;
4130
4131strict_unlock:
4132 if (!fsp->print_file) {
4133 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4134 }
4135
4136 END_PROFILE(SMBwritebraw);
4137 return;
4138}
4139
4140#undef DBGC_CLASS
4141#define DBGC_CLASS DBGC_LOCKING
4142
4143/****************************************************************************
4144 Reply to a writeunlock (core+).
4145****************************************************************************/
4146
4147void reply_writeunlock(struct smb_request *req)
4148{
4149 connection_struct *conn = req->conn;
4150 ssize_t nwritten = -1;
4151 size_t numtowrite;
4152 SMB_OFF_T startpos;
4153 const char *data;
4154 NTSTATUS status = NT_STATUS_OK;
4155 files_struct *fsp;
4156 struct lock_struct lock;
4157 int saved_errno = 0;
4158
4159 START_PROFILE(SMBwriteunlock);
4160
4161 if (req->wct < 5) {
4162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4163 END_PROFILE(SMBwriteunlock);
4164 return;
4165 }
4166
4167 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4168
4169 if (!check_fsp(conn, req, fsp)) {
4170 END_PROFILE(SMBwriteunlock);
4171 return;
4172 }
4173
4174 if (!CHECK_WRITE(fsp)) {
4175 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4176 END_PROFILE(SMBwriteunlock);
4177 return;
4178 }
4179
4180 numtowrite = SVAL(req->vwv+1, 0);
4181 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4182 data = (const char *)req->buf + 3;
4183
4184 if (!fsp->print_file && numtowrite > 0) {
4185 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4186 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4187 &lock);
4188
4189 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4190 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4191 END_PROFILE(SMBwriteunlock);
4192 return;
4193 }
4194 }
4195
4196 /* The special X/Open SMB protocol handling of
4197 zero length writes is *NOT* done for
4198 this call */
4199 if(numtowrite == 0) {
4200 nwritten = 0;
4201 } else {
4202 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4203 saved_errno = errno;
4204 }
4205
4206 status = sync_file(conn, fsp, False /* write through */);
4207 if (!NT_STATUS_IS_OK(status)) {
4208 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4209 fsp_str_dbg(fsp), nt_errstr(status)));
4210 reply_nterror(req, status);
4211 goto strict_unlock;
4212 }
4213
4214 if(nwritten < 0) {
4215 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4216 goto strict_unlock;
4217 }
4218
4219 if((nwritten < numtowrite) && (numtowrite != 0)) {
4220 reply_nterror(req, NT_STATUS_DISK_FULL);
4221 goto strict_unlock;
4222 }
4223
4224 if (numtowrite && !fsp->print_file) {
4225 status = do_unlock(req->sconn->msg_ctx,
4226 fsp,
4227 (uint64_t)req->smbpid,
4228 (uint64_t)numtowrite,
4229 (uint64_t)startpos,
4230 WINDOWS_LOCK);
4231
4232 if (NT_STATUS_V(status)) {
4233 reply_nterror(req, status);
4234 goto strict_unlock;
4235 }
4236 }
4237
4238 reply_outbuf(req, 1, 0);
4239
4240 SSVAL(req->outbuf,smb_vwv0,nwritten);
4241
4242 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4243 fsp->fnum, (int)numtowrite, (int)nwritten));
4244
4245strict_unlock:
4246 if (numtowrite && !fsp->print_file) {
4247 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4248 }
4249
4250 END_PROFILE(SMBwriteunlock);
4251 return;
4252}
4253
4254#undef DBGC_CLASS
4255#define DBGC_CLASS DBGC_ALL
4256
4257/****************************************************************************
4258 Reply to a write.
4259****************************************************************************/
4260
4261void reply_write(struct smb_request *req)
4262{
4263 connection_struct *conn = req->conn;
4264 size_t numtowrite;
4265 ssize_t nwritten = -1;
4266 SMB_OFF_T startpos;
4267 const char *data;
4268 files_struct *fsp;
4269 struct lock_struct lock;
4270 NTSTATUS status;
4271 int saved_errno = 0;
4272
4273 START_PROFILE(SMBwrite);
4274
4275 if (req->wct < 5) {
4276 END_PROFILE(SMBwrite);
4277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4278 return;
4279 }
4280
4281 /* If it's an IPC, pass off the pipe handler. */
4282 if (IS_IPC(conn)) {
4283 reply_pipe_write(req);
4284 END_PROFILE(SMBwrite);
4285 return;
4286 }
4287
4288 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4289
4290 if (!check_fsp(conn, req, fsp)) {
4291 END_PROFILE(SMBwrite);
4292 return;
4293 }
4294
4295 if (!CHECK_WRITE(fsp)) {
4296 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4297 END_PROFILE(SMBwrite);
4298 return;
4299 }
4300
4301 numtowrite = SVAL(req->vwv+1, 0);
4302 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4303 data = (const char *)req->buf + 3;
4304
4305 if (!fsp->print_file) {
4306 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4307 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4308 &lock);
4309
4310 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4311 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4312 END_PROFILE(SMBwrite);
4313 return;
4314 }
4315 }
4316
4317 /*
4318 * X/Open SMB protocol says that if smb_vwv1 is
4319 * zero then the file size should be extended or
4320 * truncated to the size given in smb_vwv[2-3].
4321 */
4322
4323 if(numtowrite == 0) {
4324 /*
4325 * This is actually an allocate call, and set EOF. JRA.
4326 */
4327 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4328 if (nwritten < 0) {
4329 reply_nterror(req, NT_STATUS_DISK_FULL);
4330 goto strict_unlock;
4331 }
4332 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4333 if (nwritten < 0) {
4334 reply_nterror(req, NT_STATUS_DISK_FULL);
4335 goto strict_unlock;
4336 }
4337 trigger_write_time_update_immediate(fsp);
4338 } else {
4339 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4340 }
4341
4342 status = sync_file(conn, fsp, False);
4343 if (!NT_STATUS_IS_OK(status)) {
4344 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4345 fsp_str_dbg(fsp), nt_errstr(status)));
4346 reply_nterror(req, status);
4347 goto strict_unlock;
4348 }
4349
4350 if(nwritten < 0) {
4351 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4352 goto strict_unlock;
4353 }
4354
4355 if((nwritten == 0) && (numtowrite != 0)) {
4356 reply_nterror(req, NT_STATUS_DISK_FULL);
4357 goto strict_unlock;
4358 }
4359
4360 reply_outbuf(req, 1, 0);
4361
4362 SSVAL(req->outbuf,smb_vwv0,nwritten);
4363
4364 if (nwritten < (ssize_t)numtowrite) {
4365 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4366 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4367 }
4368
4369 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4370
4371strict_unlock:
4372 if (!fsp->print_file) {
4373 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4374 }
4375
4376 END_PROFILE(SMBwrite);
4377 return;
4378}
4379
4380/****************************************************************************
4381 Ensure a buffer is a valid writeX for recvfile purposes.
4382****************************************************************************/
4383
4384#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4385 (2*14) + /* word count (including bcc) */ \
4386 1 /* pad byte */)
4387
4388bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4389 const uint8_t *inbuf)
4390{
4391 size_t numtowrite;
4392 connection_struct *conn = NULL;
4393 unsigned int doff = 0;
4394 size_t len = smb_len_large(inbuf);
4395
4396 if (is_encrypted_packet(inbuf)) {
4397 /* Can't do this on encrypted
4398 * connections. */
4399 return false;
4400 }
4401
4402 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4403 return false;
4404 }
4405
4406 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4407 CVAL(inbuf,smb_wct) != 14) {
4408 DEBUG(10,("is_valid_writeX_buffer: chained or "
4409 "invalid word length.\n"));
4410 return false;
4411 }
4412
4413 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4414 if (conn == NULL) {
4415 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4416 return false;
4417 }
4418 if (IS_IPC(conn)) {
4419 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4420 return false;
4421 }
4422 if (IS_PRINT(conn)) {
4423 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4424 return false;
4425 }
4426 doff = SVAL(inbuf,smb_vwv11);
4427
4428 numtowrite = SVAL(inbuf,smb_vwv10);
4429
4430 if (len > doff && len - doff > 0xFFFF) {
4431 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4432 }
4433
4434 if (numtowrite == 0) {
4435 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4436 return false;
4437 }
4438
4439 /* Ensure the sizes match up. */
4440 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4441 /* no pad byte...old smbclient :-( */
4442 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4443 (unsigned int)doff,
4444 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4445 return false;
4446 }
4447
4448 if (len - doff != numtowrite) {
4449 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4450 "len = %u, doff = %u, numtowrite = %u\n",
4451 (unsigned int)len,
4452 (unsigned int)doff,
4453 (unsigned int)numtowrite ));
4454 return false;
4455 }
4456
4457 DEBUG(10,("is_valid_writeX_buffer: true "
4458 "len = %u, doff = %u, numtowrite = %u\n",
4459 (unsigned int)len,
4460 (unsigned int)doff,
4461 (unsigned int)numtowrite ));
4462
4463 return true;
4464}
4465
4466/****************************************************************************
4467 Reply to a write and X.
4468****************************************************************************/
4469
4470void reply_write_and_X(struct smb_request *req)
4471{
4472 connection_struct *conn = req->conn;
4473 files_struct *fsp;
4474 struct lock_struct lock;
4475 SMB_OFF_T startpos;
4476 size_t numtowrite;
4477 bool write_through;
4478 ssize_t nwritten;
4479 unsigned int smb_doff;
4480 unsigned int smblen;
4481 char *data;
4482 NTSTATUS status;
4483 int saved_errno = 0;
4484
4485 START_PROFILE(SMBwriteX);
4486
4487 if ((req->wct != 12) && (req->wct != 14)) {
4488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4489 END_PROFILE(SMBwriteX);
4490 return;
4491 }
4492
4493 numtowrite = SVAL(req->vwv+10, 0);
4494 smb_doff = SVAL(req->vwv+11, 0);
4495 smblen = smb_len(req->inbuf);
4496
4497 if (req->unread_bytes > 0xFFFF ||
4498 (smblen > smb_doff &&
4499 smblen - smb_doff > 0xFFFF)) {
4500 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4501 }
4502
4503 if (req->unread_bytes) {
4504 /* Can't do a recvfile write on IPC$ */
4505 if (IS_IPC(conn)) {
4506 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4507 END_PROFILE(SMBwriteX);
4508 return;
4509 }
4510 if (numtowrite != req->unread_bytes) {
4511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4512 END_PROFILE(SMBwriteX);
4513 return;
4514 }
4515 } else {
4516 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4517 smb_doff + numtowrite > smblen) {
4518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4519 END_PROFILE(SMBwriteX);
4520 return;
4521 }
4522 }
4523
4524 /* If it's an IPC, pass off the pipe handler. */
4525 if (IS_IPC(conn)) {
4526 if (req->unread_bytes) {
4527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4528 END_PROFILE(SMBwriteX);
4529 return;
4530 }
4531 reply_pipe_write_and_X(req);
4532 END_PROFILE(SMBwriteX);
4533 return;
4534 }
4535
4536 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4537 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4538 write_through = BITSETW(req->vwv+7,0);
4539
4540 if (!check_fsp(conn, req, fsp)) {
4541 END_PROFILE(SMBwriteX);
4542 return;
4543 }
4544
4545 if (!CHECK_WRITE(fsp)) {
4546 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4547 END_PROFILE(SMBwriteX);
4548 return;
4549 }
4550
4551 data = smb_base(req->inbuf) + smb_doff;
4552
4553 if(req->wct == 14) {
4554#ifdef LARGE_SMB_OFF_T
4555 /*
4556 * This is a large offset (64 bit) write.
4557 */
4558 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4559
4560#else /* !LARGE_SMB_OFF_T */
4561
4562 /*
4563 * Ensure we haven't been sent a >32 bit offset.
4564 */
4565
4566 if(IVAL(req->vwv+12, 0) != 0) {
4567 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4568 "used and we don't support 64 bit offsets.\n",
4569 (unsigned int)IVAL(req->vwv+12, 0) ));
4570 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4571 END_PROFILE(SMBwriteX);
4572 return;
4573 }
4574
4575#endif /* LARGE_SMB_OFF_T */
4576 }
4577
4578 /* X/Open SMB protocol says that, unlike SMBwrite
4579 if the length is zero then NO truncation is
4580 done, just a write of zero. To truncate a file,
4581 use SMBwrite. */
4582
4583 if(numtowrite == 0) {
4584 nwritten = 0;
4585 } else {
4586 if (req->unread_bytes == 0) {
4587 status = schedule_aio_write_and_X(conn,
4588 req,
4589 fsp,
4590 data,
4591 startpos,
4592 numtowrite);
4593
4594 if (NT_STATUS_IS_OK(status)) {
4595 /* write scheduled - we're done. */
4596 goto out;
4597 }
4598 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4599 /* Real error - report to client. */
4600 reply_nterror(req, status);
4601 goto out;
4602 }
4603 /* NT_STATUS_RETRY - fall through to sync write. */
4604 }
4605
4606 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4607 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4608 &lock);
4609
4610 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4611 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4612 goto out;
4613 }
4614
4615 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4616 saved_errno = errno;
4617
4618 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4619 }
4620
4621 if(nwritten < 0) {
4622 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4623 goto out;
4624 }
4625
4626 if((nwritten == 0) && (numtowrite != 0)) {
4627 reply_nterror(req, NT_STATUS_DISK_FULL);
4628 goto out;
4629 }
4630
4631 reply_outbuf(req, 6, 0);
4632 SSVAL(req->outbuf,smb_vwv2,nwritten);
4633 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4634
4635 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4636 fsp->fnum, (int)numtowrite, (int)nwritten));
4637
4638 status = sync_file(conn, fsp, write_through);
4639 if (!NT_STATUS_IS_OK(status)) {
4640 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4641 fsp_str_dbg(fsp), nt_errstr(status)));
4642 reply_nterror(req, status);
4643 goto out;
4644 }
4645
4646 END_PROFILE(SMBwriteX);
4647 chain_reply(req);
4648 return;
4649
4650out:
4651 END_PROFILE(SMBwriteX);
4652 return;
4653}
4654
4655/****************************************************************************
4656 Reply to a lseek.
4657****************************************************************************/
4658
4659void reply_lseek(struct smb_request *req)
4660{
4661 connection_struct *conn = req->conn;
4662 SMB_OFF_T startpos;
4663 SMB_OFF_T res= -1;
4664 int mode,umode;
4665 files_struct *fsp;
4666
4667 START_PROFILE(SMBlseek);
4668
4669 if (req->wct < 4) {
4670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4671 END_PROFILE(SMBlseek);
4672 return;
4673 }
4674
4675 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4676
4677 if (!check_fsp(conn, req, fsp)) {
4678 return;
4679 }
4680
4681 flush_write_cache(fsp, SEEK_FLUSH);
4682
4683 mode = SVAL(req->vwv+1, 0) & 3;
4684 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4685 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4686
4687 switch (mode) {
4688 case 0:
4689 umode = SEEK_SET;
4690 res = startpos;
4691 break;
4692 case 1:
4693 umode = SEEK_CUR;
4694 res = fsp->fh->pos + startpos;
4695 break;
4696 case 2:
4697 umode = SEEK_END;
4698 break;
4699 default:
4700 umode = SEEK_SET;
4701 res = startpos;
4702 break;
4703 }
4704
4705 if (umode == SEEK_END) {
4706 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4707 if(errno == EINVAL) {
4708 SMB_OFF_T current_pos = startpos;
4709
4710 if(fsp_stat(fsp) == -1) {
4711 reply_nterror(req,
4712 map_nt_error_from_unix(errno));
4713 END_PROFILE(SMBlseek);
4714 return;
4715 }
4716
4717 current_pos += fsp->fsp_name->st.st_ex_size;
4718 if(current_pos < 0)
4719 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4720 }
4721 }
4722
4723 if(res == -1) {
4724 reply_nterror(req, map_nt_error_from_unix(errno));
4725 END_PROFILE(SMBlseek);
4726 return;
4727 }
4728 }
4729
4730 fsp->fh->pos = res;
4731
4732 reply_outbuf(req, 2, 0);
4733 SIVAL(req->outbuf,smb_vwv0,res);
4734
4735 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4736 fsp->fnum, (double)startpos, (double)res, mode));
4737
4738 END_PROFILE(SMBlseek);
4739 return;
4740}
4741
4742/****************************************************************************
4743 Reply to a flush.
4744****************************************************************************/
4745
4746void reply_flush(struct smb_request *req)
4747{
4748 connection_struct *conn = req->conn;
4749 uint16 fnum;
4750 files_struct *fsp;
4751
4752 START_PROFILE(SMBflush);
4753
4754 if (req->wct < 1) {
4755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4756 return;
4757 }
4758
4759 fnum = SVAL(req->vwv+0, 0);
4760 fsp = file_fsp(req, fnum);
4761
4762 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4763 return;
4764 }
4765
4766 if (!fsp) {
4767 file_sync_all(conn);
4768 } else {
4769 NTSTATUS status = sync_file(conn, fsp, True);
4770 if (!NT_STATUS_IS_OK(status)) {
4771 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4772 fsp_str_dbg(fsp), nt_errstr(status)));
4773 reply_nterror(req, status);
4774 END_PROFILE(SMBflush);
4775 return;
4776 }
4777 }
4778
4779 reply_outbuf(req, 0, 0);
4780
4781 DEBUG(3,("flush\n"));
4782 END_PROFILE(SMBflush);
4783 return;
4784}
4785
4786/****************************************************************************
4787 Reply to a exit.
4788 conn POINTER CAN BE NULL HERE !
4789****************************************************************************/
4790
4791void reply_exit(struct smb_request *req)
4792{
4793 START_PROFILE(SMBexit);
4794
4795 file_close_pid(req->sconn, req->smbpid, req->vuid);
4796
4797 reply_outbuf(req, 0, 0);
4798
4799 DEBUG(3,("exit\n"));
4800
4801 END_PROFILE(SMBexit);
4802 return;
4803}
4804
4805/****************************************************************************
4806 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4807****************************************************************************/
4808
4809void reply_close(struct smb_request *req)
4810{
4811 connection_struct *conn = req->conn;
4812 NTSTATUS status = NT_STATUS_OK;
4813 files_struct *fsp = NULL;
4814 START_PROFILE(SMBclose);
4815
4816 if (req->wct < 3) {
4817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4818 END_PROFILE(SMBclose);
4819 return;
4820 }
4821
4822 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4823
4824 /*
4825 * We can only use check_fsp if we know it's not a directory.
4826 */
4827
4828 if (!check_fsp_open(conn, req, fsp)) {
4829 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4830 END_PROFILE(SMBclose);
4831 return;
4832 }
4833
4834 if(fsp->is_directory) {
4835 /*
4836 * Special case - close NT SMB directory handle.
4837 */
4838 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4839 status = close_file(req, fsp, NORMAL_CLOSE);
4840 } else {
4841 time_t t;
4842 /*
4843 * Close ordinary file.
4844 */
4845
4846 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4847 fsp->fh->fd, fsp->fnum,
4848 conn->num_files_open));
4849
4850 /*
4851 * Take care of any time sent in the close.
4852 */
4853
4854 t = srv_make_unix_date3(req->vwv+1);
4855 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4856
4857 /*
4858 * close_file() returns the unix errno if an error
4859 * was detected on close - normally this is due to
4860 * a disk full error. If not then it was probably an I/O error.
4861 */
4862
4863 status = close_file(req, fsp, NORMAL_CLOSE);
4864 }
4865
4866 if (!NT_STATUS_IS_OK(status)) {
4867 reply_nterror(req, status);
4868 END_PROFILE(SMBclose);
4869 return;
4870 }
4871
4872 reply_outbuf(req, 0, 0);
4873 END_PROFILE(SMBclose);
4874 return;
4875}
4876
4877/****************************************************************************
4878 Reply to a writeclose (Core+ protocol).
4879****************************************************************************/
4880
4881void reply_writeclose(struct smb_request *req)
4882{
4883 connection_struct *conn = req->conn;
4884 size_t numtowrite;
4885 ssize_t nwritten = -1;
4886 NTSTATUS close_status = NT_STATUS_OK;
4887 SMB_OFF_T startpos;
4888 const char *data;
4889 struct timespec mtime;
4890 files_struct *fsp;
4891 struct lock_struct lock;
4892
4893 START_PROFILE(SMBwriteclose);
4894
4895 if (req->wct < 6) {
4896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4897 END_PROFILE(SMBwriteclose);
4898 return;
4899 }
4900
4901 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4902
4903 if (!check_fsp(conn, req, fsp)) {
4904 END_PROFILE(SMBwriteclose);
4905 return;
4906 }
4907 if (!CHECK_WRITE(fsp)) {
4908 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4909 END_PROFILE(SMBwriteclose);
4910 return;
4911 }
4912
4913 numtowrite = SVAL(req->vwv+1, 0);
4914 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4915 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4916 data = (const char *)req->buf + 1;
4917
4918 if (!fsp->print_file) {
4919 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4920 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4921 &lock);
4922
4923 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4924 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4925 END_PROFILE(SMBwriteclose);
4926 return;
4927 }
4928 }
4929
4930 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4931
4932 set_close_write_time(fsp, mtime);
4933
4934 /*
4935 * More insanity. W2K only closes the file if writelen > 0.
4936 * JRA.
4937 */
4938
4939 if (numtowrite) {
4940 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4941 "file %s\n", fsp_str_dbg(fsp)));
4942 close_status = close_file(req, fsp, NORMAL_CLOSE);
4943 }
4944
4945 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4946 fsp->fnum, (int)numtowrite, (int)nwritten,
4947 conn->num_files_open));
4948
4949 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4950 reply_nterror(req, NT_STATUS_DISK_FULL);
4951 goto strict_unlock;
4952 }
4953
4954 if(!NT_STATUS_IS_OK(close_status)) {
4955 reply_nterror(req, close_status);
4956 goto strict_unlock;
4957 }
4958
4959 reply_outbuf(req, 1, 0);
4960
4961 SSVAL(req->outbuf,smb_vwv0,nwritten);
4962
4963strict_unlock:
4964 if (numtowrite && !fsp->print_file) {
4965 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4966 }
4967
4968 END_PROFILE(SMBwriteclose);
4969 return;
4970}
4971
4972#undef DBGC_CLASS
4973#define DBGC_CLASS DBGC_LOCKING
4974
4975/****************************************************************************
4976 Reply to a lock.
4977****************************************************************************/
4978
4979void reply_lock(struct smb_request *req)
4980{
4981 connection_struct *conn = req->conn;
4982 uint64_t count,offset;
4983 NTSTATUS status;
4984 files_struct *fsp;
4985 struct byte_range_lock *br_lck = NULL;
4986
4987 START_PROFILE(SMBlock);
4988
4989 if (req->wct < 5) {
4990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4991 END_PROFILE(SMBlock);
4992 return;
4993 }
4994
4995 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4996
4997 if (!check_fsp(conn, req, fsp)) {
4998 END_PROFILE(SMBlock);
4999 return;
5000 }
5001
5002 count = (uint64_t)IVAL(req->vwv+1, 0);
5003 offset = (uint64_t)IVAL(req->vwv+3, 0);
5004
5005 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5006 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5007
5008 br_lck = do_lock(req->sconn->msg_ctx,
5009 fsp,
5010 (uint64_t)req->smbpid,
5011 count,
5012 offset,
5013 WRITE_LOCK,
5014 WINDOWS_LOCK,
5015 False, /* Non-blocking lock. */
5016 &status,
5017 NULL,
5018 NULL);
5019
5020 TALLOC_FREE(br_lck);
5021
5022 if (NT_STATUS_V(status)) {
5023 reply_nterror(req, status);
5024 END_PROFILE(SMBlock);
5025 return;
5026 }
5027
5028 reply_outbuf(req, 0, 0);
5029
5030 END_PROFILE(SMBlock);
5031 return;
5032}
5033
5034/****************************************************************************
5035 Reply to a unlock.
5036****************************************************************************/
5037
5038void reply_unlock(struct smb_request *req)
5039{
5040 connection_struct *conn = req->conn;
5041 uint64_t count,offset;
5042 NTSTATUS status;
5043 files_struct *fsp;
5044
5045 START_PROFILE(SMBunlock);
5046
5047 if (req->wct < 5) {
5048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5049 END_PROFILE(SMBunlock);
5050 return;
5051 }
5052
5053 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5054
5055 if (!check_fsp(conn, req, fsp)) {
5056 END_PROFILE(SMBunlock);
5057 return;
5058 }
5059
5060 count = (uint64_t)IVAL(req->vwv+1, 0);
5061 offset = (uint64_t)IVAL(req->vwv+3, 0);
5062
5063 status = do_unlock(req->sconn->msg_ctx,
5064 fsp,
5065 (uint64_t)req->smbpid,
5066 count,
5067 offset,
5068 WINDOWS_LOCK);
5069
5070 if (NT_STATUS_V(status)) {
5071 reply_nterror(req, status);
5072 END_PROFILE(SMBunlock);
5073 return;
5074 }
5075
5076 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5077 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5078
5079 reply_outbuf(req, 0, 0);
5080
5081 END_PROFILE(SMBunlock);
5082 return;
5083}
5084
5085#undef DBGC_CLASS
5086#define DBGC_CLASS DBGC_ALL
5087
5088/****************************************************************************
5089 Reply to a tdis.
5090 conn POINTER CAN BE NULL HERE !
5091****************************************************************************/
5092
5093void reply_tdis(struct smb_request *req)
5094{
5095 connection_struct *conn = req->conn;
5096 START_PROFILE(SMBtdis);
5097
5098 if (!conn) {
5099 DEBUG(4,("Invalid connection in tdis\n"));
5100 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5101 END_PROFILE(SMBtdis);
5102 return;
5103 }
5104
5105 conn->used = False;
5106
5107 close_cnum(conn,req->vuid);
5108 req->conn = NULL;
5109
5110 reply_outbuf(req, 0, 0);
5111 END_PROFILE(SMBtdis);
5112 return;
5113}
5114
5115/****************************************************************************
5116 Reply to a echo.
5117 conn POINTER CAN BE NULL HERE !
5118****************************************************************************/
5119
5120void reply_echo(struct smb_request *req)
5121{
5122 connection_struct *conn = req->conn;
5123 struct smb_perfcount_data local_pcd;
5124 struct smb_perfcount_data *cur_pcd;
5125 int smb_reverb;
5126 int seq_num;
5127
5128 START_PROFILE(SMBecho);
5129
5130 smb_init_perfcount_data(&local_pcd);
5131
5132 if (req->wct < 1) {
5133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5134 END_PROFILE(SMBecho);
5135 return;
5136 }
5137
5138 smb_reverb = SVAL(req->vwv+0, 0);
5139
5140 reply_outbuf(req, 1, req->buflen);
5141
5142 /* copy any incoming data back out */
5143 if (req->buflen > 0) {
5144 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5145 }
5146
5147 if (smb_reverb > 100) {
5148 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5149 smb_reverb = 100;
5150 }
5151
5152 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5153
5154 /* this makes sure we catch the request pcd */
5155 if (seq_num == smb_reverb) {
5156 cur_pcd = &req->pcd;
5157 } else {
5158 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5159 cur_pcd = &local_pcd;
5160 }
5161
5162 SSVAL(req->outbuf,smb_vwv0,seq_num);
5163
5164 show_msg((char *)req->outbuf);
5165 if (!srv_send_smb(req->sconn,
5166 (char *)req->outbuf,
5167 true, req->seqnum+1,
5168 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5169 cur_pcd))
5170 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5171 }
5172
5173 DEBUG(3,("echo %d times\n", smb_reverb));
5174
5175 TALLOC_FREE(req->outbuf);
5176
5177 END_PROFILE(SMBecho);
5178 return;
5179}
5180
5181/****************************************************************************
5182 Reply to a printopen.
5183****************************************************************************/
5184
5185void reply_printopen(struct smb_request *req)
5186{
5187 connection_struct *conn = req->conn;
5188 files_struct *fsp;
5189 NTSTATUS status;
5190
5191 START_PROFILE(SMBsplopen);
5192
5193 if (req->wct < 2) {
5194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5195 END_PROFILE(SMBsplopen);
5196 return;
5197 }
5198
5199 if (!CAN_PRINT(conn)) {
5200 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5201 END_PROFILE(SMBsplopen);
5202 return;
5203 }
5204
5205 status = file_new(req, conn, &fsp);
5206 if(!NT_STATUS_IS_OK(status)) {
5207 reply_nterror(req, status);
5208 END_PROFILE(SMBsplopen);
5209 return;
5210 }
5211
5212 /* Open for exclusive use, write only. */
5213 status = print_spool_open(fsp, NULL, req->vuid);
5214
5215 if (!NT_STATUS_IS_OK(status)) {
5216 file_free(req, fsp);
5217 reply_nterror(req, status);
5218 END_PROFILE(SMBsplopen);
5219 return;
5220 }
5221
5222 reply_outbuf(req, 1, 0);
5223 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5224
5225 DEBUG(3,("openprint fd=%d fnum=%d\n",
5226 fsp->fh->fd, fsp->fnum));
5227
5228 END_PROFILE(SMBsplopen);
5229 return;
5230}
5231
5232/****************************************************************************
5233 Reply to a printclose.
5234****************************************************************************/
5235
5236void reply_printclose(struct smb_request *req)
5237{
5238 connection_struct *conn = req->conn;
5239 files_struct *fsp;
5240 NTSTATUS status;
5241
5242 START_PROFILE(SMBsplclose);
5243
5244 if (req->wct < 1) {
5245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5246 END_PROFILE(SMBsplclose);
5247 return;
5248 }
5249
5250 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5251
5252 if (!check_fsp(conn, req, fsp)) {
5253 END_PROFILE(SMBsplclose);
5254 return;
5255 }
5256
5257 if (!CAN_PRINT(conn)) {
5258 reply_force_doserror(req, ERRSRV, ERRerror);
5259 END_PROFILE(SMBsplclose);
5260 return;
5261 }
5262
5263 DEBUG(3,("printclose fd=%d fnum=%d\n",
5264 fsp->fh->fd,fsp->fnum));
5265
5266 status = close_file(req, fsp, NORMAL_CLOSE);
5267
5268 if(!NT_STATUS_IS_OK(status)) {
5269 reply_nterror(req, status);
5270 END_PROFILE(SMBsplclose);
5271 return;
5272 }
5273
5274 reply_outbuf(req, 0, 0);
5275
5276 END_PROFILE(SMBsplclose);
5277 return;
5278}
5279
5280/****************************************************************************
5281 Reply to a printqueue.
5282****************************************************************************/
5283
5284void reply_printqueue(struct smb_request *req)
5285{
5286 connection_struct *conn = req->conn;
5287 int max_count;
5288 int start_index;
5289
5290 START_PROFILE(SMBsplretq);
5291
5292 if (req->wct < 2) {
5293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5294 END_PROFILE(SMBsplretq);
5295 return;
5296 }
5297
5298 max_count = SVAL(req->vwv+0, 0);
5299 start_index = SVAL(req->vwv+1, 0);
5300
5301 /* we used to allow the client to get the cnum wrong, but that
5302 is really quite gross and only worked when there was only
5303 one printer - I think we should now only accept it if they
5304 get it right (tridge) */
5305 if (!CAN_PRINT(conn)) {
5306 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5307 END_PROFILE(SMBsplretq);
5308 return;
5309 }
5310
5311 reply_outbuf(req, 2, 3);
5312 SSVAL(req->outbuf,smb_vwv0,0);
5313 SSVAL(req->outbuf,smb_vwv1,0);
5314 SCVAL(smb_buf(req->outbuf),0,1);
5315 SSVAL(smb_buf(req->outbuf),1,0);
5316
5317 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5318 start_index, max_count));
5319
5320 {
5321 TALLOC_CTX *mem_ctx = talloc_tos();
5322 NTSTATUS status;
5323 WERROR werr;
5324 const char *sharename = lp_servicename(SNUM(conn));
5325 struct rpc_pipe_client *cli = NULL;
5326 struct dcerpc_binding_handle *b = NULL;
5327 struct policy_handle handle;
5328 struct spoolss_DevmodeContainer devmode_ctr;
5329 union spoolss_JobInfo *info;
5330 uint32_t count;
5331 uint32_t num_to_get;
5332 uint32_t first;
5333 uint32_t i;
5334
5335 ZERO_STRUCT(handle);
5336
5337 status = rpc_pipe_open_interface(conn,
5338 &ndr_table_spoolss.syntax_id,
5339 conn->session_info,
5340 &conn->sconn->client_id,
5341 conn->sconn->msg_ctx,
5342 &cli);
5343 if (!NT_STATUS_IS_OK(status)) {
5344 DEBUG(0, ("reply_printqueue: "
5345 "could not connect to spoolss: %s\n",
5346 nt_errstr(status)));
5347 reply_nterror(req, status);
5348 goto out;
5349 }
5350 b = cli->binding_handle;
5351
5352 ZERO_STRUCT(devmode_ctr);
5353
5354 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5355 sharename,
5356 NULL, devmode_ctr,
5357 SEC_FLAG_MAXIMUM_ALLOWED,
5358 &handle,
5359 &werr);
5360 if (!NT_STATUS_IS_OK(status)) {
5361 reply_nterror(req, status);
5362 goto out;
5363 }
5364 if (!W_ERROR_IS_OK(werr)) {
5365 reply_nterror(req, werror_to_ntstatus(werr));
5366 goto out;
5367 }
5368
5369 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5370 &handle,
5371 0, /* firstjob */
5372 0xff, /* numjobs */
5373 2, /* level */
5374 0, /* offered */
5375 &count,
5376 &info);
5377 if (!W_ERROR_IS_OK(werr)) {
5378 reply_nterror(req, werror_to_ntstatus(werr));
5379 goto out;
5380 }
5381
5382 if (max_count > 0) {
5383 first = start_index;
5384 } else {
5385 first = start_index + max_count + 1;
5386 }
5387
5388 if (first >= count) {
5389 num_to_get = first;
5390 } else {
5391 num_to_get = first + MIN(ABS(max_count), count - first);
5392 }
5393
5394 for (i = first; i < num_to_get; i++) {
5395 char blob[28];
5396 char *p = blob;
5397 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5398 int qstatus;
5399 uint16_t qrapjobid = pjobid_to_rap(sharename,
5400 info[i].info2.job_id);
5401
5402 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5403 qstatus = 2;
5404 } else {
5405 qstatus = 3;
5406 }
5407
5408 srv_put_dos_date2(p, 0, qtime);
5409 SCVAL(p, 4, qstatus);
5410 SSVAL(p, 5, qrapjobid);
5411 SIVAL(p, 7, info[i].info2.size);
5412 SCVAL(p, 11, 0);
5413 srvstr_push(blob, req->flags2, p+12,
5414 info[i].info2.notify_name, 16, STR_ASCII);
5415
5416 if (message_push_blob(
5417 &req->outbuf,
5418 data_blob_const(
5419 blob, sizeof(blob))) == -1) {
5420 reply_nterror(req, NT_STATUS_NO_MEMORY);
5421 goto out;
5422 }
5423 }
5424
5425 if (count > 0) {
5426 SSVAL(req->outbuf,smb_vwv0,count);
5427 SSVAL(req->outbuf,smb_vwv1,
5428 (max_count>0?first+count:first-1));
5429 SCVAL(smb_buf(req->outbuf),0,1);
5430 SSVAL(smb_buf(req->outbuf),1,28*count);
5431 }
5432
5433
5434 DEBUG(3, ("%u entries returned in queue\n",
5435 (unsigned)count));
5436
5437out:
5438 if (b && is_valid_policy_hnd(&handle)) {
5439 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5440 }
5441
5442 }
5443
5444 END_PROFILE(SMBsplretq);
5445 return;
5446}
5447
5448/****************************************************************************
5449 Reply to a printwrite.
5450****************************************************************************/
5451
5452void reply_printwrite(struct smb_request *req)
5453{
5454 connection_struct *conn = req->conn;
5455 int numtowrite;
5456 const char *data;
5457 files_struct *fsp;
5458
5459 START_PROFILE(SMBsplwr);
5460
5461 if (req->wct < 1) {
5462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5463 END_PROFILE(SMBsplwr);
5464 return;
5465 }
5466
5467 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5468
5469 if (!check_fsp(conn, req, fsp)) {
5470 END_PROFILE(SMBsplwr);
5471 return;
5472 }
5473
5474 if (!fsp->print_file) {
5475 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5476 END_PROFILE(SMBsplwr);
5477 return;
5478 }
5479
5480 if (!CHECK_WRITE(fsp)) {
5481 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5482 END_PROFILE(SMBsplwr);
5483 return;
5484 }
5485
5486 numtowrite = SVAL(req->buf, 1);
5487
5488 if (req->buflen < numtowrite + 3) {
5489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5490 END_PROFILE(SMBsplwr);
5491 return;
5492 }
5493
5494 data = (const char *)req->buf + 3;
5495
5496 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5497 reply_nterror(req, map_nt_error_from_unix(errno));
5498 END_PROFILE(SMBsplwr);
5499 return;
5500 }
5501
5502 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5503
5504 END_PROFILE(SMBsplwr);
5505 return;
5506}
5507
5508/****************************************************************************
5509 Reply to a mkdir.
5510****************************************************************************/
5511
5512void reply_mkdir(struct smb_request *req)
5513{
5514 connection_struct *conn = req->conn;
5515 struct smb_filename *smb_dname = NULL;
5516 char *directory = NULL;
5517 NTSTATUS status;
5518 TALLOC_CTX *ctx = talloc_tos();
5519
5520 START_PROFILE(SMBmkdir);
5521
5522 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5523 STR_TERMINATE, &status);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 reply_nterror(req, status);
5526 goto out;
5527 }
5528
5529 status = filename_convert(ctx, conn,
5530 req->flags2 & FLAGS2_DFS_PATHNAMES,
5531 directory,
5532 0,
5533 NULL,
5534 &smb_dname);
5535 if (!NT_STATUS_IS_OK(status)) {
5536 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5537 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5538 ERRSRV, ERRbadpath);
5539 goto out;
5540 }
5541 reply_nterror(req, status);
5542 goto out;
5543 }
5544
5545 status = create_directory(conn, req, smb_dname);
5546
5547 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5548
5549 if (!NT_STATUS_IS_OK(status)) {
5550
5551 if (!use_nt_status()
5552 && NT_STATUS_EQUAL(status,
5553 NT_STATUS_OBJECT_NAME_COLLISION)) {
5554 /*
5555 * Yes, in the DOS error code case we get a
5556 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5557 * samba4 torture test.
5558 */
5559 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5560 }
5561
5562 reply_nterror(req, status);
5563 goto out;
5564 }
5565
5566 reply_outbuf(req, 0, 0);
5567
5568 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5569 out:
5570 TALLOC_FREE(smb_dname);
5571 END_PROFILE(SMBmkdir);
5572 return;
5573}
5574
5575/****************************************************************************
5576 Reply to a rmdir.
5577****************************************************************************/
5578
5579void reply_rmdir(struct smb_request *req)
5580{
5581 connection_struct *conn = req->conn;
5582 struct smb_filename *smb_dname = NULL;
5583 char *directory = NULL;
5584 NTSTATUS status;
5585 TALLOC_CTX *ctx = talloc_tos();
5586 files_struct *fsp = NULL;
5587 int info = 0;
5588 struct smbd_server_connection *sconn = req->sconn;
5589
5590 START_PROFILE(SMBrmdir);
5591
5592 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5593 STR_TERMINATE, &status);
5594 if (!NT_STATUS_IS_OK(status)) {
5595 reply_nterror(req, status);
5596 goto out;
5597 }
5598
5599 status = filename_convert(ctx, conn,
5600 req->flags2 & FLAGS2_DFS_PATHNAMES,
5601 directory,
5602 0,
5603 NULL,
5604 &smb_dname);
5605 if (!NT_STATUS_IS_OK(status)) {
5606 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5607 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5608 ERRSRV, ERRbadpath);
5609 goto out;
5610 }
5611 reply_nterror(req, status);
5612 goto out;
5613 }
5614
5615 if (is_ntfs_stream_smb_fname(smb_dname)) {
5616 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5617 goto out;
5618 }
5619
5620 status = SMB_VFS_CREATE_FILE(
5621 conn, /* conn */
5622 req, /* req */
5623 0, /* root_dir_fid */
5624 smb_dname, /* fname */
5625 DELETE_ACCESS, /* access_mask */
5626 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5627 FILE_SHARE_DELETE),
5628 FILE_OPEN, /* create_disposition*/
5629 FILE_DIRECTORY_FILE, /* create_options */
5630 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5631 0, /* oplock_request */
5632 0, /* allocation_size */
5633 0, /* private_flags */
5634 NULL, /* sd */
5635 NULL, /* ea_list */
5636 &fsp, /* result */
5637 &info); /* pinfo */
5638
5639 if (!NT_STATUS_IS_OK(status)) {
5640 if (open_was_deferred(req->mid)) {
5641 /* We have re-scheduled this call. */
5642 goto out;
5643 }
5644 reply_nterror(req, status);
5645 goto out;
5646 }
5647
5648 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5649 if (!NT_STATUS_IS_OK(status)) {
5650 close_file(req, fsp, ERROR_CLOSE);
5651 reply_nterror(req, status);
5652 goto out;
5653 }
5654
5655 if (!set_delete_on_close(fsp, true,
5656 conn->session_info->security_token,
5657 &conn->session_info->utok)) {
5658 close_file(req, fsp, ERROR_CLOSE);
5659 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5660 goto out;
5661 }
5662
5663 status = close_file(req, fsp, NORMAL_CLOSE);
5664 if (!NT_STATUS_IS_OK(status)) {
5665 reply_nterror(req, status);
5666 } else {
5667 reply_outbuf(req, 0, 0);
5668 }
5669
5670 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5671
5672 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5673 out:
5674 TALLOC_FREE(smb_dname);
5675 END_PROFILE(SMBrmdir);
5676 return;
5677}
5678
5679/*******************************************************************
5680 Resolve wildcards in a filename rename.
5681********************************************************************/
5682
5683static bool resolve_wildcards(TALLOC_CTX *ctx,
5684 const char *name1,
5685 const char *name2,
5686 char **pp_newname)
5687{
5688 char *name2_copy = NULL;
5689 char *root1 = NULL;
5690 char *root2 = NULL;
5691 char *ext1 = NULL;
5692 char *ext2 = NULL;
5693 char *p,*p2, *pname1, *pname2;
5694
5695 name2_copy = talloc_strdup(ctx, name2);
5696 if (!name2_copy) {
5697 return False;
5698 }
5699
5700 pname1 = strrchr_m(name1,'/');
5701 pname2 = strrchr_m(name2_copy,'/');
5702
5703 if (!pname1 || !pname2) {
5704 return False;
5705 }
5706
5707 /* Truncate the copy of name2 at the last '/' */
5708 *pname2 = '\0';
5709
5710 /* Now go past the '/' */
5711 pname1++;
5712 pname2++;
5713
5714 root1 = talloc_strdup(ctx, pname1);
5715 root2 = talloc_strdup(ctx, pname2);
5716
5717 if (!root1 || !root2) {
5718 return False;
5719 }
5720
5721 p = strrchr_m(root1,'.');
5722 if (p) {
5723 *p = 0;
5724 ext1 = talloc_strdup(ctx, p+1);
5725 } else {
5726 ext1 = talloc_strdup(ctx, "");
5727 }
5728 p = strrchr_m(root2,'.');
5729 if (p) {
5730 *p = 0;
5731 ext2 = talloc_strdup(ctx, p+1);
5732 } else {
5733 ext2 = talloc_strdup(ctx, "");
5734 }
5735
5736 if (!ext1 || !ext2) {
5737 return False;
5738 }
5739
5740 p = root1;
5741 p2 = root2;
5742 while (*p2) {
5743 if (*p2 == '?') {
5744 /* Hmmm. Should this be mb-aware ? */
5745 *p2 = *p;
5746 p2++;
5747 } else if (*p2 == '*') {
5748 *p2 = '\0';
5749 root2 = talloc_asprintf(ctx, "%s%s",
5750 root2,
5751 p);
5752 if (!root2) {
5753 return False;
5754 }
5755 break;
5756 } else {
5757 p2++;
5758 }
5759 if (*p) {
5760 p++;
5761 }
5762 }
5763
5764 p = ext1;
5765 p2 = ext2;
5766 while (*p2) {
5767 if (*p2 == '?') {
5768 /* Hmmm. Should this be mb-aware ? */
5769 *p2 = *p;
5770 p2++;
5771 } else if (*p2 == '*') {
5772 *p2 = '\0';
5773 ext2 = talloc_asprintf(ctx, "%s%s",
5774 ext2,
5775 p);
5776 if (!ext2) {
5777 return False;
5778 }
5779 break;
5780 } else {
5781 p2++;
5782 }
5783 if (*p) {
5784 p++;
5785 }
5786 }
5787
5788 if (*ext2) {
5789 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5790 name2_copy,
5791 root2,
5792 ext2);
5793 } else {
5794 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5795 name2_copy,
5796 root2);
5797 }
5798
5799 if (!*pp_newname) {
5800 return False;
5801 }
5802
5803 return True;
5804}
5805
5806/****************************************************************************
5807 Ensure open files have their names updated. Updated to notify other smbd's
5808 asynchronously.
5809****************************************************************************/
5810
5811static void rename_open_files(connection_struct *conn,
5812 struct share_mode_lock *lck,
5813 uint32_t orig_name_hash,
5814 const struct smb_filename *smb_fname_dst)
5815{
5816 files_struct *fsp;
5817 bool did_rename = False;
5818 NTSTATUS status;
5819 uint32_t new_name_hash;
5820
5821 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5822 fsp = file_find_di_next(fsp)) {
5823 /* fsp_name is a relative path under the fsp. To change this for other
5824 sharepaths we need to manipulate relative paths. */
5825 /* TODO - create the absolute path and manipulate the newname
5826 relative to the sharepath. */
5827 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5828 continue;
5829 }
5830 if (fsp->name_hash != orig_name_hash) {
5831 continue;
5832 }
5833 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5834 "(file_id %s) from %s -> %s\n", fsp->fnum,
5835 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5836 smb_fname_str_dbg(smb_fname_dst)));
5837
5838 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5839 if (NT_STATUS_IS_OK(status)) {
5840 did_rename = True;
5841 new_name_hash = fsp->name_hash;
5842 }
5843 }
5844
5845 if (!did_rename) {
5846 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5847 "for %s\n", file_id_string_tos(&lck->id),
5848 smb_fname_str_dbg(smb_fname_dst)));
5849 }
5850
5851 /* Send messages to all smbd's (not ourself) that the name has changed. */
5852 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5853 orig_name_hash, new_name_hash,
5854 smb_fname_dst);
5855
5856}
5857
5858/****************************************************************************
5859 We need to check if the source path is a parent directory of the destination
5860 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5861 refuse the rename with a sharing violation. Under UNIX the above call can
5862 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5863 probably need to check that the client is a Windows one before disallowing
5864 this as a UNIX client (one with UNIX extensions) can know the source is a
5865 symlink and make this decision intelligently. Found by an excellent bug
5866 report from <AndyLiebman@aol.com>.
5867****************************************************************************/
5868
5869static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5870 const struct smb_filename *smb_fname_dst)
5871{
5872 const char *psrc = smb_fname_src->base_name;
5873 const char *pdst = smb_fname_dst->base_name;
5874 size_t slen;
5875
5876 if (psrc[0] == '.' && psrc[1] == '/') {
5877 psrc += 2;
5878 }
5879 if (pdst[0] == '.' && pdst[1] == '/') {
5880 pdst += 2;
5881 }
5882 if ((slen = strlen(psrc)) > strlen(pdst)) {
5883 return False;
5884 }
5885 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5886}
5887
5888/*
5889 * Do the notify calls from a rename
5890 */
5891
5892static void notify_rename(connection_struct *conn, bool is_dir,
5893 const struct smb_filename *smb_fname_src,
5894 const struct smb_filename *smb_fname_dst)
5895{
5896 char *parent_dir_src = NULL;
5897 char *parent_dir_dst = NULL;
5898 uint32 mask;
5899
5900 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5901 : FILE_NOTIFY_CHANGE_FILE_NAME;
5902
5903 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5904 &parent_dir_src, NULL) ||
5905 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5906 &parent_dir_dst, NULL)) {
5907 goto out;
5908 }
5909
5910 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5911 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5912 smb_fname_src->base_name);
5913 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5914 smb_fname_dst->base_name);
5915 }
5916 else {
5917 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5918 smb_fname_src->base_name);
5919 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5920 smb_fname_dst->base_name);
5921 }
5922
5923 /* this is a strange one. w2k3 gives an additional event for
5924 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5925 files, but not directories */
5926 if (!is_dir) {
5927 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5928 FILE_NOTIFY_CHANGE_ATTRIBUTES
5929 |FILE_NOTIFY_CHANGE_CREATION,
5930 smb_fname_dst->base_name);
5931 }
5932 out:
5933 TALLOC_FREE(parent_dir_src);
5934 TALLOC_FREE(parent_dir_dst);
5935}
5936
5937/****************************************************************************
5938 Returns an error if the parent directory for a filename is open in an
5939 incompatible way.
5940****************************************************************************/
5941
5942static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5943 const struct smb_filename *smb_fname_dst_in)
5944{
5945 char *parent_dir = NULL;
5946 struct smb_filename smb_fname_parent;
5947 struct file_id id;
5948 files_struct *fsp = NULL;
5949 int ret;
5950
5951 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5952 &parent_dir, NULL)) {
5953 return NT_STATUS_NO_MEMORY;
5954 }
5955 ZERO_STRUCT(smb_fname_parent);
5956 smb_fname_parent.base_name = parent_dir;
5957
5958 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5959 if (ret == -1) {
5960 return map_nt_error_from_unix(errno);
5961 }
5962
5963 /*
5964 * We're only checking on this smbd here, mostly good
5965 * enough.. and will pass tests.
5966 */
5967
5968 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5969 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5970 fsp = file_find_di_next(fsp)) {
5971 if (fsp->access_mask & DELETE_ACCESS) {
5972 return NT_STATUS_SHARING_VIOLATION;
5973 }
5974 }
5975 return NT_STATUS_OK;
5976}
5977
5978/****************************************************************************
5979 Rename an open file - given an fsp.
5980****************************************************************************/
5981
5982NTSTATUS rename_internals_fsp(connection_struct *conn,
5983 files_struct *fsp,
5984 const struct smb_filename *smb_fname_dst_in,
5985 uint32 attrs,
5986 bool replace_if_exists)
5987{
5988 TALLOC_CTX *ctx = talloc_tos();
5989 struct smb_filename *smb_fname_dst = NULL;
5990 NTSTATUS status = NT_STATUS_OK;
5991 struct share_mode_lock *lck = NULL;
5992 bool dst_exists, old_is_stream, new_is_stream;
5993
5994/* borrowed from 3.3 source patch by Apple */
5995#ifdef __OS2__
5996 bool check_dest_exist = False;
5997#else
5998 bool check_dest_exist = True;
5999#endif
6000
6001 status = check_name(conn, smb_fname_dst_in->base_name);
6002 if (!NT_STATUS_IS_OK(status)) {
6003 return status;
6004 }
6005
6006 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 return status;
6009 }
6010
6011 /* Make a copy of the dst smb_fname structs */
6012
6013 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6014 if (!NT_STATUS_IS_OK(status)) {
6015 goto out;
6016 }
6017
6018 /*
6019 * Check for special case with case preserving and not
6020 * case sensitive. If the old last component differs from the original
6021 * last component only by case, then we should allow
6022 * the rename (user is trying to change the case of the
6023 * filename).
6024 */
6025 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6026 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6027 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6028 char *last_slash;
6029 char *fname_dst_lcomp_base_mod = NULL;
6030 struct smb_filename *smb_fname_orig_lcomp = NULL;
6031
6032 /*
6033 * Get the last component of the destination name.
6034 */
6035 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6036 if (last_slash) {
6037 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6038 } else {
6039 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6040 }
6041 if (!fname_dst_lcomp_base_mod) {
6042 status = NT_STATUS_NO_MEMORY;
6043 goto out;
6044 }
6045
6046 /*
6047 * Create an smb_filename struct using the original last
6048 * component of the destination.
6049 */
6050 status = create_synthetic_smb_fname_split(ctx,
6051 smb_fname_dst->original_lcomp, NULL,
6052 &smb_fname_orig_lcomp);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 TALLOC_FREE(fname_dst_lcomp_base_mod);
6055 goto out;
6056 }
6057
6058 /* If the base names only differ by case, use original. */
6059 if(!strcsequal(fname_dst_lcomp_base_mod,
6060 smb_fname_orig_lcomp->base_name)) {
6061 char *tmp;
6062 /*
6063 * Replace the modified last component with the
6064 * original.
6065 */
6066 if (last_slash) {
6067 *last_slash = '\0'; /* Truncate at the '/' */
6068 tmp = talloc_asprintf(smb_fname_dst,
6069 "%s/%s",
6070 smb_fname_dst->base_name,
6071 smb_fname_orig_lcomp->base_name);
6072 } else {
6073 tmp = talloc_asprintf(smb_fname_dst,
6074 "%s",
6075 smb_fname_orig_lcomp->base_name);
6076 }
6077 if (tmp == NULL) {
6078 status = NT_STATUS_NO_MEMORY;
6079 TALLOC_FREE(fname_dst_lcomp_base_mod);
6080 TALLOC_FREE(smb_fname_orig_lcomp);
6081 goto out;
6082 }
6083 TALLOC_FREE(smb_fname_dst->base_name);
6084 smb_fname_dst->base_name = tmp;
6085 }
6086
6087 /* If the stream_names only differ by case, use original. */
6088 if(!strcsequal(smb_fname_dst->stream_name,
6089 smb_fname_orig_lcomp->stream_name)) {
6090 char *tmp = NULL;
6091 /* Use the original stream. */
6092 tmp = talloc_strdup(smb_fname_dst,
6093 smb_fname_orig_lcomp->stream_name);
6094 if (tmp == NULL) {
6095 status = NT_STATUS_NO_MEMORY;
6096 TALLOC_FREE(fname_dst_lcomp_base_mod);
6097 TALLOC_FREE(smb_fname_orig_lcomp);
6098 goto out;
6099 }
6100 TALLOC_FREE(smb_fname_dst->stream_name);
6101 smb_fname_dst->stream_name = tmp;
6102 }
6103 TALLOC_FREE(fname_dst_lcomp_base_mod);
6104 TALLOC_FREE(smb_fname_orig_lcomp);
6105 }
6106
6107 /*
6108 * If the src and dest names are identical - including case,
6109 * don't do the rename, just return success.
6110 */
6111
6112 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6113 strcsequal(fsp->fsp_name->stream_name,
6114 smb_fname_dst->stream_name)) {
6115 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6116 "- returning success\n",
6117 smb_fname_str_dbg(smb_fname_dst)));
6118 status = NT_STATUS_OK;
6119 goto out;
6120 }
6121
6122 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6123 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6124
6125 /* Return the correct error code if both names aren't streams. */
6126 if (!old_is_stream && new_is_stream) {
6127 status = NT_STATUS_OBJECT_NAME_INVALID;
6128 goto out;
6129 }
6130
6131 if (old_is_stream && !new_is_stream) {
6132 status = NT_STATUS_INVALID_PARAMETER;
6133 goto out;
6134 }
6135
6136 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6137
6138 if(check_dest_exist && !replace_if_exists && dst_exists) {
6139 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6140 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6141 smb_fname_str_dbg(smb_fname_dst)));
6142 status = NT_STATUS_OBJECT_NAME_COLLISION;
6143 goto out;
6144 }
6145
6146 if (dst_exists) {
6147 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6148 &smb_fname_dst->st);
6149 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6150 fileid);
6151 /* The file can be open when renaming a stream */
6152 if (dst_fsp && !new_is_stream) {
6153 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6154 status = NT_STATUS_ACCESS_DENIED;
6155 goto out;
6156 }
6157 }
6158
6159 /* Ensure we have a valid stat struct for the source. */
6160 status = vfs_stat_fsp(fsp);
6161 if (!NT_STATUS_IS_OK(status)) {
6162 goto out;
6163 }
6164
6165 status = can_rename(conn, fsp, attrs);
6166
6167 if (!NT_STATUS_IS_OK(status)) {
6168 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6169 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6170 smb_fname_str_dbg(smb_fname_dst)));
6171 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6172 status = NT_STATUS_ACCESS_DENIED;
6173 goto out;
6174 }
6175
6176 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6177 status = NT_STATUS_ACCESS_DENIED;
6178 }
6179
6180 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6181 NULL);
6182
6183 /*
6184 * We have the file open ourselves, so not being able to get the
6185 * corresponding share mode lock is a fatal error.
6186 */
6187
6188 SMB_ASSERT(lck != NULL);
6189
6190 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6191 uint32 create_options = fsp->fh->private_options;
6192
6193 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6194 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6195 smb_fname_str_dbg(smb_fname_dst)));
6196
6197 if (!lp_posix_pathnames() &&
6198 (lp_map_archive(SNUM(conn)) ||
6199 lp_store_dos_attributes(SNUM(conn)))) {
6200 /* We must set the archive bit on the newly
6201 renamed file. */
6202 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6203 uint32_t old_dosmode = dos_mode(conn,
6204 smb_fname_dst);
6205 file_set_dosmode(conn,
6206 smb_fname_dst,
6207 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6208 NULL,
6209 true);
6210 }
6211 }
6212
6213 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6214 smb_fname_dst);
6215
6216 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6217
6218 /*
6219 * A rename acts as a new file create w.r.t. allowing an initial delete
6220 * on close, probably because in Windows there is a new handle to the
6221 * new file. If initial delete on close was requested but not
6222 * originally set, we need to set it here. This is probably not 100% correct,
6223 * but will work for the CIFSFS client which in non-posix mode
6224 * depends on these semantics. JRA.
6225 */
6226
6227 if (create_options & FILE_DELETE_ON_CLOSE) {
6228 status = can_set_delete_on_close(fsp, 0);
6229
6230 if (NT_STATUS_IS_OK(status)) {
6231 /* Note that here we set the *inital* delete on close flag,
6232 * not the regular one. The magic gets handled in close. */
6233 fsp->initial_delete_on_close = True;
6234 }
6235 }
6236 TALLOC_FREE(lck);
6237 status = NT_STATUS_OK;
6238 goto out;
6239 }
6240
6241 TALLOC_FREE(lck);
6242
6243 if (errno == ENOTDIR || errno == EISDIR) {
6244 status = NT_STATUS_OBJECT_NAME_COLLISION;
6245 } else {
6246 status = map_nt_error_from_unix(errno);
6247 }
6248
6249 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6250 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6251 smb_fname_str_dbg(smb_fname_dst)));
6252
6253 out:
6254 TALLOC_FREE(smb_fname_dst);
6255
6256 return status;
6257}
6258
6259/****************************************************************************
6260 The guts of the rename command, split out so it may be called by the NT SMB
6261 code.
6262****************************************************************************/
6263
6264NTSTATUS rename_internals(TALLOC_CTX *ctx,
6265 connection_struct *conn,
6266 struct smb_request *req,
6267 struct smb_filename *smb_fname_src,
6268 struct smb_filename *smb_fname_dst,
6269 uint32 attrs,
6270 bool replace_if_exists,
6271 bool src_has_wild,
6272 bool dest_has_wild,
6273 uint32_t access_mask)
6274{
6275 char *fname_src_dir = NULL;
6276 char *fname_src_mask = NULL;
6277 int count=0;
6278 NTSTATUS status = NT_STATUS_OK;
6279 struct smb_Dir *dir_hnd = NULL;
6280 const char *dname = NULL;
6281 char *talloced = NULL;
6282 long offset = 0;
6283 int create_options = 0;
6284 bool posix_pathnames = lp_posix_pathnames();
6285
6286 /*
6287 * Split the old name into directory and last component
6288 * strings. Note that unix_convert may have stripped off a
6289 * leading ./ from both name and newname if the rename is
6290 * at the root of the share. We need to make sure either both
6291 * name and newname contain a / character or neither of them do
6292 * as this is checked in resolve_wildcards().
6293 */
6294
6295 /* Split up the directory from the filename/mask. */
6296 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6297 &fname_src_dir, &fname_src_mask);
6298 if (!NT_STATUS_IS_OK(status)) {
6299 status = NT_STATUS_NO_MEMORY;
6300 goto out;
6301 }
6302
6303 /*
6304 * We should only check the mangled cache
6305 * here if unix_convert failed. This means
6306 * that the path in 'mask' doesn't exist
6307 * on the file system and so we need to look
6308 * for a possible mangle. This patch from
6309 * Tine Smukavec <valentin.smukavec@hermes.si>.
6310 */
6311
6312 if (!VALID_STAT(smb_fname_src->st) &&
6313 mangle_is_mangled(fname_src_mask, conn->params)) {
6314 char *new_mask = NULL;
6315 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6316 conn->params);
6317 if (new_mask) {
6318 TALLOC_FREE(fname_src_mask);
6319 fname_src_mask = new_mask;
6320 }
6321 }
6322
6323 if (!src_has_wild) {
6324 files_struct *fsp;
6325
6326 /*
6327 * Only one file needs to be renamed. Append the mask back
6328 * onto the directory.
6329 */
6330 TALLOC_FREE(smb_fname_src->base_name);
6331 if (ISDOT(fname_src_dir)) {
6332 /* Ensure we use canonical names on open. */
6333 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6334 "%s",
6335 fname_src_mask);
6336 } else {
6337 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6338 "%s/%s",
6339 fname_src_dir,
6340 fname_src_mask);
6341 }
6342 if (!smb_fname_src->base_name) {
6343 status = NT_STATUS_NO_MEMORY;
6344 goto out;
6345 }
6346
6347 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6348 "case_preserve = %d, short case preserve = %d, "
6349 "directory = %s, newname = %s, "
6350 "last_component_dest = %s\n",
6351 conn->case_sensitive, conn->case_preserve,
6352 conn->short_case_preserve,
6353 smb_fname_str_dbg(smb_fname_src),
6354 smb_fname_str_dbg(smb_fname_dst),
6355 smb_fname_dst->original_lcomp));
6356
6357 /* The dest name still may have wildcards. */
6358 if (dest_has_wild) {
6359 char *fname_dst_mod = NULL;
6360 if (!resolve_wildcards(smb_fname_dst,
6361 smb_fname_src->base_name,
6362 smb_fname_dst->base_name,
6363 &fname_dst_mod)) {
6364 DEBUG(6, ("rename_internals: resolve_wildcards "
6365 "%s %s failed\n",
6366 smb_fname_src->base_name,
6367 smb_fname_dst->base_name));
6368 status = NT_STATUS_NO_MEMORY;
6369 goto out;
6370 }
6371 TALLOC_FREE(smb_fname_dst->base_name);
6372 smb_fname_dst->base_name = fname_dst_mod;
6373 }
6374
6375 ZERO_STRUCT(smb_fname_src->st);
6376 if (posix_pathnames) {
6377 SMB_VFS_LSTAT(conn, smb_fname_src);
6378 } else {
6379 SMB_VFS_STAT(conn, smb_fname_src);
6380 }
6381
6382 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6383 create_options |= FILE_DIRECTORY_FILE;
6384 }
6385
6386 status = SMB_VFS_CREATE_FILE(
6387 conn, /* conn */
6388 req, /* req */
6389 0, /* root_dir_fid */
6390 smb_fname_src, /* fname */
6391 access_mask, /* access_mask */
6392 (FILE_SHARE_READ | /* share_access */
6393 FILE_SHARE_WRITE),
6394 FILE_OPEN, /* create_disposition*/
6395 create_options, /* create_options */
6396 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6397 0, /* oplock_request */
6398 0, /* allocation_size */
6399 0, /* private_flags */
6400 NULL, /* sd */
6401 NULL, /* ea_list */
6402 &fsp, /* result */
6403 NULL); /* pinfo */
6404
6405 if (!NT_STATUS_IS_OK(status)) {
6406 DEBUG(3, ("Could not open rename source %s: %s\n",
6407 smb_fname_str_dbg(smb_fname_src),
6408 nt_errstr(status)));
6409 goto out;
6410 }
6411
6412 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6413 attrs, replace_if_exists);
6414
6415 close_file(req, fsp, NORMAL_CLOSE);
6416
6417 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6418 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6419 smb_fname_str_dbg(smb_fname_dst)));
6420
6421 goto out;
6422 }
6423
6424 /*
6425 * Wildcards - process each file that matches.
6426 */
6427 if (strequal(fname_src_mask, "????????.???")) {
6428 TALLOC_FREE(fname_src_mask);
6429 fname_src_mask = talloc_strdup(ctx, "*");
6430 if (!fname_src_mask) {
6431 status = NT_STATUS_NO_MEMORY;
6432 goto out;
6433 }
6434 }
6435
6436 status = check_name(conn, fname_src_dir);
6437 if (!NT_STATUS_IS_OK(status)) {
6438 goto out;
6439 }
6440
6441 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6442 attrs);
6443 if (dir_hnd == NULL) {
6444 status = map_nt_error_from_unix(errno);
6445 goto out;
6446 }
6447
6448 status = NT_STATUS_NO_SUCH_FILE;
6449 /*
6450 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6451 * - gentest fix. JRA
6452 */
6453
6454 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6455 &talloced))) {
6456 files_struct *fsp = NULL;
6457 char *destname = NULL;
6458 bool sysdir_entry = False;
6459
6460 /* Quick check for "." and ".." */
6461 if (ISDOT(dname) || ISDOTDOT(dname)) {
6462 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6463 sysdir_entry = True;
6464 } else {
6465 TALLOC_FREE(talloced);
6466 continue;
6467 }
6468 }
6469
6470 if (!is_visible_file(conn, fname_src_dir, dname,
6471 &smb_fname_src->st, false)) {
6472 TALLOC_FREE(talloced);
6473 continue;
6474 }
6475
6476 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6477 TALLOC_FREE(talloced);
6478 continue;
6479 }
6480
6481 if (sysdir_entry) {
6482 status = NT_STATUS_OBJECT_NAME_INVALID;
6483 break;
6484 }
6485
6486 TALLOC_FREE(smb_fname_src->base_name);
6487 if (ISDOT(fname_src_dir)) {
6488 /* Ensure we use canonical names on open. */
6489 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6490 "%s",
6491 dname);
6492 } else {
6493 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6494 "%s/%s",
6495 fname_src_dir,
6496 dname);
6497 }
6498 if (!smb_fname_src->base_name) {
6499 status = NT_STATUS_NO_MEMORY;
6500 goto out;
6501 }
6502
6503 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6504 smb_fname_dst->base_name,
6505 &destname)) {
6506 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6507 smb_fname_src->base_name, destname));
6508 TALLOC_FREE(talloced);
6509 continue;
6510 }
6511 if (!destname) {
6512 status = NT_STATUS_NO_MEMORY;
6513 goto out;
6514 }
6515
6516 TALLOC_FREE(smb_fname_dst->base_name);
6517 smb_fname_dst->base_name = destname;
6518
6519 ZERO_STRUCT(smb_fname_src->st);
6520 if (posix_pathnames) {
6521 SMB_VFS_LSTAT(conn, smb_fname_src);
6522 } else {
6523 SMB_VFS_STAT(conn, smb_fname_src);
6524 }
6525
6526 create_options = 0;
6527
6528 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6529 create_options |= FILE_DIRECTORY_FILE;
6530 }
6531
6532 status = SMB_VFS_CREATE_FILE(
6533 conn, /* conn */
6534 req, /* req */
6535 0, /* root_dir_fid */
6536 smb_fname_src, /* fname */
6537 access_mask, /* access_mask */
6538 (FILE_SHARE_READ | /* share_access */
6539 FILE_SHARE_WRITE),
6540 FILE_OPEN, /* create_disposition*/
6541 create_options, /* create_options */
6542 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6543 0, /* oplock_request */
6544 0, /* allocation_size */
6545 0, /* private_flags */
6546 NULL, /* sd */
6547 NULL, /* ea_list */
6548 &fsp, /* result */
6549 NULL); /* pinfo */
6550
6551 if (!NT_STATUS_IS_OK(status)) {
6552 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6553 "returned %s rename %s -> %s\n",
6554 nt_errstr(status),
6555 smb_fname_str_dbg(smb_fname_src),
6556 smb_fname_str_dbg(smb_fname_dst)));
6557 break;
6558 }
6559
6560 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6561 dname);
6562 if (!smb_fname_dst->original_lcomp) {
6563 status = NT_STATUS_NO_MEMORY;
6564 goto out;
6565 }
6566
6567 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6568 attrs, replace_if_exists);
6569
6570 close_file(req, fsp, NORMAL_CLOSE);
6571
6572 if (!NT_STATUS_IS_OK(status)) {
6573 DEBUG(3, ("rename_internals_fsp returned %s for "
6574 "rename %s -> %s\n", nt_errstr(status),
6575 smb_fname_str_dbg(smb_fname_src),
6576 smb_fname_str_dbg(smb_fname_dst)));
6577 break;
6578 }
6579
6580 count++;
6581
6582 DEBUG(3,("rename_internals: doing rename on %s -> "
6583 "%s\n", smb_fname_str_dbg(smb_fname_src),
6584 smb_fname_str_dbg(smb_fname_src)));
6585 TALLOC_FREE(talloced);
6586 }
6587 TALLOC_FREE(dir_hnd);
6588
6589 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6590 status = map_nt_error_from_unix(errno);
6591 }
6592
6593 out:
6594 TALLOC_FREE(talloced);
6595 TALLOC_FREE(fname_src_dir);
6596 TALLOC_FREE(fname_src_mask);
6597 return status;
6598}
6599
6600/****************************************************************************
6601 Reply to a mv.
6602****************************************************************************/
6603
6604void reply_mv(struct smb_request *req)
6605{
6606 connection_struct *conn = req->conn;
6607 char *name = NULL;
6608 char *newname = NULL;
6609 const char *p;
6610 uint32 attrs;
6611 NTSTATUS status;
6612 bool src_has_wcard = False;
6613 bool dest_has_wcard = False;
6614 TALLOC_CTX *ctx = talloc_tos();
6615 struct smb_filename *smb_fname_src = NULL;
6616 struct smb_filename *smb_fname_dst = NULL;
6617 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6618 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6619 bool stream_rename = false;
6620
6621 START_PROFILE(SMBmv);
6622
6623 if (req->wct < 1) {
6624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6625 goto out;
6626 }
6627
6628 attrs = SVAL(req->vwv+0, 0);
6629
6630 p = (const char *)req->buf + 1;
6631 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6632 &status, &src_has_wcard);
6633 if (!NT_STATUS_IS_OK(status)) {
6634 reply_nterror(req, status);
6635 goto out;
6636 }
6637 p++;
6638 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6639 &status, &dest_has_wcard);
6640 if (!NT_STATUS_IS_OK(status)) {
6641 reply_nterror(req, status);
6642 goto out;
6643 }
6644
6645 if (!lp_posix_pathnames()) {
6646 /* The newname must begin with a ':' if the
6647 name contains a ':'. */
6648 if (strchr_m(name, ':')) {
6649 if (newname[0] != ':') {
6650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6651 goto out;
6652 }
6653 stream_rename = true;
6654 }
6655 }
6656
6657 status = filename_convert(ctx,
6658 conn,
6659 req->flags2 & FLAGS2_DFS_PATHNAMES,
6660 name,
6661 src_ucf_flags,
6662 &src_has_wcard,
6663 &smb_fname_src);
6664
6665 if (!NT_STATUS_IS_OK(status)) {
6666 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6667 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6668 ERRSRV, ERRbadpath);
6669 goto out;
6670 }
6671 reply_nterror(req, status);
6672 goto out;
6673 }
6674
6675 status = filename_convert(ctx,
6676 conn,
6677 req->flags2 & FLAGS2_DFS_PATHNAMES,
6678 newname,
6679 dst_ucf_flags,
6680 &dest_has_wcard,
6681 &smb_fname_dst);
6682
6683 if (!NT_STATUS_IS_OK(status)) {
6684 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6685 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6686 ERRSRV, ERRbadpath);
6687 goto out;
6688 }
6689 reply_nterror(req, status);
6690 goto out;
6691 }
6692
6693 if (stream_rename) {
6694 /* smb_fname_dst->base_name must be the same as
6695 smb_fname_src->base_name. */
6696 TALLOC_FREE(smb_fname_dst->base_name);
6697 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6698 smb_fname_src->base_name);
6699 if (!smb_fname_dst->base_name) {
6700 reply_nterror(req, NT_STATUS_NO_MEMORY);
6701 goto out;
6702 }
6703 }
6704
6705 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6706 smb_fname_str_dbg(smb_fname_dst)));
6707
6708 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6709 attrs, False, src_has_wcard, dest_has_wcard,
6710 DELETE_ACCESS);
6711 if (!NT_STATUS_IS_OK(status)) {
6712 if (open_was_deferred(req->mid)) {
6713 /* We have re-scheduled this call. */
6714 goto out;
6715 }
6716 reply_nterror(req, status);
6717 goto out;
6718 }
6719
6720 reply_outbuf(req, 0, 0);
6721 out:
6722 TALLOC_FREE(smb_fname_src);
6723 TALLOC_FREE(smb_fname_dst);
6724 END_PROFILE(SMBmv);
6725 return;
6726}
6727
6728/*******************************************************************
6729 Copy a file as part of a reply_copy.
6730******************************************************************/
6731
6732/*
6733 * TODO: check error codes on all callers
6734 */
6735
6736NTSTATUS copy_file(TALLOC_CTX *ctx,
6737 connection_struct *conn,
6738 struct smb_filename *smb_fname_src,
6739 struct smb_filename *smb_fname_dst,
6740 int ofun,
6741 int count,
6742 bool target_is_directory)
6743{
6744 struct smb_filename *smb_fname_dst_tmp = NULL;
6745 SMB_OFF_T ret=-1;
6746 files_struct *fsp1,*fsp2;
6747 uint32 dosattrs;
6748 uint32 new_create_disposition;
6749 NTSTATUS status;
6750
6751
6752 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6753 if (!NT_STATUS_IS_OK(status)) {
6754 return status;
6755 }
6756
6757 /*
6758 * If the target is a directory, extract the last component from the
6759 * src filename and append it to the dst filename
6760 */
6761 if (target_is_directory) {
6762 const char *p;
6763
6764 /* dest/target can't be a stream if it's a directory. */
6765 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6766
6767 p = strrchr_m(smb_fname_src->base_name,'/');
6768 if (p) {
6769 p++;
6770 } else {
6771 p = smb_fname_src->base_name;
6772 }
6773 smb_fname_dst_tmp->base_name =
6774 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6775 p);
6776 if (!smb_fname_dst_tmp->base_name) {
6777 status = NT_STATUS_NO_MEMORY;
6778 goto out;
6779 }
6780 }
6781
6782 status = vfs_file_exist(conn, smb_fname_src);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 goto out;
6785 }
6786
6787 if (!target_is_directory && count) {
6788 new_create_disposition = FILE_OPEN;
6789 } else {
6790 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6791 0, ofun,
6792 NULL, NULL,
6793 &new_create_disposition,
6794 NULL,
6795 NULL)) {
6796 status = NT_STATUS_INVALID_PARAMETER;
6797 goto out;
6798 }
6799 }
6800
6801 /* Open the src file for reading. */
6802 status = SMB_VFS_CREATE_FILE(
6803 conn, /* conn */
6804 NULL, /* req */
6805 0, /* root_dir_fid */
6806 smb_fname_src, /* fname */
6807 FILE_GENERIC_READ, /* access_mask */
6808 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6809 FILE_OPEN, /* create_disposition*/
6810 0, /* create_options */
6811 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6812 INTERNAL_OPEN_ONLY, /* oplock_request */
6813 0, /* allocation_size */
6814 0, /* private_flags */
6815 NULL, /* sd */
6816 NULL, /* ea_list */
6817 &fsp1, /* result */
6818 NULL); /* psbuf */
6819
6820 if (!NT_STATUS_IS_OK(status)) {
6821 goto out;
6822 }
6823
6824 dosattrs = dos_mode(conn, smb_fname_src);
6825
6826 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6827 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6828 }
6829
6830 /* Open the dst file for writing. */
6831 status = SMB_VFS_CREATE_FILE(
6832 conn, /* conn */
6833 NULL, /* req */
6834 0, /* root_dir_fid */
6835 smb_fname_dst, /* fname */
6836 FILE_GENERIC_WRITE, /* access_mask */
6837 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6838 new_create_disposition, /* create_disposition*/
6839 0, /* create_options */
6840 dosattrs, /* file_attributes */
6841 INTERNAL_OPEN_ONLY, /* oplock_request */
6842 0, /* allocation_size */
6843 0, /* private_flags */
6844 NULL, /* sd */
6845 NULL, /* ea_list */
6846 &fsp2, /* result */
6847 NULL); /* psbuf */
6848
6849 if (!NT_STATUS_IS_OK(status)) {
6850 close_file(NULL, fsp1, ERROR_CLOSE);
6851 goto out;
6852 }
6853
6854 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6855 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6856 if (ret == -1) {
6857 DEBUG(0, ("error - vfs lseek returned error %s\n",
6858 strerror(errno)));
6859 status = map_nt_error_from_unix(errno);
6860 close_file(NULL, fsp1, ERROR_CLOSE);
6861 close_file(NULL, fsp2, ERROR_CLOSE);
6862 goto out;
6863 }
6864 }
6865
6866 /* Do the actual copy. */
6867 if (smb_fname_src->st.st_ex_size) {
6868 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6869 } else {
6870 ret = 0;
6871 }
6872
6873 close_file(NULL, fsp1, NORMAL_CLOSE);
6874
6875 /* Ensure the modtime is set correctly on the destination file. */
6876 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6877
6878 /*
6879 * As we are opening fsp1 read-only we only expect
6880 * an error on close on fsp2 if we are out of space.
6881 * Thus we don't look at the error return from the
6882 * close of fsp1.
6883 */
6884 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6885
6886 if (!NT_STATUS_IS_OK(status)) {
6887 goto out;
6888 }
6889
6890 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6891 status = NT_STATUS_DISK_FULL;
6892 goto out;
6893 }
6894
6895 status = NT_STATUS_OK;
6896
6897 out:
6898 TALLOC_FREE(smb_fname_dst_tmp);
6899 return status;
6900}
6901
6902/****************************************************************************
6903 Reply to a file copy.
6904****************************************************************************/
6905
6906void reply_copy(struct smb_request *req)
6907{
6908 connection_struct *conn = req->conn;
6909 struct smb_filename *smb_fname_src = NULL;
6910 struct smb_filename *smb_fname_dst = NULL;
6911 char *fname_src = NULL;
6912 char *fname_dst = NULL;
6913 char *fname_src_mask = NULL;
6914 char *fname_src_dir = NULL;
6915 const char *p;
6916 int count=0;
6917 int error = ERRnoaccess;
6918 int tid2;
6919 int ofun;
6920 int flags;
6921 bool target_is_directory=False;
6922 bool source_has_wild = False;
6923 bool dest_has_wild = False;
6924 NTSTATUS status;
6925 TALLOC_CTX *ctx = talloc_tos();
6926
6927 START_PROFILE(SMBcopy);
6928
6929 if (req->wct < 3) {
6930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6931 goto out;
6932 }
6933
6934 tid2 = SVAL(req->vwv+0, 0);
6935 ofun = SVAL(req->vwv+1, 0);
6936 flags = SVAL(req->vwv+2, 0);
6937
6938 p = (const char *)req->buf;
6939 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6940 &status, &source_has_wild);
6941 if (!NT_STATUS_IS_OK(status)) {
6942 reply_nterror(req, status);
6943 goto out;
6944 }
6945 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6946 &status, &dest_has_wild);
6947 if (!NT_STATUS_IS_OK(status)) {
6948 reply_nterror(req, status);
6949 goto out;
6950 }
6951
6952 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6953
6954 if (tid2 != conn->cnum) {
6955 /* can't currently handle inter share copies XXXX */
6956 DEBUG(3,("Rejecting inter-share copy\n"));
6957 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6958 goto out;
6959 }
6960
6961 status = filename_convert(ctx, conn,
6962 req->flags2 & FLAGS2_DFS_PATHNAMES,
6963 fname_src,
6964 UCF_COND_ALLOW_WCARD_LCOMP,
6965 &source_has_wild,
6966 &smb_fname_src);
6967 if (!NT_STATUS_IS_OK(status)) {
6968 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6969 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6970 ERRSRV, ERRbadpath);
6971 goto out;
6972 }
6973 reply_nterror(req, status);
6974 goto out;
6975 }
6976
6977 status = filename_convert(ctx, conn,
6978 req->flags2 & FLAGS2_DFS_PATHNAMES,
6979 fname_dst,
6980 UCF_COND_ALLOW_WCARD_LCOMP,
6981 &dest_has_wild,
6982 &smb_fname_dst);
6983 if (!NT_STATUS_IS_OK(status)) {
6984 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6985 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6986 ERRSRV, ERRbadpath);
6987 goto out;
6988 }
6989 reply_nterror(req, status);
6990 goto out;
6991 }
6992
6993 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6994
6995 if ((flags&1) && target_is_directory) {
6996 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6997 goto out;
6998 }
6999
7000 if ((flags&2) && !target_is_directory) {
7001 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7002 goto out;
7003 }
7004
7005 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7006 /* wants a tree copy! XXXX */
7007 DEBUG(3,("Rejecting tree copy\n"));
7008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7009 goto out;
7010 }
7011
7012 /* Split up the directory from the filename/mask. */
7013 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7014 &fname_src_dir, &fname_src_mask);
7015 if (!NT_STATUS_IS_OK(status)) {
7016 reply_nterror(req, NT_STATUS_NO_MEMORY);
7017 goto out;
7018 }
7019
7020 /*
7021 * We should only check the mangled cache
7022 * here if unix_convert failed. This means
7023 * that the path in 'mask' doesn't exist
7024 * on the file system and so we need to look
7025 * for a possible mangle. This patch from
7026 * Tine Smukavec <valentin.smukavec@hermes.si>.
7027 */
7028 if (!VALID_STAT(smb_fname_src->st) &&
7029 mangle_is_mangled(fname_src_mask, conn->params)) {
7030 char *new_mask = NULL;
7031 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7032 &new_mask, conn->params);
7033
7034 /* Use demangled name if one was successfully found. */
7035 if (new_mask) {
7036 TALLOC_FREE(fname_src_mask);
7037 fname_src_mask = new_mask;
7038 }
7039 }
7040
7041 if (!source_has_wild) {
7042
7043 /*
7044 * Only one file needs to be copied. Append the mask back onto
7045 * the directory.
7046 */
7047 TALLOC_FREE(smb_fname_src->base_name);
7048 if (ISDOT(fname_src_dir)) {
7049 /* Ensure we use canonical names on open. */
7050 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7051 "%s",
7052 fname_src_mask);
7053 } else {
7054 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7055 "%s/%s",
7056 fname_src_dir,
7057 fname_src_mask);
7058 }
7059 if (!smb_fname_src->base_name) {
7060 reply_nterror(req, NT_STATUS_NO_MEMORY);
7061 goto out;
7062 }
7063
7064 if (dest_has_wild) {
7065 char *fname_dst_mod = NULL;
7066 if (!resolve_wildcards(smb_fname_dst,
7067 smb_fname_src->base_name,
7068 smb_fname_dst->base_name,
7069 &fname_dst_mod)) {
7070 reply_nterror(req, NT_STATUS_NO_MEMORY);
7071 goto out;
7072 }
7073 TALLOC_FREE(smb_fname_dst->base_name);
7074 smb_fname_dst->base_name = fname_dst_mod;
7075 }
7076
7077 status = check_name(conn, smb_fname_src->base_name);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 reply_nterror(req, status);
7080 goto out;
7081 }
7082
7083 status = check_name(conn, smb_fname_dst->base_name);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 reply_nterror(req, status);
7086 goto out;
7087 }
7088
7089 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7090 ofun, count, target_is_directory);
7091
7092 if(!NT_STATUS_IS_OK(status)) {
7093 reply_nterror(req, status);
7094 goto out;
7095 } else {
7096 count++;
7097 }
7098 } else {
7099 struct smb_Dir *dir_hnd = NULL;
7100 const char *dname = NULL;
7101 char *talloced = NULL;
7102 long offset = 0;
7103
7104 /*
7105 * There is a wildcard that requires us to actually read the
7106 * src dir and copy each file matching the mask to the dst.
7107 * Right now streams won't be copied, but this could
7108 * presumably be added with a nested loop for reach dir entry.
7109 */
7110 SMB_ASSERT(!smb_fname_src->stream_name);
7111 SMB_ASSERT(!smb_fname_dst->stream_name);
7112
7113 smb_fname_src->stream_name = NULL;
7114 smb_fname_dst->stream_name = NULL;
7115
7116 if (strequal(fname_src_mask,"????????.???")) {
7117 TALLOC_FREE(fname_src_mask);
7118 fname_src_mask = talloc_strdup(ctx, "*");
7119 if (!fname_src_mask) {
7120 reply_nterror(req, NT_STATUS_NO_MEMORY);
7121 goto out;
7122 }
7123 }
7124
7125 status = check_name(conn, fname_src_dir);
7126 if (!NT_STATUS_IS_OK(status)) {
7127 reply_nterror(req, status);
7128 goto out;
7129 }
7130
7131 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7132 if (dir_hnd == NULL) {
7133 status = map_nt_error_from_unix(errno);
7134 reply_nterror(req, status);
7135 goto out;
7136 }
7137
7138 error = ERRbadfile;
7139
7140 /* Iterate over the src dir copying each entry to the dst. */
7141 while ((dname = ReadDirName(dir_hnd, &offset,
7142 &smb_fname_src->st, &talloced))) {
7143 char *destname = NULL;
7144
7145 if (ISDOT(dname) || ISDOTDOT(dname)) {
7146 TALLOC_FREE(talloced);
7147 continue;
7148 }
7149
7150 if (!is_visible_file(conn, fname_src_dir, dname,
7151 &smb_fname_src->st, false)) {
7152 TALLOC_FREE(talloced);
7153 continue;
7154 }
7155
7156 if(!mask_match(dname, fname_src_mask,
7157 conn->case_sensitive)) {
7158 TALLOC_FREE(talloced);
7159 continue;
7160 }
7161
7162 error = ERRnoaccess;
7163
7164 /* Get the src smb_fname struct setup. */
7165 TALLOC_FREE(smb_fname_src->base_name);
7166 if (ISDOT(fname_src_dir)) {
7167 /* Ensure we use canonical names on open. */
7168 smb_fname_src->base_name =
7169 talloc_asprintf(smb_fname_src, "%s",
7170 dname);
7171 } else {
7172 smb_fname_src->base_name =
7173 talloc_asprintf(smb_fname_src, "%s/%s",
7174 fname_src_dir, dname);
7175 }
7176
7177 if (!smb_fname_src->base_name) {
7178 TALLOC_FREE(dir_hnd);
7179 TALLOC_FREE(talloced);
7180 reply_nterror(req, NT_STATUS_NO_MEMORY);
7181 goto out;
7182 }
7183
7184 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7185 smb_fname_dst->base_name,
7186 &destname)) {
7187 TALLOC_FREE(talloced);
7188 continue;
7189 }
7190 if (!destname) {
7191 TALLOC_FREE(dir_hnd);
7192 TALLOC_FREE(talloced);
7193 reply_nterror(req, NT_STATUS_NO_MEMORY);
7194 goto out;
7195 }
7196
7197 TALLOC_FREE(smb_fname_dst->base_name);
7198 smb_fname_dst->base_name = destname;
7199
7200 status = check_name(conn, smb_fname_src->base_name);
7201 if (!NT_STATUS_IS_OK(status)) {
7202 TALLOC_FREE(dir_hnd);
7203 TALLOC_FREE(talloced);
7204 reply_nterror(req, status);
7205 goto out;
7206 }
7207
7208 status = check_name(conn, smb_fname_dst->base_name);
7209 if (!NT_STATUS_IS_OK(status)) {
7210 TALLOC_FREE(dir_hnd);
7211 TALLOC_FREE(talloced);
7212 reply_nterror(req, status);
7213 goto out;
7214 }
7215
7216 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7217 smb_fname_src->base_name,
7218 smb_fname_dst->base_name));
7219
7220 status = copy_file(ctx, conn, smb_fname_src,
7221 smb_fname_dst, ofun, count,
7222 target_is_directory);
7223 if (NT_STATUS_IS_OK(status)) {
7224 count++;
7225 }
7226
7227 TALLOC_FREE(talloced);
7228 }
7229 TALLOC_FREE(dir_hnd);
7230 }
7231
7232 if (count == 0) {
7233 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7234 goto out;
7235 }
7236
7237 reply_outbuf(req, 1, 0);
7238 SSVAL(req->outbuf,smb_vwv0,count);
7239 out:
7240 TALLOC_FREE(smb_fname_src);
7241 TALLOC_FREE(smb_fname_dst);
7242 TALLOC_FREE(fname_src);
7243 TALLOC_FREE(fname_dst);
7244 TALLOC_FREE(fname_src_mask);
7245 TALLOC_FREE(fname_src_dir);
7246
7247 END_PROFILE(SMBcopy);
7248 return;
7249}
7250
7251#undef DBGC_CLASS
7252#define DBGC_CLASS DBGC_LOCKING
7253
7254/****************************************************************************
7255 Get a lock pid, dealing with large count requests.
7256****************************************************************************/
7257
7258uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7259 bool large_file_format)
7260{
7261 if(!large_file_format)
7262 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7263 else
7264 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7265}
7266
7267/****************************************************************************
7268 Get a lock count, dealing with large count requests.
7269****************************************************************************/
7270
7271uint64_t get_lock_count(const uint8_t *data, int data_offset,
7272 bool large_file_format)
7273{
7274 uint64_t count = 0;
7275
7276 if(!large_file_format) {
7277 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7278 } else {
7279
7280#if defined(HAVE_LONGLONG)
7281 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7282 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7283#else /* HAVE_LONGLONG */
7284
7285 /*
7286 * NT4.x seems to be broken in that it sends large file (64 bit)
7287 * lockingX calls even if the CAP_LARGE_FILES was *not*
7288 * negotiated. For boxes without large unsigned ints truncate the
7289 * lock count by dropping the top 32 bits.
7290 */
7291
7292 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7293 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7294 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7295 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7296 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7297 }
7298
7299 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7300#endif /* HAVE_LONGLONG */
7301 }
7302
7303 return count;
7304}
7305
7306#if !defined(HAVE_LONGLONG)
7307/****************************************************************************
7308 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7309****************************************************************************/
7310
7311static uint32 map_lock_offset(uint32 high, uint32 low)
7312{
7313 unsigned int i;
7314 uint32 mask = 0;
7315 uint32 highcopy = high;
7316
7317 /*
7318 * Try and find out how many significant bits there are in high.
7319 */
7320
7321 for(i = 0; highcopy; i++)
7322 highcopy >>= 1;
7323
7324 /*
7325 * We use 31 bits not 32 here as POSIX
7326 * lock offsets may not be negative.
7327 */
7328
7329 mask = (~0) << (31 - i);
7330
7331 if(low & mask)
7332 return 0; /* Fail. */
7333
7334 high <<= (31 - i);
7335
7336 return (high|low);
7337}
7338#endif /* !defined(HAVE_LONGLONG) */
7339
7340/****************************************************************************
7341 Get a lock offset, dealing with large offset requests.
7342****************************************************************************/
7343
7344uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7345 bool large_file_format, bool *err)
7346{
7347 uint64_t offset = 0;
7348
7349 *err = False;
7350
7351 if(!large_file_format) {
7352 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7353 } else {
7354
7355#if defined(HAVE_LONGLONG)
7356 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7357 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7358#else /* HAVE_LONGLONG */
7359
7360 /*
7361 * NT4.x seems to be broken in that it sends large file (64 bit)
7362 * lockingX calls even if the CAP_LARGE_FILES was *not*
7363 * negotiated. For boxes without large unsigned ints mangle the
7364 * lock offset by mapping the top 32 bits onto the lower 32.
7365 */
7366
7367 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7368 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7369 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7370 uint32 new_low = 0;
7371
7372 if((new_low = map_lock_offset(high, low)) == 0) {
7373 *err = True;
7374 return (uint64_t)-1;
7375 }
7376
7377 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7378 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7379 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7380 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7381 }
7382
7383 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7384#endif /* HAVE_LONGLONG */
7385 }
7386
7387 return offset;
7388}
7389
7390NTSTATUS smbd_do_locking(struct smb_request *req,
7391 files_struct *fsp,
7392 uint8_t type,
7393 int32_t timeout,
7394 uint16_t num_ulocks,
7395 struct smbd_lock_element *ulocks,
7396 uint16_t num_locks,
7397 struct smbd_lock_element *locks,
7398 bool *async)
7399{
7400 connection_struct *conn = req->conn;
7401 int i;
7402 NTSTATUS status = NT_STATUS_OK;
7403
7404 *async = false;
7405
7406 /* Data now points at the beginning of the list
7407 of smb_unlkrng structs */
7408 for(i = 0; i < (int)num_ulocks; i++) {
7409 struct smbd_lock_element *e = &ulocks[i];
7410
7411 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7412 "pid %u, file %s\n",
7413 (double)e->offset,
7414 (double)e->count,
7415 (unsigned int)e->smblctx,
7416 fsp_str_dbg(fsp)));
7417
7418 if (e->brltype != UNLOCK_LOCK) {
7419 /* this can only happen with SMB2 */
7420 return NT_STATUS_INVALID_PARAMETER;
7421 }
7422
7423 status = do_unlock(req->sconn->msg_ctx,
7424 fsp,
7425 e->smblctx,
7426 e->count,
7427 e->offset,
7428 WINDOWS_LOCK);
7429
7430 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7431 nt_errstr(status)));
7432
7433 if (!NT_STATUS_IS_OK(status)) {
7434 return status;
7435 }
7436 }
7437
7438 /* Setup the timeout in seconds. */
7439
7440 if (!lp_blocking_locks(SNUM(conn))) {
7441 timeout = 0;
7442 }
7443
7444 /* Data now points at the beginning of the list
7445 of smb_lkrng structs */
7446
7447 for(i = 0; i < (int)num_locks; i++) {
7448 struct smbd_lock_element *e = &locks[i];
7449
7450 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7451 "%llu, file %s timeout = %d\n",
7452 (double)e->offset,
7453 (double)e->count,
7454 (unsigned long long)e->smblctx,
7455 fsp_str_dbg(fsp),
7456 (int)timeout));
7457
7458 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7459 struct blocking_lock_record *blr = NULL;
7460
7461 if (num_locks > 1) {
7462 /*
7463 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7464 * if the lock vector contains one entry. When given mutliple cancel
7465 * requests in a single PDU we expect the server to return an
7466 * error. Windows servers seem to accept the request but only
7467 * cancel the first lock.
7468 * JRA - Do what Windows does (tm) :-).
7469 */
7470
7471#if 0
7472 /* MS-CIFS (2.2.4.32.1) behavior. */
7473 return NT_STATUS_DOS(ERRDOS,
7474 ERRcancelviolation);
7475#else
7476 /* Windows behavior. */
7477 if (i != 0) {
7478 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7479 "cancel request\n"));
7480 continue;
7481 }
7482#endif
7483 }
7484
7485 if (lp_blocking_locks(SNUM(conn))) {
7486
7487 /* Schedule a message to ourselves to
7488 remove the blocking lock record and
7489 return the right error. */
7490
7491 blr = blocking_lock_cancel_smb1(fsp,
7492 e->smblctx,
7493 e->offset,
7494 e->count,
7495 WINDOWS_LOCK,
7496 type,
7497 NT_STATUS_FILE_LOCK_CONFLICT);
7498 if (blr == NULL) {
7499 return NT_STATUS_DOS(
7500 ERRDOS,
7501 ERRcancelviolation);
7502 }
7503 }
7504 /* Remove a matching pending lock. */
7505 status = do_lock_cancel(fsp,
7506 e->smblctx,
7507 e->count,
7508 e->offset,
7509 WINDOWS_LOCK,
7510 blr);
7511 } else {
7512 bool blocking_lock = timeout ? true : false;
7513 bool defer_lock = false;
7514 struct byte_range_lock *br_lck;
7515 uint64_t block_smblctx;
7516
7517 br_lck = do_lock(req->sconn->msg_ctx,
7518 fsp,
7519 e->smblctx,
7520 e->count,
7521 e->offset,
7522 e->brltype,
7523 WINDOWS_LOCK,
7524 blocking_lock,
7525 &status,
7526 &block_smblctx,
7527 NULL);
7528
7529 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7530 /* Windows internal resolution for blocking locks seems
7531 to be about 200ms... Don't wait for less than that. JRA. */
7532 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7533 timeout = lp_lock_spin_time();
7534 }
7535 defer_lock = true;
7536 }
7537
7538 /* If a lock sent with timeout of zero would fail, and
7539 * this lock has been requested multiple times,
7540 * according to brl_lock_failed() we convert this
7541 * request to a blocking lock with a timeout of between
7542 * 150 - 300 milliseconds.
7543 *
7544 * If lp_lock_spin_time() has been set to 0, we skip
7545 * this blocking retry and fail immediately.
7546 *
7547 * Replacement for do_lock_spin(). JRA. */
7548
7549 if (!req->sconn->using_smb2 &&
7550 br_lck && lp_blocking_locks(SNUM(conn)) &&
7551 lp_lock_spin_time() && !blocking_lock &&
7552 NT_STATUS_EQUAL((status),
7553 NT_STATUS_FILE_LOCK_CONFLICT))
7554 {
7555 defer_lock = true;
7556 timeout = lp_lock_spin_time();
7557 }
7558
7559 if (br_lck && defer_lock) {
7560 /*
7561 * A blocking lock was requested. Package up
7562 * this smb into a queued request and push it
7563 * onto the blocking lock queue.
7564 */
7565 if(push_blocking_lock_request(br_lck,
7566 req,
7567 fsp,
7568 timeout,
7569 i,
7570 e->smblctx,
7571 e->brltype,
7572 WINDOWS_LOCK,
7573 e->offset,
7574 e->count,
7575 block_smblctx)) {
7576 TALLOC_FREE(br_lck);
7577 *async = true;
7578 return NT_STATUS_OK;
7579 }
7580 }
7581
7582 TALLOC_FREE(br_lck);
7583 }
7584
7585 if (!NT_STATUS_IS_OK(status)) {
7586 break;
7587 }
7588 }
7589
7590 /* If any of the above locks failed, then we must unlock
7591 all of the previous locks (X/Open spec). */
7592
7593 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7594
7595 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7596 i = -1; /* we want to skip the for loop */
7597 }
7598
7599 /*
7600 * Ensure we don't do a remove on the lock that just failed,
7601 * as under POSIX rules, if we have a lock already there, we
7602 * will delete it (and we shouldn't) .....
7603 */
7604 for(i--; i >= 0; i--) {
7605 struct smbd_lock_element *e = &locks[i];
7606
7607 do_unlock(req->sconn->msg_ctx,
7608 fsp,
7609 e->smblctx,
7610 e->count,
7611 e->offset,
7612 WINDOWS_LOCK);
7613 }
7614 return status;
7615 }
7616
7617 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7618 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7619
7620 return NT_STATUS_OK;
7621}
7622
7623/****************************************************************************
7624 Reply to a lockingX request.
7625****************************************************************************/
7626
7627void reply_lockingX(struct smb_request *req)
7628{
7629 connection_struct *conn = req->conn;
7630 files_struct *fsp;
7631 unsigned char locktype;
7632 unsigned char oplocklevel;
7633 uint16 num_ulocks;
7634 uint16 num_locks;
7635 int32 lock_timeout;
7636 int i;
7637 const uint8_t *data;
7638 bool large_file_format;
7639 bool err;
7640 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7641 struct smbd_lock_element *ulocks;
7642 struct smbd_lock_element *locks;
7643 bool async = false;
7644
7645 START_PROFILE(SMBlockingX);
7646
7647 if (req->wct < 8) {
7648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7649 END_PROFILE(SMBlockingX);
7650 return;
7651 }
7652
7653 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7654 locktype = CVAL(req->vwv+3, 0);
7655 oplocklevel = CVAL(req->vwv+3, 1);
7656 num_ulocks = SVAL(req->vwv+6, 0);
7657 num_locks = SVAL(req->vwv+7, 0);
7658 lock_timeout = IVAL(req->vwv+4, 0);
7659 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7660
7661 if (!check_fsp(conn, req, fsp)) {
7662 END_PROFILE(SMBlockingX);
7663 return;
7664 }
7665
7666 data = req->buf;
7667
7668 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7669 /* we don't support these - and CANCEL_LOCK makes w2k
7670 and XP reboot so I don't really want to be
7671 compatible! (tridge) */
7672 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7673 END_PROFILE(SMBlockingX);
7674 return;
7675 }
7676
7677 /* Check if this is an oplock break on a file
7678 we have granted an oplock on.
7679 */
7680 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7681 /* Client can insist on breaking to none. */
7682 bool break_to_none = (oplocklevel == 0);
7683 bool result;
7684
7685 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7686 "for fnum = %d\n", (unsigned int)oplocklevel,
7687 fsp->fnum ));
7688
7689 /*
7690 * Make sure we have granted an exclusive or batch oplock on
7691 * this file.
7692 */
7693
7694 if (fsp->oplock_type == 0) {
7695
7696 /* The Samba4 nbench simulator doesn't understand
7697 the difference between break to level2 and break
7698 to none from level2 - it sends oplock break
7699 replies in both cases. Don't keep logging an error
7700 message here - just ignore it. JRA. */
7701
7702 DEBUG(5,("reply_lockingX: Error : oplock break from "
7703 "client for fnum = %d (oplock=%d) and no "
7704 "oplock granted on this file (%s).\n",
7705 fsp->fnum, fsp->oplock_type,
7706 fsp_str_dbg(fsp)));
7707
7708 /* if this is a pure oplock break request then don't
7709 * send a reply */
7710 if (num_locks == 0 && num_ulocks == 0) {
7711 END_PROFILE(SMBlockingX);
7712 return;
7713 } else {
7714 END_PROFILE(SMBlockingX);
7715 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7716 return;
7717 }
7718 }
7719
7720 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7721 (break_to_none)) {
7722 result = remove_oplock(fsp);
7723 } else {
7724 result = downgrade_oplock(fsp);
7725 }
7726
7727 if (!result) {
7728 DEBUG(0, ("reply_lockingX: error in removing "
7729 "oplock on file %s\n", fsp_str_dbg(fsp)));
7730 /* Hmmm. Is this panic justified? */
7731 smb_panic("internal tdb error");
7732 }
7733
7734 reply_to_oplock_break_requests(fsp);
7735
7736 /* if this is a pure oplock break request then don't send a
7737 * reply */
7738 if (num_locks == 0 && num_ulocks == 0) {
7739 /* Sanity check - ensure a pure oplock break is not a
7740 chained request. */
7741 if(CVAL(req->vwv+0, 0) != 0xff)
7742 DEBUG(0,("reply_lockingX: Error : pure oplock "
7743 "break is a chained %d request !\n",
7744 (unsigned int)CVAL(req->vwv+0, 0)));
7745 END_PROFILE(SMBlockingX);
7746 return;
7747 }
7748 }
7749
7750 if (req->buflen <
7751 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7752 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7753 END_PROFILE(SMBlockingX);
7754 return;
7755 }
7756
7757 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7758 if (ulocks == NULL) {
7759 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760 END_PROFILE(SMBlockingX);
7761 return;
7762 }
7763
7764 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7765 if (locks == NULL) {
7766 reply_nterror(req, NT_STATUS_NO_MEMORY);
7767 END_PROFILE(SMBlockingX);
7768 return;
7769 }
7770
7771 /* Data now points at the beginning of the list
7772 of smb_unlkrng structs */
7773 for(i = 0; i < (int)num_ulocks; i++) {
7774 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7775 ulocks[i].count = get_lock_count(data, i, large_file_format);
7776 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7777 ulocks[i].brltype = UNLOCK_LOCK;
7778
7779 /*
7780 * There is no error code marked "stupid client bug".... :-).
7781 */
7782 if(err) {
7783 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7784 END_PROFILE(SMBlockingX);
7785 return;
7786 }
7787 }
7788
7789 /* Now do any requested locks */
7790 data += ((large_file_format ? 20 : 10)*num_ulocks);
7791
7792 /* Data now points at the beginning of the list
7793 of smb_lkrng structs */
7794
7795 for(i = 0; i < (int)num_locks; i++) {
7796 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7797 locks[i].count = get_lock_count(data, i, large_file_format);
7798 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7799
7800 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7801 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7802 locks[i].brltype = PENDING_READ_LOCK;
7803 } else {
7804 locks[i].brltype = READ_LOCK;
7805 }
7806 } else {
7807 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7808 locks[i].brltype = PENDING_WRITE_LOCK;
7809 } else {
7810 locks[i].brltype = WRITE_LOCK;
7811 }
7812 }
7813
7814 /*
7815 * There is no error code marked "stupid client bug".... :-).
7816 */
7817 if(err) {
7818 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7819 END_PROFILE(SMBlockingX);
7820 return;
7821 }
7822 }
7823
7824 status = smbd_do_locking(req, fsp,
7825 locktype, lock_timeout,
7826 num_ulocks, ulocks,
7827 num_locks, locks,
7828 &async);
7829 if (!NT_STATUS_IS_OK(status)) {
7830 END_PROFILE(SMBlockingX);
7831 reply_nterror(req, status);
7832 return;
7833 }
7834 if (async) {
7835 END_PROFILE(SMBlockingX);
7836 return;
7837 }
7838
7839 reply_outbuf(req, 2, 0);
7840
7841 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7842 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7843
7844 END_PROFILE(SMBlockingX);
7845 chain_reply(req);
7846}
7847
7848#undef DBGC_CLASS
7849#define DBGC_CLASS DBGC_ALL
7850
7851/****************************************************************************
7852 Reply to a SMBreadbmpx (read block multiplex) request.
7853 Always reply with an error, if someone has a platform really needs this,
7854 please contact vl@samba.org
7855****************************************************************************/
7856
7857void reply_readbmpx(struct smb_request *req)
7858{
7859 START_PROFILE(SMBreadBmpx);
7860 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7861 END_PROFILE(SMBreadBmpx);
7862 return;
7863}
7864
7865/****************************************************************************
7866 Reply to a SMBreadbs (read block multiplex secondary) request.
7867 Always reply with an error, if someone has a platform really needs this,
7868 please contact vl@samba.org
7869****************************************************************************/
7870
7871void reply_readbs(struct smb_request *req)
7872{
7873 START_PROFILE(SMBreadBs);
7874 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7875 END_PROFILE(SMBreadBs);
7876 return;
7877}
7878
7879/****************************************************************************
7880 Reply to a SMBsetattrE.
7881****************************************************************************/
7882
7883void reply_setattrE(struct smb_request *req)
7884{
7885 connection_struct *conn = req->conn;
7886 struct smb_file_time ft;
7887 files_struct *fsp;
7888 NTSTATUS status;
7889
7890 START_PROFILE(SMBsetattrE);
7891 ZERO_STRUCT(ft);
7892
7893 if (req->wct < 7) {
7894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7895 goto out;
7896 }
7897
7898 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7899
7900 if(!fsp || (fsp->conn != conn)) {
7901 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7902 goto out;
7903 }
7904
7905 /*
7906 * Convert the DOS times into unix times.
7907 */
7908
7909 ft.atime = convert_time_t_to_timespec(
7910 srv_make_unix_date2(req->vwv+3));
7911 ft.mtime = convert_time_t_to_timespec(
7912 srv_make_unix_date2(req->vwv+5));
7913 ft.create_time = convert_time_t_to_timespec(
7914 srv_make_unix_date2(req->vwv+1));
7915
7916 reply_outbuf(req, 0, 0);
7917
7918 /*
7919 * Patch from Ray Frush <frush@engr.colostate.edu>
7920 * Sometimes times are sent as zero - ignore them.
7921 */
7922
7923 /* Ensure we have a valid stat struct for the source. */
7924 status = vfs_stat_fsp(fsp);
7925 if (!NT_STATUS_IS_OK(status)) {
7926 reply_nterror(req, status);
7927 goto out;
7928 }
7929
7930 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7931 if (!NT_STATUS_IS_OK(status)) {
7932 reply_nterror(req, status);
7933 goto out;
7934 }
7935
7936 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7937 " createtime=%u\n",
7938 fsp->fnum,
7939 (unsigned int)ft.atime.tv_sec,
7940 (unsigned int)ft.mtime.tv_sec,
7941 (unsigned int)ft.create_time.tv_sec
7942 ));
7943 out:
7944 END_PROFILE(SMBsetattrE);
7945 return;
7946}
7947
7948
7949/* Back from the dead for OS/2..... JRA. */
7950
7951/****************************************************************************
7952 Reply to a SMBwritebmpx (write block multiplex primary) request.
7953 Always reply with an error, if someone has a platform really needs this,
7954 please contact vl@samba.org
7955****************************************************************************/
7956
7957void reply_writebmpx(struct smb_request *req)
7958{
7959 START_PROFILE(SMBwriteBmpx);
7960 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7961 END_PROFILE(SMBwriteBmpx);
7962 return;
7963}
7964
7965/****************************************************************************
7966 Reply to a SMBwritebs (write block multiplex secondary) request.
7967 Always reply with an error, if someone has a platform really needs this,
7968 please contact vl@samba.org
7969****************************************************************************/
7970
7971void reply_writebs(struct smb_request *req)
7972{
7973 START_PROFILE(SMBwriteBs);
7974 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7975 END_PROFILE(SMBwriteBs);
7976 return;
7977}
7978
7979/****************************************************************************
7980 Reply to a SMBgetattrE.
7981****************************************************************************/
7982
7983void reply_getattrE(struct smb_request *req)
7984{
7985 connection_struct *conn = req->conn;
7986 int mode;
7987 files_struct *fsp;
7988 struct timespec create_ts;
7989
7990 START_PROFILE(SMBgetattrE);
7991
7992 if (req->wct < 1) {
7993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7994 END_PROFILE(SMBgetattrE);
7995 return;
7996 }
7997
7998 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7999
8000 if(!fsp || (fsp->conn != conn)) {
8001 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8002 END_PROFILE(SMBgetattrE);
8003 return;
8004 }
8005
8006 /* Do an fstat on this file */
8007 if(fsp_stat(fsp)) {
8008 reply_nterror(req, map_nt_error_from_unix(errno));
8009 END_PROFILE(SMBgetattrE);
8010 return;
8011 }
8012
8013 mode = dos_mode(conn, fsp->fsp_name);
8014
8015 /*
8016 * Convert the times into dos times. Set create
8017 * date to be last modify date as UNIX doesn't save
8018 * this.
8019 */
8020
8021 reply_outbuf(req, 11, 0);
8022
8023 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8024 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8025 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8026 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8027 /* Should we check pending modtime here ? JRA */
8028 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8029 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8030
8031 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8032 SIVAL(req->outbuf, smb_vwv6, 0);
8033 SIVAL(req->outbuf, smb_vwv8, 0);
8034 } else {
8035 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8036 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8037 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8038 }
8039 SSVAL(req->outbuf,smb_vwv10, mode);
8040
8041 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8042
8043 END_PROFILE(SMBgetattrE);
8044 return;
8045}
Note: See TracBrowser for help on using the repository browser.