source: branches/samba-3.3.x/source/smbd/reply.c@ 309

Last change on this file since 309 was 242, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #90 (by diver) in 3.3 branch

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