source: trunk/server/source3/smbd/reply.c@ 620

Last change on this file since 620 was 590, checked in by Herwig Bauernfeind, 14 years ago

Samba 3.5: Update trunk to 3.5.6

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