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

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

Update Samba 3.3 to 3.3.10 (source)

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