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

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

Update 3.3 to 3.3.9

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