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

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

Update 3.2 branch to 3.2.9

File size: 182.4 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 ZERO_STRUCT(sbuf);
5491
5492 status = check_name(conn, newname);
5493 if (!NT_STATUS_IS_OK(status)) {
5494 return status;
5495 }
5496
5497 /* Ensure newname contains a '/' */
5498 if(strrchr_m(newname,'/') == 0) {
5499 newname = talloc_asprintf(ctx,
5500 "./%s",
5501 newname);
5502 if (!newname) {
5503 return NT_STATUS_NO_MEMORY;
5504 }
5505 }
5506
5507 /*
5508 * Check for special case with case preserving and not
5509 * case sensitive. If the old last component differs from the original
5510 * last component only by case, then we should allow
5511 * the rename (user is trying to change the case of the
5512 * filename).
5513 */
5514
5515 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5516 strequal(newname, fsp->fsp_name)) {
5517 char *p;
5518 char *newname_modified_last_component = NULL;
5519
5520 /*
5521 * Get the last component of the modified name.
5522 * Note that we guarantee that newname contains a '/'
5523 * character above.
5524 */
5525 p = strrchr_m(newname,'/');
5526 newname_modified_last_component = talloc_strdup(ctx,
5527 p+1);
5528 if (!newname_modified_last_component) {
5529 return NT_STATUS_NO_MEMORY;
5530 }
5531
5532 if(strcsequal(newname_modified_last_component,
5533 newname_last_component) == False) {
5534 /*
5535 * Replace the modified last component with
5536 * the original.
5537 */
5538 *p = '\0'; /* Truncate at the '/' */
5539 newname = talloc_asprintf(ctx,
5540 "%s/%s",
5541 newname,
5542 newname_last_component);
5543 }
5544 }
5545
5546 /*
5547 * If the src and dest names are identical - including case,
5548 * don't do the rename, just return success.
5549 */
5550
5551 if (strcsequal(fsp->fsp_name, newname)) {
5552 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
5553 newname));
5554 return NT_STATUS_OK;
5555 }
5556
5557 old_is_stream = is_ntfs_stream_name(fsp->fsp_name);
5558 new_is_stream = is_ntfs_stream_name(newname);
5559
5560 /* Return the correct error code if both names aren't streams. */
5561 if (!old_is_stream && new_is_stream) {
5562 return NT_STATUS_OBJECT_NAME_INVALID;
5563 }
5564
5565 if (old_is_stream && !new_is_stream) {
5566 return NT_STATUS_INVALID_PARAMETER;
5567 }
5568
5569 /*
5570 * Have vfs_object_exist also fill sbuf1
5571 */
5572 dst_exists = vfs_object_exist(conn, newname, &sbuf1);
5573
5574 if(!replace_if_exists && dst_exists) {
5575 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
5576 fsp->fsp_name,newname));
5577 return NT_STATUS_OBJECT_NAME_COLLISION;
5578 }
5579
5580 if (dst_exists) {
5581 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
5582 files_struct *dst_fsp = file_find_di_first(fileid);
5583 /* The file can be open when renaming a stream */
5584 if (dst_fsp && !new_is_stream) {
5585 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5586 return NT_STATUS_ACCESS_DENIED;
5587 }
5588 }
5589
5590 /* Ensure we have a valid stat struct for the source. */
5591 if (fsp->fh->fd != -1) {
5592 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
5593 return map_nt_error_from_unix(errno);
5594 }
5595 } else {
5596 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
5597 return map_nt_error_from_unix(errno);
5598 }
5599 }
5600
5601 status = can_rename(conn, fsp, attrs, &sbuf);
5602
5603 if (!NT_STATUS_IS_OK(status)) {
5604 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5605 nt_errstr(status), fsp->fsp_name,newname));
5606 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5607 status = NT_STATUS_ACCESS_DENIED;
5608 return status;
5609 }
5610
5611 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
5612 return NT_STATUS_ACCESS_DENIED;
5613 }
5614
5615 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5616 NULL);
5617
5618 /*
5619 * We have the file open ourselves, so not being able to get the
5620 * corresponding share mode lock is a fatal error.
5621 */
5622
5623 SMB_ASSERT(lck != NULL);
5624
5625 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
5626 uint32 create_options = fsp->fh->private_options;
5627
5628 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
5629 fsp->fsp_name,newname));
5630
5631 notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
5632
5633 rename_open_files(conn, lck, newname);
5634
5635 /*
5636 * A rename acts as a new file create w.r.t. allowing an initial delete
5637 * on close, probably because in Windows there is a new handle to the
5638 * new file. If initial delete on close was requested but not
5639 * originally set, we need to set it here. This is probably not 100% correct,
5640 * but will work for the CIFSFS client which in non-posix mode
5641 * depends on these semantics. JRA.
5642 */
5643
5644 if (create_options & FILE_DELETE_ON_CLOSE) {
5645 status = can_set_delete_on_close(fsp, True, 0);
5646
5647 if (NT_STATUS_IS_OK(status)) {
5648 /* Note that here we set the *inital* delete on close flag,
5649 * not the regular one. The magic gets handled in close. */
5650 fsp->initial_delete_on_close = True;
5651 }
5652 }
5653 TALLOC_FREE(lck);
5654 return NT_STATUS_OK;
5655 }
5656
5657 TALLOC_FREE(lck);
5658
5659 if (errno == ENOTDIR || errno == EISDIR) {
5660 DEBUG( 0, ( "PS - ENOTDIR3\n" ) );
5661 status = NT_STATUS_OBJECT_NAME_COLLISION;
5662 } else {
5663 status = map_nt_error_from_unix(errno);
5664 }
5665
5666 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
5667 nt_errstr(status), fsp->fsp_name,newname));
5668
5669 return status;
5670}
5671
5672/****************************************************************************
5673 The guts of the rename command, split out so it may be called by the NT SMB
5674 code.
5675****************************************************************************/
5676
5677NTSTATUS rename_internals(TALLOC_CTX *ctx,
5678 connection_struct *conn,
5679 struct smb_request *req,
5680 const char *name_in,
5681 const char *newname_in,
5682 uint32 attrs,
5683 bool replace_if_exists,
5684 bool src_has_wild,
5685 bool dest_has_wild,
5686 uint32_t access_mask)
5687{
5688 char *directory = NULL;
5689 char *mask = NULL;
5690 char *last_component_src = NULL;
5691 char *last_component_dest = NULL;
5692 char *name = NULL;
5693 char *newname = NULL;
5694 char *p;
5695 int count=0;
5696 NTSTATUS status = NT_STATUS_OK;
5697 SMB_STRUCT_STAT sbuf1, sbuf2;
5698 struct smb_Dir *dir_hnd = NULL;
5699 const char *dname;
5700 long offset = 0;
5701
5702 ZERO_STRUCT(sbuf1);
5703 ZERO_STRUCT(sbuf2);
5704
5705 status = unix_convert(ctx, conn, name_in, src_has_wild, &name,
5706 &last_component_src, &sbuf1);
5707 if (!NT_STATUS_IS_OK(status)) {
5708 return status;
5709 }
5710
5711 status = unix_convert(ctx, conn, newname_in, dest_has_wild, &newname,
5712 &last_component_dest, &sbuf2);
5713 if (!NT_STATUS_IS_OK(status)) {
5714 return status;
5715 }
5716
5717 /*
5718 * Split the old name into directory and last component
5719 * strings. Note that unix_convert may have stripped off a
5720 * leading ./ from both name and newname if the rename is
5721 * at the root of the share. We need to make sure either both
5722 * name and newname contain a / character or neither of them do
5723 * as this is checked in resolve_wildcards().
5724 */
5725
5726 p = strrchr_m(name,'/');
5727 if (!p) {
5728 directory = talloc_strdup(ctx, ".");
5729 if (!directory) {
5730 return NT_STATUS_NO_MEMORY;
5731 }
5732 mask = name;
5733 } else {
5734 *p = 0;
5735 directory = talloc_strdup(ctx, name);
5736 if (!directory) {
5737 return NT_STATUS_NO_MEMORY;
5738 }
5739 mask = p+1;
5740 *p = '/'; /* Replace needed for exceptional test below. */
5741 }
5742
5743 /*
5744 * We should only check the mangled cache
5745 * here if unix_convert failed. This means
5746 * that the path in 'mask' doesn't exist
5747 * on the file system and so we need to look
5748 * for a possible mangle. This patch from
5749 * Tine Smukavec <valentin.smukavec@hermes.si>.
5750 */
5751
5752 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5753 char *new_mask = NULL;
5754 mangle_lookup_name_from_8_3(ctx,
5755 mask,
5756 &new_mask,
5757 conn->params );
5758 if (new_mask) {
5759 mask = new_mask;
5760 }
5761 }
5762
5763 if (!src_has_wild) {
5764 files_struct *fsp;
5765
5766 /*
5767 * No wildcards - just process the one file.
5768 */
5769 bool is_short_name = mangle_is_8_3(name, True, conn->params);
5770
5771 /* Add a terminating '/' to the directory name. */
5772 directory = talloc_asprintf_append(directory,
5773 "/%s",
5774 mask);
5775 if (!directory) {
5776 return NT_STATUS_NO_MEMORY;
5777 }
5778
5779 /* Ensure newname contains a '/' also */
5780 if(strrchr_m(newname,'/') == 0) {
5781 newname = talloc_asprintf(ctx,
5782 "./%s",
5783 newname);
5784 if (!newname) {
5785 return NT_STATUS_NO_MEMORY;
5786 }
5787 }
5788
5789 DEBUG(3, ("rename_internals: case_sensitive = %d, "
5790 "case_preserve = %d, short case preserve = %d, "
5791 "directory = %s, newname = %s, "
5792 "last_component_dest = %s, is_8_3 = %d\n",
5793 conn->case_sensitive, conn->case_preserve,
5794 conn->short_case_preserve, directory,
5795 newname, last_component_dest, is_short_name));
5796
5797 /* The dest name still may have wildcards. */
5798 if (dest_has_wild) {
5799 char *mod_newname = NULL;
5800 if (!resolve_wildcards(ctx,
5801 directory,newname,&mod_newname)) {
5802 DEBUG(6, ("rename_internals: resolve_wildcards "
5803 "%s %s failed\n",
5804 directory,
5805 newname));
5806 return NT_STATUS_NO_MEMORY;
5807 }
5808 newname = mod_newname;
5809 }
5810
5811 ZERO_STRUCT(sbuf1);
5812 SMB_VFS_STAT(conn, directory, &sbuf1);
5813
5814 status = S_ISDIR(sbuf1.st_mode) ?
5815 open_directory(conn, req, directory, &sbuf1,
5816 access_mask,
5817 FILE_SHARE_READ|FILE_SHARE_WRITE,
5818 FILE_OPEN, 0, 0, NULL,
5819 &fsp)
5820 : open_file_ntcreate(conn, req, directory, &sbuf1,
5821 access_mask,
5822 FILE_SHARE_READ|FILE_SHARE_WRITE,
5823 FILE_OPEN, 0, 0, 0, NULL,
5824 &fsp);
5825
5826 if (!NT_STATUS_IS_OK(status)) {
5827 DEBUG(3, ("Could not open rename source %s: %s\n",
5828 directory, nt_errstr(status)));
5829 return status;
5830 }
5831
5832 status = rename_internals_fsp(conn, fsp, newname,
5833 last_component_dest,
5834 attrs, replace_if_exists);
5835
5836 close_file(fsp, NORMAL_CLOSE);
5837
5838 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
5839 nt_errstr(status), directory,newname));
5840
5841 return status;
5842 }
5843
5844 /*
5845 * Wildcards - process each file that matches.
5846 */
5847 if (strequal(mask,"????????.???")) {
5848 mask[0] = '*';
5849 mask[1] = '\0';
5850 }
5851
5852 status = check_name(conn, directory);
5853 if (!NT_STATUS_IS_OK(status)) {
5854 return status;
5855 }
5856
5857 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, attrs);
5858 if (dir_hnd == NULL) {
5859 return map_nt_error_from_unix(errno);
5860 }
5861
5862 status = NT_STATUS_NO_SUCH_FILE;
5863 /*
5864 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
5865 * - gentest fix. JRA
5866 */
5867
5868 while ((dname = ReadDirName(dir_hnd, &offset))) {
5869 files_struct *fsp = NULL;
5870 char *fname = NULL;
5871 char *destname = NULL;
5872 bool sysdir_entry = False;
5873
5874 /* Quick check for "." and ".." */
5875 if (ISDOT(dname) || ISDOTDOT(dname)) {
5876 if (attrs & aDIR) {
5877 sysdir_entry = True;
5878 } else {
5879 continue;
5880 }
5881 }
5882
5883 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5884 continue;
5885 }
5886
5887 if(!mask_match(dname, mask, conn->case_sensitive)) {
5888 continue;
5889 }
5890
5891 if (sysdir_entry) {
5892 status = NT_STATUS_OBJECT_NAME_INVALID;
5893 break;
5894 }
5895
5896 fname = talloc_asprintf(ctx,
5897 "%s/%s",
5898 directory,
5899 dname);
5900 if (!fname) {
5901 return NT_STATUS_NO_MEMORY;
5902 }
5903
5904 if (!resolve_wildcards(ctx,
5905 fname,newname,&destname)) {
5906 DEBUG(6, ("resolve_wildcards %s %s failed\n",
5907 fname, destname));
5908 TALLOC_FREE(fname);
5909 continue;
5910 }
5911 if (!destname) {
5912 return NT_STATUS_NO_MEMORY;
5913 }
5914
5915 ZERO_STRUCT(sbuf1);
5916 SMB_VFS_STAT(conn, fname, &sbuf1);
5917
5918 status = S_ISDIR(sbuf1.st_mode) ?
5919 open_directory(conn, req, fname, &sbuf1,
5920 access_mask,
5921 FILE_SHARE_READ|FILE_SHARE_WRITE,
5922 FILE_OPEN, 0, 0, NULL,
5923 &fsp)
5924 : open_file_ntcreate(conn, req, fname, &sbuf1,
5925 access_mask,
5926 FILE_SHARE_READ|FILE_SHARE_WRITE,
5927 FILE_OPEN, 0, 0, 0, NULL,
5928 &fsp);
5929
5930 if (!NT_STATUS_IS_OK(status)) {
5931 DEBUG(3,("rename_internals: open_file_ntcreate "
5932 "returned %s rename %s -> %s\n",
5933 nt_errstr(status), directory, newname));
5934 break;
5935 }
5936
5937 status = rename_internals_fsp(conn, fsp, destname, dname,
5938 attrs, replace_if_exists);
5939
5940 close_file(fsp, NORMAL_CLOSE);
5941
5942 if (!NT_STATUS_IS_OK(status)) {
5943 DEBUG(3, ("rename_internals_fsp returned %s for "
5944 "rename %s -> %s\n", nt_errstr(status),
5945 directory, newname));
5946 break;
5947 }
5948
5949 count++;
5950
5951 DEBUG(3,("rename_internals: doing rename on %s -> "
5952 "%s\n",fname,destname));
5953
5954 TALLOC_FREE(fname);
5955 TALLOC_FREE(destname);
5956 }
5957 TALLOC_FREE(dir_hnd);
5958
5959 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
5960 status = map_nt_error_from_unix(errno);
5961 }
5962
5963 return status;
5964}
5965
5966/****************************************************************************
5967 Reply to a mv.
5968****************************************************************************/
5969
5970void reply_mv(struct smb_request *req)
5971{
5972 connection_struct *conn = req->conn;
5973 char *name = NULL;
5974 char *newname = NULL;
5975 char *p;
5976 uint32 attrs;
5977 NTSTATUS status;
5978 bool src_has_wcard = False;
5979 bool dest_has_wcard = False;
5980 TALLOC_CTX *ctx = talloc_tos();
5981
5982 START_PROFILE(SMBmv);
5983
5984 if (req->wct < 1) {
5985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5986 END_PROFILE(SMBmv);
5987 return;
5988 }
5989
5990 attrs = SVAL(req->inbuf,smb_vwv0);
5991
5992 p = smb_buf(req->inbuf) + 1;
5993 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
5994 0, STR_TERMINATE, &status,
5995 &src_has_wcard);
5996 if (!NT_STATUS_IS_OK(status)) {
5997 reply_nterror(req, status);
5998 END_PROFILE(SMBmv);
5999 return;
6000 }
6001 p++;
6002 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6003 0, STR_TERMINATE, &status,
6004 &dest_has_wcard);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 reply_nterror(req, status);
6007 END_PROFILE(SMBmv);
6008 return;
6009 }
6010
6011 status = resolve_dfspath_wcard(ctx, conn,
6012 req->flags2 & FLAGS2_DFS_PATHNAMES,
6013 name,
6014 &name,
6015 &src_has_wcard);
6016 if (!NT_STATUS_IS_OK(status)) {
6017 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6018 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6019 ERRSRV, ERRbadpath);
6020 END_PROFILE(SMBmv);
6021 return;
6022 }
6023 reply_nterror(req, status);
6024 END_PROFILE(SMBmv);
6025 return;
6026 }
6027
6028 status = resolve_dfspath_wcard(ctx, conn,
6029 req->flags2 & FLAGS2_DFS_PATHNAMES,
6030 newname,
6031 &newname,
6032 &dest_has_wcard);
6033 if (!NT_STATUS_IS_OK(status)) {
6034 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6035 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6036 ERRSRV, ERRbadpath);
6037 END_PROFILE(SMBmv);
6038 return;
6039 }
6040 reply_nterror(req, status);
6041 END_PROFILE(SMBmv);
6042 return;
6043 }
6044
6045 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
6046
6047 status = rename_internals(ctx, conn, req, name, newname, attrs, False,
6048 src_has_wcard, dest_has_wcard, DELETE_ACCESS);
6049 if (!NT_STATUS_IS_OK(status)) {
6050 if (open_was_deferred(req->mid)) {
6051 /* We have re-scheduled this call. */
6052 END_PROFILE(SMBmv);
6053 return;
6054 }
6055 reply_nterror(req, status);
6056 END_PROFILE(SMBmv);
6057 return;
6058 }
6059
6060 reply_outbuf(req, 0, 0);
6061
6062 END_PROFILE(SMBmv);
6063 return;
6064}
6065
6066/*******************************************************************
6067 Copy a file as part of a reply_copy.
6068******************************************************************/
6069
6070/*
6071 * TODO: check error codes on all callers
6072 */
6073
6074NTSTATUS copy_file(TALLOC_CTX *ctx,
6075 connection_struct *conn,
6076 const char *src,
6077 const char *dest1,
6078 int ofun,
6079 int count,
6080 bool target_is_directory)
6081{
6082 SMB_STRUCT_STAT src_sbuf, sbuf2;
6083 SMB_OFF_T ret=-1;
6084 files_struct *fsp1,*fsp2;
6085 char *dest = NULL;
6086 uint32 dosattrs;
6087 uint32 new_create_disposition;
6088 NTSTATUS status;
6089
6090 dest = talloc_strdup(ctx, dest1);
6091 if (!dest) {
6092 return NT_STATUS_NO_MEMORY;
6093 }
6094 if (target_is_directory) {
6095 const char *p = strrchr_m(src,'/');
6096 if (p) {
6097 p++;
6098 } else {
6099 p = src;
6100 }
6101 dest = talloc_asprintf_append(dest,
6102 "/%s",
6103 p);
6104 if (!dest) {
6105 return NT_STATUS_NO_MEMORY;
6106 }
6107 }
6108
6109 if (!vfs_file_exist(conn,src,&src_sbuf)) {
6110 TALLOC_FREE(dest);
6111 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6112 }
6113
6114 if (!target_is_directory && count) {
6115 new_create_disposition = FILE_OPEN;
6116 } else {
6117 if (!map_open_params_to_ntcreate(dest1,0,ofun,
6118 NULL, NULL, &new_create_disposition, NULL)) {
6119 TALLOC_FREE(dest);
6120 return NT_STATUS_INVALID_PARAMETER;
6121 }
6122 }
6123
6124 status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
6125 FILE_GENERIC_READ,
6126 FILE_SHARE_READ|FILE_SHARE_WRITE,
6127 FILE_OPEN,
6128 0,
6129 FILE_ATTRIBUTE_NORMAL,
6130 INTERNAL_OPEN_ONLY,
6131 NULL, &fsp1);
6132
6133 if (!NT_STATUS_IS_OK(status)) {
6134 TALLOC_FREE(dest);
6135 return status;
6136 }
6137
6138 dosattrs = dos_mode(conn, src, &src_sbuf);
6139 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
6140 ZERO_STRUCTP(&sbuf2);
6141 }
6142
6143 status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
6144 FILE_GENERIC_WRITE,
6145 FILE_SHARE_READ|FILE_SHARE_WRITE,
6146 new_create_disposition,
6147 0,
6148 dosattrs,
6149 INTERNAL_OPEN_ONLY,
6150 NULL, &fsp2);
6151
6152 TALLOC_FREE(dest);
6153
6154 if (!NT_STATUS_IS_OK(status)) {
6155 close_file(fsp1,ERROR_CLOSE);
6156 return status;
6157 }
6158
6159 if ((ofun&3) == 1) {
6160 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6161 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6162 /*
6163 * Stop the copy from occurring.
6164 */
6165 ret = -1;
6166 src_sbuf.st_size = 0;
6167 }
6168 }
6169
6170 if (src_sbuf.st_size) {
6171 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
6172 }
6173
6174 close_file(fsp1,NORMAL_CLOSE);
6175
6176 /* Ensure the modtime is set correctly on the destination file. */
6177 set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
6178
6179 /*
6180 * As we are opening fsp1 read-only we only expect
6181 * an error on close on fsp2 if we are out of space.
6182 * Thus we don't look at the error return from the
6183 * close of fsp1.
6184 */
6185 status = close_file(fsp2,NORMAL_CLOSE);
6186
6187 if (!NT_STATUS_IS_OK(status)) {
6188 return status;
6189 }
6190
6191 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
6192 return NT_STATUS_DISK_FULL;
6193 }
6194
6195 return NT_STATUS_OK;
6196}
6197
6198/****************************************************************************
6199 Reply to a file copy.
6200****************************************************************************/
6201
6202void reply_copy(struct smb_request *req)
6203{
6204 connection_struct *conn = req->conn;
6205 char *name = NULL;
6206 char *newname = NULL;
6207 char *directory = NULL;
6208 char *mask = NULL;
6209 char *p;
6210 int count=0;
6211 int error = ERRnoaccess;
6212 int err = 0;
6213 int tid2;
6214 int ofun;
6215 int flags;
6216 bool target_is_directory=False;
6217 bool source_has_wild = False;
6218 bool dest_has_wild = False;
6219 SMB_STRUCT_STAT sbuf1, sbuf2;
6220 NTSTATUS status;
6221 TALLOC_CTX *ctx = talloc_tos();
6222
6223 START_PROFILE(SMBcopy);
6224
6225 if (req->wct < 3) {
6226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6227 END_PROFILE(SMBcopy);
6228 return;
6229 }
6230
6231 tid2 = SVAL(req->inbuf,smb_vwv0);
6232 ofun = SVAL(req->inbuf,smb_vwv1);
6233 flags = SVAL(req->inbuf,smb_vwv2);
6234
6235 p = smb_buf(req->inbuf);
6236 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
6237 0, STR_TERMINATE, &status,
6238 &source_has_wild);
6239 if (!NT_STATUS_IS_OK(status)) {
6240 reply_nterror(req, status);
6241 END_PROFILE(SMBcopy);
6242 return;
6243 }
6244 p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
6245 0, STR_TERMINATE, &status,
6246 &dest_has_wild);
6247 if (!NT_STATUS_IS_OK(status)) {
6248 reply_nterror(req, status);
6249 END_PROFILE(SMBcopy);
6250 return;
6251 }
6252
6253 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
6254
6255 if (tid2 != conn->cnum) {
6256 /* can't currently handle inter share copies XXXX */
6257 DEBUG(3,("Rejecting inter-share copy\n"));
6258 reply_doserror(req, ERRSRV, ERRinvdevice);
6259 END_PROFILE(SMBcopy);
6260 return;
6261 }
6262
6263 status = resolve_dfspath_wcard(ctx, conn,
6264 req->flags2 & FLAGS2_DFS_PATHNAMES,
6265 name,
6266 &name,
6267 &source_has_wild);
6268 if (!NT_STATUS_IS_OK(status)) {
6269 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6270 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6271 ERRSRV, ERRbadpath);
6272 END_PROFILE(SMBcopy);
6273 return;
6274 }
6275 reply_nterror(req, status);
6276 END_PROFILE(SMBcopy);
6277 return;
6278 }
6279
6280 status = resolve_dfspath_wcard(ctx, conn,
6281 req->flags2 & FLAGS2_DFS_PATHNAMES,
6282 newname,
6283 &newname,
6284 &dest_has_wild);
6285 if (!NT_STATUS_IS_OK(status)) {
6286 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6287 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6288 ERRSRV, ERRbadpath);
6289 END_PROFILE(SMBcopy);
6290 return;
6291 }
6292 reply_nterror(req, status);
6293 END_PROFILE(SMBcopy);
6294 return;
6295 }
6296
6297 status = unix_convert(ctx, conn, name, source_has_wild,
6298 &name, NULL, &sbuf1);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 reply_nterror(req, status);
6301 END_PROFILE(SMBcopy);
6302 return;
6303 }
6304
6305 status = unix_convert(ctx, conn, newname, dest_has_wild,
6306 &newname, NULL, &sbuf2);
6307 if (!NT_STATUS_IS_OK(status)) {
6308 reply_nterror(req, status);
6309 END_PROFILE(SMBcopy);
6310 return;
6311 }
6312
6313 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
6314
6315 if ((flags&1) && target_is_directory) {
6316 reply_doserror(req, ERRDOS, ERRbadfile);
6317 END_PROFILE(SMBcopy);
6318 return;
6319 }
6320
6321 if ((flags&2) && !target_is_directory) {
6322 reply_doserror(req, ERRDOS, ERRbadpath);
6323 END_PROFILE(SMBcopy);
6324 return;
6325 }
6326
6327 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
6328 /* wants a tree copy! XXXX */
6329 DEBUG(3,("Rejecting tree copy\n"));
6330 reply_doserror(req, ERRSRV, ERRerror);
6331 END_PROFILE(SMBcopy);
6332 return;
6333 }
6334
6335 p = strrchr_m(name,'/');
6336 if (!p) {
6337 directory = talloc_strdup(ctx, "./");
6338 if (!directory) {
6339 reply_nterror(req, NT_STATUS_NO_MEMORY);
6340 END_PROFILE(SMBcopy);
6341 return;
6342 }
6343 mask = name;
6344 } else {
6345 *p = 0;
6346 directory = talloc_strdup(ctx, name);
6347 if (!directory) {
6348 reply_nterror(req, NT_STATUS_NO_MEMORY);
6349 END_PROFILE(SMBcopy);
6350 return;
6351 }
6352 mask = p+1;
6353 }
6354
6355 /*
6356 * We should only check the mangled cache
6357 * here if unix_convert failed. This means
6358 * that the path in 'mask' doesn't exist
6359 * on the file system and so we need to look
6360 * for a possible mangle. This patch from
6361 * Tine Smukavec <valentin.smukavec@hermes.si>.
6362 */
6363
6364 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
6365 char *new_mask = NULL;
6366 mangle_lookup_name_from_8_3(ctx,
6367 mask,
6368 &new_mask,
6369 conn->params );
6370 if (new_mask) {
6371 mask = new_mask;
6372 }
6373 }
6374
6375 if (!source_has_wild) {
6376 directory = talloc_asprintf_append(directory,
6377 "/%s",
6378 mask);
6379 if (dest_has_wild) {
6380 char *mod_newname = NULL;
6381 if (!resolve_wildcards(ctx,
6382 directory,newname,&mod_newname)) {
6383 reply_nterror(req, NT_STATUS_NO_MEMORY);
6384 END_PROFILE(SMBcopy);
6385 return;
6386 }
6387 newname = mod_newname;
6388 }
6389
6390 status = check_name(conn, directory);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 reply_nterror(req, status);
6393 END_PROFILE(SMBcopy);
6394 return;
6395 }
6396
6397 status = check_name(conn, newname);
6398 if (!NT_STATUS_IS_OK(status)) {
6399 reply_nterror(req, status);
6400 END_PROFILE(SMBcopy);
6401 return;
6402 }
6403
6404 status = copy_file(ctx,conn,directory,newname,ofun,
6405 count,target_is_directory);
6406
6407 if(!NT_STATUS_IS_OK(status)) {
6408 reply_nterror(req, status);
6409 END_PROFILE(SMBcopy);
6410 return;
6411 } else {
6412 count++;
6413 }
6414 } else {
6415 struct smb_Dir *dir_hnd = NULL;
6416 const char *dname = NULL;
6417 long offset = 0;
6418
6419 if (strequal(mask,"????????.???")) {
6420 mask[0] = '*';
6421 mask[1] = '\0';
6422 }
6423
6424 status = check_name(conn, directory);
6425 if (!NT_STATUS_IS_OK(status)) {
6426 reply_nterror(req, status);
6427 END_PROFILE(SMBcopy);
6428 return;
6429 }
6430
6431 dir_hnd = OpenDir(talloc_tos(), conn, directory, mask, 0);
6432 if (dir_hnd == NULL) {
6433 status = map_nt_error_from_unix(errno);
6434 reply_nterror(req, status);
6435 END_PROFILE(SMBcopy);
6436 return;
6437 }
6438
6439 error = ERRbadfile;
6440
6441 while ((dname = ReadDirName(dir_hnd, &offset))) {
6442 char *destname = NULL;
6443 char *fname = NULL;
6444
6445 if (ISDOT(dname) || ISDOTDOT(dname)) {
6446 continue;
6447 }
6448
6449 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
6450 continue;
6451 }
6452
6453 if(!mask_match(dname, mask, conn->case_sensitive)) {
6454 continue;
6455 }
6456
6457 error = ERRnoaccess;
6458 fname = talloc_asprintf(ctx,
6459 "%s/%s",
6460 directory,
6461 dname);
6462 if (!fname) {
6463 TALLOC_FREE(dir_hnd);
6464 reply_nterror(req, NT_STATUS_NO_MEMORY);
6465 END_PROFILE(SMBcopy);
6466 return;
6467 }
6468
6469 if (!resolve_wildcards(ctx,
6470 fname,newname,&destname)) {
6471 continue;
6472 }
6473 if (!destname) {
6474 TALLOC_FREE(dir_hnd);
6475 reply_nterror(req, NT_STATUS_NO_MEMORY);
6476 END_PROFILE(SMBcopy);
6477 return;
6478 }
6479
6480 status = check_name(conn, fname);
6481 if (!NT_STATUS_IS_OK(status)) {
6482 TALLOC_FREE(dir_hnd);
6483 reply_nterror(req, status);
6484 END_PROFILE(SMBcopy);
6485 return;
6486 }
6487
6488 status = check_name(conn, destname);
6489 if (!NT_STATUS_IS_OK(status)) {
6490 TALLOC_FREE(dir_hnd);
6491 reply_nterror(req, status);
6492 END_PROFILE(SMBcopy);
6493 return;
6494 }
6495
6496 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
6497
6498 status = copy_file(ctx,conn,fname,destname,ofun,
6499 count,target_is_directory);
6500 if (NT_STATUS_IS_OK(status)) {
6501 count++;
6502 }
6503 TALLOC_FREE(fname);
6504 TALLOC_FREE(destname);
6505 }
6506 TALLOC_FREE(dir_hnd);
6507 }
6508
6509 if (count == 0) {
6510 if(err) {
6511 /* Error on close... */
6512 errno = err;
6513 reply_unixerror(req, ERRHRD, ERRgeneral);
6514 END_PROFILE(SMBcopy);
6515 return;
6516 }
6517
6518 reply_doserror(req, ERRDOS, error);
6519 END_PROFILE(SMBcopy);
6520 return;
6521 }
6522
6523 reply_outbuf(req, 1, 0);
6524 SSVAL(req->outbuf,smb_vwv0,count);
6525
6526 END_PROFILE(SMBcopy);
6527 return;
6528}
6529
6530#undef DBGC_CLASS
6531#define DBGC_CLASS DBGC_LOCKING
6532
6533/****************************************************************************
6534 Get a lock pid, dealing with large count requests.
6535****************************************************************************/
6536
6537uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
6538{
6539 if(!large_file_format)
6540 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6541 else
6542 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6543}
6544
6545/****************************************************************************
6546 Get a lock count, dealing with large count requests.
6547****************************************************************************/
6548
6549SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
6550{
6551 SMB_BIG_UINT count = 0;
6552
6553 if(!large_file_format) {
6554 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6555 } else {
6556
6557#if defined(HAVE_LONGLONG)
6558 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6559 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6560#else /* HAVE_LONGLONG */
6561
6562 /*
6563 * NT4.x seems to be broken in that it sends large file (64 bit)
6564 * lockingX calls even if the CAP_LARGE_FILES was *not*
6565 * negotiated. For boxes without large unsigned ints truncate the
6566 * lock count by dropping the top 32 bits.
6567 */
6568
6569 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6570 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6571 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6572 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6573 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6574 }
6575
6576 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6577#endif /* HAVE_LONGLONG */
6578 }
6579
6580 return count;
6581}
6582
6583#if !defined(HAVE_LONGLONG)
6584/****************************************************************************
6585 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6586****************************************************************************/
6587
6588static uint32 map_lock_offset(uint32 high, uint32 low)
6589{
6590 unsigned int i;
6591 uint32 mask = 0;
6592 uint32 highcopy = high;
6593
6594 /*
6595 * Try and find out how many significant bits there are in high.
6596 */
6597
6598 for(i = 0; highcopy; i++)
6599 highcopy >>= 1;
6600
6601 /*
6602 * We use 31 bits not 32 here as POSIX
6603 * lock offsets may not be negative.
6604 */
6605
6606 mask = (~0) << (31 - i);
6607
6608 if(low & mask)
6609 return 0; /* Fail. */
6610
6611 high <<= (31 - i);
6612
6613 return (high|low);
6614}
6615#endif /* !defined(HAVE_LONGLONG) */
6616
6617/****************************************************************************
6618 Get a lock offset, dealing with large offset requests.
6619****************************************************************************/
6620
6621SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
6622{
6623 SMB_BIG_UINT offset = 0;
6624
6625 *err = False;
6626
6627 if(!large_file_format) {
6628 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6629 } else {
6630
6631#if defined(HAVE_LONGLONG)
6632 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6633 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6634#else /* HAVE_LONGLONG */
6635
6636 /*
6637 * NT4.x seems to be broken in that it sends large file (64 bit)
6638 * lockingX calls even if the CAP_LARGE_FILES was *not*
6639 * negotiated. For boxes without large unsigned ints mangle the
6640 * lock offset by mapping the top 32 bits onto the lower 32.
6641 */
6642
6643 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6644 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6645 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6646 uint32 new_low = 0;
6647
6648 if((new_low = map_lock_offset(high, low)) == 0) {
6649 *err = True;
6650 return (SMB_BIG_UINT)-1;
6651 }
6652
6653 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
6654 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
6655 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
6656 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
6657 }
6658
6659 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6660#endif /* HAVE_LONGLONG */
6661 }
6662
6663 return offset;
6664}
6665
6666/****************************************************************************
6667 Reply to a lockingX request.
6668****************************************************************************/
6669
6670void reply_lockingX(struct smb_request *req)
6671{
6672 connection_struct *conn = req->conn;
6673 files_struct *fsp;
6674 unsigned char locktype;
6675 unsigned char oplocklevel;
6676 uint16 num_ulocks;
6677 uint16 num_locks;
6678 SMB_BIG_UINT count = 0, offset = 0;
6679 uint32 lock_pid;
6680 int32 lock_timeout;
6681 int i;
6682 char *data;
6683 bool large_file_format;
6684 bool err;
6685 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
6686
6687 START_PROFILE(SMBlockingX);
6688
6689 if (req->wct < 8) {
6690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6691 END_PROFILE(SMBlockingX);
6692 return;
6693 }
6694
6695 fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
6696 locktype = CVAL(req->inbuf,smb_vwv3);
6697 oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
6698 num_ulocks = SVAL(req->inbuf,smb_vwv6);
6699 num_locks = SVAL(req->inbuf,smb_vwv7);
6700 lock_timeout = IVAL(req->inbuf,smb_vwv4);
6701 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
6702
6703 if (!check_fsp(conn, req, fsp, &current_user)) {
6704 END_PROFILE(SMBlockingX);
6705 return;
6706 }
6707
6708 data = smb_buf(req->inbuf);
6709
6710 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
6711 /* we don't support these - and CANCEL_LOCK makes w2k
6712 and XP reboot so I don't really want to be
6713 compatible! (tridge) */
6714 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
6715 END_PROFILE(SMBlockingX);
6716 return;
6717 }
6718
6719 /* Check if this is an oplock break on a file
6720 we have granted an oplock on.
6721 */
6722 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
6723 /* Client can insist on breaking to none. */
6724 bool break_to_none = (oplocklevel == 0);
6725 bool result;
6726
6727 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
6728 "for fnum = %d\n", (unsigned int)oplocklevel,
6729 fsp->fnum ));
6730
6731 /*
6732 * Make sure we have granted an exclusive or batch oplock on
6733 * this file.
6734 */
6735
6736 if (fsp->oplock_type == 0) {
6737
6738 /* The Samba4 nbench simulator doesn't understand
6739 the difference between break to level2 and break
6740 to none from level2 - it sends oplock break
6741 replies in both cases. Don't keep logging an error
6742 message here - just ignore it. JRA. */
6743
6744 DEBUG(5,("reply_lockingX: Error : oplock break from "
6745 "client for fnum = %d (oplock=%d) and no "
6746 "oplock granted on this file (%s).\n",
6747 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
6748
6749 /* if this is a pure oplock break request then don't
6750 * send a reply */
6751 if (num_locks == 0 && num_ulocks == 0) {
6752 END_PROFILE(SMBlockingX);
6753 return;
6754 } else {
6755 END_PROFILE(SMBlockingX);
6756 reply_doserror(req, ERRDOS, ERRlock);
6757 return;
6758 }
6759 }
6760
6761 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
6762 (break_to_none)) {
6763 result = remove_oplock(fsp);
6764 } else {
6765 result = downgrade_oplock(fsp);
6766 }
6767
6768 if (!result) {
6769 DEBUG(0, ("reply_lockingX: error in removing "
6770 "oplock on file %s\n", fsp->fsp_name));
6771 /* Hmmm. Is this panic justified? */
6772 smb_panic("internal tdb error");
6773 }
6774
6775 reply_to_oplock_break_requests(fsp);
6776
6777 /* if this is a pure oplock break request then don't send a
6778 * reply */
6779 if (num_locks == 0 && num_ulocks == 0) {
6780 /* Sanity check - ensure a pure oplock break is not a
6781 chained request. */
6782 if(CVAL(req->inbuf,smb_vwv0) != 0xff)
6783 DEBUG(0,("reply_lockingX: Error : pure oplock "
6784 "break is a chained %d request !\n",
6785 (unsigned int)CVAL(req->inbuf,
6786 smb_vwv0) ));
6787 END_PROFILE(SMBlockingX);
6788 return;
6789 }
6790 }
6791
6792 /*
6793 * We do this check *after* we have checked this is not a oplock break
6794 * response message. JRA.
6795 */
6796
6797 release_level_2_oplocks_on_change(fsp);
6798
6799 if (smb_buflen(req->inbuf) <
6800 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
6801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6802 END_PROFILE(SMBlockingX);
6803 return;
6804 }
6805
6806 /* Data now points at the beginning of the list
6807 of smb_unlkrng structs */
6808 for(i = 0; i < (int)num_ulocks; i++) {
6809 lock_pid = get_lock_pid( data, i, large_file_format);
6810 count = get_lock_count( data, i, large_file_format);
6811 offset = get_lock_offset( data, i, large_file_format, &err);
6812
6813 /*
6814 * There is no error code marked "stupid client bug".... :-).
6815 */
6816 if(err) {
6817 END_PROFILE(SMBlockingX);
6818 reply_doserror(req, ERRDOS, ERRnoaccess);
6819 return;
6820 }
6821
6822 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
6823 "pid %u, file %s\n", (double)offset, (double)count,
6824 (unsigned int)lock_pid, fsp->fsp_name ));
6825
6826 status = do_unlock(smbd_messaging_context(),
6827 fsp,
6828 lock_pid,
6829 count,
6830 offset,
6831 WINDOWS_LOCK);
6832
6833 if (NT_STATUS_V(status)) {
6834 END_PROFILE(SMBlockingX);
6835 reply_nterror(req, status);
6836 return;
6837 }
6838 }
6839
6840 /* Setup the timeout in seconds. */
6841
6842 if (!lp_blocking_locks(SNUM(conn))) {
6843 lock_timeout = 0;
6844 }
6845
6846 /* Now do any requested locks */
6847 data += ((large_file_format ? 20 : 10)*num_ulocks);
6848
6849 /* Data now points at the beginning of the list
6850 of smb_lkrng structs */
6851
6852 for(i = 0; i < (int)num_locks; i++) {
6853 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
6854 READ_LOCK:WRITE_LOCK);
6855 lock_pid = get_lock_pid( data, i, large_file_format);
6856 count = get_lock_count( data, i, large_file_format);
6857 offset = get_lock_offset( data, i, large_file_format, &err);
6858
6859 /*
6860 * There is no error code marked "stupid client bug".... :-).
6861 */
6862 if(err) {
6863 END_PROFILE(SMBlockingX);
6864 reply_doserror(req, ERRDOS, ERRnoaccess);
6865 return;
6866 }
6867
6868 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
6869 "%u, file %s timeout = %d\n", (double)offset,
6870 (double)count, (unsigned int)lock_pid,
6871 fsp->fsp_name, (int)lock_timeout ));
6872
6873 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
6874 if (lp_blocking_locks(SNUM(conn))) {
6875
6876 /* Schedule a message to ourselves to
6877 remove the blocking lock record and
6878 return the right error. */
6879
6880 if (!blocking_lock_cancel(fsp,
6881 lock_pid,
6882 offset,
6883 count,
6884 WINDOWS_LOCK,
6885 locktype,
6886 NT_STATUS_FILE_LOCK_CONFLICT)) {
6887 END_PROFILE(SMBlockingX);
6888 reply_nterror(
6889 req,
6890 NT_STATUS_DOS(
6891 ERRDOS,
6892 ERRcancelviolation));
6893 return;
6894 }
6895 }
6896 /* Remove a matching pending lock. */
6897 status = do_lock_cancel(fsp,
6898 lock_pid,
6899 count,
6900 offset,
6901 WINDOWS_LOCK);
6902 } else {
6903 bool blocking_lock = lock_timeout ? True : False;
6904 bool defer_lock = False;
6905 struct byte_range_lock *br_lck;
6906 uint32 block_smbpid;
6907
6908 br_lck = do_lock(smbd_messaging_context(),
6909 fsp,
6910 lock_pid,
6911 count,
6912 offset,
6913 lock_type,
6914 WINDOWS_LOCK,
6915 blocking_lock,
6916 &status,
6917 &block_smbpid);
6918
6919 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6920 /* Windows internal resolution for blocking locks seems
6921 to be about 200ms... Don't wait for less than that. JRA. */
6922 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
6923 lock_timeout = lp_lock_spin_time();
6924 }
6925 defer_lock = True;
6926 }
6927
6928 /* This heuristic seems to match W2K3 very well. If a
6929 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
6930 it pretends we asked for a timeout of between 150 - 300 milliseconds as
6931 far as I can tell. Replacement for do_lock_spin(). JRA. */
6932
6933 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
6934 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
6935 defer_lock = True;
6936 lock_timeout = lp_lock_spin_time();
6937 }
6938
6939 if (br_lck && defer_lock) {
6940 /*
6941 * A blocking lock was requested. Package up
6942 * this smb into a queued request and push it
6943 * onto the blocking lock queue.
6944 */
6945 if(push_blocking_lock_request(br_lck,
6946 req,
6947 fsp,
6948 lock_timeout,
6949 i,
6950 lock_pid,
6951 lock_type,
6952 WINDOWS_LOCK,
6953 offset,
6954 count,
6955 block_smbpid)) {
6956 TALLOC_FREE(br_lck);
6957 END_PROFILE(SMBlockingX);
6958 return;
6959 }
6960 }
6961
6962 TALLOC_FREE(br_lck);
6963 }
6964
6965 if (NT_STATUS_V(status)) {
6966 END_PROFILE(SMBlockingX);
6967 reply_nterror(req, status);
6968 return;
6969 }
6970 }
6971
6972 /* If any of the above locks failed, then we must unlock
6973 all of the previous locks (X/Open spec). */
6974
6975 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
6976 (i != num_locks) &&
6977 (num_locks != 0)) {
6978 /*
6979 * Ensure we don't do a remove on the lock that just failed,
6980 * as under POSIX rules, if we have a lock already there, we
6981 * will delete it (and we shouldn't) .....
6982 */
6983 for(i--; i >= 0; i--) {
6984 lock_pid = get_lock_pid( data, i, large_file_format);
6985 count = get_lock_count( data, i, large_file_format);
6986 offset = get_lock_offset( data, i, large_file_format,
6987 &err);
6988
6989 /*
6990 * There is no error code marked "stupid client
6991 * bug".... :-).
6992 */
6993 if(err) {
6994 END_PROFILE(SMBlockingX);
6995 reply_doserror(req, ERRDOS, ERRnoaccess);
6996 return;
6997 }
6998
6999 do_unlock(smbd_messaging_context(),
7000 fsp,
7001 lock_pid,
7002 count,
7003 offset,
7004 WINDOWS_LOCK);
7005 }
7006 END_PROFILE(SMBlockingX);
7007 reply_nterror(req, status);
7008 return;
7009 }
7010
7011 reply_outbuf(req, 2, 0);
7012
7013 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7014 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7015
7016 END_PROFILE(SMBlockingX);
7017 chain_reply(req);
7018}
7019
7020#undef DBGC_CLASS
7021#define DBGC_CLASS DBGC_ALL
7022
7023/****************************************************************************
7024 Reply to a SMBreadbmpx (read block multiplex) request.
7025 Always reply with an error, if someone has a platform really needs this,
7026 please contact vl@samba.org
7027****************************************************************************/
7028
7029void reply_readbmpx(struct smb_request *req)
7030{
7031 START_PROFILE(SMBreadBmpx);
7032 reply_doserror(req, ERRSRV, ERRuseSTD);
7033 END_PROFILE(SMBreadBmpx);
7034 return;
7035}
7036
7037/****************************************************************************
7038 Reply to a SMBreadbs (read block multiplex secondary) request.
7039 Always reply with an error, if someone has a platform really needs this,
7040 please contact vl@samba.org
7041****************************************************************************/
7042
7043void reply_readbs(struct smb_request *req)
7044{
7045 START_PROFILE(SMBreadBs);
7046 reply_doserror(req, ERRSRV, ERRuseSTD);
7047 END_PROFILE(SMBreadBs);
7048 return;
7049}
7050
7051/****************************************************************************
7052 Reply to a SMBsetattrE.
7053****************************************************************************/
7054
7055void reply_setattrE(struct smb_request *req)
7056{
7057 connection_struct *conn = req->conn;
7058 struct timespec ts[2];
7059 files_struct *fsp;
7060 SMB_STRUCT_STAT sbuf;
7061 NTSTATUS status;
7062
7063 START_PROFILE(SMBsetattrE);
7064
7065 if (req->wct < 7) {
7066 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7067 END_PROFILE(SMBsetattrE);
7068 return;
7069 }
7070
7071 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7072
7073 if(!fsp || (fsp->conn != conn)) {
7074 reply_doserror(req, ERRDOS, ERRbadfid);
7075 END_PROFILE(SMBsetattrE);
7076 return;
7077 }
7078
7079
7080 /*
7081 * Convert the DOS times into unix times. Ignore create
7082 * time as UNIX can't set this.
7083 */
7084
7085 ts[0] = convert_time_t_to_timespec(
7086 srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
7087 ts[1] = convert_time_t_to_timespec(
7088 srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
7089
7090 reply_outbuf(req, 0, 0);
7091
7092 /*
7093 * Patch from Ray Frush <frush@engr.colostate.edu>
7094 * Sometimes times are sent as zero - ignore them.
7095 */
7096
7097 /* Ensure we have a valid stat struct for the source. */
7098 if (fsp->fh->fd != -1) {
7099 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
7100 status = map_nt_error_from_unix(errno);
7101 reply_nterror(req, status);
7102 END_PROFILE(SMBsetattrE);
7103 return;
7104 }
7105 } else {
7106 if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
7107 status = map_nt_error_from_unix(errno);
7108 reply_nterror(req, status);
7109 END_PROFILE(SMBsetattrE);
7110 return;
7111 }
7112 }
7113
7114 status = smb_set_file_time(conn, fsp, fsp->fsp_name,
7115 &sbuf, ts, true);
7116 if (!NT_STATUS_IS_OK(status)) {
7117 reply_doserror(req, ERRDOS, ERRnoaccess);
7118 END_PROFILE(SMBsetattrE);
7119 return;
7120 }
7121
7122 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
7123 fsp->fnum,
7124 (unsigned int)ts[0].tv_sec,
7125 (unsigned int)ts[1].tv_sec));
7126
7127 END_PROFILE(SMBsetattrE);
7128 return;
7129}
7130
7131
7132/* Back from the dead for OS/2..... JRA. */
7133
7134/****************************************************************************
7135 Reply to a SMBwritebmpx (write block multiplex primary) request.
7136 Always reply with an error, if someone has a platform really needs this,
7137 please contact vl@samba.org
7138****************************************************************************/
7139
7140void reply_writebmpx(struct smb_request *req)
7141{
7142 START_PROFILE(SMBwriteBmpx);
7143 reply_doserror(req, ERRSRV, ERRuseSTD);
7144 END_PROFILE(SMBwriteBmpx);
7145 return;
7146}
7147
7148/****************************************************************************
7149 Reply to a SMBwritebs (write block multiplex secondary) request.
7150 Always reply with an error, if someone has a platform really needs this,
7151 please contact vl@samba.org
7152****************************************************************************/
7153
7154void reply_writebs(struct smb_request *req)
7155{
7156 START_PROFILE(SMBwriteBs);
7157 reply_doserror(req, ERRSRV, ERRuseSTD);
7158 END_PROFILE(SMBwriteBs);
7159 return;
7160}
7161
7162/****************************************************************************
7163 Reply to a SMBgetattrE.
7164****************************************************************************/
7165
7166void reply_getattrE(struct smb_request *req)
7167{
7168 connection_struct *conn = req->conn;
7169 SMB_STRUCT_STAT sbuf;
7170 int mode;
7171 files_struct *fsp;
7172 struct timespec create_ts;
7173
7174 START_PROFILE(SMBgetattrE);
7175
7176 if (req->wct < 1) {
7177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7178 END_PROFILE(SMBgetattrE);
7179 return;
7180 }
7181
7182 fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
7183
7184 if(!fsp || (fsp->conn != conn)) {
7185 reply_doserror(req, ERRDOS, ERRbadfid);
7186 END_PROFILE(SMBgetattrE);
7187 return;
7188 }
7189
7190 /* Do an fstat on this file */
7191 if(fsp_stat(fsp, &sbuf)) {
7192 reply_unixerror(req, ERRDOS, ERRnoaccess);
7193 END_PROFILE(SMBgetattrE);
7194 return;
7195 }
7196
7197 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
7198
7199 /*
7200 * Convert the times into dos times. Set create
7201 * date to be last modify date as UNIX doesn't save
7202 * this.
7203 */
7204
7205 reply_outbuf(req, 11, 0);
7206
7207 create_ts = get_create_timespec(&sbuf,
7208 lp_fake_dir_create_times(SNUM(conn)));
7209 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7210 srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
7211 /* Should we check pending modtime here ? JRA */
7212 srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
7213
7214 if (mode & aDIR) {
7215 SIVAL(req->outbuf, smb_vwv6, 0);
7216 SIVAL(req->outbuf, smb_vwv8, 0);
7217 } else {
7218 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
7219 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_size);
7220 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7221 }
7222 SSVAL(req->outbuf,smb_vwv10, mode);
7223
7224 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7225
7226 END_PROFILE(SMBgetattrE);
7227 return;
7228}
Note: See TracBrowser for help on using the repository browser.