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

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

Update Samba 3.3 branch to 3.3.3

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