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

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

Samba Server: updated trunk to 3.6.0

File size: 207.3 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/* borrowed from 3.3 source patch by Apple */
5954#ifdef __OS2__
5955 bool check_dest_exist = False;
5956#else
5957 bool check_dest_exist = True;
5958#endif
5959
5960 status = check_name(conn, smb_fname_dst_in->base_name);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 return status;
5963 }
5964
5965 /* Make a copy of the dst smb_fname structs */
5966
5967 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 goto out;
5970 }
5971
5972 /*
5973 * Check for special case with case preserving and not
5974 * case sensitive. If the old last component differs from the original
5975 * last component only by case, then we should allow
5976 * the rename (user is trying to change the case of the
5977 * filename).
5978 */
5979 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5980 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5981 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5982 char *last_slash;
5983 char *fname_dst_lcomp_base_mod = NULL;
5984 struct smb_filename *smb_fname_orig_lcomp = NULL;
5985
5986 /*
5987 * Get the last component of the destination name.
5988 */
5989 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5990 if (last_slash) {
5991 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5992 } else {
5993 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5994 }
5995 if (!fname_dst_lcomp_base_mod) {
5996 status = NT_STATUS_NO_MEMORY;
5997 goto out;
5998 }
5999
6000 /*
6001 * Create an smb_filename struct using the original last
6002 * component of the destination.
6003 */
6004 status = create_synthetic_smb_fname_split(ctx,
6005 smb_fname_dst->original_lcomp, NULL,
6006 &smb_fname_orig_lcomp);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 TALLOC_FREE(fname_dst_lcomp_base_mod);
6009 goto out;
6010 }
6011
6012 /* If the base names only differ by case, use original. */
6013 if(!strcsequal(fname_dst_lcomp_base_mod,
6014 smb_fname_orig_lcomp->base_name)) {
6015 char *tmp;
6016 /*
6017 * Replace the modified last component with the
6018 * original.
6019 */
6020 if (last_slash) {
6021 *last_slash = '\0'; /* Truncate at the '/' */
6022 tmp = talloc_asprintf(smb_fname_dst,
6023 "%s/%s",
6024 smb_fname_dst->base_name,
6025 smb_fname_orig_lcomp->base_name);
6026 } else {
6027 tmp = talloc_asprintf(smb_fname_dst,
6028 "%s",
6029 smb_fname_orig_lcomp->base_name);
6030 }
6031 if (tmp == NULL) {
6032 status = NT_STATUS_NO_MEMORY;
6033 TALLOC_FREE(fname_dst_lcomp_base_mod);
6034 TALLOC_FREE(smb_fname_orig_lcomp);
6035 goto out;
6036 }
6037 TALLOC_FREE(smb_fname_dst->base_name);
6038 smb_fname_dst->base_name = tmp;
6039 }
6040
6041 /* If the stream_names only differ by case, use original. */
6042 if(!strcsequal(smb_fname_dst->stream_name,
6043 smb_fname_orig_lcomp->stream_name)) {
6044 char *tmp = NULL;
6045 /* Use the original stream. */
6046 tmp = talloc_strdup(smb_fname_dst,
6047 smb_fname_orig_lcomp->stream_name);
6048 if (tmp == NULL) {
6049 status = NT_STATUS_NO_MEMORY;
6050 TALLOC_FREE(fname_dst_lcomp_base_mod);
6051 TALLOC_FREE(smb_fname_orig_lcomp);
6052 goto out;
6053 }
6054 TALLOC_FREE(smb_fname_dst->stream_name);
6055 smb_fname_dst->stream_name = tmp;
6056 }
6057 TALLOC_FREE(fname_dst_lcomp_base_mod);
6058 TALLOC_FREE(smb_fname_orig_lcomp);
6059 }
6060
6061 /*
6062 * If the src and dest names are identical - including case,
6063 * don't do the rename, just return success.
6064 */
6065
6066 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6067 strcsequal(fsp->fsp_name->stream_name,
6068 smb_fname_dst->stream_name)) {
6069 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6070 "- returning success\n",
6071 smb_fname_str_dbg(smb_fname_dst)));
6072 status = NT_STATUS_OK;
6073 goto out;
6074 }
6075
6076 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6077 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6078
6079 /* Return the correct error code if both names aren't streams. */
6080 if (!old_is_stream && new_is_stream) {
6081 status = NT_STATUS_OBJECT_NAME_INVALID;
6082 goto out;
6083 }
6084
6085 if (old_is_stream && !new_is_stream) {
6086 status = NT_STATUS_INVALID_PARAMETER;
6087 goto out;
6088 }
6089
6090 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6091
6092 if(check_dest_exist && !replace_if_exists && dst_exists) {
6093 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6094 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6095 smb_fname_str_dbg(smb_fname_dst)));
6096 status = NT_STATUS_OBJECT_NAME_COLLISION;
6097 goto out;
6098 }
6099
6100 if (dst_exists) {
6101 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6102 &smb_fname_dst->st);
6103 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6104 fileid);
6105 /* The file can be open when renaming a stream */
6106 if (dst_fsp && !new_is_stream) {
6107 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6108 status = NT_STATUS_ACCESS_DENIED;
6109 goto out;
6110 }
6111 }
6112
6113 /* Ensure we have a valid stat struct for the source. */
6114 status = vfs_stat_fsp(fsp);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 goto out;
6117 }
6118
6119 status = can_rename(conn, fsp, attrs);
6120
6121 if (!NT_STATUS_IS_OK(status)) {
6122 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6123 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6124 smb_fname_str_dbg(smb_fname_dst)));
6125 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6126 status = NT_STATUS_ACCESS_DENIED;
6127 goto out;
6128 }
6129
6130 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6131 status = NT_STATUS_ACCESS_DENIED;
6132 }
6133
6134 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6135 NULL);
6136
6137 /*
6138 * We have the file open ourselves, so not being able to get the
6139 * corresponding share mode lock is a fatal error.
6140 */
6141
6142 SMB_ASSERT(lck != NULL);
6143
6144 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6145 uint32 create_options = fsp->fh->private_options;
6146
6147 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6148 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6149 smb_fname_str_dbg(smb_fname_dst)));
6150
6151 if (!lp_posix_pathnames() &&
6152 (lp_map_archive(SNUM(conn)) ||
6153 lp_store_dos_attributes(SNUM(conn)))) {
6154 /* We must set the archive bit on the newly
6155 renamed file. */
6156 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6157 uint32_t old_dosmode = dos_mode(conn,
6158 smb_fname_dst);
6159 file_set_dosmode(conn,
6160 smb_fname_dst,
6161 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6162 NULL,
6163 true);
6164 }
6165 }
6166
6167 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6168 smb_fname_dst);
6169
6170 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6171
6172 /*
6173 * A rename acts as a new file create w.r.t. allowing an initial delete
6174 * on close, probably because in Windows there is a new handle to the
6175 * new file. If initial delete on close was requested but not
6176 * originally set, we need to set it here. This is probably not 100% correct,
6177 * but will work for the CIFSFS client which in non-posix mode
6178 * depends on these semantics. JRA.
6179 */
6180
6181 if (create_options & FILE_DELETE_ON_CLOSE) {
6182 status = can_set_delete_on_close(fsp, 0);
6183
6184 if (NT_STATUS_IS_OK(status)) {
6185 /* Note that here we set the *inital* delete on close flag,
6186 * not the regular one. The magic gets handled in close. */
6187 fsp->initial_delete_on_close = True;
6188 }
6189 }
6190 TALLOC_FREE(lck);
6191 status = NT_STATUS_OK;
6192 goto out;
6193 }
6194
6195 TALLOC_FREE(lck);
6196
6197 if (errno == ENOTDIR || errno == EISDIR) {
6198 status = NT_STATUS_OBJECT_NAME_COLLISION;
6199 } else {
6200 status = map_nt_error_from_unix(errno);
6201 }
6202
6203 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6204 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6205 smb_fname_str_dbg(smb_fname_dst)));
6206
6207 out:
6208 TALLOC_FREE(smb_fname_dst);
6209
6210 return status;
6211}
6212
6213/****************************************************************************
6214 The guts of the rename command, split out so it may be called by the NT SMB
6215 code.
6216****************************************************************************/
6217
6218NTSTATUS rename_internals(TALLOC_CTX *ctx,
6219 connection_struct *conn,
6220 struct smb_request *req,
6221 struct smb_filename *smb_fname_src,
6222 struct smb_filename *smb_fname_dst,
6223 uint32 attrs,
6224 bool replace_if_exists,
6225 bool src_has_wild,
6226 bool dest_has_wild,
6227 uint32_t access_mask)
6228{
6229 char *fname_src_dir = NULL;
6230 char *fname_src_mask = NULL;
6231 int count=0;
6232 NTSTATUS status = NT_STATUS_OK;
6233 struct smb_Dir *dir_hnd = NULL;
6234 const char *dname = NULL;
6235 char *talloced = NULL;
6236 long offset = 0;
6237 int create_options = 0;
6238 bool posix_pathnames = lp_posix_pathnames();
6239
6240 /*
6241 * Split the old name into directory and last component
6242 * strings. Note that unix_convert may have stripped off a
6243 * leading ./ from both name and newname if the rename is
6244 * at the root of the share. We need to make sure either both
6245 * name and newname contain a / character or neither of them do
6246 * as this is checked in resolve_wildcards().
6247 */
6248
6249 /* Split up the directory from the filename/mask. */
6250 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6251 &fname_src_dir, &fname_src_mask);
6252 if (!NT_STATUS_IS_OK(status)) {
6253 status = NT_STATUS_NO_MEMORY;
6254 goto out;
6255 }
6256
6257 /*
6258 * We should only check the mangled cache
6259 * here if unix_convert failed. This means
6260 * that the path in 'mask' doesn't exist
6261 * on the file system and so we need to look
6262 * for a possible mangle. This patch from
6263 * Tine Smukavec <valentin.smukavec@hermes.si>.
6264 */
6265
6266 if (!VALID_STAT(smb_fname_src->st) &&
6267 mangle_is_mangled(fname_src_mask, conn->params)) {
6268 char *new_mask = NULL;
6269 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6270 conn->params);
6271 if (new_mask) {
6272 TALLOC_FREE(fname_src_mask);
6273 fname_src_mask = new_mask;
6274 }
6275 }
6276
6277 if (!src_has_wild) {
6278 files_struct *fsp;
6279
6280 /*
6281 * Only one file needs to be renamed. Append the mask back
6282 * onto the directory.
6283 */
6284 TALLOC_FREE(smb_fname_src->base_name);
6285 if (ISDOT(fname_src_dir)) {
6286 /* Ensure we use canonical names on open. */
6287 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6288 "%s",
6289 fname_src_mask);
6290 } else {
6291 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6292 "%s/%s",
6293 fname_src_dir,
6294 fname_src_mask);
6295 }
6296 if (!smb_fname_src->base_name) {
6297 status = NT_STATUS_NO_MEMORY;
6298 goto out;
6299 }
6300
6301 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6302 "case_preserve = %d, short case preserve = %d, "
6303 "directory = %s, newname = %s, "
6304 "last_component_dest = %s\n",
6305 conn->case_sensitive, conn->case_preserve,
6306 conn->short_case_preserve,
6307 smb_fname_str_dbg(smb_fname_src),
6308 smb_fname_str_dbg(smb_fname_dst),
6309 smb_fname_dst->original_lcomp));
6310
6311 /* The dest name still may have wildcards. */
6312 if (dest_has_wild) {
6313 char *fname_dst_mod = NULL;
6314 if (!resolve_wildcards(smb_fname_dst,
6315 smb_fname_src->base_name,
6316 smb_fname_dst->base_name,
6317 &fname_dst_mod)) {
6318 DEBUG(6, ("rename_internals: resolve_wildcards "
6319 "%s %s failed\n",
6320 smb_fname_src->base_name,
6321 smb_fname_dst->base_name));
6322 status = NT_STATUS_NO_MEMORY;
6323 goto out;
6324 }
6325 TALLOC_FREE(smb_fname_dst->base_name);
6326 smb_fname_dst->base_name = fname_dst_mod;
6327 }
6328
6329 ZERO_STRUCT(smb_fname_src->st);
6330 if (posix_pathnames) {
6331 SMB_VFS_LSTAT(conn, smb_fname_src);
6332 } else {
6333 SMB_VFS_STAT(conn, smb_fname_src);
6334 }
6335
6336 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6337 create_options |= FILE_DIRECTORY_FILE;
6338 }
6339
6340 status = SMB_VFS_CREATE_FILE(
6341 conn, /* conn */
6342 req, /* req */
6343 0, /* root_dir_fid */
6344 smb_fname_src, /* fname */
6345 access_mask, /* access_mask */
6346 (FILE_SHARE_READ | /* share_access */
6347 FILE_SHARE_WRITE),
6348 FILE_OPEN, /* create_disposition*/
6349 create_options, /* create_options */
6350 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6351 0, /* oplock_request */
6352 0, /* allocation_size */
6353 0, /* private_flags */
6354 NULL, /* sd */
6355 NULL, /* ea_list */
6356 &fsp, /* result */
6357 NULL); /* pinfo */
6358
6359 if (!NT_STATUS_IS_OK(status)) {
6360 DEBUG(3, ("Could not open rename source %s: %s\n",
6361 smb_fname_str_dbg(smb_fname_src),
6362 nt_errstr(status)));
6363 goto out;
6364 }
6365
6366 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6367 attrs, replace_if_exists);
6368
6369 close_file(req, fsp, NORMAL_CLOSE);
6370
6371 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6372 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6373 smb_fname_str_dbg(smb_fname_dst)));
6374
6375 goto out;
6376 }
6377
6378 /*
6379 * Wildcards - process each file that matches.
6380 */
6381 if (strequal(fname_src_mask, "????????.???")) {
6382 TALLOC_FREE(fname_src_mask);
6383 fname_src_mask = talloc_strdup(ctx, "*");
6384 if (!fname_src_mask) {
6385 status = NT_STATUS_NO_MEMORY;
6386 goto out;
6387 }
6388 }
6389
6390 status = check_name(conn, fname_src_dir);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 goto out;
6393 }
6394
6395 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6396 attrs);
6397 if (dir_hnd == NULL) {
6398 status = map_nt_error_from_unix(errno);
6399 goto out;
6400 }
6401
6402 status = NT_STATUS_NO_SUCH_FILE;
6403 /*
6404 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6405 * - gentest fix. JRA
6406 */
6407
6408 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6409 &talloced))) {
6410 files_struct *fsp = NULL;
6411 char *destname = NULL;
6412 bool sysdir_entry = False;
6413
6414 /* Quick check for "." and ".." */
6415 if (ISDOT(dname) || ISDOTDOT(dname)) {
6416 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6417 sysdir_entry = True;
6418 } else {
6419 TALLOC_FREE(talloced);
6420 continue;
6421 }
6422 }
6423
6424 if (!is_visible_file(conn, fname_src_dir, dname,
6425 &smb_fname_src->st, false)) {
6426 TALLOC_FREE(talloced);
6427 continue;
6428 }
6429
6430 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6431 TALLOC_FREE(talloced);
6432 continue;
6433 }
6434
6435 if (sysdir_entry) {
6436 status = NT_STATUS_OBJECT_NAME_INVALID;
6437 break;
6438 }
6439
6440 TALLOC_FREE(smb_fname_src->base_name);
6441 if (ISDOT(fname_src_dir)) {
6442 /* Ensure we use canonical names on open. */
6443 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6444 "%s",
6445 dname);
6446 } else {
6447 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6448 "%s/%s",
6449 fname_src_dir,
6450 dname);
6451 }
6452 if (!smb_fname_src->base_name) {
6453 status = NT_STATUS_NO_MEMORY;
6454 goto out;
6455 }
6456
6457 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6458 smb_fname_dst->base_name,
6459 &destname)) {
6460 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6461 smb_fname_src->base_name, destname));
6462 TALLOC_FREE(talloced);
6463 continue;
6464 }
6465 if (!destname) {
6466 status = NT_STATUS_NO_MEMORY;
6467 goto out;
6468 }
6469
6470 TALLOC_FREE(smb_fname_dst->base_name);
6471 smb_fname_dst->base_name = destname;
6472
6473 ZERO_STRUCT(smb_fname_src->st);
6474 if (posix_pathnames) {
6475 SMB_VFS_LSTAT(conn, smb_fname_src);
6476 } else {
6477 SMB_VFS_STAT(conn, smb_fname_src);
6478 }
6479
6480 create_options = 0;
6481
6482 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6483 create_options |= FILE_DIRECTORY_FILE;
6484 }
6485
6486 status = SMB_VFS_CREATE_FILE(
6487 conn, /* conn */
6488 req, /* req */
6489 0, /* root_dir_fid */
6490 smb_fname_src, /* fname */
6491 access_mask, /* access_mask */
6492 (FILE_SHARE_READ | /* share_access */
6493 FILE_SHARE_WRITE),
6494 FILE_OPEN, /* create_disposition*/
6495 create_options, /* create_options */
6496 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6497 0, /* oplock_request */
6498 0, /* allocation_size */
6499 0, /* private_flags */
6500 NULL, /* sd */
6501 NULL, /* ea_list */
6502 &fsp, /* result */
6503 NULL); /* pinfo */
6504
6505 if (!NT_STATUS_IS_OK(status)) {
6506 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6507 "returned %s rename %s -> %s\n",
6508 nt_errstr(status),
6509 smb_fname_str_dbg(smb_fname_src),
6510 smb_fname_str_dbg(smb_fname_dst)));
6511 break;
6512 }
6513
6514 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6515 dname);
6516 if (!smb_fname_dst->original_lcomp) {
6517 status = NT_STATUS_NO_MEMORY;
6518 goto out;
6519 }
6520
6521 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6522 attrs, replace_if_exists);
6523
6524 close_file(req, fsp, NORMAL_CLOSE);
6525
6526 if (!NT_STATUS_IS_OK(status)) {
6527 DEBUG(3, ("rename_internals_fsp returned %s for "
6528 "rename %s -> %s\n", nt_errstr(status),
6529 smb_fname_str_dbg(smb_fname_src),
6530 smb_fname_str_dbg(smb_fname_dst)));
6531 break;
6532 }
6533
6534 count++;
6535
6536 DEBUG(3,("rename_internals: doing rename on %s -> "
6537 "%s\n", smb_fname_str_dbg(smb_fname_src),
6538 smb_fname_str_dbg(smb_fname_src)));
6539 TALLOC_FREE(talloced);
6540 }
6541 TALLOC_FREE(dir_hnd);
6542
6543 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6544 status = map_nt_error_from_unix(errno);
6545 }
6546
6547 out:
6548 TALLOC_FREE(talloced);
6549 TALLOC_FREE(fname_src_dir);
6550 TALLOC_FREE(fname_src_mask);
6551 return status;
6552}
6553
6554/****************************************************************************
6555 Reply to a mv.
6556****************************************************************************/
6557
6558void reply_mv(struct smb_request *req)
6559{
6560 connection_struct *conn = req->conn;
6561 char *name = NULL;
6562 char *newname = NULL;
6563 const char *p;
6564 uint32 attrs;
6565 NTSTATUS status;
6566 bool src_has_wcard = False;
6567 bool dest_has_wcard = False;
6568 TALLOC_CTX *ctx = talloc_tos();
6569 struct smb_filename *smb_fname_src = NULL;
6570 struct smb_filename *smb_fname_dst = NULL;
6571 bool stream_rename = false;
6572
6573 START_PROFILE(SMBmv);
6574
6575 if (req->wct < 1) {
6576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6577 goto out;
6578 }
6579
6580 attrs = SVAL(req->vwv+0, 0);
6581
6582 p = (const char *)req->buf + 1;
6583 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6584 &status, &src_has_wcard);
6585 if (!NT_STATUS_IS_OK(status)) {
6586 reply_nterror(req, status);
6587 goto out;
6588 }
6589 p++;
6590 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6591 &status, &dest_has_wcard);
6592 if (!NT_STATUS_IS_OK(status)) {
6593 reply_nterror(req, status);
6594 goto out;
6595 }
6596
6597 if (!lp_posix_pathnames()) {
6598 /* The newname must begin with a ':' if the
6599 name contains a ':'. */
6600 if (strchr_m(name, ':')) {
6601 if (newname[0] != ':') {
6602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6603 goto out;
6604 }
6605 stream_rename = true;
6606 }
6607 }
6608
6609 status = filename_convert(ctx,
6610 conn,
6611 req->flags2 & FLAGS2_DFS_PATHNAMES,
6612 name,
6613 UCF_COND_ALLOW_WCARD_LCOMP,
6614 &src_has_wcard,
6615 &smb_fname_src);
6616
6617 if (!NT_STATUS_IS_OK(status)) {
6618 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6619 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6620 ERRSRV, ERRbadpath);
6621 goto out;
6622 }
6623 reply_nterror(req, status);
6624 goto out;
6625 }
6626
6627 status = filename_convert(ctx,
6628 conn,
6629 req->flags2 & FLAGS2_DFS_PATHNAMES,
6630 newname,
6631 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6632 &dest_has_wcard,
6633 &smb_fname_dst);
6634
6635 if (!NT_STATUS_IS_OK(status)) {
6636 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6637 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6638 ERRSRV, ERRbadpath);
6639 goto out;
6640 }
6641 reply_nterror(req, status);
6642 goto out;
6643 }
6644
6645 if (stream_rename) {
6646 /* smb_fname_dst->base_name must be the same as
6647 smb_fname_src->base_name. */
6648 TALLOC_FREE(smb_fname_dst->base_name);
6649 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6650 smb_fname_src->base_name);
6651 if (!smb_fname_dst->base_name) {
6652 reply_nterror(req, NT_STATUS_NO_MEMORY);
6653 goto out;
6654 }
6655 }
6656
6657 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6658 smb_fname_str_dbg(smb_fname_dst)));
6659
6660 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6661 attrs, False, src_has_wcard, dest_has_wcard,
6662 DELETE_ACCESS);
6663 if (!NT_STATUS_IS_OK(status)) {
6664 if (open_was_deferred(req->mid)) {
6665 /* We have re-scheduled this call. */
6666 goto out;
6667 }
6668 reply_nterror(req, status);
6669 goto out;
6670 }
6671
6672 reply_outbuf(req, 0, 0);
6673 out:
6674 TALLOC_FREE(smb_fname_src);
6675 TALLOC_FREE(smb_fname_dst);
6676 END_PROFILE(SMBmv);
6677 return;
6678}
6679
6680/*******************************************************************
6681 Copy a file as part of a reply_copy.
6682******************************************************************/
6683
6684/*
6685 * TODO: check error codes on all callers
6686 */
6687
6688NTSTATUS copy_file(TALLOC_CTX *ctx,
6689 connection_struct *conn,
6690 struct smb_filename *smb_fname_src,
6691 struct smb_filename *smb_fname_dst,
6692 int ofun,
6693 int count,
6694 bool target_is_directory)
6695{
6696 struct smb_filename *smb_fname_dst_tmp = NULL;
6697 SMB_OFF_T ret=-1;
6698 files_struct *fsp1,*fsp2;
6699 uint32 dosattrs;
6700 uint32 new_create_disposition;
6701 NTSTATUS status;
6702
6703
6704 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6705 if (!NT_STATUS_IS_OK(status)) {
6706 return status;
6707 }
6708
6709 /*
6710 * If the target is a directory, extract the last component from the
6711 * src filename and append it to the dst filename
6712 */
6713 if (target_is_directory) {
6714 const char *p;
6715
6716 /* dest/target can't be a stream if it's a directory. */
6717 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6718
6719 p = strrchr_m(smb_fname_src->base_name,'/');
6720 if (p) {
6721 p++;
6722 } else {
6723 p = smb_fname_src->base_name;
6724 }
6725 smb_fname_dst_tmp->base_name =
6726 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6727 p);
6728 if (!smb_fname_dst_tmp->base_name) {
6729 status = NT_STATUS_NO_MEMORY;
6730 goto out;
6731 }
6732 }
6733
6734 status = vfs_file_exist(conn, smb_fname_src);
6735 if (!NT_STATUS_IS_OK(status)) {
6736 goto out;
6737 }
6738
6739 if (!target_is_directory && count) {
6740 new_create_disposition = FILE_OPEN;
6741 } else {
6742 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6743 NULL, NULL,
6744 &new_create_disposition,
6745 NULL,
6746 NULL)) {
6747 status = NT_STATUS_INVALID_PARAMETER;
6748 goto out;
6749 }
6750 }
6751
6752 /* Open the src file for reading. */
6753 status = SMB_VFS_CREATE_FILE(
6754 conn, /* conn */
6755 NULL, /* req */
6756 0, /* root_dir_fid */
6757 smb_fname_src, /* fname */
6758 FILE_GENERIC_READ, /* access_mask */
6759 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6760 FILE_OPEN, /* create_disposition*/
6761 0, /* create_options */
6762 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6763 INTERNAL_OPEN_ONLY, /* oplock_request */
6764 0, /* allocation_size */
6765 0, /* private_flags */
6766 NULL, /* sd */
6767 NULL, /* ea_list */
6768 &fsp1, /* result */
6769 NULL); /* psbuf */
6770
6771 if (!NT_STATUS_IS_OK(status)) {
6772 goto out;
6773 }
6774
6775 dosattrs = dos_mode(conn, smb_fname_src);
6776
6777 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6778 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6779 }
6780
6781 /* Open the dst file for writing. */
6782 status = SMB_VFS_CREATE_FILE(
6783 conn, /* conn */
6784 NULL, /* req */
6785 0, /* root_dir_fid */
6786 smb_fname_dst, /* fname */
6787 FILE_GENERIC_WRITE, /* access_mask */
6788 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6789 new_create_disposition, /* create_disposition*/
6790 0, /* create_options */
6791 dosattrs, /* file_attributes */
6792 INTERNAL_OPEN_ONLY, /* oplock_request */
6793 0, /* allocation_size */
6794 0, /* private_flags */
6795 NULL, /* sd */
6796 NULL, /* ea_list */
6797 &fsp2, /* result */
6798 NULL); /* psbuf */
6799
6800 if (!NT_STATUS_IS_OK(status)) {
6801 close_file(NULL, fsp1, ERROR_CLOSE);
6802 goto out;
6803 }
6804
6805 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6806 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6807 if (ret == -1) {
6808 DEBUG(0, ("error - vfs lseek returned error %s\n",
6809 strerror(errno)));
6810 status = map_nt_error_from_unix(errno);
6811 close_file(NULL, fsp1, ERROR_CLOSE);
6812 close_file(NULL, fsp2, ERROR_CLOSE);
6813 goto out;
6814 }
6815 }
6816
6817 /* Do the actual copy. */
6818 if (smb_fname_src->st.st_ex_size) {
6819 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6820 } else {
6821 ret = 0;
6822 }
6823
6824 close_file(NULL, fsp1, NORMAL_CLOSE);
6825
6826 /* Ensure the modtime is set correctly on the destination file. */
6827 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6828
6829 /*
6830 * As we are opening fsp1 read-only we only expect
6831 * an error on close on fsp2 if we are out of space.
6832 * Thus we don't look at the error return from the
6833 * close of fsp1.
6834 */
6835 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6836
6837 if (!NT_STATUS_IS_OK(status)) {
6838 goto out;
6839 }
6840
6841 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6842 status = NT_STATUS_DISK_FULL;
6843 goto out;
6844 }
6845
6846 status = NT_STATUS_OK;
6847
6848 out:
6849 TALLOC_FREE(smb_fname_dst_tmp);
6850 return status;
6851}
6852
6853/****************************************************************************
6854 Reply to a file copy.
6855****************************************************************************/
6856
6857void reply_copy(struct smb_request *req)
6858{
6859 connection_struct *conn = req->conn;
6860 struct smb_filename *smb_fname_src = NULL;
6861 struct smb_filename *smb_fname_dst = NULL;
6862 char *fname_src = NULL;
6863 char *fname_dst = NULL;
6864 char *fname_src_mask = NULL;
6865 char *fname_src_dir = NULL;
6866 const char *p;
6867 int count=0;
6868 int error = ERRnoaccess;
6869 int tid2;
6870 int ofun;
6871 int flags;
6872 bool target_is_directory=False;
6873 bool source_has_wild = False;
6874 bool dest_has_wild = False;
6875 NTSTATUS status;
6876 TALLOC_CTX *ctx = talloc_tos();
6877
6878 START_PROFILE(SMBcopy);
6879
6880 if (req->wct < 3) {
6881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6882 goto out;
6883 }
6884
6885 tid2 = SVAL(req->vwv+0, 0);
6886 ofun = SVAL(req->vwv+1, 0);
6887 flags = SVAL(req->vwv+2, 0);
6888
6889 p = (const char *)req->buf;
6890 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6891 &status, &source_has_wild);
6892 if (!NT_STATUS_IS_OK(status)) {
6893 reply_nterror(req, status);
6894 goto out;
6895 }
6896 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6897 &status, &dest_has_wild);
6898 if (!NT_STATUS_IS_OK(status)) {
6899 reply_nterror(req, status);
6900 goto out;
6901 }
6902
6903 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6904
6905 if (tid2 != conn->cnum) {
6906 /* can't currently handle inter share copies XXXX */
6907 DEBUG(3,("Rejecting inter-share copy\n"));
6908 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6909 goto out;
6910 }
6911
6912 status = filename_convert(ctx, conn,
6913 req->flags2 & FLAGS2_DFS_PATHNAMES,
6914 fname_src,
6915 UCF_COND_ALLOW_WCARD_LCOMP,
6916 &source_has_wild,
6917 &smb_fname_src);
6918 if (!NT_STATUS_IS_OK(status)) {
6919 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6920 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6921 ERRSRV, ERRbadpath);
6922 goto out;
6923 }
6924 reply_nterror(req, status);
6925 goto out;
6926 }
6927
6928 status = filename_convert(ctx, conn,
6929 req->flags2 & FLAGS2_DFS_PATHNAMES,
6930 fname_dst,
6931 UCF_COND_ALLOW_WCARD_LCOMP,
6932 &dest_has_wild,
6933 &smb_fname_dst);
6934 if (!NT_STATUS_IS_OK(status)) {
6935 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6936 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6937 ERRSRV, ERRbadpath);
6938 goto out;
6939 }
6940 reply_nterror(req, status);
6941 goto out;
6942 }
6943
6944 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6945
6946 if ((flags&1) && target_is_directory) {
6947 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6948 goto out;
6949 }
6950
6951 if ((flags&2) && !target_is_directory) {
6952 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6953 goto out;
6954 }
6955
6956 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6957 /* wants a tree copy! XXXX */
6958 DEBUG(3,("Rejecting tree copy\n"));
6959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6960 goto out;
6961 }
6962
6963 /* Split up the directory from the filename/mask. */
6964 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6965 &fname_src_dir, &fname_src_mask);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 reply_nterror(req, NT_STATUS_NO_MEMORY);
6968 goto out;
6969 }
6970
6971 /*
6972 * We should only check the mangled cache
6973 * here if unix_convert failed. This means
6974 * that the path in 'mask' doesn't exist
6975 * on the file system and so we need to look
6976 * for a possible mangle. This patch from
6977 * Tine Smukavec <valentin.smukavec@hermes.si>.
6978 */
6979 if (!VALID_STAT(smb_fname_src->st) &&
6980 mangle_is_mangled(fname_src_mask, conn->params)) {
6981 char *new_mask = NULL;
6982 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6983 &new_mask, conn->params);
6984
6985 /* Use demangled name if one was successfully found. */
6986 if (new_mask) {
6987 TALLOC_FREE(fname_src_mask);
6988 fname_src_mask = new_mask;
6989 }
6990 }
6991
6992 if (!source_has_wild) {
6993
6994 /*
6995 * Only one file needs to be copied. Append the mask back onto
6996 * the directory.
6997 */
6998 TALLOC_FREE(smb_fname_src->base_name);
6999 if (ISDOT(fname_src_dir)) {
7000 /* Ensure we use canonical names on open. */
7001 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7002 "%s",
7003 fname_src_mask);
7004 } else {
7005 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7006 "%s/%s",
7007 fname_src_dir,
7008 fname_src_mask);
7009 }
7010 if (!smb_fname_src->base_name) {
7011 reply_nterror(req, NT_STATUS_NO_MEMORY);
7012 goto out;
7013 }
7014
7015 if (dest_has_wild) {
7016 char *fname_dst_mod = NULL;
7017 if (!resolve_wildcards(smb_fname_dst,
7018 smb_fname_src->base_name,
7019 smb_fname_dst->base_name,
7020 &fname_dst_mod)) {
7021 reply_nterror(req, NT_STATUS_NO_MEMORY);
7022 goto out;
7023 }
7024 TALLOC_FREE(smb_fname_dst->base_name);
7025 smb_fname_dst->base_name = fname_dst_mod;
7026 }
7027
7028 status = check_name(conn, smb_fname_src->base_name);
7029 if (!NT_STATUS_IS_OK(status)) {
7030 reply_nterror(req, status);
7031 goto out;
7032 }
7033
7034 status = check_name(conn, smb_fname_dst->base_name);
7035 if (!NT_STATUS_IS_OK(status)) {
7036 reply_nterror(req, status);
7037 goto out;
7038 }
7039
7040 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7041 ofun, count, target_is_directory);
7042
7043 if(!NT_STATUS_IS_OK(status)) {
7044 reply_nterror(req, status);
7045 goto out;
7046 } else {
7047 count++;
7048 }
7049 } else {
7050 struct smb_Dir *dir_hnd = NULL;
7051 const char *dname = NULL;
7052 char *talloced = NULL;
7053 long offset = 0;
7054
7055 /*
7056 * There is a wildcard that requires us to actually read the
7057 * src dir and copy each file matching the mask to the dst.
7058 * Right now streams won't be copied, but this could
7059 * presumably be added with a nested loop for reach dir entry.
7060 */
7061 SMB_ASSERT(!smb_fname_src->stream_name);
7062 SMB_ASSERT(!smb_fname_dst->stream_name);
7063
7064 smb_fname_src->stream_name = NULL;
7065 smb_fname_dst->stream_name = NULL;
7066
7067 if (strequal(fname_src_mask,"????????.???")) {
7068 TALLOC_FREE(fname_src_mask);
7069 fname_src_mask = talloc_strdup(ctx, "*");
7070 if (!fname_src_mask) {
7071 reply_nterror(req, NT_STATUS_NO_MEMORY);
7072 goto out;
7073 }
7074 }
7075
7076 status = check_name(conn, fname_src_dir);
7077 if (!NT_STATUS_IS_OK(status)) {
7078 reply_nterror(req, status);
7079 goto out;
7080 }
7081
7082 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7083 if (dir_hnd == NULL) {
7084 status = map_nt_error_from_unix(errno);
7085 reply_nterror(req, status);
7086 goto out;
7087 }
7088
7089 error = ERRbadfile;
7090
7091 /* Iterate over the src dir copying each entry to the dst. */
7092 while ((dname = ReadDirName(dir_hnd, &offset,
7093 &smb_fname_src->st, &talloced))) {
7094 char *destname = NULL;
7095
7096 if (ISDOT(dname) || ISDOTDOT(dname)) {
7097 TALLOC_FREE(talloced);
7098 continue;
7099 }
7100
7101 if (!is_visible_file(conn, fname_src_dir, dname,
7102 &smb_fname_src->st, false)) {
7103 TALLOC_FREE(talloced);
7104 continue;
7105 }
7106
7107 if(!mask_match(dname, fname_src_mask,
7108 conn->case_sensitive)) {
7109 TALLOC_FREE(talloced);
7110 continue;
7111 }
7112
7113 error = ERRnoaccess;
7114
7115 /* Get the src smb_fname struct setup. */
7116 TALLOC_FREE(smb_fname_src->base_name);
7117 if (ISDOT(fname_src_dir)) {
7118 /* Ensure we use canonical names on open. */
7119 smb_fname_src->base_name =
7120 talloc_asprintf(smb_fname_src, "%s",
7121 dname);
7122 } else {
7123 smb_fname_src->base_name =
7124 talloc_asprintf(smb_fname_src, "%s/%s",
7125 fname_src_dir, dname);
7126 }
7127
7128 if (!smb_fname_src->base_name) {
7129 TALLOC_FREE(dir_hnd);
7130 TALLOC_FREE(talloced);
7131 reply_nterror(req, NT_STATUS_NO_MEMORY);
7132 goto out;
7133 }
7134
7135 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7136 smb_fname_dst->base_name,
7137 &destname)) {
7138 TALLOC_FREE(talloced);
7139 continue;
7140 }
7141 if (!destname) {
7142 TALLOC_FREE(dir_hnd);
7143 TALLOC_FREE(talloced);
7144 reply_nterror(req, NT_STATUS_NO_MEMORY);
7145 goto out;
7146 }
7147
7148 TALLOC_FREE(smb_fname_dst->base_name);
7149 smb_fname_dst->base_name = destname;
7150
7151 status = check_name(conn, smb_fname_src->base_name);
7152 if (!NT_STATUS_IS_OK(status)) {
7153 TALLOC_FREE(dir_hnd);
7154 TALLOC_FREE(talloced);
7155 reply_nterror(req, status);
7156 goto out;
7157 }
7158
7159 status = check_name(conn, smb_fname_dst->base_name);
7160 if (!NT_STATUS_IS_OK(status)) {
7161 TALLOC_FREE(dir_hnd);
7162 TALLOC_FREE(talloced);
7163 reply_nterror(req, status);
7164 goto out;
7165 }
7166
7167 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7168 smb_fname_src->base_name,
7169 smb_fname_dst->base_name));
7170
7171 status = copy_file(ctx, conn, smb_fname_src,
7172 smb_fname_dst, ofun, count,
7173 target_is_directory);
7174 if (NT_STATUS_IS_OK(status)) {
7175 count++;
7176 }
7177
7178 TALLOC_FREE(talloced);
7179 }
7180 TALLOC_FREE(dir_hnd);
7181 }
7182
7183 if (count == 0) {
7184 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7185 goto out;
7186 }
7187
7188 reply_outbuf(req, 1, 0);
7189 SSVAL(req->outbuf,smb_vwv0,count);
7190 out:
7191 TALLOC_FREE(smb_fname_src);
7192 TALLOC_FREE(smb_fname_dst);
7193 TALLOC_FREE(fname_src);
7194 TALLOC_FREE(fname_dst);
7195 TALLOC_FREE(fname_src_mask);
7196 TALLOC_FREE(fname_src_dir);
7197
7198 END_PROFILE(SMBcopy);
7199 return;
7200}
7201
7202#undef DBGC_CLASS
7203#define DBGC_CLASS DBGC_LOCKING
7204
7205/****************************************************************************
7206 Get a lock pid, dealing with large count requests.
7207****************************************************************************/
7208
7209uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7210 bool large_file_format)
7211{
7212 if(!large_file_format)
7213 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7214 else
7215 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7216}
7217
7218/****************************************************************************
7219 Get a lock count, dealing with large count requests.
7220****************************************************************************/
7221
7222uint64_t get_lock_count(const uint8_t *data, int data_offset,
7223 bool large_file_format)
7224{
7225 uint64_t count = 0;
7226
7227 if(!large_file_format) {
7228 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7229 } else {
7230
7231#if defined(HAVE_LONGLONG)
7232 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7233 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7234#else /* HAVE_LONGLONG */
7235
7236 /*
7237 * NT4.x seems to be broken in that it sends large file (64 bit)
7238 * lockingX calls even if the CAP_LARGE_FILES was *not*
7239 * negotiated. For boxes without large unsigned ints truncate the
7240 * lock count by dropping the top 32 bits.
7241 */
7242
7243 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7244 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7245 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7246 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7247 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7248 }
7249
7250 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7251#endif /* HAVE_LONGLONG */
7252 }
7253
7254 return count;
7255}
7256
7257#if !defined(HAVE_LONGLONG)
7258/****************************************************************************
7259 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7260****************************************************************************/
7261
7262static uint32 map_lock_offset(uint32 high, uint32 low)
7263{
7264 unsigned int i;
7265 uint32 mask = 0;
7266 uint32 highcopy = high;
7267
7268 /*
7269 * Try and find out how many significant bits there are in high.
7270 */
7271
7272 for(i = 0; highcopy; i++)
7273 highcopy >>= 1;
7274
7275 /*
7276 * We use 31 bits not 32 here as POSIX
7277 * lock offsets may not be negative.
7278 */
7279
7280 mask = (~0) << (31 - i);
7281
7282 if(low & mask)
7283 return 0; /* Fail. */
7284
7285 high <<= (31 - i);
7286
7287 return (high|low);
7288}
7289#endif /* !defined(HAVE_LONGLONG) */
7290
7291/****************************************************************************
7292 Get a lock offset, dealing with large offset requests.
7293****************************************************************************/
7294
7295uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7296 bool large_file_format, bool *err)
7297{
7298 uint64_t offset = 0;
7299
7300 *err = False;
7301
7302 if(!large_file_format) {
7303 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7304 } else {
7305
7306#if defined(HAVE_LONGLONG)
7307 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7308 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7309#else /* HAVE_LONGLONG */
7310
7311 /*
7312 * NT4.x seems to be broken in that it sends large file (64 bit)
7313 * lockingX calls even if the CAP_LARGE_FILES was *not*
7314 * negotiated. For boxes without large unsigned ints mangle the
7315 * lock offset by mapping the top 32 bits onto the lower 32.
7316 */
7317
7318 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7319 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7320 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7321 uint32 new_low = 0;
7322
7323 if((new_low = map_lock_offset(high, low)) == 0) {
7324 *err = True;
7325 return (uint64_t)-1;
7326 }
7327
7328 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7329 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7330 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7331 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7332 }
7333
7334 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7335#endif /* HAVE_LONGLONG */
7336 }
7337
7338 return offset;
7339}
7340
7341NTSTATUS smbd_do_locking(struct smb_request *req,
7342 files_struct *fsp,
7343 uint8_t type,
7344 int32_t timeout,
7345 uint16_t num_ulocks,
7346 struct smbd_lock_element *ulocks,
7347 uint16_t num_locks,
7348 struct smbd_lock_element *locks,
7349 bool *async)
7350{
7351 connection_struct *conn = req->conn;
7352 int i;
7353 NTSTATUS status = NT_STATUS_OK;
7354
7355 *async = false;
7356
7357 /* Data now points at the beginning of the list
7358 of smb_unlkrng structs */
7359 for(i = 0; i < (int)num_ulocks; i++) {
7360 struct smbd_lock_element *e = &ulocks[i];
7361
7362 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7363 "pid %u, file %s\n",
7364 (double)e->offset,
7365 (double)e->count,
7366 (unsigned int)e->smblctx,
7367 fsp_str_dbg(fsp)));
7368
7369 if (e->brltype != UNLOCK_LOCK) {
7370 /* this can only happen with SMB2 */
7371 return NT_STATUS_INVALID_PARAMETER;
7372 }
7373
7374 status = do_unlock(req->sconn->msg_ctx,
7375 fsp,
7376 e->smblctx,
7377 e->count,
7378 e->offset,
7379 WINDOWS_LOCK);
7380
7381 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7382 nt_errstr(status)));
7383
7384 if (!NT_STATUS_IS_OK(status)) {
7385 return status;
7386 }
7387 }
7388
7389 /* Setup the timeout in seconds. */
7390
7391 if (!lp_blocking_locks(SNUM(conn))) {
7392 timeout = 0;
7393 }
7394
7395 /* Data now points at the beginning of the list
7396 of smb_lkrng structs */
7397
7398 for(i = 0; i < (int)num_locks; i++) {
7399 struct smbd_lock_element *e = &locks[i];
7400
7401 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7402 "%llu, file %s timeout = %d\n",
7403 (double)e->offset,
7404 (double)e->count,
7405 (unsigned long long)e->smblctx,
7406 fsp_str_dbg(fsp),
7407 (int)timeout));
7408
7409 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7410 struct blocking_lock_record *blr = NULL;
7411
7412 if (num_locks > 1) {
7413 /*
7414 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7415 * if the lock vector contains one entry. When given mutliple cancel
7416 * requests in a single PDU we expect the server to return an
7417 * error. Windows servers seem to accept the request but only
7418 * cancel the first lock.
7419 * JRA - Do what Windows does (tm) :-).
7420 */
7421
7422#if 0
7423 /* MS-CIFS (2.2.4.32.1) behavior. */
7424 return NT_STATUS_DOS(ERRDOS,
7425 ERRcancelviolation);
7426#else
7427 /* Windows behavior. */
7428 if (i != 0) {
7429 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7430 "cancel request\n"));
7431 continue;
7432 }
7433#endif
7434 }
7435
7436 if (lp_blocking_locks(SNUM(conn))) {
7437
7438 /* Schedule a message to ourselves to
7439 remove the blocking lock record and
7440 return the right error. */
7441
7442 blr = blocking_lock_cancel_smb1(fsp,
7443 e->smblctx,
7444 e->offset,
7445 e->count,
7446 WINDOWS_LOCK,
7447 type,
7448 NT_STATUS_FILE_LOCK_CONFLICT);
7449 if (blr == NULL) {
7450 return NT_STATUS_DOS(
7451 ERRDOS,
7452 ERRcancelviolation);
7453 }
7454 }
7455 /* Remove a matching pending lock. */
7456 status = do_lock_cancel(fsp,
7457 e->smblctx,
7458 e->count,
7459 e->offset,
7460 WINDOWS_LOCK,
7461 blr);
7462 } else {
7463 bool blocking_lock = timeout ? true : false;
7464 bool defer_lock = false;
7465 struct byte_range_lock *br_lck;
7466 uint64_t block_smblctx;
7467
7468 br_lck = do_lock(req->sconn->msg_ctx,
7469 fsp,
7470 e->smblctx,
7471 e->count,
7472 e->offset,
7473 e->brltype,
7474 WINDOWS_LOCK,
7475 blocking_lock,
7476 &status,
7477 &block_smblctx,
7478 NULL);
7479
7480 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7481 /* Windows internal resolution for blocking locks seems
7482 to be about 200ms... Don't wait for less than that. JRA. */
7483 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7484 timeout = lp_lock_spin_time();
7485 }
7486 defer_lock = true;
7487 }
7488
7489 /* If a lock sent with timeout of zero would fail, and
7490 * this lock has been requested multiple times,
7491 * according to brl_lock_failed() we convert this
7492 * request to a blocking lock with a timeout of between
7493 * 150 - 300 milliseconds.
7494 *
7495 * If lp_lock_spin_time() has been set to 0, we skip
7496 * this blocking retry and fail immediately.
7497 *
7498 * Replacement for do_lock_spin(). JRA. */
7499
7500 if (!req->sconn->using_smb2 &&
7501 br_lck && lp_blocking_locks(SNUM(conn)) &&
7502 lp_lock_spin_time() && !blocking_lock &&
7503 NT_STATUS_EQUAL((status),
7504 NT_STATUS_FILE_LOCK_CONFLICT))
7505 {
7506 defer_lock = true;
7507 timeout = lp_lock_spin_time();
7508 }
7509
7510 if (br_lck && defer_lock) {
7511 /*
7512 * A blocking lock was requested. Package up
7513 * this smb into a queued request and push it
7514 * onto the blocking lock queue.
7515 */
7516 if(push_blocking_lock_request(br_lck,
7517 req,
7518 fsp,
7519 timeout,
7520 i,
7521 e->smblctx,
7522 e->brltype,
7523 WINDOWS_LOCK,
7524 e->offset,
7525 e->count,
7526 block_smblctx)) {
7527 TALLOC_FREE(br_lck);
7528 *async = true;
7529 return NT_STATUS_OK;
7530 }
7531 }
7532
7533 TALLOC_FREE(br_lck);
7534 }
7535
7536 if (!NT_STATUS_IS_OK(status)) {
7537 break;
7538 }
7539 }
7540
7541 /* If any of the above locks failed, then we must unlock
7542 all of the previous locks (X/Open spec). */
7543
7544 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7545
7546 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7547 i = -1; /* we want to skip the for loop */
7548 }
7549
7550 /*
7551 * Ensure we don't do a remove on the lock that just failed,
7552 * as under POSIX rules, if we have a lock already there, we
7553 * will delete it (and we shouldn't) .....
7554 */
7555 for(i--; i >= 0; i--) {
7556 struct smbd_lock_element *e = &locks[i];
7557
7558 do_unlock(req->sconn->msg_ctx,
7559 fsp,
7560 e->smblctx,
7561 e->count,
7562 e->offset,
7563 WINDOWS_LOCK);
7564 }
7565 return status;
7566 }
7567
7568 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7569 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7570
7571 return NT_STATUS_OK;
7572}
7573
7574/****************************************************************************
7575 Reply to a lockingX request.
7576****************************************************************************/
7577
7578void reply_lockingX(struct smb_request *req)
7579{
7580 connection_struct *conn = req->conn;
7581 files_struct *fsp;
7582 unsigned char locktype;
7583 unsigned char oplocklevel;
7584 uint16 num_ulocks;
7585 uint16 num_locks;
7586 int32 lock_timeout;
7587 int i;
7588 const uint8_t *data;
7589 bool large_file_format;
7590 bool err;
7591 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7592 struct smbd_lock_element *ulocks;
7593 struct smbd_lock_element *locks;
7594 bool async = false;
7595
7596 START_PROFILE(SMBlockingX);
7597
7598 if (req->wct < 8) {
7599 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7600 END_PROFILE(SMBlockingX);
7601 return;
7602 }
7603
7604 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7605 locktype = CVAL(req->vwv+3, 0);
7606 oplocklevel = CVAL(req->vwv+3, 1);
7607 num_ulocks = SVAL(req->vwv+6, 0);
7608 num_locks = SVAL(req->vwv+7, 0);
7609 lock_timeout = IVAL(req->vwv+4, 0);
7610 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7611
7612 if (!check_fsp(conn, req, fsp)) {
7613 END_PROFILE(SMBlockingX);
7614 return;
7615 }
7616
7617 data = req->buf;
7618
7619 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7620 /* we don't support these - and CANCEL_LOCK makes w2k
7621 and XP reboot so I don't really want to be
7622 compatible! (tridge) */
7623 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7624 END_PROFILE(SMBlockingX);
7625 return;
7626 }
7627
7628 /* Check if this is an oplock break on a file
7629 we have granted an oplock on.
7630 */
7631 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7632 /* Client can insist on breaking to none. */
7633 bool break_to_none = (oplocklevel == 0);
7634 bool result;
7635
7636 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7637 "for fnum = %d\n", (unsigned int)oplocklevel,
7638 fsp->fnum ));
7639
7640 /*
7641 * Make sure we have granted an exclusive or batch oplock on
7642 * this file.
7643 */
7644
7645 if (fsp->oplock_type == 0) {
7646
7647 /* The Samba4 nbench simulator doesn't understand
7648 the difference between break to level2 and break
7649 to none from level2 - it sends oplock break
7650 replies in both cases. Don't keep logging an error
7651 message here - just ignore it. JRA. */
7652
7653 DEBUG(5,("reply_lockingX: Error : oplock break from "
7654 "client for fnum = %d (oplock=%d) and no "
7655 "oplock granted on this file (%s).\n",
7656 fsp->fnum, fsp->oplock_type,
7657 fsp_str_dbg(fsp)));
7658
7659 /* if this is a pure oplock break request then don't
7660 * send a reply */
7661 if (num_locks == 0 && num_ulocks == 0) {
7662 END_PROFILE(SMBlockingX);
7663 return;
7664 } else {
7665 END_PROFILE(SMBlockingX);
7666 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7667 return;
7668 }
7669 }
7670
7671 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7672 (break_to_none)) {
7673 result = remove_oplock(fsp);
7674 } else {
7675 result = downgrade_oplock(fsp);
7676 }
7677
7678 if (!result) {
7679 DEBUG(0, ("reply_lockingX: error in removing "
7680 "oplock on file %s\n", fsp_str_dbg(fsp)));
7681 /* Hmmm. Is this panic justified? */
7682 smb_panic("internal tdb error");
7683 }
7684
7685 reply_to_oplock_break_requests(fsp);
7686
7687 /* if this is a pure oplock break request then don't send a
7688 * reply */
7689 if (num_locks == 0 && num_ulocks == 0) {
7690 /* Sanity check - ensure a pure oplock break is not a
7691 chained request. */
7692 if(CVAL(req->vwv+0, 0) != 0xff)
7693 DEBUG(0,("reply_lockingX: Error : pure oplock "
7694 "break is a chained %d request !\n",
7695 (unsigned int)CVAL(req->vwv+0, 0)));
7696 END_PROFILE(SMBlockingX);
7697 return;
7698 }
7699 }
7700
7701 if (req->buflen <
7702 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7703 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7704 END_PROFILE(SMBlockingX);
7705 return;
7706 }
7707
7708 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7709 if (ulocks == NULL) {
7710 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 END_PROFILE(SMBlockingX);
7712 return;
7713 }
7714
7715 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7716 if (locks == NULL) {
7717 reply_nterror(req, NT_STATUS_NO_MEMORY);
7718 END_PROFILE(SMBlockingX);
7719 return;
7720 }
7721
7722 /* Data now points at the beginning of the list
7723 of smb_unlkrng structs */
7724 for(i = 0; i < (int)num_ulocks; i++) {
7725 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7726 ulocks[i].count = get_lock_count(data, i, large_file_format);
7727 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7728 ulocks[i].brltype = UNLOCK_LOCK;
7729
7730 /*
7731 * There is no error code marked "stupid client bug".... :-).
7732 */
7733 if(err) {
7734 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7735 END_PROFILE(SMBlockingX);
7736 return;
7737 }
7738 }
7739
7740 /* Now do any requested locks */
7741 data += ((large_file_format ? 20 : 10)*num_ulocks);
7742
7743 /* Data now points at the beginning of the list
7744 of smb_lkrng structs */
7745
7746 for(i = 0; i < (int)num_locks; i++) {
7747 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7748 locks[i].count = get_lock_count(data, i, large_file_format);
7749 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7750
7751 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7752 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7753 locks[i].brltype = PENDING_READ_LOCK;
7754 } else {
7755 locks[i].brltype = READ_LOCK;
7756 }
7757 } else {
7758 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7759 locks[i].brltype = PENDING_WRITE_LOCK;
7760 } else {
7761 locks[i].brltype = WRITE_LOCK;
7762 }
7763 }
7764
7765 /*
7766 * There is no error code marked "stupid client bug".... :-).
7767 */
7768 if(err) {
7769 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7770 END_PROFILE(SMBlockingX);
7771 return;
7772 }
7773 }
7774
7775 status = smbd_do_locking(req, fsp,
7776 locktype, lock_timeout,
7777 num_ulocks, ulocks,
7778 num_locks, locks,
7779 &async);
7780 if (!NT_STATUS_IS_OK(status)) {
7781 END_PROFILE(SMBlockingX);
7782 reply_nterror(req, status);
7783 return;
7784 }
7785 if (async) {
7786 END_PROFILE(SMBlockingX);
7787 return;
7788 }
7789
7790 reply_outbuf(req, 2, 0);
7791
7792 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7793 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7794
7795 END_PROFILE(SMBlockingX);
7796 chain_reply(req);
7797}
7798
7799#undef DBGC_CLASS
7800#define DBGC_CLASS DBGC_ALL
7801
7802/****************************************************************************
7803 Reply to a SMBreadbmpx (read block multiplex) request.
7804 Always reply with an error, if someone has a platform really needs this,
7805 please contact vl@samba.org
7806****************************************************************************/
7807
7808void reply_readbmpx(struct smb_request *req)
7809{
7810 START_PROFILE(SMBreadBmpx);
7811 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7812 END_PROFILE(SMBreadBmpx);
7813 return;
7814}
7815
7816/****************************************************************************
7817 Reply to a SMBreadbs (read block multiplex secondary) request.
7818 Always reply with an error, if someone has a platform really needs this,
7819 please contact vl@samba.org
7820****************************************************************************/
7821
7822void reply_readbs(struct smb_request *req)
7823{
7824 START_PROFILE(SMBreadBs);
7825 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7826 END_PROFILE(SMBreadBs);
7827 return;
7828}
7829
7830/****************************************************************************
7831 Reply to a SMBsetattrE.
7832****************************************************************************/
7833
7834void reply_setattrE(struct smb_request *req)
7835{
7836 connection_struct *conn = req->conn;
7837 struct smb_file_time ft;
7838 files_struct *fsp;
7839 NTSTATUS status;
7840
7841 START_PROFILE(SMBsetattrE);
7842 ZERO_STRUCT(ft);
7843
7844 if (req->wct < 7) {
7845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7846 goto out;
7847 }
7848
7849 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7850
7851 if(!fsp || (fsp->conn != conn)) {
7852 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7853 goto out;
7854 }
7855
7856 /*
7857 * Convert the DOS times into unix times.
7858 */
7859
7860 ft.atime = convert_time_t_to_timespec(
7861 srv_make_unix_date2(req->vwv+3));
7862 ft.mtime = convert_time_t_to_timespec(
7863 srv_make_unix_date2(req->vwv+5));
7864 ft.create_time = convert_time_t_to_timespec(
7865 srv_make_unix_date2(req->vwv+1));
7866
7867 reply_outbuf(req, 0, 0);
7868
7869 /*
7870 * Patch from Ray Frush <frush@engr.colostate.edu>
7871 * Sometimes times are sent as zero - ignore them.
7872 */
7873
7874 /* Ensure we have a valid stat struct for the source. */
7875 status = vfs_stat_fsp(fsp);
7876 if (!NT_STATUS_IS_OK(status)) {
7877 reply_nterror(req, status);
7878 goto out;
7879 }
7880
7881 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7882 if (!NT_STATUS_IS_OK(status)) {
7883 reply_nterror(req, status);
7884 goto out;
7885 }
7886
7887 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7888 " createtime=%u\n",
7889 fsp->fnum,
7890 (unsigned int)ft.atime.tv_sec,
7891 (unsigned int)ft.mtime.tv_sec,
7892 (unsigned int)ft.create_time.tv_sec
7893 ));
7894 out:
7895 END_PROFILE(SMBsetattrE);
7896 return;
7897}
7898
7899
7900/* Back from the dead for OS/2..... JRA. */
7901
7902/****************************************************************************
7903 Reply to a SMBwritebmpx (write block multiplex primary) request.
7904 Always reply with an error, if someone has a platform really needs this,
7905 please contact vl@samba.org
7906****************************************************************************/
7907
7908void reply_writebmpx(struct smb_request *req)
7909{
7910 START_PROFILE(SMBwriteBmpx);
7911 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7912 END_PROFILE(SMBwriteBmpx);
7913 return;
7914}
7915
7916/****************************************************************************
7917 Reply to a SMBwritebs (write block multiplex secondary) request.
7918 Always reply with an error, if someone has a platform really needs this,
7919 please contact vl@samba.org
7920****************************************************************************/
7921
7922void reply_writebs(struct smb_request *req)
7923{
7924 START_PROFILE(SMBwriteBs);
7925 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7926 END_PROFILE(SMBwriteBs);
7927 return;
7928}
7929
7930/****************************************************************************
7931 Reply to a SMBgetattrE.
7932****************************************************************************/
7933
7934void reply_getattrE(struct smb_request *req)
7935{
7936 connection_struct *conn = req->conn;
7937 int mode;
7938 files_struct *fsp;
7939 struct timespec create_ts;
7940
7941 START_PROFILE(SMBgetattrE);
7942
7943 if (req->wct < 1) {
7944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7945 END_PROFILE(SMBgetattrE);
7946 return;
7947 }
7948
7949 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7950
7951 if(!fsp || (fsp->conn != conn)) {
7952 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7953 END_PROFILE(SMBgetattrE);
7954 return;
7955 }
7956
7957 /* Do an fstat on this file */
7958 if(fsp_stat(fsp)) {
7959 reply_nterror(req, map_nt_error_from_unix(errno));
7960 END_PROFILE(SMBgetattrE);
7961 return;
7962 }
7963
7964 mode = dos_mode(conn, fsp->fsp_name);
7965
7966 /*
7967 * Convert the times into dos times. Set create
7968 * date to be last modify date as UNIX doesn't save
7969 * this.
7970 */
7971
7972 reply_outbuf(req, 11, 0);
7973
7974 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7975 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7976 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7977 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7978 /* Should we check pending modtime here ? JRA */
7979 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7980 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7981
7982 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7983 SIVAL(req->outbuf, smb_vwv6, 0);
7984 SIVAL(req->outbuf, smb_vwv8, 0);
7985 } else {
7986 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7987 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7988 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7989 }
7990 SSVAL(req->outbuf,smb_vwv10, mode);
7991
7992 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7993
7994 END_PROFILE(SMBgetattrE);
7995 return;
7996}
Note: See TracBrowser for help on using the repository browser.