source: vendor/3.6.0/source3/smbd/reply.c

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

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