source: branches/samba-3.2.x/source/smbd/reply.c@ 539

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

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

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